From patchwork Mon May 2 19:52:47 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jason Merrill X-Patchwork-Id: 53405 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id E0F143858010 for ; Mon, 2 May 2022 19:53:22 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org E0F143858010 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1651521202; bh=DCJ5M8+n7/WZH4BSdzJkq3Dzl/JryYUvbxR0Ibif0+Q=; h=To:Subject:Date:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:From; b=yz/VDttXSkhrVMChO+zVEVgqxUjLTO9RCzftpFu6PbBetEaA6Yyhwy/klBjVQ32Kw 29GZL+ywCPu0gp+qinByRupAqPKRQ0Ft6wOd+LG/W4TVENrx4W4IcOU5x8wVDImauB EkUfIqEm47PJ9mWRk2R5DSA1Mslqo0Bcn2DVkE9o= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by sourceware.org (Postfix) with ESMTPS id 25A573858C50 for ; Mon, 2 May 2022 19:52:53 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 25A573858C50 Received: from mail-qk1-f197.google.com (mail-qk1-f197.google.com [209.85.222.197]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-160-arIG6EP3PUS3CJF7cnkkZA-1; Mon, 02 May 2022 15:52:51 -0400 X-MC-Unique: arIG6EP3PUS3CJF7cnkkZA-1 Received: by mail-qk1-f197.google.com with SMTP id u7-20020ae9d807000000b00680a8111ef6so10835632qkf.17 for ; Mon, 02 May 2022 12:52:51 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:subject:date:message-id:mime-version :content-transfer-encoding; bh=DCJ5M8+n7/WZH4BSdzJkq3Dzl/JryYUvbxR0Ibif0+Q=; b=rw+llpe9cEWIN5wseHPJYUADdewissjLRq9oJ5znpTor04s/nzK11agCRcJhbFpYhx tTWZsZ8MZBkDVN8+nLTLFWiO7pmFVDwPpakIXYP62PeIG2QHquaYmN/O4WKNmkR+o4Uw 6u1Boys+kQItOXaVOLcUj1T0f9dedhXKm6COXdlVv1DwDbJx4spgTebv4YaxLeCuCwg9 jeRKsr1GuMTTb/ENKPxvuiF/7PCSNn5rPVRoQbvRcT4VcbCmmcCi4NKLhe3UGyQnz1gx oAJB2fpr7iVqxmPnEOKuN8RMzxBbJEBrOhWZIv4rjX/1J4JdY+PqJQDpQlcyzzx/MCAG hCXw== X-Gm-Message-State: AOAM531sZFGNF8oTWkqCbGeH8+H2ms2hQsI+rR/fge7kZSLHiZJ00a6a 0qkRTnP9rRB6R5avAq8hNk7VHsgl7lMLKG4z/+sWbVB8mUX1mTlf0xh6iW0Ptcp+1j3tK5Zt3Yc QHHWLGFQKamGuShmLD6E/lLUVJu3vB45Fnl4MtK22AdeD/U9POdgNivt2CEm/PLjsgg== X-Received: by 2002:a37:411:0:b0:69f:cc35:773e with SMTP id 17-20020a370411000000b0069fcc35773emr7474234qke.385.1651521170538; Mon, 02 May 2022 12:52:50 -0700 (PDT) X-Google-Smtp-Source: ABdhPJyrFwFhQllHy94ZhvjRSCiD1uMcPKOaHmFc6f8BF7Ch2qlVTc8285m7c3/88SAkRMxESQY4DA== X-Received: by 2002:a37:411:0:b0:69f:cc35:773e with SMTP id 17-20020a370411000000b0069fcc35773emr7474211qke.385.1651521170020; Mon, 02 May 2022 12:52:50 -0700 (PDT) Received: from barrymore.redhat.com (130-44-159-43.s15913.c3-0.arl-cbr1.sbo-arl.ma.cable.rcncustomer.com. [130.44.159.43]) by smtp.gmail.com with ESMTPSA id w6-20020a05620a0e8600b0069fd57d435fsm2932899qkm.101.2022.05.02.12.52.48 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 02 May 2022 12:52:49 -0700 (PDT) To: gcc-patches@gcc.gnu.org Subject: [pushed] c++: also note name used in enclosing class Date: Mon, 2 May 2022 15:52:47 -0400 Message-Id: <20220502195247.1484300-1-jason@redhat.com> X-Mailer: git-send-email 2.27.0 MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-13.4 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_LOW, SPF_HELO_NONE, SPF_NONE, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Jason Merrill via Gcc-patches From: Jason Merrill Reply-To: Jason Merrill Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" While looking at PR96645 I noticed that while we were diagnosing names changing meaning in the full class context, we weren't doing this for lookups in nested class bodies. Note that this breaks current range-v3; I've submitted a pull request to fix its violation of the rule. Tested x86_64-pc-linux-gnu, applying to trunk. gcc/cp/ChangeLog: * class.cc (maybe_note_name_used_in_class): Note in all enclosing classes. Remember location of use. (note_name_declared_in_class): Adjust. gcc/testsuite/ChangeLog: * g++.dg/lookup/name-clash13.C: New test. * g++.dg/lookup/name-clash14.C: New test. * g++.dg/lookup/name-clash15.C: New test. * g++.dg/lookup/name-clash16.C: New test. --- gcc/cp/class.cc | 61 +++++++++++++++------- gcc/testsuite/g++.dg/lookup/name-clash13.C | 7 +++ gcc/testsuite/g++.dg/lookup/name-clash14.C | 9 ++++ gcc/testsuite/g++.dg/lookup/name-clash15.C | 14 +++++ gcc/testsuite/g++.dg/lookup/name-clash16.C | 13 +++++ 5 files changed, 86 insertions(+), 18 deletions(-) create mode 100644 gcc/testsuite/g++.dg/lookup/name-clash13.C create mode 100644 gcc/testsuite/g++.dg/lookup/name-clash14.C create mode 100644 gcc/testsuite/g++.dg/lookup/name-clash15.C create mode 100644 gcc/testsuite/g++.dg/lookup/name-clash16.C base-commit: 7e1f30d7edd433ca0fc28ae9ac1ce9b522790baf diff --git a/gcc/cp/class.cc b/gcc/cp/class.cc index bfda0065bf4..bc94ed45e17 100644 --- a/gcc/cp/class.cc +++ b/gcc/cp/class.cc @@ -8931,32 +8931,53 @@ is_really_empty_class (tree type, bool ignore_vptr) void maybe_note_name_used_in_class (tree name, tree decl) { - splay_tree names_used; - /* If we're not defining a class, there's nothing to do. */ if (!(innermost_scope_kind() == sk_class && TYPE_BEING_DEFINED (current_class_type) && !LAMBDA_TYPE_P (current_class_type))) return; - /* If there's already a binding for this NAME, then we don't have - anything to worry about. */ - if (lookup_member (current_class_type, name, - /*protect=*/0, /*want_type=*/false, tf_warning_or_error)) - return; + const cp_binding_level *blev = nullptr; + if (const cxx_binding *binding = IDENTIFIER_BINDING (name)) + blev = binding->scope; + const cp_binding_level *lev = current_binding_level; - if (!current_class_stack[current_class_depth - 1].names_used) - current_class_stack[current_class_depth - 1].names_used - = splay_tree_new (splay_tree_compare_pointers, 0, 0); - names_used = current_class_stack[current_class_depth - 1].names_used; + /* Record the binding in the names_used tables for classes inside blev. */ + for (int i = current_class_depth; i > 0; --i) + { + tree type = (i == current_class_depth + ? current_class_type + : current_class_stack[i].type); - splay_tree_insert (names_used, - (splay_tree_key) name, - (splay_tree_value) decl); + for (; lev; lev = lev->level_chain) + { + if (lev == blev) + /* We found the declaration. */ + return; + if (lev->kind == sk_class && lev->this_entity == type) + /* This class is inside the declaration scope. */ + break; + } + + auto &names_used = current_class_stack[i-1].names_used; + if (!names_used) + names_used = splay_tree_new (splay_tree_compare_pointers, 0, 0); + + tree use = build1_loc (input_location, VIEW_CONVERT_EXPR, + TREE_TYPE (decl), decl); + EXPR_LOCATION_WRAPPER_P (use) = 1; + splay_tree_insert (names_used, + (splay_tree_key) name, + (splay_tree_value) use); + } } /* Note that NAME was declared (as DECL) in the current class. Check - to see that the declaration is valid. */ + to see that the declaration is valid under [class.member.lookup]: + + If [the result of a search in T for N at point P] differs from the result of + a search in T for N from immediately after the class-specifier of T, the + program is ill-formed, no diagnostic required. */ void note_name_declared_in_class (tree name, tree decl) @@ -8979,6 +9000,9 @@ note_name_declared_in_class (tree name, tree decl) n = splay_tree_lookup (names_used, (splay_tree_key) name); if (n) { + tree use = (tree) n->value; + location_t loc = EXPR_LOCATION (use); + tree olddecl = OVL_FIRST (TREE_OPERAND (use, 0)); /* [basic.scope.class] A name N used in a class S shall refer to the same declaration @@ -8987,9 +9011,10 @@ note_name_declared_in_class (tree name, tree decl) if (permerror (location_of (decl), "declaration of %q#D changes meaning of %qD", decl, OVL_NAME (decl))) - inform (location_of ((tree) n->value), - "%qD declared here as %q#D", - OVL_NAME (decl), (tree) n->value); + { + inform (loc, "used here to mean %q#D", olddecl); + inform (location_of (olddecl), "declared here" ); + } } } diff --git a/gcc/testsuite/g++.dg/lookup/name-clash13.C b/gcc/testsuite/g++.dg/lookup/name-clash13.C new file mode 100644 index 00000000000..ce43435f011 --- /dev/null +++ b/gcc/testsuite/g++.dg/lookup/name-clash13.C @@ -0,0 +1,7 @@ +typedef int T; +struct A { + struct B { + static T t; + }; + typedef float T; // { dg-error "changes meaning" } +}; diff --git a/gcc/testsuite/g++.dg/lookup/name-clash14.C b/gcc/testsuite/g++.dg/lookup/name-clash14.C new file mode 100644 index 00000000000..71305ba082c --- /dev/null +++ b/gcc/testsuite/g++.dg/lookup/name-clash14.C @@ -0,0 +1,9 @@ +const int x = 24; +struct A +{ + struct B + { + enum { E = x }; + }; + static const int x = 42; // { dg-error "changes meaning" } +}; diff --git a/gcc/testsuite/g++.dg/lookup/name-clash15.C b/gcc/testsuite/g++.dg/lookup/name-clash15.C new file mode 100644 index 00000000000..5c123bf7005 --- /dev/null +++ b/gcc/testsuite/g++.dg/lookup/name-clash15.C @@ -0,0 +1,14 @@ +struct C { + static const int x = 24; +}; + +struct A +{ + struct B: C + { + enum { E = x }; + }; + + // OK, earlier x was found in a base, lookup didn't pass through A. + static const int x = 42; +}; diff --git a/gcc/testsuite/g++.dg/lookup/name-clash16.C b/gcc/testsuite/g++.dg/lookup/name-clash16.C new file mode 100644 index 00000000000..250d6147c73 --- /dev/null +++ b/gcc/testsuite/g++.dg/lookup/name-clash16.C @@ -0,0 +1,13 @@ +typedef int T; + +struct A +{ + template + struct B + { + T t; + }; + + // OK, earlier T was found in template header, didn't look in A. + typedef float T; +};