From patchwork Fri Nov 18 09:10:10 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Jelinek X-Patchwork-Id: 22213 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:adf:f944:0:0:0:0:0 with SMTP id q4csp79110wrr; Fri, 18 Nov 2022 01:11:46 -0800 (PST) X-Google-Smtp-Source: AA0mqf5ISaDeqiFzb7ECufLgWf7VjHWhWK+BALl4NuTLMTp2uueNzbbWqV2LrkoDhAfZBgk5cQc2 X-Received: by 2002:a05:6402:28ac:b0:461:9512:ebfd with SMTP id eg44-20020a05640228ac00b004619512ebfdmr5497502edb.103.1668762706157; Fri, 18 Nov 2022 01:11:46 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1668762706; cv=none; d=google.com; s=arc-20160816; b=QDuXYwSABPR3gKUcx4sHyQJSTWuJwJCfcK/StnlCTDEb35CElmHrsewUOL2Od2DIsp 6oTAKWL3eRXLXeFqzxoyVyqyYLXZkvK5hzvKUqo3fcOgAKvxkTkco6I63NDvcFkV6vUQ kdaVS2RcWebGHgM9azymKJ+IJVr/A2BGivYcAUqmUH6uzxf7UNv8plgeMvEzOjy1Oy7h VtUaXigPkk7enAYaDhkl6GFTXx6pa2sVprxc310oGvQuZBbX686cyGAEoUqrMxm1CWe6 hHr1DItmbRyPaE0DNR7U7cXPJC8gkzys1n43nflTwV3huR/PhQRCK4OwW/dCFEqUdQQy rDsg== 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=uPfEXFHZQuxR2ibU9oS+7gJxlspj4xThvH9GAiOpZdc=; b=VvuGJlc85T1CttVz9O3zp21w6ptqA+hm78esjJ/uwva4fzmKoFpR3FHq8MPwIzhB4B HrhrlDw5YNO95XkcxEcs6r97Or5azG9RwrPoKaa5TgbJTlchdHVyiHEbBW+Y98ItOJQv wg7q+aNmIYdHil7MLYX9iU36nXOWcSFWPIvhFu60jY5GHvgmLwiGr8LWz23Te2KXrBPP OBRL5U7e/xcUNW8d5KZk6tmW9EWzVPpwV8u8yEzcupiKppPF+1Vn+S/TzOtkVDnTU3LT cQqHzXXJ8epc4g4WpB1rRAcn8pIi2frcc6RMteljDdQR+epLl+isJ/lq622eoFVzdn1a 6v6Q== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gcc.gnu.org header.s=default header.b=WxO6JsYQ; spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 8.43.85.97 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 sourceware.org (server2.sourceware.org. [8.43.85.97]) by mx.google.com with ESMTPS id x13-20020a05640226cd00b00468c952c935si3074611edd.146.2022.11.18.01.11.45 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 18 Nov 2022 01:11:46 -0800 (PST) Received-SPF: pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 8.43.85.97 as permitted sender) client-ip=8.43.85.97; Authentication-Results: mx.google.com; dkim=pass header.i=@gcc.gnu.org header.s=default header.b=WxO6JsYQ; spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 8.43.85.97 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 987F43839F58 for ; Fri, 18 Nov 2022 09:11:16 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 987F43839F58 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1668762676; bh=uPfEXFHZQuxR2ibU9oS+7gJxlspj4xThvH9GAiOpZdc=; 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=WxO6JsYQTVRg+5yHTilO7u9fJmxSe8JGD8P309TEua2gUJU+MQp8ELX6Veuj3o7yF h7J3Xm1izF6N41EkNwxEnUsvU+Zd7wN9ozv5pfexXWn8ZzAamPVYQj/pFpz51jxoUc 04EjtS0+p84FiLvmXy2wkfTgxDZvbK+N45TAyo9U= 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 53B72384F4AD for ; Fri, 18 Nov 2022 09:10:19 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 53B72384F4AD Received: from mimecast-mx02.redhat.com (mx3-rdu2.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-563-GI73jkqrPTWqtYux5aLNAw-1; Fri, 18 Nov 2022 04:10:16 -0500 X-MC-Unique: GI73jkqrPTWqtYux5aLNAw-1 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.rdu2.redhat.com [10.11.54.3]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 15FA91C05EC6 for ; Fri, 18 Nov 2022 09:10:16 +0000 (UTC) Received: from tucnak.zalov.cz (unknown [10.39.192.21]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 734B01121330; Fri, 18 Nov 2022 09:10:15 +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 2AI9AAVg1896378 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Fri, 18 Nov 2022 10:10:11 +0100 Received: (from jakub@localhost) by tucnak.zalov.cz (8.17.1/8.17.1/Submit) id 2AI9AAus1896377; Fri, 18 Nov 2022 10:10:10 +0100 Date: Fri, 18 Nov 2022 10:10:10 +0100 To: Jason Merrill Cc: Jonathan Wakely , gcc-patches@gcc.gnu.org, Marek Polacek Subject: [PATCH] c++, v5: Implement C++23 P2647R1 - Permitting static constexpr variables in constexpr functions Message-ID: References: <016f168b-f143-baff-5f71-c48d4611ae11@redhat.com> <740b5e1e-7143-c291-5594-af937867fbc3@redhat.com> <9674a824-0b3d-ee36-cc66-f788fe0d0058@redhat.com> MIME-Version: 1.0 In-Reply-To: <9674a824-0b3d-ee36-cc66-f788fe0d0058@redhat.com> X-Scanned-By: MIMEDefang 3.1 on 10.11.54.3 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Disposition: inline X-Spam-Status: No, score=-3.9 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_H2, 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.29 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: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1749824523500331823?= X-GMAIL-MSGID: =?utf-8?q?1749824523500331823?= On Thu, Nov 17, 2022 at 07:28:56PM -0500, Jason Merrill wrote: > On 11/17/22 15:42, Jakub Jelinek wrote: > > On Thu, Nov 17, 2022 at 07:42:40PM +0100, Jakub Jelinek via Gcc-patches wrote: > > > I thought for older C++ this is to catch > > > void > > > foo () > > > { > > > constexpr int a = ({ static constexpr int b = 2; b; }); > > > } > > > and for C++23 the only 3 spots that diagnose those. > > > But perhaps for C++20 or older we can check if the var has a context > > > of a constexpr function (then assume cp_finish_decl errored or pedwarned > > > already) and only error or pedwarn otherwise. > > We could, but I wouldn't bother to enforce this specially for > statement-expressions, which are already an extension. Ok. > OTOH, we should test that static constexpr is handled properly for lambdas, > i.e. this should still fail: > > constexpr int q = [](int i) > { static constexpr int x = 42; return x+i; }(24); I guess that is related on how to handle the lambda-generic-func1.C constexpr-lambda16.C FAILs. Attached are 3 patches, one is just an updated version of the previous patch with simplified constexpr.cc (and fixed the function comment Marek talked about), this one will accept the statement expression case with decl_constant_var_p static in it, and passes GXX_TESTSUITE_STDS=98,11,14,17,20,2b make check-g++ \ RUNTESTFLAGS="--target_board=unix\{-m32,-m64\} dg.exp='constexpr-nonlit* feat-cxx2b* stmtexpr19.C stmtexpr25.C lambda-generic-func1.C constexpr-lambda16.C'" except for: +FAIL: g++.dg/cpp1y/lambda-generic-func1.C -std=c++17 (test for excess errors) +FAIL: g++.dg/cpp1y/lambda-generic-func1.C -std=c++20 (test for excess errors) +FAIL: g++.dg/cpp1z/constexpr-lambda16.C -std=c++17 (test for excess errors) +FAIL: g++.dg/cpp1z/constexpr-lambda16.C -std=c++20 (test for excess errors) plus the testcase above needs to be dealt with if we want to pedwarn on it for older C++. The third one is if we just want something for C++23 and don't want to touch C++20 and older at all (that one doesn't regress anything), the second one similarly but will no longer reject the statement expression cases for C++11 .. 20. Jakub 2022-11-18 Jakub Jelinek gcc/c-family/ * c-cppbuiltin.cc (c_cpp_builtins): Bump __cpp_constexpr value from 202207L to 202211L. gcc/cp/ * constexpr.cc (cxx_eval_constant_expression): Implement C++23 P2647R1 - Permitting static constexpr variables in constexpr functions. Allow DECL_EXPRs of decl_constant_var_p static or thread_local vars. (potential_constant_expression_1): Similarly, except use decl_maybe_constant_var_p instead of decl_constant_var_p if processing_template_decl. * decl.cc (diagnose_static_in_constexpr): New function. (start_decl): Remove diagnostics of static or thread_local vars in constexpr or consteval functions. (cp_finish_decl): Call diagnose_static_in_constexpr. gcc/testsuite/ * g++.dg/cpp23/constexpr-nonlit17.C: New test. * g++.dg/cpp23/constexpr-nonlit18.C: New test. * g++.dg/cpp23/constexpr-nonlit19.C: New test. * g++.dg/cpp23/constexpr-nonlit20.C: New test. * g++.dg/cpp23/feat-cxx2b.C: Adjust expected __cpp_constexpr value. * g++.dg/ext/stmtexpr19.C: Don't expect an error. * g++.dg/ext/stmtexpr25.C: New test. 2022-11-18 Jakub Jelinek gcc/c-family/ * c-cppbuiltin.cc (c_cpp_builtins): Bump __cpp_constexpr value from 202207L to 202211L. gcc/cp/ * constexpr.cc (cxx_eval_constant_expression): Implement C++23 P2647R1 - Permitting static constexpr variables in constexpr functions. Allow DECL_EXPRs of decl_constant_var_p static or thread_local vars. (potential_constant_expression_1): Similarly, except use decl_maybe_constant_var_p instead of decl_constant_var_p if processing_template_decl. gcc/testsuite/ * g++.dg/cpp23/constexpr-nonlit17.C: New test. * g++.dg/cpp23/constexpr-nonlit18.C: New test. * g++.dg/cpp23/feat-cxx2b.C: Adjust expected __cpp_constexpr value. * g++.dg/ext/stmtexpr19.C: Don't expect an error. * g++.dg/ext/stmtexpr25.C: New test. --- gcc/c-family/c-cppbuiltin.cc.jj 2022-11-18 09:00:17.102704379 +0100 +++ gcc/c-family/c-cppbuiltin.cc 2022-11-18 09:32:00.389372850 +0100 @@ -1074,7 +1074,7 @@ c_cpp_builtins (cpp_reader *pfile) /* Set feature test macros for C++23. */ cpp_define (pfile, "__cpp_size_t_suffix=202011L"); cpp_define (pfile, "__cpp_if_consteval=202106L"); - cpp_define (pfile, "__cpp_constexpr=202207L"); + cpp_define (pfile, "__cpp_constexpr=202211L"); cpp_define (pfile, "__cpp_multidimensional_subscript=202211L"); cpp_define (pfile, "__cpp_named_character_escapes=202207L"); cpp_define (pfile, "__cpp_static_call_operator=202207L"); --- gcc/cp/constexpr.cc.jj 2022-11-18 09:00:17.108704295 +0100 +++ gcc/cp/constexpr.cc 2022-11-18 09:35:39.822342414 +0100 @@ -7098,7 +7098,8 @@ cxx_eval_constant_expression (const cons && (TREE_STATIC (r) || (CP_DECL_THREAD_LOCAL_P (r) && !DECL_REALLY_EXTERN (r))) /* Allow __FUNCTION__ etc. */ - && !DECL_ARTIFICIAL (r)) + && !DECL_ARTIFICIAL (r) + && !decl_constant_var_p (r)) { if (!ctx->quiet) { @@ -9586,7 +9587,10 @@ potential_constant_expression_1 (tree t, case DECL_EXPR: tmp = DECL_EXPR_DECL (t); - if (VAR_P (tmp) && !DECL_ARTIFICIAL (tmp)) + if (VAR_P (tmp) && !DECL_ARTIFICIAL (tmp) + && (processing_template_decl + ? !decl_maybe_constant_var_p (tmp) + : !decl_constant_var_p (tmp))) { if (CP_DECL_THREAD_LOCAL_P (tmp) && !DECL_REALLY_EXTERN (tmp)) { --- gcc/testsuite/g++.dg/cpp23/constexpr-nonlit17.C.jj 2022-11-18 09:32:00.393372795 +0100 +++ gcc/testsuite/g++.dg/cpp23/constexpr-nonlit17.C 2022-11-18 09:32:00.393372795 +0100 @@ -0,0 +1,12 @@ +// P2647R1 - Permitting static constexpr variables in constexpr functions +// { dg-do compile { target c++23 } } + +constexpr char +test () +{ + static const int x = 5; + static constexpr char c[] = "Hello World"; + return *(c + x); +} + +static_assert (test () == ' '); --- gcc/testsuite/g++.dg/cpp23/constexpr-nonlit18.C.jj 2022-11-18 09:32:00.394372781 +0100 +++ gcc/testsuite/g++.dg/cpp23/constexpr-nonlit18.C 2022-11-18 09:57:48.159986371 +0100 @@ -0,0 +1,49 @@ +// P2647R1 - Permitting static constexpr variables in constexpr functions +// { dg-do compile { target c++14 } } + +constexpr int +f1 (int x) +{ + if (x) + throw 1; + return 0; +} + +constexpr int +f2 () +{ + static const int a = f1 (1); // { dg-error "'a' defined 'static' in 'constexpr' function only available with" "" { target c++20_down } } + return 0; +} + +constexpr int +f3 () +{ + static const int a = 5; // { dg-error "'a' defined 'static' in 'constexpr' function only available with" "" { target c++20_down } } + return 0; +} + +constexpr int +f4 () // { dg-message "declared here" "" { target c++20_down } } +{ // { dg-message "is not usable as a 'constexpr' function because:" "" { target c++23 } .-1 } + static const int a = f1 (1); // { dg-error "'a' defined 'static' in 'constexpr' function only available with" "" { target c++20_down } } + return 0; // { dg-error "'a' defined 'static' in 'constexpr' context" "" { target c++23 } .-1 } +} + +constexpr int a4 = f4 (); // { dg-error "called in a constant expression" } + +constexpr int +f5 () +{ + static const int a = f1 (0); // { dg-error "'a' defined 'static' in 'constexpr' function only available with" "" { target c++20_down } } + return 0; +} + +constexpr int +f6 () +{ + static const int a = f1 (0); // { dg-error "'a' defined 'static' in 'constexpr' function only available with" "" { target c++20_down } } + return 0; +} + +constexpr int a6 = f6 (); // { dg-error "called in a constant expression" "" { target c++20_down } } --- gcc/testsuite/g++.dg/cpp23/feat-cxx2b.C.jj 2022-11-18 09:00:17.293701708 +0100 +++ gcc/testsuite/g++.dg/cpp23/feat-cxx2b.C 2022-11-18 09:32:00.394372781 +0100 @@ -134,8 +134,8 @@ #ifndef __cpp_constexpr # error "__cpp_constexpr" -#elif __cpp_constexpr != 202207 -# error "__cpp_constexpr != 202207" +#elif __cpp_constexpr != 202211 +# error "__cpp_constexpr != 202211" #endif #ifndef __cpp_decltype_auto --- gcc/testsuite/g++.dg/ext/stmtexpr19.C.jj 2022-11-18 09:00:17.367700673 +0100 +++ gcc/testsuite/g++.dg/ext/stmtexpr19.C 2022-11-18 09:43:20.682975254 +0100 @@ -8,7 +8,7 @@ const test* setup() { static constexpr test atest = { - ({ static const int inner = 123; &inner; }) // { dg-error "static" } + ({ static const int inner = 123; &inner; }) }; return &atest; --- gcc/testsuite/g++.dg/ext/stmtexpr25.C.jj 2022-11-18 09:43:08.505143556 +0100 +++ gcc/testsuite/g++.dg/ext/stmtexpr25.C 2022-11-18 09:44:39.672883560 +0100 @@ -0,0 +1,17 @@ +// PR c++/81073 +// { dg-options "" } +// { dg-do compile { target c++11 } } + +struct test { const int *addr; }; + +const test* setup() +{ + static constexpr test atest = + { + ({ static const int inner = (throw 1, 1); &inner; }) // { dg-error "static" "" } + }; + + return &atest; +} + +int main(){} 2022-11-18 Jakub Jelinek gcc/c-family/ * c-cppbuiltin.cc (c_cpp_builtins): Bump __cpp_constexpr value from 202207L to 202211L. gcc/cp/ * constexpr.cc (cxx_eval_constant_expression): Implement C++23 P2647R1 - Permitting static constexpr variables in constexpr functions. Allow DECL_EXPRs of decl_constant_var_p static or thread_local vars for C++23. (potential_constant_expression_1): Similarly, except use decl_maybe_constant_var_p instead of decl_constant_var_p if processing_template_decl. gcc/testsuite/ * g++.dg/cpp23/constexpr-nonlit17.C: New test. * g++.dg/cpp23/constexpr-nonlit18.C: New test. * g++.dg/cpp23/feat-cxx2b.C: Adjust expected __cpp_constexpr value. * g++.dg/ext/stmtexpr19.C: Don't expect an error. * g++.dg/ext/stmtexpr25.C: New test. --- gcc/c-family/c-cppbuiltin.cc.jj 2022-11-18 09:00:17.102704379 +0100 +++ gcc/c-family/c-cppbuiltin.cc 2022-11-18 09:32:00.389372850 +0100 @@ -1074,7 +1074,7 @@ c_cpp_builtins (cpp_reader *pfile) /* Set feature test macros for C++23. */ cpp_define (pfile, "__cpp_size_t_suffix=202011L"); cpp_define (pfile, "__cpp_if_consteval=202106L"); - cpp_define (pfile, "__cpp_constexpr=202207L"); + cpp_define (pfile, "__cpp_constexpr=202211L"); cpp_define (pfile, "__cpp_multidimensional_subscript=202211L"); cpp_define (pfile, "__cpp_named_character_escapes=202207L"); cpp_define (pfile, "__cpp_static_call_operator=202207L"); --- gcc/cp/constexpr.cc.jj 2022-11-18 09:00:17.108704295 +0100 +++ gcc/cp/constexpr.cc 2022-11-18 09:35:39.822342414 +0100 @@ -7098,7 +7098,8 @@ cxx_eval_constant_expression (const cons && (TREE_STATIC (r) || (CP_DECL_THREAD_LOCAL_P (r) && !DECL_REALLY_EXTERN (r))) /* Allow __FUNCTION__ etc. */ - && !DECL_ARTIFICIAL (r)) + && !DECL_ARTIFICIAL (r) + && (cxx_dialect < cxx23 || !decl_constant_var_p (r))) { if (!ctx->quiet) { @@ -9586,7 +9587,10 @@ potential_constant_expression_1 (tree t, case DECL_EXPR: tmp = DECL_EXPR_DECL (t); - if (VAR_P (tmp) && !DECL_ARTIFICIAL (tmp)) + if (VAR_P (tmp) && !DECL_ARTIFICIAL (tmp) + && (cxx_dialect < cxx23 || (processing_template_decl + ? !decl_maybe_constant_var_p (tmp) + : !decl_constant_var_p (tmp)))) { if (CP_DECL_THREAD_LOCAL_P (tmp) && !DECL_REALLY_EXTERN (tmp)) { --- gcc/testsuite/g++.dg/cpp23/constexpr-nonlit17.C.jj 2022-11-18 09:32:00.393372795 +0100 +++ gcc/testsuite/g++.dg/cpp23/constexpr-nonlit17.C 2022-11-18 09:32:00.393372795 +0100 @@ -0,0 +1,12 @@ +// P2647R1 - Permitting static constexpr variables in constexpr functions +// { dg-do compile { target c++23 } } + +constexpr char +test () +{ + static const int x = 5; + static constexpr char c[] = "Hello World"; + return *(c + x); +} + +static_assert (test () == ' '); --- gcc/testsuite/g++.dg/cpp23/constexpr-nonlit18.C.jj 2022-11-18 09:32:00.394372781 +0100 +++ gcc/testsuite/g++.dg/cpp23/constexpr-nonlit18.C 2022-11-18 09:57:48.159986371 +0100 @@ -0,0 +1,49 @@ +// P2647R1 - Permitting static constexpr variables in constexpr functions +// { dg-do compile { target c++14 } } + +constexpr int +f1 (int x) +{ + if (x) + throw 1; + return 0; +} + +constexpr int +f2 () +{ + static const int a = f1 (1); // { dg-error "'a' defined 'static' in 'constexpr' function only available with" "" { target c++20_down } } + return 0; +} + +constexpr int +f3 () +{ + static const int a = 5; // { dg-error "'a' defined 'static' in 'constexpr' function only available with" "" { target c++20_down } } + return 0; +} + +constexpr int +f4 () // { dg-message "declared here" "" { target c++20_down } } +{ // { dg-message "is not usable as a 'constexpr' function because:" "" { target c++23 } .-1 } + static const int a = f1 (1); // { dg-error "'a' defined 'static' in 'constexpr' function only available with" "" { target c++20_down } } + return 0; // { dg-error "'a' defined 'static' in 'constexpr' context" "" { target c++23 } .-1 } +} + +constexpr int a4 = f4 (); // { dg-error "called in a constant expression" } + +constexpr int +f5 () +{ + static const int a = f1 (0); // { dg-error "'a' defined 'static' in 'constexpr' function only available with" "" { target c++20_down } } + return 0; +} + +constexpr int +f6 () +{ + static const int a = f1 (0); // { dg-error "'a' defined 'static' in 'constexpr' function only available with" "" { target c++20_down } } + return 0; +} + +constexpr int a6 = f6 (); // { dg-error "called in a constant expression" "" { target c++20_down } } --- gcc/testsuite/g++.dg/cpp23/feat-cxx2b.C.jj 2022-11-18 09:00:17.293701708 +0100 +++ gcc/testsuite/g++.dg/cpp23/feat-cxx2b.C 2022-11-18 09:32:00.394372781 +0100 @@ -134,8 +134,8 @@ #ifndef __cpp_constexpr # error "__cpp_constexpr" -#elif __cpp_constexpr != 202207 -# error "__cpp_constexpr != 202207" +#elif __cpp_constexpr != 202211 +# error "__cpp_constexpr != 202211" #endif #ifndef __cpp_decltype_auto --- gcc/testsuite/g++.dg/ext/stmtexpr19.C.jj 2022-11-18 09:00:17.367700673 +0100 +++ gcc/testsuite/g++.dg/ext/stmtexpr19.C 2022-11-18 09:43:20.682975254 +0100 @@ -8,7 +8,7 @@ const test* setup() { static constexpr test atest = { - ({ static const int inner = 123; &inner; }) // { dg-error "static" } + ({ static const int inner = 123; &inner; }) // { dg-error "static" "" { target c++20_down } .-1 } }; return &atest; --- gcc/testsuite/g++.dg/ext/stmtexpr25.C.jj 2022-11-18 09:43:08.505143556 +0100 +++ gcc/testsuite/g++.dg/ext/stmtexpr25.C 2022-11-18 09:44:39.672883560 +0100 @@ -0,0 +1,17 @@ +// PR c++/81073 +// { dg-options "" } +// { dg-do compile { target c++11 } } + +struct test { const int *addr; }; + +const test* setup() +{ + static constexpr test atest = + { + ({ static const int inner = (throw 1, 1); &inner; }) // { dg-error "static" "" } + }; + + return &atest; +} + +int main(){} --- gcc/c-family/c-cppbuiltin.cc.jj 2022-11-18 09:00:17.102704379 +0100 +++ gcc/c-family/c-cppbuiltin.cc 2022-11-18 09:32:00.389372850 +0100 @@ -1074,7 +1074,7 @@ c_cpp_builtins (cpp_reader *pfile) /* Set feature test macros for C++23. */ cpp_define (pfile, "__cpp_size_t_suffix=202011L"); cpp_define (pfile, "__cpp_if_consteval=202106L"); - cpp_define (pfile, "__cpp_constexpr=202207L"); + cpp_define (pfile, "__cpp_constexpr=202211L"); cpp_define (pfile, "__cpp_multidimensional_subscript=202211L"); cpp_define (pfile, "__cpp_named_character_escapes=202207L"); cpp_define (pfile, "__cpp_static_call_operator=202207L"); --- gcc/cp/constexpr.cc.jj 2022-11-18 09:00:17.108704295 +0100 +++ gcc/cp/constexpr.cc 2022-11-18 09:35:39.822342414 +0100 @@ -7098,7 +7098,8 @@ cxx_eval_constant_expression (const cons && (TREE_STATIC (r) || (CP_DECL_THREAD_LOCAL_P (r) && !DECL_REALLY_EXTERN (r))) /* Allow __FUNCTION__ etc. */ - && !DECL_ARTIFICIAL (r)) + && !DECL_ARTIFICIAL (r) + && !decl_constant_var_p (r)) { if (!ctx->quiet) { @@ -9586,7 +9587,10 @@ potential_constant_expression_1 (tree t, case DECL_EXPR: tmp = DECL_EXPR_DECL (t); - if (VAR_P (tmp) && !DECL_ARTIFICIAL (tmp)) + if (VAR_P (tmp) && !DECL_ARTIFICIAL (tmp) + && (processing_template_decl + ? !decl_maybe_constant_var_p (tmp) + : !decl_constant_var_p (tmp))) { if (CP_DECL_THREAD_LOCAL_P (tmp) && !DECL_REALLY_EXTERN (tmp)) { --- gcc/cp/decl.cc.jj 2022-11-18 09:03:51.592704514 +0100 +++ gcc/cp/decl.cc 2022-11-18 09:32:00.393372795 +0100 @@ -5600,6 +5600,57 @@ groktypename (cp_decl_specifier_seq *typ return type; } +/* For C++20 and older diagnose static or thread_local decls in constexpr + or consteval functions. If they are usable in constant expressions, + just pedwarn on them. */ + +static void +diagnose_static_in_constexpr (tree decl) +{ + if (cxx_dialect >= cxx23) + return; + if (current_function_decl + && VAR_P (decl) + && DECL_DECLARED_CONSTEXPR_P (current_function_decl)) + { + bool ok = false; + if (processing_template_decl + ? decl_maybe_constant_var_p (decl) + : decl_constant_var_p (decl)) + { + if (CP_DECL_THREAD_LOCAL_P (decl) && !DECL_REALLY_EXTERN (decl)) + pedwarn (DECL_SOURCE_LOCATION (decl), OPT_Wpedantic, + "%qD defined % in %qs function only " + "available with %<-std=c++2b%> or %<-std=gnu++2b%>", decl, + DECL_IMMEDIATE_FUNCTION_P (current_function_decl) + ? "consteval" : "constexpr"); + else if (TREE_STATIC (decl)) + pedwarn (DECL_SOURCE_LOCATION (decl), OPT_Wpedantic, + "%qD defined % in %qs function only available " + "with %<-std=c++2b%> or %<-std=gnu++2b%>", decl, + DECL_IMMEDIATE_FUNCTION_P (current_function_decl) + ? "consteval" : "constexpr"); + ok = true; + } + else if (CP_DECL_THREAD_LOCAL_P (decl) && !DECL_REALLY_EXTERN (decl)) + error_at (DECL_SOURCE_LOCATION (decl), + "%qD defined % in %qs function only " + "available with %<-std=c++2b%> or %<-std=gnu++2b%>", decl, + DECL_IMMEDIATE_FUNCTION_P (current_function_decl) + ? "consteval" : "constexpr"); + else if (TREE_STATIC (decl)) + error_at (DECL_SOURCE_LOCATION (decl), + "%qD defined % in %qs function only available " + "with %<-std=c++2b%> or %<-std=gnu++2b%>", decl, + DECL_IMMEDIATE_FUNCTION_P (current_function_decl) + ? "consteval" : "constexpr"); + else + ok = true; + if (!ok) + cp_function_chain->invalid_constexpr = true; + } +} + /* Process a DECLARATOR for a function-scope or namespace-scope variable or function declaration. (Function definitions go through start_function; class member @@ -5860,29 +5911,6 @@ start_decl (const cp_declarator *declara DECL_THIS_STATIC (decl) = 1; } - if (current_function_decl && VAR_P (decl) - && DECL_DECLARED_CONSTEXPR_P (current_function_decl) - && cxx_dialect < cxx23) - { - bool ok = false; - if (CP_DECL_THREAD_LOCAL_P (decl) && !DECL_REALLY_EXTERN (decl)) - error_at (DECL_SOURCE_LOCATION (decl), - "%qD defined % in %qs function only " - "available with %<-std=c++2b%> or %<-std=gnu++2b%>", decl, - DECL_IMMEDIATE_FUNCTION_P (current_function_decl) - ? "consteval" : "constexpr"); - else if (TREE_STATIC (decl)) - error_at (DECL_SOURCE_LOCATION (decl), - "%qD defined % in %qs function only available " - "with %<-std=c++2b%> or %<-std=gnu++2b%>", decl, - DECL_IMMEDIATE_FUNCTION_P (current_function_decl) - ? "consteval" : "constexpr"); - else - ok = true; - if (!ok) - cp_function_chain->invalid_constexpr = true; - } - if (!processing_template_decl && VAR_P (decl)) start_decl_1 (decl, initialized); @@ -8424,6 +8452,9 @@ cp_finish_decl (tree decl, tree init, bo set_user_assembler_name (decl, asmspec); DECL_HARD_REGISTER (decl) = 1; } + + diagnose_static_in_constexpr (decl); + return; } @@ -8749,6 +8780,8 @@ cp_finish_decl (tree decl, tree init, bo && !DECL_HARD_REGISTER (decl)) targetm.lower_local_decl_alignment (decl); + diagnose_static_in_constexpr (decl); + invoke_plugin_callbacks (PLUGIN_FINISH_DECL, decl); } --- gcc/testsuite/g++.dg/cpp23/constexpr-nonlit17.C.jj 2022-11-18 09:32:00.393372795 +0100 +++ gcc/testsuite/g++.dg/cpp23/constexpr-nonlit17.C 2022-11-18 09:32:00.393372795 +0100 @@ -0,0 +1,12 @@ +// P2647R1 - Permitting static constexpr variables in constexpr functions +// { dg-do compile { target c++23 } } + +constexpr char +test () +{ + static const int x = 5; + static constexpr char c[] = "Hello World"; + return *(c + x); +} + +static_assert (test () == ' '); --- gcc/testsuite/g++.dg/cpp23/constexpr-nonlit18.C.jj 2022-11-18 09:32:00.394372781 +0100 +++ gcc/testsuite/g++.dg/cpp23/constexpr-nonlit18.C 2022-11-18 09:32:00.394372781 +0100 @@ -0,0 +1,49 @@ +// P2647R1 - Permitting static constexpr variables in constexpr functions +// { dg-do compile { target c++14 } } + +constexpr int +f1 (int x) +{ + if (x) + throw 1; + return 0; +} + +constexpr int +f2 () +{ + static const int a = f1 (1); // { dg-error "'a' defined 'static' in 'constexpr' function only available with" "" { target c++20_down } } + return 0; +} + +constexpr int +f3 () +{ + static const int a = 5; // { dg-error "'a' defined 'static' in 'constexpr' function only available with" "" { target c++20_down } } + return 0; +} + +constexpr int +f4 () // { dg-message "declared here" "" { target c++20_down } } +{ // { dg-message "is not usable as a 'constexpr' function because:" "" { target c++23 } .-1 } + static const int a = f1 (1); // { dg-error "'a' defined 'static' in 'constexpr' function only available with" "" { target c++20_down } } + return 0; // { dg-error "'a' defined 'static' in 'constexpr' context" "" { target c++23 } .-1 } +} + +constexpr int a4 = f4 (); // { dg-error "called in a constant expression" } + +constexpr int +f5 () +{ + static const int a = f1 (0); // { dg-error "'a' defined 'static' in 'constexpr' function only available with" "" { target c++20_down } } + return 0; +} + +constexpr int +f6 () +{ + static const int a = f1 (0); // { dg-error "'a' defined 'static' in 'constexpr' function only available with" "" { target c++20_down } } + return 0; +} + +constexpr int a6 = f6 (); --- gcc/testsuite/g++.dg/cpp23/constexpr-nonlit19.C.jj 2022-11-18 09:32:00.394372781 +0100 +++ gcc/testsuite/g++.dg/cpp23/constexpr-nonlit19.C 2022-11-18 09:32:00.394372781 +0100 @@ -0,0 +1,50 @@ +// P2647R1 - Permitting static constexpr variables in constexpr functions +// { dg-do compile { target c++14 } } +// { dg-options "-pedantic" } + +constexpr int +f1 (int x) +{ + if (x) + throw 1; + return 0; +} + +constexpr int +f2 () +{ + static const int a = f1 (1); // { dg-error "'a' defined 'static' in 'constexpr' function only available with" "" { target c++20_down } } + return 0; +} + +constexpr int +f3 () +{ + static const int a = 5; // { dg-warning "'a' defined 'static' in 'constexpr' function only available with" "" { target c++20_down } } + return 0; +} + +constexpr int +f4 () // { dg-message "declared here" "" { target c++20_down } } +{ // { dg-message "is not usable as a 'constexpr' function because:" "" { target c++23 } .-1 } + static const int a = f1 (1); // { dg-error "'a' defined 'static' in 'constexpr' function only available with" "" { target c++20_down } } + return 0; // { dg-error "'a' defined 'static' in 'constexpr' context" "" { target c++23 } .-1 } +} + +constexpr int a4 = f4 (); // { dg-error "called in a constant expression" } + +constexpr int +f5 () +{ + static const int a = f1 (0); // { dg-warning "'a' defined 'static' in 'constexpr' function only available with" "" { target c++20_down } } + return 0; +} + +constexpr int +f6 () +{ + static const int a = f1 (0); // { dg-warning "'a' defined 'static' in 'constexpr' function only available with" "" { target c++20_down } } + return 0; +} + +constexpr int a6 = f6 (); --- gcc/testsuite/g++.dg/cpp23/constexpr-nonlit20.C.jj 2022-11-18 09:32:00.394372781 +0100 +++ gcc/testsuite/g++.dg/cpp23/constexpr-nonlit20.C 2022-11-18 09:32:00.394372781 +0100 @@ -0,0 +1,50 @@ +// P2647R1 - Permitting static constexpr variables in constexpr functions +// { dg-do compile { target c++14 } } +// { dg-options "-Wno-pedantic" } + +constexpr int +f1 (int x) +{ + if (x) + throw 1; + return 0; +} + +constexpr int +f2 () +{ + static const int a = f1 (1); // { dg-error "'a' defined 'static' in 'constexpr' function only available with" "" { target c++20_down } } + return 0; +} + +constexpr int +f3 () +{ + static const int a = 5; + return 0; +} + +constexpr int +f4 () // { dg-message "declared here" "" { target c++20_down } } +{ // { dg-message "is not usable as a 'constexpr' function because:" "" { target c++23 } .-1 } + static const int a = f1 (1); // { dg-error "'a' defined 'static' in 'constexpr' function only available with" "" { target c++20_down } } + return 0; // { dg-error "'a' defined 'static' in 'constexpr' context" "" { target c++23 } .-1 } +} + +constexpr int a4 = f4 (); // { dg-error "called in a constant expression" } + +constexpr int +f5 () +{ + static const int a = f1 (0); + return 0; +} + +constexpr int +f6 () +{ + static const int a = f1 (0); + return 0; +} + +constexpr int a6 = f6 (); --- gcc/testsuite/g++.dg/cpp23/feat-cxx2b.C.jj 2022-11-18 09:00:17.293701708 +0100 +++ gcc/testsuite/g++.dg/cpp23/feat-cxx2b.C 2022-11-18 09:32:00.394372781 +0100 @@ -134,8 +134,8 @@ #ifndef __cpp_constexpr # error "__cpp_constexpr" -#elif __cpp_constexpr != 202207 -# error "__cpp_constexpr != 202207" +#elif __cpp_constexpr != 202211 +# error "__cpp_constexpr != 202211" #endif #ifndef __cpp_decltype_auto --- gcc/testsuite/g++.dg/ext/stmtexpr19.C.jj 2022-11-18 09:00:17.367700673 +0100 +++ gcc/testsuite/g++.dg/ext/stmtexpr19.C 2022-11-18 09:43:20.682975254 +0100 @@ -8,7 +8,7 @@ const test* setup() { static constexpr test atest = { - ({ static const int inner = 123; &inner; }) // { dg-error "static" } + ({ static const int inner = 123; &inner; }) }; return &atest; --- gcc/testsuite/g++.dg/ext/stmtexpr25.C.jj 2022-11-18 09:43:08.505143556 +0100 +++ gcc/testsuite/g++.dg/ext/stmtexpr25.C 2022-11-18 09:44:39.672883560 +0100 @@ -0,0 +1,17 @@ +// PR c++/81073 +// { dg-options "" } +// { dg-do compile { target c++11 } } + +struct test { const int *addr; }; + +const test* setup() +{ + static constexpr test atest = + { + ({ static const int inner = (throw 1, 1); &inner; }) // { dg-error "static" "" } + }; + + return &atest; +} + +int main(){}