From patchwork Thu Aug 31 08:08:07 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Jelinek X-Patchwork-Id: 137236 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:c792:0:b0:3f2:4152:657d with SMTP id b18csp91278vqu; Thu, 31 Aug 2023 01:09:12 -0700 (PDT) X-Google-Smtp-Source: AGHT+IGiWTSq1dRImf5qmM6lgaaUuPVEiiB0hyXAHDkpuzPu82rWKEskCOuMvLtD+3lUUnJ0hjJG X-Received: by 2002:a17:907:724b:b0:9a1:f9c5:f612 with SMTP id ds11-20020a170907724b00b009a1f9c5f612mr1831103ejc.5.1693469352184; Thu, 31 Aug 2023 01:09:12 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1693469352; cv=none; d=google.com; s=arc-20160816; b=nzyJg7bQOCU3SBzPIL8zCN7lzDuQ8YTbOFTucicUkiRRaBhEqCPH5SPPgLtbpD7sGB n5c+ng19SNM/OS7B7tYsrJG6hQxPBldtsaQOJbUF+DNe8vMtqxT3SOuRzXf7U+75g97K 33QzgxdX3hFWgQBtfl9xLZJVoylnxtCgEDiHS/IruKuWwmlBB80F5BOH+gtDSHWrZFCH 7G+ZIDuH4uY/Tjm9tlDZgkYMD20TcuW4A8zkbBZPC9nALWnu6d43J6YfRil776IO9lTI iZv8FaFYWdFgw7DxSdv+EbfTICiGkyGCFjBs6dcR718dCPaQaQa+BbVXrXLGov6nXVHZ d11w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:reply-to:from:list-subscribe:list-help:list-post :list-archive:list-unsubscribe:list-id:precedence :content-disposition:mime-version:message-id:subject:cc:to:date :dmarc-filter:delivered-to:dkim-signature:dkim-filter; bh=6kM920Tqa9G3Dg62A+O3R7tSbHS6RkkTsOXjj0pgL8k=; fh=0xZT+NBKSeH8qOu04/61f1ZGePpF4jF/gxp331YE14k=; b=FUa3ogQuLzLbY/yo8a8trI0leDM2YKU+u///0sis49O1Pw1/fUiTk++MRYPiq08ZIo WUAMMPP9AuZ/Zj+sBQBC205b4nQHu+c8K9i7WXmlIczAsNlIcBSZbFTQHWBsJio3Bvng ZOClXHg5AEl+lOmhgO/jTgeFo+P1FLeCr+vTw+XaylTmXKQKel//rvJPncpwW5X69qr8 ZD+Oiwe3ihIofGFofFMzPk+KlW2Qw1pgZotnbXIr0mt1pc4ZqDW0/JUBFYBN8A1IfVrQ A67TVTU1wsW7W/K4kqSmg8drw8Sqo03AbiVEV9NPDNNq1ypIangMI0dv7fvCLEXX4TkA YTXA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gcc.gnu.org header.s=default header.b=cmhAXpOI; spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) smtp.mailfrom="gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=gnu.org Received: from server2.sourceware.org (server2.sourceware.org. [2620:52:3:1:0:246e:9693:128c]) by mx.google.com with ESMTPS id z7-20020a1709060ac700b009929566f00asi618925ejf.467.2023.08.31.01.09.11 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 31 Aug 2023 01:09:12 -0700 (PDT) Received-SPF: pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) client-ip=2620:52:3:1:0:246e:9693:128c; Authentication-Results: mx.google.com; dkim=pass header.i=@gcc.gnu.org header.s=default header.b=cmhAXpOI; spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) smtp.mailfrom="gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=gnu.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 291FD3857700 for ; Thu, 31 Aug 2023 08:09:01 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 291FD3857700 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1693469341; bh=6kM920Tqa9G3Dg62A+O3R7tSbHS6RkkTsOXjj0pgL8k=; h=Date:To:Cc:Subject:List-Id:List-Unsubscribe:List-Archive: List-Post:List-Help:List-Subscribe:From:Reply-To:From; b=cmhAXpOIalEEoU1Swo4ibw124/3NTvjgGrDnrOKRtFSRncLM9jUvYfVoeNoPD8AsE O2dzuZoGZqhLnLMd9bvx5CoYGFaWHPUXAcoejV7Yuvq7btI/XzTdUQf0AgOw6+NH4s n6poSVNgPP4j44SddddbfPl0ZOC6cBOWXczc8weM= 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 77CA03858407 for ; Thu, 31 Aug 2023 08:08:11 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 77CA03858407 Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-528-BCWYtZFlNuC0cL6ZgrSMSw-1; Thu, 31 Aug 2023 04:08:09 -0400 X-MC-Unique: BCWYtZFlNuC0cL6ZgrSMSw-1 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.rdu2.redhat.com [10.11.54.8]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 97F1F803E2E for ; Thu, 31 Aug 2023 08:08:09 +0000 (UTC) Received: from tucnak.zalov.cz (unknown [10.45.224.16]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 421F6C15BAE; Thu, 31 Aug 2023 08:08:09 +0000 (UTC) Received: from tucnak.zalov.cz (localhost [127.0.0.1]) by tucnak.zalov.cz (8.17.1/8.17.1) with ESMTPS id 37V887cx265137 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Thu, 31 Aug 2023 10:08:07 +0200 Received: (from jakub@localhost) by tucnak.zalov.cz (8.17.1/8.17.1/Submit) id 37V887R1265136; Thu, 31 Aug 2023 10:08:07 +0200 Date: Thu, 31 Aug 2023 10:08:07 +0200 To: Jason Merrill Cc: gcc-patches@gcc.gnu.org Subject: [RFC PATCH] c++: Diagnose [basic.scope.block]/2 violations even for block externs [PR52953] Message-ID: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.8 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Disposition: inline X-Spam-Status: No, score=-3.4 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, KAM_SHORT, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H4, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_NONE, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Jakub Jelinek via Gcc-patches From: Jakub Jelinek Reply-To: Jakub Jelinek Errors-To: gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org Sender: "Gcc-patches" X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1775731319397986515 X-GMAIL-MSGID: 1775731319397986515 Hi! C++17 had in [basic.block.scope]/2 "A parameter name shall not be redeclared in the outermost block of the function definition nor in the outermost block of any handler associated with a function-try-block." and in [basic.block.scope]/4 similar rule for selection/iteration statements. My reading of that is that it applied even for block local externs in all those spots, while they declare something at namespace scope, the redeclaration happens in that outermost block etc. and introduces names into that. Those wordings seemed to have been moved somewhere else in C++20, but what's worse, they were moved back and completely rewritten in P1787R6: Declarations and where to find them which has been applied as a DR (but admittedly, we don't claim yet to implement that). The current wording at https://eel.is/c++draft/basic.scope#block-2 and https://eel.is/c++draft/basic.scope#scope-2.10 seem to imply at least to me that it doesn't apply to extern block local decls because their target scope is the namespace scope and [basic.scope.block]/2 says "and whose target scope is the block scope"... Now, it is unclear if that is actually the intent or not. There seems to be quite large implementation divergence on this as well. Unpatched g++ e.g. on the redeclaration-5.C testcase diagnoses just lines 55,58,67,70 (i.e. where the previous declaration is in for's condition). clang++ trunk diagnoses just lines 8 and 27, i.e. redeclaration in the function body vs. parameter both in normal fn and lambda (but not e.g. function-try-block and others, including ctors, but it diagnoses those for non-extern decls). ICC 19 diagnoses lines 8,32,38,41,45,52,55,58,61,64,67,70,76. And MSCV trunk diagnoses 8,27,32,38,41,45,48,52,55,58,67,70,76,87,100,137 although the last 4 are just warnings. g++ with the patch diagnoses 8,15,27,32,38,41,45,48,52,55,58,61,64,67,70,76,87,100,121,137 as the dg-error directives test. So, I'm not really sure what to do. Intuitively the patch seems right because even block externs redeclare stuff and change meaning of the identifiers and void foo () { int i; extern int i (int); } is rejected by all compilers. 2023-08-31 Jakub Jelinek PR c++/52953 * name-lookup.cc (check_local_shadow): Defer punting on DECL_EXTERNAL (decl) from the start of function to right before the -Wshadow* checks. * g++.dg/diagnostic/redeclaration-4.C: New test. * g++.dg/diagnostic/redeclaration-5.C: New test. Jakub --- gcc/cp/name-lookup.cc.jj 2023-08-30 20:07:18.584830291 +0200 +++ gcc/cp/name-lookup.cc 2023-08-30 20:01:05.796967755 +0200 @@ -3096,10 +3096,6 @@ check_local_shadow (tree decl) if (TREE_CODE (decl) == PARM_DECL && !DECL_CONTEXT (decl)) return; - /* External decls are something else. */ - if (DECL_EXTERNAL (decl)) - return; - tree old = NULL_TREE; cp_binding_level *old_scope = NULL; if (cxx_binding *binding = outer_binding (DECL_NAME (decl), NULL, true)) @@ -3219,6 +3215,9 @@ check_local_shadow (tree decl) return; } + if (DECL_EXTERNAL (decl)) + return; + /* If '-Wshadow=compatible-local' is specified without other -Wshadow= flags, we will warn only when the type of the shadowing variable (DECL) can be converted to that of the @@ -3274,6 +3273,9 @@ check_local_shadow (tree decl) return; } + if (DECL_EXTERNAL (decl)) + return; + if (!warn_shadow) return; --- gcc/testsuite/g++.dg/diagnostic/redeclaration-4.C.jj 2023-08-30 20:01:37.013537549 +0200 +++ gcc/testsuite/g++.dg/diagnostic/redeclaration-4.C 2023-08-30 20:12:03.763900190 +0200 @@ -0,0 +1,167 @@ +// PR c++/52953 +// { dg-do compile } +// { dg-options "-pedantic-errors -Wno-switch-unreachable" } + +void +foo (int x) // { dg-message "'int x' previously declared here" } +{ + extern int x; // { dg-error "declaration of 'int x' shadows a parameter" } +} + +void +bar (int x) // { dg-message "'int x' previously declared here" } +try +{ + extern int x; // { dg-error "declaration of 'int x' shadows a parameter" } +} +catch (...) +{ +} + +volatile int v; + +void +baz () +{ +#if __cplusplus >= 201103L + auto f = [] (int x) { extern int x; };// { dg-error "declaration of 'int x' shadows a parameter" "" { target c++11 } } + // { dg-message "'int x' previously declared here" "" { target c++11 } .-1 } +#endif + if (int x = 1) // { dg-message "'int x' previously declared here" } + { + extern int x; // { dg-error "redeclaration of 'int x'" } + } + if (int x = 0) // { dg-message "'int x' previously declared here" } + ; + else + { + extern int x; // { dg-error "redeclaration of 'int x'" } + } + if (int x = 1) // { dg-message "'int x' previously declared here" } + extern int x; // { dg-error "redeclaration of 'int x'" } + if (int x = 0) // { dg-message "'int x' previously declared here" } + ; + else + extern int x; // { dg-error "redeclaration of 'int x'" } + switch (int x = 1) // { dg-message "'int x' previously declared here" } + { + extern int x; // { dg-error "redeclaration of 'int x'" } + default:; + } + switch (int x = 1) // { dg-message "'int x' previously declared here" } + extern int x; // { dg-error "redeclaration of 'int x'" } + while (int x = v) + { + extern int x; // { dg-error "'int x' conflicts with a previous declaration" } + } + while (int x = v) + extern int x; // { dg-error "'int x' conflicts with a previous declaration" } + for (int x = v; x; ++x) // { dg-message "'int x' previously declared here" } + { + extern int x; // { dg-error "redeclaration of 'int x'" } + } + for (int x = v; x; ++x) // { dg-message "'int x' previously declared here" } + extern int x; // { dg-error "redeclaration of 'int x'" } + for (; int x = v; ) + { + extern int x; // { dg-error "'int x' conflicts with a previous declaration" } + } + for (; int x = v; ) + extern int x; // { dg-error "'int x' conflicts with a previous declaration" } + try + { + } + catch (int x) // { dg-message "'int x' previously declared here" } + { + extern int x; // { dg-error "redeclaration of 'int x'" } + } +} + +void +corge (int x) // { dg-message "'int x' previously declared here" } +try +{ +} +catch (...) +{ + extern int x; // { dg-error "redeclaration of 'int x'" } +} + +void +fred (int x) // { dg-message "'int x' previously declared here" } +try +{ +} +catch (int) +{ +} +catch (long) +{ + extern int x; // { dg-error "redeclaration of 'int x'" } +} + +void +garply (int x) +{ + try + { + extern int x; + } + catch (...) + { + extern int x; + } +} + +struct S +{ + S (int x) // { dg-message "'int x' previously declared here" } + try : s (x) + { + extern int x; // { dg-error "declaration of 'int x' shadows a parameter" } + } + catch (...) + { + } + int s; +}; + +struct T +{ + T (int x) // { dg-message "'int x' previously declared here" } + try : t (x) + { + } + catch (...) + { + extern int x; // { dg-error "redeclaration of 'int x'" } + } + int t; +}; + +struct U +{ + U (int x) : u (x) + { + try + { + extern int x; + } + catch (...) + { + extern int x; + } + } + int u; +}; + +struct V +{ + V (int x) : v (x) + { + { + extern int x; + } + } + int v; +}; --- gcc/testsuite/g++.dg/diagnostic/redeclaration-5.C.jj 2023-08-30 20:03:56.662613023 +0200 +++ gcc/testsuite/g++.dg/diagnostic/redeclaration-5.C 2023-08-30 20:16:00.749641990 +0200 @@ -0,0 +1,167 @@ +// PR c++/52953 +// { dg-do compile } +// { dg-options "-pedantic-errors -Wno-switch-unreachable" } + +void +foo (int x) // { dg-message "'int x' previously declared here" } +{ + extern int x (int); // { dg-error "declaration of 'int x\\\(int\\\)' shadows a parameter" } +} + +void +bar (int x) // { dg-message "'int x' previously declared here" } +try +{ + extern int x (int); // { dg-error "declaration of 'int x\\\(int\\\)' shadows a parameter" } +} +catch (...) +{ +} + +volatile int v; + +void +baz () +{ +#if __cplusplus >= 201103L + auto f = [] (int x) { extern int x (int); };// { dg-error "declaration of 'int x\\\(int\\\)' shadows a parameter" "" { target c++11 } } + // { dg-message "'int x' previously declared here" "" { target c++11 } .-1 } +#endif + if (int x = 1) // { dg-message "'int x' previously declared here" } + { + extern int x (int); // { dg-error "redeclaration of 'int x\\\(int\\\)'" } + } + if (int x = 0) // { dg-message "'int x' previously declared here" } + ; + else + { + extern int x (int); // { dg-error "redeclaration of 'int x\\\(int\\\)'" } + } + if (int x = 1) // { dg-message "'int x' previously declared here" } + extern int x (int); // { dg-error "redeclaration of 'int x\\\(int\\\)'" } + if (int x = 0) // { dg-message "'int x' previously declared here" } + ; + else + extern int x (int); // { dg-error "redeclaration of 'int x\\\(int\\\)'" } + switch (int x = 1) // { dg-message "'int x' previously declared here" } + { + extern int x (int); // { dg-error "redeclaration of 'int x\\\(int\\\)'" } + default:; + } + switch (int x = 1) // { dg-message "'int x' previously declared here" } + extern int x (int); // { dg-error "redeclaration of 'int x\\\(int\\\)'" } + while (int x = v) + { + extern int x (int); // { dg-error "'int x\\\(int\\\)' redeclared as different kind of entity" } + } + while (int x = v) + extern int x (int); // { dg-error "'int x\\\(int\\\)' redeclared as different kind of entity" } + for (int x = v; x; ++x) // { dg-message "'int x' previously declared here" } + { + extern int x (int); // { dg-error "redeclaration of 'int x\\\(int\\\)'" } + } + for (int x = v; x; ++x) // { dg-message "'int x' previously declared here" } + extern int x (int); // { dg-error "redeclaration of 'int x\\\(int\\\)'" } + for (; int x = v; ) + { + extern int x (int); // { dg-error "'int x\\\(int\\\)' redeclared as different kind of entity" } + } + for (; int x = v; ) + extern int x (int); // { dg-error "'int x\\\(int\\\)' redeclared as different kind of entity" } + try + { + } + catch (int x) // { dg-message "'int x' previously declared here" } + { + extern int x (int); // { dg-error "redeclaration of 'int x\\\(int\\\)'" } + } +} + +void +corge (int x) // { dg-message "'int x' previously declared here" } +try +{ +} +catch (...) +{ + extern int x (int); // { dg-error "redeclaration of 'int x\\\(int\\\)'" } +} + +void +fred (int x) // { dg-message "'int x' previously declared here" } +try +{ +} +catch (int) +{ +} +catch (long) +{ + extern int x (int); // { dg-error "redeclaration of 'int x\\\(int\\\)'" } +} + +void +garply (int x) +{ + try + { + extern int x (int); + } + catch (...) + { + extern int x (int); + } +} + +struct S +{ + S (int x) // { dg-message "'int x' previously declared here" } + try : s (x) + { + extern int x (int); // { dg-error "declaration of 'int x\\\(int\\\)' shadows a parameter" } + } + catch (...) + { + } + int s; +}; + +struct T +{ + T (int x) // { dg-message "'int x' previously declared here" } + try : t (x) + { + } + catch (...) + { + extern int x (int); // { dg-error "redeclaration of 'int x\\\(int\\\)'" } + } + int t; +}; + +struct U +{ + U (int x) : u (x) + { + try + { + extern int x (int); + } + catch (...) + { + extern int x (int); + } + } + int u; +}; + +struct V +{ + V (int x) : v (x) + { + { + extern int x (int); + } + } + int v; +};