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: 60818 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 D218B383B2F8 for ; Fri, 18 Nov 2022 09:10:59 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org D218B383B2F8 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1668762659; 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=AVEiKew7OU5k6o8YyiD/b09yd2kgg2wjEJOZCoSJiVCZ7cXMyxcsBXpKQyOf2ufph aIKYSNxVXv3WbZoM3LmO71MiWjOpGXv2rpPbqukdNCotqRZgBX+nyo7xOGMBUhsRdr IbNTp99vcXXj2t8rFLMsusbyi2hdaAkiWBUb9HqY= 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+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" 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(){}