c++, v2: Implement C++23 P2647R1 - Permitting static constexpr variables in constexpr functions
Checks
Commit Message
On Fri, Nov 11, 2022 at 06:07:04PM +0100, Jakub Jelinek wrote:
> The following patch on top of Marek's P2448 PR106649 patch
> (mainly because that patch implements the previous __cpp_constexpr
> feature test macro bump so this can't go in earlier; OT,
> P2280R4 doesn't have any feature test macro?) implements this
> simple paper.
>
> Ok for trunk if it passes bootstrap/regtest and is voted into C++23?
Here is an updated patch that passed bootstrap/regtest, the only
change is another testcase tweak.
2022-11-13 Jakub Jelinek <jakub@redhat.com>
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_maybe_constant_var_p static or thread_local vars for
C++23.
(potential_constant_expression_1): Likewise.
gcc/testsuite/
* g++.dg/cpp23/constexpr-nonlit17.C: New test.
* g++.dg/cpp23/feat-cxx2b.C: Adjust expected __cpp_constexpr
value.
* g++.dg/ext/stmtexpr19.C: Don't expect an error for C++23 or later.
Jakub
Comments
On 11/13/22 01:45, Jakub Jelinek wrote:
> On Fri, Nov 11, 2022 at 06:07:04PM +0100, Jakub Jelinek wrote:
>> The following patch on top of Marek's P2448 PR106649 patch
>> (mainly because that patch implements the previous __cpp_constexpr
>> feature test macro bump so this can't go in earlier; OT,
>> P2280R4 doesn't have any feature test macro?) implements this
>> simple paper.
>>
>> Ok for trunk if it passes bootstrap/regtest and is voted into C++23?
>
> Here is an updated patch that passed bootstrap/regtest, the only
> change is another testcase tweak.
>
> 2022-11-13 Jakub Jelinek <jakub@redhat.com>
>
> 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_maybe_constant_var_p static or thread_local vars for
> C++23.
This was accepted as a DR, so it shouldn't be limited to C++23 mode.
Certainly it should be allowed in C++20 mode; I don't have a strong
opinion about C++14/17. Jonathan, do you?
> (potential_constant_expression_1): Likewise.
> gcc/testsuite/
> * g++.dg/cpp23/constexpr-nonlit17.C: New test.
> * g++.dg/cpp23/feat-cxx2b.C: Adjust expected __cpp_constexpr
> value.
> * g++.dg/ext/stmtexpr19.C: Don't expect an error for C++23 or later.
>
> --- gcc/c-family/c-cppbuiltin.cc.jj 2022-11-11 17:14:52.021613271 +0100
> +++ gcc/c-family/c-cppbuiltin.cc 2022-11-11 17:17:45.065265246 +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=202110L");
> cpp_define (pfile, "__cpp_named_character_escapes=202207L");
> cpp_define (pfile, "__cpp_static_call_operator=202207L");
> --- gcc/cp/constexpr.cc.jj 2022-11-11 17:14:52.024613231 +0100
> +++ gcc/cp/constexpr.cc 2022-11-11 17:16:54.384952917 +0100
> @@ -7085,7 +7085,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_maybe_constant_var_p (r)))
> {
> if (!ctx->quiet)
> {
> @@ -9577,7 +9578,10 @@ potential_constant_expression_1 (tree t,
> tmp = DECL_EXPR_DECL (t);
> if (VAR_P (tmp) && !DECL_ARTIFICIAL (tmp))
> {
> - if (CP_DECL_THREAD_LOCAL_P (tmp) && !DECL_REALLY_EXTERN (tmp))
> + if (CP_DECL_THREAD_LOCAL_P (tmp)
> + && !DECL_REALLY_EXTERN (tmp)
> + && (cxx_dialect < cxx23
> + || !decl_maybe_constant_var_p (tmp)))
> {
> if (flags & tf_error)
> constexpr_error (DECL_SOURCE_LOCATION (tmp), fundef_p,
> @@ -9585,7 +9589,9 @@ potential_constant_expression_1 (tree t,
> "%<constexpr%> context", tmp);
> return false;
> }
> - else if (TREE_STATIC (tmp))
> + else if (TREE_STATIC (tmp)
> + && (cxx_dialect < cxx23
> + || !decl_maybe_constant_var_p (tmp)))
> {
> if (flags & tf_error)
> constexpr_error (DECL_SOURCE_LOCATION (tmp), fundef_p,
> --- gcc/testsuite/g++.dg/cpp23/constexpr-nonlit17.C.jj 2022-11-11 17:59:59.972852793 +0100
> +++ gcc/testsuite/g++.dg/cpp23/constexpr-nonlit17.C 2022-11-11 17:59:38.725141231 +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/feat-cxx2b.C.jj 2022-11-11 17:14:52.194610922 +0100
> +++ gcc/testsuite/g++.dg/cpp23/feat-cxx2b.C 2022-11-11 17:48:56.038865825 +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 2020-01-14 20:02:46.839608995 +0100
> +++ gcc/testsuite/g++.dg/ext/stmtexpr19.C 2022-11-12 09:17:40.706245495 +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 } }
> };
>
> return &atest;
>
>
> Jakub
>
On Tue, Nov 15, 2022 at 06:36:38PM -0500, Jason Merrill wrote:
> > Here is an updated patch that passed bootstrap/regtest, the only
> > change is another testcase tweak.
> >
> > 2022-11-13 Jakub Jelinek <jakub@redhat.com>
> >
> > 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_maybe_constant_var_p static or thread_local vars for
> > C++23.
>
> This was accepted as a DR, so it shouldn't be limited to C++23 mode.
> Certainly it should be allowed in C++20 mode; I don't have a strong opinion
> about C++14/17. Jonathan, do you?
How will a feature with feature test macro with multiple values work as DR?
Or will everything but the macro be treated as a DR (so __cpp_constexpr >=
202211L only for C++23)?
Because __cpp_constexpr >= 202211L is >= 202207L too and that implies
P2448R2 which wasn't a DR and >= 202110L which implies P2242R3 which wasn't a
DR. And C++20 added other 2 non-DR papers that bumped the value.
C++17 another one.
> > (potential_constant_expression_1): Likewise.
> > gcc/testsuite/
> > * g++.dg/cpp23/constexpr-nonlit17.C: New test.
> > * g++.dg/cpp23/feat-cxx2b.C: Adjust expected __cpp_constexpr
> > value.
> > * g++.dg/ext/stmtexpr19.C: Don't expect an error for C++23 or later.
Jakub
On Tue, 15 Nov 2022 at 23:36, Jason Merrill <jason@redhat.com> wrote:
>
> On 11/13/22 01:45, Jakub Jelinek wrote:
> > On Fri, Nov 11, 2022 at 06:07:04PM +0100, Jakub Jelinek wrote:
> >> The following patch on top of Marek's P2448 PR106649 patch
> >> (mainly because that patch implements the previous __cpp_constexpr
> >> feature test macro bump so this can't go in earlier; OT,
> >> P2280R4 doesn't have any feature test macro?) implements this
> >> simple paper.
> >>
> >> Ok for trunk if it passes bootstrap/regtest and is voted into C++23?
> >
> > Here is an updated patch that passed bootstrap/regtest, the only
> > change is another testcase tweak.
> >
> > 2022-11-13 Jakub Jelinek <jakub@redhat.com>
> >
> > 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_maybe_constant_var_p static or thread_local vars for
> > C++23.
>
> This was accepted as a DR, so it shouldn't be limited to C++23 mode.
> Certainly it should be allowed in C++20 mode; I don't have a strong
> opinion about C++14/17. Jonathan, do you?
I don't. The lack of this feature caused some awkwardness implementing
a C++23 library feature in <charconv>, but that means my desire for it
was only in C++23 mode. And that has been mitigated by changes Patrick
made to work around it anyway.
I think it does make sense for C++20, where constexpr is pretty close
to "normal" code, what with dynamic allocations, std::string etc. but
I don't see a great need for it before C++20.
>
> > (potential_constant_expression_1): Likewise.
> > gcc/testsuite/
> > * g++.dg/cpp23/constexpr-nonlit17.C: New test.
> > * g++.dg/cpp23/feat-cxx2b.C: Adjust expected __cpp_constexpr
> > value.
> > * g++.dg/ext/stmtexpr19.C: Don't expect an error for C++23 or later.
> >
> > --- gcc/c-family/c-cppbuiltin.cc.jj 2022-11-11 17:14:52.021613271 +0100
> > +++ gcc/c-family/c-cppbuiltin.cc 2022-11-11 17:17:45.065265246 +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=202110L");
> > cpp_define (pfile, "__cpp_named_character_escapes=202207L");
> > cpp_define (pfile, "__cpp_static_call_operator=202207L");
> > --- gcc/cp/constexpr.cc.jj 2022-11-11 17:14:52.024613231 +0100
> > +++ gcc/cp/constexpr.cc 2022-11-11 17:16:54.384952917 +0100
> > @@ -7085,7 +7085,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_maybe_constant_var_p (r)))
> > {
> > if (!ctx->quiet)
> > {
> > @@ -9577,7 +9578,10 @@ potential_constant_expression_1 (tree t,
> > tmp = DECL_EXPR_DECL (t);
> > if (VAR_P (tmp) && !DECL_ARTIFICIAL (tmp))
> > {
> > - if (CP_DECL_THREAD_LOCAL_P (tmp) && !DECL_REALLY_EXTERN (tmp))
> > + if (CP_DECL_THREAD_LOCAL_P (tmp)
> > + && !DECL_REALLY_EXTERN (tmp)
> > + && (cxx_dialect < cxx23
> > + || !decl_maybe_constant_var_p (tmp)))
> > {
> > if (flags & tf_error)
> > constexpr_error (DECL_SOURCE_LOCATION (tmp), fundef_p,
> > @@ -9585,7 +9589,9 @@ potential_constant_expression_1 (tree t,
> > "%<constexpr%> context", tmp);
> > return false;
> > }
> > - else if (TREE_STATIC (tmp))
> > + else if (TREE_STATIC (tmp)
> > + && (cxx_dialect < cxx23
> > + || !decl_maybe_constant_var_p (tmp)))
> > {
> > if (flags & tf_error)
> > constexpr_error (DECL_SOURCE_LOCATION (tmp), fundef_p,
> > --- gcc/testsuite/g++.dg/cpp23/constexpr-nonlit17.C.jj 2022-11-11 17:59:59.972852793 +0100
> > +++ gcc/testsuite/g++.dg/cpp23/constexpr-nonlit17.C 2022-11-11 17:59:38.725141231 +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/feat-cxx2b.C.jj 2022-11-11 17:14:52.194610922 +0100
> > +++ gcc/testsuite/g++.dg/cpp23/feat-cxx2b.C 2022-11-11 17:48:56.038865825 +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 2020-01-14 20:02:46.839608995 +0100
> > +++ gcc/testsuite/g++.dg/ext/stmtexpr19.C 2022-11-12 09:17:40.706245495 +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 } }
> > };
> >
> > return &atest;
> >
> >
> > Jakub
> >
>
On Tue, 15 Nov 2022 at 23:50, Jakub Jelinek <jakub@redhat.com> wrote:
>
> On Tue, Nov 15, 2022 at 06:36:38PM -0500, Jason Merrill wrote:
> > > Here is an updated patch that passed bootstrap/regtest, the only
> > > change is another testcase tweak.
> > >
> > > 2022-11-13 Jakub Jelinek <jakub@redhat.com>
> > >
> > > 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_maybe_constant_var_p static or thread_local vars for
> > > C++23.
> >
> > This was accepted as a DR, so it shouldn't be limited to C++23 mode.
> > Certainly it should be allowed in C++20 mode; I don't have a strong opinion
> > about C++14/17. Jonathan, do you?
>
> How will a feature with feature test macro with multiple values work as DR?
> Or will everything but the macro be treated as a DR (so __cpp_constexpr >=
> 202211L only for C++23)?
Yes, I think so. We just won't be able to advertise this feature as
supported in C++20.
> Because __cpp_constexpr >= 202211L is >= 202207L too and that implies
> P2448R2 which wasn't a DR and >= 202110L which implies P2242R3 which wasn't a
> DR. And C++20 added other 2 non-DR papers that bumped the value.
> C++17 another one.
>
> > > (potential_constant_expression_1): Likewise.
> > > gcc/testsuite/
> > > * g++.dg/cpp23/constexpr-nonlit17.C: New test.
> > > * g++.dg/cpp23/feat-cxx2b.C: Adjust expected __cpp_constexpr
> > > value.
> > > * g++.dg/ext/stmtexpr19.C: Don't expect an error for C++23 or later.
>
> Jakub
>
On Wed, Nov 16, 2022 at 12:27:02AM +0000, Jonathan Wakely wrote:
> On Tue, 15 Nov 2022 at 23:50, Jakub Jelinek <jakub@redhat.com> wrote:
> >
> > On Tue, Nov 15, 2022 at 06:36:38PM -0500, Jason Merrill wrote:
> > > > Here is an updated patch that passed bootstrap/regtest, the only
> > > > change is another testcase tweak.
> > > >
> > > > 2022-11-13 Jakub Jelinek <jakub@redhat.com>
> > > >
> > > > 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_maybe_constant_var_p static or thread_local vars for
> > > > C++23.
> > >
> > > This was accepted as a DR, so it shouldn't be limited to C++23 mode.
> > > Certainly it should be allowed in C++20 mode; I don't have a strong opinion
> > > about C++14/17. Jonathan, do you?
> >
> > How will a feature with feature test macro with multiple values work as DR?
> > Or will everything but the macro be treated as a DR (so __cpp_constexpr >=
> > 202211L only for C++23)?
>
> Yes, I think so. We just won't be able to advertise this feature as
> supported in C++20.
Ok. But there is another issue, the
https://eel.is/c++draft/expr.const#5.2
spot that P2647R1 is changing didn't exist in C++20, it was only added with
P2242R3. So, if one would treat P2647R1 as a DR for C++20, one has to come up with
a different standard modification.
Probably change the last bullet of:
[dcl.constexpr]/3
its function-body shall not enclose
a goto statement,
an identifier label,
a definition of a variable of non-literal type or of static or thread storage duration.
to
a definition of a variable of non-literal type or of a non-constexpr
variable of static or thread storage duration.
or so.
Jakub
On 11/16/22 01:19, Jakub Jelinek wrote:
> On Wed, Nov 16, 2022 at 12:27:02AM +0000, Jonathan Wakely wrote:
>> On Tue, 15 Nov 2022 at 23:50, Jakub Jelinek <jakub@redhat.com> wrote:
>>>
>>> On Tue, Nov 15, 2022 at 06:36:38PM -0500, Jason Merrill wrote:
>>>>> Here is an updated patch that passed bootstrap/regtest, the only
>>>>> change is another testcase tweak.
>>>>>
>>>>> 2022-11-13 Jakub Jelinek <jakub@redhat.com>
>>>>>
>>>>> 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_maybe_constant_var_p static or thread_local vars for
>>>>> C++23.
>>>>
>>>> This was accepted as a DR, so it shouldn't be limited to C++23 mode.
>>>> Certainly it should be allowed in C++20 mode; I don't have a strong opinion
>>>> about C++14/17. Jonathan, do you?
>>>
>>> How will a feature with feature test macro with multiple values work as DR?
>>> Or will everything but the macro be treated as a DR (so __cpp_constexpr >=
>>> 202211L only for C++23)?
>>
>> Yes, I think so. We just won't be able to advertise this feature as
>> supported in C++20.
>
> Ok. But there is another issue, the
> https://eel.is/c++draft/expr.const#5.2
> spot that P2647R1 is changing didn't exist in C++20, it was only added with
> P2242R3. So, if one would treat P2647R1 as a DR for C++20, one has to come up with
> a different standard modification.
> Probably change the last bullet of:
> [dcl.constexpr]/3
> its function-body shall not enclose
>
> a goto statement,
> an identifier label,
> a definition of a variable of non-literal type or of static or thread storage duration.
> to
> a definition of a variable of non-literal type or of a non-constexpr
> variable of static or thread storage duration.
> or so.
Indeed, though the hypothetical C++20 change could still use the "usable
in constant expressions" phrase.
Jason
On Wed, Nov 16, 2022 at 08:20:34AM -0500, Jason Merrill wrote:
> > Ok. But there is another issue, the
> > https://eel.is/c++draft/expr.const#5.2
> > spot that P2647R1 is changing didn't exist in C++20, it was only added with
> > P2242R3. So, if one would treat P2647R1 as a DR for C++20, one has to come up with
> > a different standard modification.
> > Probably change the last bullet of:
> > [dcl.constexpr]/3
> > its function-body shall not enclose
> >
> > a goto statement,
> > an identifier label,
> > a definition of a variable of non-literal type or of static or thread storage duration.
> > to
> > a definition of a variable of non-literal type or of a non-constexpr
> > variable of static or thread storage duration.
> > or so.
>
> Indeed, though the hypothetical C++20 change could still use the "usable in
> constant expressions" phrase.
Yes.
Though, with -std=c++20 we are rejected already in start_decl's
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 %<thread_local%> 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 %<static%> 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;
}
and at that point I fear decl_maybe_constant_var_p will not work
properly. Shall this hunk be moved somewhere else (cp_finish_decl?)
where we can already call it, or do the above in start_decl for
cxx_dialect < cxx20 and add a cxx_dialect == cxx20 hunk in cp_finish_decl?
Jakub
On 11/16/22 09:08, Jakub Jelinek wrote:
> On Wed, Nov 16, 2022 at 08:20:34AM -0500, Jason Merrill wrote:
>>> Ok. But there is another issue, the
>>> https://eel.is/c++draft/expr.const#5.2
>>> spot that P2647R1 is changing didn't exist in C++20, it was only added with
>>> P2242R3. So, if one would treat P2647R1 as a DR for C++20, one has to come up with
>>> a different standard modification.
>>> Probably change the last bullet of:
>>> [dcl.constexpr]/3
>>> its function-body shall not enclose
>>>
>>> a goto statement,
>>> an identifier label,
>>> a definition of a variable of non-literal type or of static or thread storage duration.
>>> to
>>> a definition of a variable of non-literal type or of a non-constexpr
>>> variable of static or thread storage duration.
>>> or so.
>>
>> Indeed, though the hypothetical C++20 change could still use the "usable in
>> constant expressions" phrase.
>
> Yes.
> Though, with -std=c++20 we are rejected already in start_decl's
> 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 %<thread_local%> 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 %<static%> 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;
> }
> and at that point I fear decl_maybe_constant_var_p will not work
> properly. Shall this hunk be moved somewhere else (cp_finish_decl?)
> where we can already call it, or do the above in start_decl for
> cxx_dialect < cxx20 and add a cxx_dialect == cxx20 hunk in cp_finish_decl?
Hmm, I'd expect decl_maybe_constant_var_p to work fine at this point.
Jason
On Wed, Nov 16, 2022 at 09:33:27AM -0500, Jason Merrill wrote:
> > and at that point I fear decl_maybe_constant_var_p will not work
> > properly. Shall this hunk be moved somewhere else (cp_finish_decl?)
> > where we can already call it, or do the above in start_decl for
> > cxx_dialect < cxx20 and add a cxx_dialect == cxx20 hunk in cp_finish_decl?
>
> Hmm, I'd expect decl_maybe_constant_var_p to work fine at this point.
For static constexpr vars sure, but what about
static const where start_decl doesn't know the initializer?
Sure, decl_maybe_constant_var_p will not crash in that case, but
it will return true even if the static const var doesn't have
a constant initializer. Sure, we'd catch that later on when actually
trying to constexpr evaluate the function and hitting there the
spots added for C++23 in potential_constant_expression*/cxx_eval_*,
but it would mean that we don't reject it when nothing calls the functions.
I meant something like:
constexpr int bar (int x) { if (x) throw 1; return 0; }
constexpr int foo () { static const int a = bar (1); return 0; }
with -std=c++20 IMHO shouldn't be accepted, while in C++23 it should.
With
constexpr int a = foo ();
added we reject it in C++23 (correct), but the diagnostics is too weird:
test.C:3:23: in ‘constexpr’ expansion of ‘foo()’
test.C:3:24: error: ‘__atomic_load_1((& _ZGVZ3foovE1a), 2)’ is not a constant expression
3 | constexpr int a = foo ();
| ^
Jakub
On 11/16/22 09:46, Jakub Jelinek wrote:
> On Wed, Nov 16, 2022 at 09:33:27AM -0500, Jason Merrill wrote:
>>> and at that point I fear decl_maybe_constant_var_p will not work
>>> properly. Shall this hunk be moved somewhere else (cp_finish_decl?)
>>> where we can already call it, or do the above in start_decl for
>>> cxx_dialect < cxx20 and add a cxx_dialect == cxx20 hunk in cp_finish_decl?
>>
>> Hmm, I'd expect decl_maybe_constant_var_p to work fine at this point.
>
> For static constexpr vars sure, but what about
> static const where start_decl doesn't know the initializer?
> Sure, decl_maybe_constant_var_p will not crash in that case, but
> it will return true even if the static const var doesn't have
> a constant initializer. Sure, we'd catch that later on when actually
> trying to constexpr evaluate the function and hitting there the
> spots added for C++23 in potential_constant_expression*/cxx_eval_*,
> but it would mean that we don't reject it when nothing calls the functions.
>
> I meant something like:
> constexpr int bar (int x) { if (x) throw 1; return 0; }
> constexpr int foo () { static const int a = bar (1); return 0; }
> with -std=c++20 IMHO shouldn't be accepted, while in C++23 it should.
I'd expect us to reject that in C++20 in potential_constant_expression,
but it's a fair point; it is awkward that P2242 wasn't also accepted as
a DR.
Moving the check from start_decl to cp_finish_decl makes sense to me.
Jason
@@ -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=202110L");
cpp_define (pfile, "__cpp_named_character_escapes=202207L");
cpp_define (pfile, "__cpp_static_call_operator=202207L");
@@ -7085,7 +7085,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_maybe_constant_var_p (r)))
{
if (!ctx->quiet)
{
@@ -9577,7 +9578,10 @@ potential_constant_expression_1 (tree t,
tmp = DECL_EXPR_DECL (t);
if (VAR_P (tmp) && !DECL_ARTIFICIAL (tmp))
{
- if (CP_DECL_THREAD_LOCAL_P (tmp) && !DECL_REALLY_EXTERN (tmp))
+ if (CP_DECL_THREAD_LOCAL_P (tmp)
+ && !DECL_REALLY_EXTERN (tmp)
+ && (cxx_dialect < cxx23
+ || !decl_maybe_constant_var_p (tmp)))
{
if (flags & tf_error)
constexpr_error (DECL_SOURCE_LOCATION (tmp), fundef_p,
@@ -9585,7 +9589,9 @@ potential_constant_expression_1 (tree t,
"%<constexpr%> context", tmp);
return false;
}
- else if (TREE_STATIC (tmp))
+ else if (TREE_STATIC (tmp)
+ && (cxx_dialect < cxx23
+ || !decl_maybe_constant_var_p (tmp)))
{
if (flags & tf_error)
constexpr_error (DECL_SOURCE_LOCATION (tmp), fundef_p,
@@ -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 () == ' ');
@@ -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
@@ -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 } }
};
return &atest;