From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by sourceware.org (Postfix) with ESMTPS id 537403857342 for ; Fri, 1 Sep 2023 13:24:59 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 537403857342 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=redhat.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1693574698; h=from:from:reply-to:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type:in-reply-to:in-reply-to: references:references; bh=0mKiac/UkZLsngWsMA6Yb2K6ET72ccNSp7tQyxaV8wk=; b=aE1OdHQttyssycAO+Rn97vDb3SSdpzw6sMohSRPeHYitC9tAKJUN8P3/ycXpIivqlowXN+ tzuDyH2tXn2HxZFb0xTWdXI+0lS3RASb053ZVwVAoDLRJhZAwJW0NbyV9txaMcM6N5cFCq 9C5tYxQNWvLePbeFsaOonK6ApXceJ/4= 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-137-fcGAXngfMGiyq07ClsuUgg-1; Fri, 01 Sep 2023 09:24:57 -0400 X-MC-Unique: fcGAXngfMGiyq07ClsuUgg-1 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.rdu2.redhat.com [10.11.54.6]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 59C5B926361 for ; Fri, 1 Sep 2023 13:24:57 +0000 (UTC) Received: from tucnak.zalov.cz (unknown [10.45.224.16]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 1C3EE21D4F3F; Fri, 1 Sep 2023 13:24:56 +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 381DOtGl2768435 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Fri, 1 Sep 2023 15:24:55 +0200 Received: (from jakub@localhost) by tucnak.zalov.cz (8.17.1/8.17.1/Submit) id 381DOtje2768434; Fri, 1 Sep 2023 15:24:55 +0200 Date: Fri, 1 Sep 2023 15:24:54 +0200 From: Jakub Jelinek To: Jason Merrill Cc: gcc-patches@gcc.gnu.org Subject: [PATCH] c++, v2: Diagnose [basic.scope.block]/2 violations even in compound-stmt of function-try-block [PR52953] Message-ID: Reply-To: Jakub Jelinek References: MIME-Version: 1.0 In-Reply-To: X-Scanned-By: MIMEDefang 3.1 on 10.11.54.6 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Type: text/plain; charset=us-ascii 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,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 List-Id: On Thu, Aug 31, 2023 at 03:52:22PM -0400, Jason Merrill wrote: > On 8/31/23 03:20, Jakub Jelinek wrote: > > As the following testcase shows, while check_local_shadow diagnoses most of > > the [basic.scope.block]/2 violations, it doesn't diagnose when parameter's > > name is redeclared inside of the compound-stmt of a function-try-block. > > > > There is in that case an extra scope (sk_try with parent artificial > > sk_block with for FUNCTION_NEEDS_BODY_BLOCK another sk_block and only then > > sk_function_param). > > > > The following patch fixes that. > > > > Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? > > > > 2023-08-31 Jakub Jelinek > > > > PR c++/52953 > > * cp-tree.h (struct language_function): Add x_in_function_try_block > > member. > > How about adding a flag to cp_binding_level instead? Maybe to mark the > artificial sk_block level as such, which we could use for both this case and > the FUNCTION_NEEDS_BODY_BLOCK cases. So like this? It actually changes behaviour on the void foo (int x) try {} catch (int x) {} case, where previously this triggered the || (TREE_CODE (old) == PARM_DECL && (current_binding_level->kind == sk_catch || current_binding_level->level_chain->kind == sk_catch) && in_function_try_handler)) { auto_diagnostic_group d; if (permerror (DECL_SOURCE_LOCATION (decl), "redeclaration of %q#D", decl)) inform (DECL_SOURCE_LOCATION (old), "%q#D previously declared here", old); diagnostics (note, just the current_binding_level->kind == sk_catch case), while now it triggers already the earlier if (b->kind == sk_function_parms) { error_at (DECL_SOURCE_LOCATION (decl), "declaration of %q#D shadows a parameter", decl); inform (DECL_SOURCE_LOCATION (old), "%q#D previously declared here", old); error. If you think it is important to differentiate that, I guess I could guard the while (b->artificial) loop with say + if (!in_function_try_handler + || current_binding_level->kind != sk_catch) while (b->artificial) b = b->level_chain; and adjust the 2 testcases. Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk or with modification? 2023-09-01 Jakub Jelinek PR c++/52953 * name-lookup.h (struct cp_binding_level): Add artificial bit-field. Formatting fixes. * name-lookup.cc (check_local_shadow): Skip artificial bindings when checking if parameter scope is parent scope. Don't special case FUNCTION_NEEDS_BODY_BLOCK. * decl.cc (begin_function_body): Set current_binding_level->artificial. * semantics.cc (begin_function_try_block): Likewise. * g++.dg/diagnostic/redeclaration-3.C: New test. * g++.dg/parse/pr31952-3.C: Expect different diagnostic wording. --- gcc/cp/name-lookup.h.jj 2023-08-21 11:57:33.105460770 +0200 +++ gcc/cp/name-lookup.h 2023-09-01 10:15:20.137943395 +0200 @@ -292,11 +292,11 @@ struct GTY(()) cp_binding_level { only valid if KIND == SK_TEMPLATE_PARMS. */ BOOL_BITFIELD explicit_spec_p : 1; - /* true means make a BLOCK for this level regardless of all else. */ + /* True means make a BLOCK for this level regardless of all else. */ unsigned keep : 1; /* Nonzero if this level can safely have additional - cleanup-needing variables added to it. */ + cleanup-needing variables added to it. */ unsigned more_cleanups_ok : 1; unsigned have_cleanups : 1; @@ -308,9 +308,13 @@ struct GTY(()) cp_binding_level { unsigned defining_class_p : 1; /* True for SK_FUNCTION_PARMS of a requires-expression. */ - unsigned requires_expression: 1; + unsigned requires_expression : 1; - /* 22 bits left to fill a 32-bit word. */ + /* True for artificial blocks which should be ignored when finding + parent scope. */ + unsigned artificial : 1; + + /* 21 bits left to fill a 32-bit word. */ }; /* The binding level currently in effect. */ --- gcc/cp/name-lookup.cc.jj 2023-08-31 14:31:06.055762306 +0200 +++ gcc/cp/name-lookup.cc 2023-09-01 10:21:03.658118594 +0200 @@ -3146,8 +3146,10 @@ check_local_shadow (tree decl) them there. */ cp_binding_level *b = current_binding_level->level_chain; - if (FUNCTION_NEEDS_BODY_BLOCK (current_function_decl)) - /* Skip the ctor/dtor cleanup level. */ + /* Skip artificially added scopes which aren't present + in the C++ standard, e.g. for function-try-block or + ctor/dtor cleanups. */ + while (b->artificial) b = b->level_chain; /* [basic.scope.param] A parameter name shall not be redeclared --- gcc/cp/decl.cc.jj 2023-08-31 20:48:21.127722180 +0200 +++ gcc/cp/decl.cc 2023-09-01 10:18:40.125134543 +0200 @@ -18002,6 +18002,7 @@ begin_function_body (void) keep_next_level (true); tree stmt = begin_compound_stmt (BCS_FN_BODY); + current_binding_level->artificial = 1; if (processing_template_decl) /* Do nothing now. */; --- gcc/cp/semantics.cc.jj 2023-08-31 14:31:06.102761661 +0200 +++ gcc/cp/semantics.cc 2023-09-01 10:17:49.044851974 +0200 @@ -1624,6 +1624,7 @@ begin_function_try_block (tree *compound /* This outer scope does not exist in the C++ standard, but we need a place to put __FUNCTION__ and similar variables. */ *compound_stmt = begin_compound_stmt (0); + current_binding_level->artificial = 1; r = begin_try_block (); FN_TRY_BLOCK_P (r) = 1; return r; --- gcc/testsuite/g++.dg/diagnostic/redeclaration-3.C.jj 2023-09-01 09:40:12.061707730 +0200 +++ gcc/testsuite/g++.dg/diagnostic/redeclaration-3.C 2023-09-01 10:32:36.315429575 +0200 @@ -0,0 +1,204 @@ +// PR c++/52953 +// { dg-do compile } +// { dg-options "-pedantic-errors -Wno-switch-unreachable" } + +void +foo (int x) // { dg-message "'int x' previously declared here" } +{ + int x; // { dg-error "declaration of 'int x' shadows a parameter" } +} + +void +bar (int x) // { dg-message "'int x' previously declared here" } +try +{ + int x; // { dg-error "declaration of 'int x' shadows a parameter" } +} +catch (...) +{ +} + +volatile int v; + +void +baz () +{ +#if __cplusplus >= 201103L + auto f = [] (int x) { 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" } + { + int x; // { dg-error "redeclaration of 'int x'" } + } + if (int x = 0) // { dg-message "'int x' previously declared here" } + ; + else + { + int x; // { dg-error "redeclaration of 'int x'" } + } + if (int x = 1) // { dg-message "'int x' previously declared here" } + int x; // { dg-error "redeclaration of 'int x'" } + if (int x = 0) // { dg-message "'int x' previously declared here" } + ; + else + int x; // { dg-error "redeclaration of 'int x'" } + switch (int x = 1) // { dg-message "'int x' previously declared here" } + { + int x; // { dg-error "redeclaration of 'int x'" } + default:; + } + switch (int x = 1) // { dg-message "'int x' previously declared here" } + int x; // { dg-error "redeclaration of 'int x'" } + while (int x = v) // { dg-message "'int x' previously declared here" } + { + int x; // { dg-error "redeclaration of 'int x'" } + } + while (int x = v) // { dg-message "'int x' previously declared here" } + int x; // { dg-error "redeclaration of 'int x'" } + for (int x = v; x; ++x) // { dg-message "'int x' previously declared here" } + { + int x; // { dg-error "redeclaration of 'int x'" } + } + for (int x = v; x; ++x) // { dg-message "'int x' previously declared here" } + int x; // { dg-error "redeclaration of 'int x'" } + for (; int x = v; ) // { dg-message "'int x' previously declared here" } + { + int x; // { dg-error "redeclaration of 'int x'" } + } + for (; int x = v; ) // { dg-message "'int x' previously declared here" } + int x; // { dg-error "redeclaration of 'int x'" } + try + { + } + catch (int x) // { dg-message "'int x' previously declared here" } + { + int x; // { dg-error "redeclaration of 'int x'" } + } + if (int x = 1) + if (int x = 1) + ; + if (int x = 0) + ; + else + if (int x = 1) + ; + if (int x = 1) + switch (int x = 1) + ; + if (int x = 0) + while (int x = v) + ; + if (int x = 0) + for (int x = v; x; ++x) + ; + switch (int x = 1) + switch (int x = 1) + { + case 1:; + } + while (int x = 0) + if (int x = 1) + ; + for (int x = v; x; ++x) + for (int x = v; x; ++x) + ; +} + +void +qux (int x) // { dg-message "'int x' previously declared here" } +try +{ +} +catch (int x) // { dg-error "declaration of 'int x' shadows a parameter" } +{ +} + +void +corge (int x) // { dg-message "'int x' previously declared here" } +try +{ +} +catch (...) +{ + int x; // { dg-error "redeclaration of 'int x'" } +} + +void +fred (int x) // { dg-message "'int x' previously declared here" } +try +{ +} +catch (int) +{ +} +catch (long) +{ + int x; // { dg-error "redeclaration of 'int x'" } +} + +void +garply (int x) +{ + try + { + int x; + } + catch (...) + { + int x; + } +} + +struct S +{ + S (int x) // { dg-message "'int x' previously declared here" } + try : s (x) + { + 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 (...) + { + int x; // { dg-error "redeclaration of 'int x'" } + } + int t; +}; + +struct U +{ + U (int x) : u (x) + { + try + { + int x; + } + catch (...) + { + int x; + } + } + int u; +}; + +struct V +{ + V (int x) : v (x) + { + { + int x; + } + } + int v; +}; --- gcc/testsuite/g++.dg/parse/pr31952-3.C.jj 2020-01-14 20:02:46.918607812 +0100 +++ gcc/testsuite/g++.dg/parse/pr31952-3.C 2023-09-01 14:41:12.306964831 +0200 @@ -6,7 +6,7 @@ try { return 0; } -catch (int bar) // { dg-error "redeclaration" } +catch (int bar) // { dg-error "shadows a parameter" } { return 1; } Jakub