Re: [PATCH] c++: Implement C++23 P2242R3 - Non-literal variables (and labels and gotos) in constexpr functions

2021-10-05 Thread Jason Merrill via Gcc-patches

On 10/5/21 08:39, Jakub Jelinek wrote:

Hi!

The following patch implements C++23 P2242R3 - Non-literal variables
(and labels and gotos) in constexpr functions.
I think it is mostly straightforward, don't diagnose certain
statements/declarations just because of their presence in
constexpr/consteval functions, but (except for the non-literal type
var declarations which ought to be caught by e.g. constructor or
destructor call during evaluation not being constexpr and for
labels which are now always allowed) diagnose it during constexpr
evaluation.

The only unclear thing to me is "a control flow that passes through a
declaration".  The patch implements diagnostics when encountering a
DECL_EXPR for such variables.  But because constexpr/consteval functions
support switch statements, another thing that can happen is jump over
such a declaration.  Consider e.g. following testcase (not included
in the patch).  When evaluating foo (12) or bar (12) the patch
accepts those as constant expressions, eventhough it jumps across such
declarations.  For baz (12) and corge (12) it rejects them not
because of jumping across such declarations, but because those
static or thread_local variables aren't initialized with constant
expressions and are accessed.  If baz/corge is modified not to have
const keyword, they are rejected because the vars aren't aren't const.
If they have const keyword and are initialized by constant expression,
accesses to those vars are accepted.  Is that ok?


That seems correct to me.  If they have static initialization, they are 
initialized.


Some comments in the patch below.


So far regtested with
GXX_TESTSUITE_STDS=98,11,14,17,20,2b make -j32 -k check-g++
ok for trunk if it passes full bootstrap/regtest?

// { dg-do compile }
// { dg-options "-std=c++2b" }

int qux ();

constexpr int
foo (int x)
{
   switch (x)
 {
   static int bar = qux ();
 case 12:
   return 1;
 }
   return 0;
}

constexpr int
bar (int x)
{
   switch (x)
 {
   thread_local int bar = qux ();
 case 12:
   return 1;
 }
   return 0;
}

constexpr int
baz (int x)
{
   switch (x)
 {
   static const int bar = qux ();   // { dg-message "'bar' was not initialized 
with a constant expression" }
 case 12:
   return bar;
 }
   return 0;
}

constexpr int
corge (int x)
{
   switch (x)
 {
   const thread_local int bar = qux (); // { dg-message "'bar' was not 
initialized with a constant expression" }
 case 12:
   return bar;
 }
   return 0;
}

constexpr int a = foo (12);
constexpr int b = bar (12);
constexpr int c = baz (12); // { dg-error "the value of 'bar' is not 
usable in a constant expression" }
constexpr int d = corge (12);   // { dg-error "the value of 'bar' is not 
usable in a constant expression" }


2021-10-05  Jakub Jelinek  

gcc/c-family/
* c-cppbuiltin.c (c_cpp_builtins): For -std=c++23 predefine
__cpp_constexpr to 202103L rather than 201907L.
gcc/cp/
* parser.c (cp_parser_jump_statement): Implement C++23 P2242R3.
Allow goto expressions in constexpr function bodies for C++23.
Adjust error message for older standards to mention it.
* decl.c (start_decl): Allow static and thread_local declarations
in constexpr function bodies for C++23.  Adjust error message for
older standards to mention it.
* constexpr.c (ensure_literal_type_for_constexpr_object): Allow
declarations of variables with non-literal type in constexpr function
bodies for C++23.  Adjust error message for older standards to mention
it.
(cxx_eval_constant_expression) : Diagnose declarations
of initialization of static or thread_local vars.
(cxx_eval_constant_expression) : Diagnose goto
statements for C++23.
(potential_constant_expression_1) : Allow declarations
of static and thread_local vars for C++23.
(potential_constant_expression_1) : Allow labels for
C++23.
gcc/testsuite/
* g++.dg/cpp23/feat-cxx2b.C: Expect __cpp_constexpr 202103L rather
than 201907L.
* g++.dg/cpp23/constexpr-nonlit1.C: New test.
* g++.dg/cpp23/constexpr-nonlit2.C: New test.
* g++.dg/cpp23/constexpr-nonlit3.C: New test.
* g++.dg/diagnostic/constexpr1.C: Only expect some diagnostics for
c++20_down.
* g++.dg/cpp1y/constexpr-label.C: Likewise.
* g++.dg/cpp1y/constexpr-neg1.C: Likewise.
* g++.dg/cpp2a/constexpr-try5.C: Likewise.  Adjust some expected
wording.
* g++.dg/cpp2a/constexpr-dtor3.C: Likewise.
* g++.dg/cpp2a/consteval3.C: Likewise.  Add effective target c++20
and remove dg-options.

--- gcc/c-family/c-cppbuiltin.c.jj  2021-09-21 23:31:01.016248936 +0200
+++ gcc/c-family/c-cppbuiltin.c 2021-10-05 12:54:29.898321379 +0200
@@ -1052,7 +1052,8 @@ c_cpp_builtins (cpp_reader *pfile)
  cpp_define (pfile, 

[PATCH] c++: Implement C++23 P2242R3 - Non-literal variables (and labels and gotos) in constexpr functions

2021-10-05 Thread Jakub Jelinek via Gcc-patches
Hi!

The following patch implements C++23 P2242R3 - Non-literal variables
(and labels and gotos) in constexpr functions.
I think it is mostly straightforward, don't diagnose certain
statements/declarations just because of their presence in
constexpr/consteval functions, but (except for the non-literal type
var declarations which ought to be caught by e.g. constructor or
destructor call during evaluation not being constexpr and for
labels which are now always allowed) diagnose it during constexpr
evaluation.

The only unclear thing to me is "a control flow that passes through a
declaration".  The patch implements diagnostics when encountering a
DECL_EXPR for such variables.  But because constexpr/consteval functions
support switch statements, another thing that can happen is jump over
such a declaration.  Consider e.g. following testcase (not included
in the patch).  When evaluating foo (12) or bar (12) the patch
accepts those as constant expressions, eventhough it jumps across such
declarations.  For baz (12) and corge (12) it rejects them not
because of jumping across such declarations, but because those
static or thread_local variables aren't initialized with constant
expressions and are accessed.  If baz/corge is modified not to have
const keyword, they are rejected because the vars aren't aren't const.
If they have const keyword and are initialized by constant expression,
accesses to those vars are accepted.  Is that ok?

So far regtested with
GXX_TESTSUITE_STDS=98,11,14,17,20,2b make -j32 -k check-g++
ok for trunk if it passes full bootstrap/regtest?

// { dg-do compile }
// { dg-options "-std=c++2b" }

int qux ();

constexpr int
foo (int x)
{
  switch (x)
{
  static int bar = qux ();
case 12:
  return 1;
}
  return 0;
}

constexpr int
bar (int x)
{
  switch (x)
{
  thread_local int bar = qux ();
case 12:
  return 1;
}
  return 0;
}

constexpr int
baz (int x)
{
  switch (x)
{
  static const int bar = qux ();// { dg-message "'bar' was not 
initialized with a constant expression" }
case 12:
  return bar;
}
  return 0;
}

constexpr int
corge (int x)
{
  switch (x)
{
  const thread_local int bar = qux ();  // { dg-message "'bar' was not 
initialized with a constant expression" }
case 12:
  return bar;
}
  return 0;
}

constexpr int a = foo (12);
constexpr int b = bar (12);
constexpr int c = baz (12); // { dg-error "the value of 'bar' is 
not usable in a constant expression" }
constexpr int d = corge (12);   // { dg-error "the value of 'bar' is 
not usable in a constant expression" }


2021-10-05  Jakub Jelinek  

gcc/c-family/
* c-cppbuiltin.c (c_cpp_builtins): For -std=c++23 predefine
__cpp_constexpr to 202103L rather than 201907L.
gcc/cp/
* parser.c (cp_parser_jump_statement): Implement C++23 P2242R3.
Allow goto expressions in constexpr function bodies for C++23.
Adjust error message for older standards to mention it.
* decl.c (start_decl): Allow static and thread_local declarations
in constexpr function bodies for C++23.  Adjust error message for
older standards to mention it.
* constexpr.c (ensure_literal_type_for_constexpr_object): Allow
declarations of variables with non-literal type in constexpr function
bodies for C++23.  Adjust error message for older standards to mention
it.
(cxx_eval_constant_expression) : Diagnose declarations
of initialization of static or thread_local vars.
(cxx_eval_constant_expression) : Diagnose goto
statements for C++23.
(potential_constant_expression_1) : Allow declarations
of static and thread_local vars for C++23.
(potential_constant_expression_1) : Allow labels for
C++23.
gcc/testsuite/
* g++.dg/cpp23/feat-cxx2b.C: Expect __cpp_constexpr 202103L rather
than 201907L.
* g++.dg/cpp23/constexpr-nonlit1.C: New test.
* g++.dg/cpp23/constexpr-nonlit2.C: New test.
* g++.dg/cpp23/constexpr-nonlit3.C: New test.
* g++.dg/diagnostic/constexpr1.C: Only expect some diagnostics for
c++20_down.
* g++.dg/cpp1y/constexpr-label.C: Likewise.
* g++.dg/cpp1y/constexpr-neg1.C: Likewise.
* g++.dg/cpp2a/constexpr-try5.C: Likewise.  Adjust some expected
wording.
* g++.dg/cpp2a/constexpr-dtor3.C: Likewise.
* g++.dg/cpp2a/consteval3.C: Likewise.  Add effective target c++20
and remove dg-options.

--- gcc/c-family/c-cppbuiltin.c.jj  2021-09-21 23:31:01.016248936 +0200
+++ gcc/c-family/c-cppbuiltin.c 2021-10-05 12:54:29.898321379 +0200
@@ -1052,7 +1052,8 @@ c_cpp_builtins (cpp_reader *pfile)
  cpp_define (pfile, "__cpp_init_captures=201803L");
  cpp_define (pfile, "__cpp_generic_lambdas=201707L");
  cpp_define (pfile, "__cpp_designated_initializers=201707L");
- cpp_define (pfile,