From patchwork Fri Sep 1 13:24:54 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Jelinek X-Patchwork-Id: 137396 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:c792:0:b0:3f2:4152:657d with SMTP id b18csp885644vqu; Fri, 1 Sep 2023 06:27:59 -0700 (PDT) X-Google-Smtp-Source: AGHT+IGlP6u6EItN3jd/WrRmXoUxWkALDE3pR2N92fIJV5qmm3d+IjVYrju0L0GGkI4mg8CXe6sL X-Received: by 2002:a2e:a40c:0:b0:2bc:d38e:b500 with SMTP id p12-20020a2ea40c000000b002bcd38eb500mr1881265ljn.42.1693574878935; Fri, 01 Sep 2023 06:27:58 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1693574878; cv=none; d=google.com; s=arc-20160816; b=JizN89FeGiwrs3M+z7XacEhf9CGz07x+cCtmkRm5JLIENichDT7Sq6Hrp+MX39v08d I2v84py+vxCzTb9FXsTHxrM55lQckq9Ffd9A66yrFQO6tZhAOg2TiPxaL0hBPx5Gw5Ge rjHQFeXfgwnPiB1XmArAzAOseEMZeuhv6nEBy9FLYkZc2TYEbxGvwmivOUhI8KcCVQMl AFigfQ4zED24xeLSpdIavZzQW6+bRUgXSXVykZNdB+bo6zTjZlLQCvSH8N/ggWm1UrMW Fp+G/w8pNkDtDZ5TZ4R5Oag4wCBFqf8GqUPuq6JKlPIMmgSBuR9+pn/Tyos13zrrVb8Z VQvQ== 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:in-reply-to:mime-version:references:message-id :subject:cc:to:date:dmarc-filter:delivered-to:dkim-signature :dkim-filter; bh=0mKiac/UkZLsngWsMA6Yb2K6ET72ccNSp7tQyxaV8wk=; fh=0xZT+NBKSeH8qOu04/61f1ZGePpF4jF/gxp331YE14k=; b=Ri80GFDVeFfh2sMpNQwGhfd6RSdFWm2mT+4Au5HWbH2kHALHghOH0aD+TVS2n3qC36 ckJ62OC6YAPVwvPTCtKRYjV36ly5ABw+8WXaEZeBwUP1PABw30b6yfs29apdIol5S5zb R4+CqmZxe6HvCRs2h38PmQ88rrQogYiqpMK+5IK9FTHRrF/cb68lGFIIIs8XemBHYlx4 bcpU1a8W14kN8FOjykitml4uOepr/n4vyRC5y5SoVMcMgJ3Og8cVj85Thp8X2qxgp5ji 6fw0GuhLiufqY43F0DMhHblivIJ9U/VIMHbSOfeyC3JpZBr6haqzVwaAZRucL79a2haH FtKw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gcc.gnu.org header.s=default header.b="eULw/qby"; 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 l6-20020a1709067d4600b009a6056ed90asi2253304ejp.664.2023.09.01.06.27.58 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 01 Sep 2023 06:27:58 -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="eULw/qby"; 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 1851138483EB for ; Fri, 1 Sep 2023 13:25:48 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 1851138483EB DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1693574748; bh=0mKiac/UkZLsngWsMA6Yb2K6ET72ccNSp7tQyxaV8wk=; h=Date:To:Cc:Subject:References:In-Reply-To:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From:Reply-To:From; b=eULw/qbybb/87CDmvcL4+weXg9kWOZSaaN8WgjG70CgjbEGUsZK678DhC4XL4keXv uza2YbU2cpNhyyYOONEgmQogElgX1+Kd4/HPUsHVA9Ayld44C5neThpCx/G2PmbX0q HlxejBHKkrWQZfTkt8BhFg9nS+X6ANMi3V8GDUFU= 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.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 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 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: 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-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 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: 1775841972356180704 X-GMAIL-MSGID: 1775841972356180704 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. Jakub --- 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; }