https://gcc.gnu.org/g:5c6364b09a67de8d2237f65016ea1e3365a76e8d

commit r16-968-g5c6364b09a67de8d2237f65016ea1e3365a76e8d
Author: Jason Merrill <ja...@redhat.com>
Date:   Thu May 29 12:21:28 2025 -0400

    c++: C++17 constexpr lambda and goto/static
    
    We only want the error for these cases for functions explicitly declared
    constexpr, but we still want to set invalid_constexpr on C++17 lambdas so
    maybe_save_constexpr_fundef doesn't make them implicitly constexpr.
    
    The potential_constant_expression_1 change isn't necessary for this test,
    but still seems correct.
    
    gcc/cp/ChangeLog:
    
            * decl.cc (start_decl): Also set invalid_constexpr
            for maybe_constexpr_fn.
            * parser.cc (cp_parser_jump_statement): Likewise.
            * constexpr.cc (potential_constant_expression_1): Ignore
            goto to an artificial label.
    
    gcc/testsuite/ChangeLog:
    
            * g++.dg/cpp1z/constexpr-lambda29.C: New test.

Diff:
---
 gcc/cp/constexpr.cc                             |  3 +++
 gcc/cp/decl.cc                                  | 28 +++++++++++++++----------
 gcc/cp/parser.cc                                |  7 ++++---
 gcc/testsuite/g++.dg/cpp1z/constexpr-lambda29.C | 19 +++++++++++++++++
 4 files changed, 43 insertions(+), 14 deletions(-)

diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index fa754b9a176a..272fab328968 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -10979,6 +10979,9 @@ potential_constant_expression_1 (tree t, bool 
want_rval, bool strict, bool now,
            *jump_target = *target;
            return true;
          }
+       if (DECL_ARTIFICIAL (*target))
+         /* The user didn't write this goto, this isn't the problem.  */
+         return true;
        if (flags & tf_error)
          constexpr_error (loc, fundef_p, "%<goto%> is not a constant "
                           "expression");
diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index a9ef28bfd805..ec4b6298b11a 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -6198,22 +6198,28 @@ start_decl (const cp_declarator *declarator,
     }
 
   if (current_function_decl && VAR_P (decl)
-      && DECL_DECLARED_CONSTEXPR_P (current_function_decl)
+      && maybe_constexpr_fn (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++23%> or %<-std=gnu++23%>", decl,
-                 DECL_IMMEDIATE_FUNCTION_P (current_function_decl)
-                 ? "consteval" : "constexpr");
+       {
+         if (DECL_DECLARED_CONSTEXPR_P (current_function_decl))
+           error_at (DECL_SOURCE_LOCATION (decl),
+                     "%qD defined %<thread_local%> in %qs function only "
+                     "available with %<-std=c++23%> or %<-std=gnu++23%>", 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++23%> or %<-std=gnu++23%>", decl,
-                 DECL_IMMEDIATE_FUNCTION_P (current_function_decl)
-                 ? "consteval" : "constexpr");
+       {
+         if (DECL_DECLARED_CONSTEXPR_P (current_function_decl))
+           error_at (DECL_SOURCE_LOCATION (decl),
+                     "%qD defined %<static%> in %qs function only available "
+                     "with %<-std=c++23%> or %<-std=gnu++23%>", decl,
+                     DECL_IMMEDIATE_FUNCTION_P (current_function_decl)
+                     ? "consteval" : "constexpr");
+       }
       else
        ok = true;
       if (!ok)
diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index 3e39bf33fab0..091873cbe3a9 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -15431,11 +15431,12 @@ cp_parser_jump_statement (cp_parser* parser, tree 
&std_attrs)
 
     case RID_GOTO:
       if (parser->in_function_body
-         && DECL_DECLARED_CONSTEXPR_P (current_function_decl)
+         && maybe_constexpr_fn (current_function_decl)
          && cxx_dialect < cxx23)
        {
-         error ("%<goto%> in %<constexpr%> function only available with "
-                "%<-std=c++23%> or %<-std=gnu++23%>");
+         if (DECL_DECLARED_CONSTEXPR_P (current_function_decl))
+           error ("%<goto%> in %<constexpr%> function only available with "
+                  "%<-std=c++23%> or %<-std=gnu++23%>");
          cp_function_chain->invalid_constexpr = true;
        }
 
diff --git a/gcc/testsuite/g++.dg/cpp1z/constexpr-lambda29.C 
b/gcc/testsuite/g++.dg/cpp1z/constexpr-lambda29.C
new file mode 100644
index 000000000000..9e661b6a55d4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/constexpr-lambda29.C
@@ -0,0 +1,19 @@
+// Test that we don't make lambdas with goto/static implicitly constexpr
+// when an explicitly constexpr function would be ill-formed.
+
+// { dg-do compile { target c++17 } }
+
+int main()
+{
+  constexpr int a = [] {
+    return 42;
+    goto label;
+  label:
+    return 142;
+  }();                         // { dg-error "" "" { target c++20_down } }
+
+  constexpr int b = [] {
+    return 42;
+    static int i;
+  }();                         // { dg-error "" "" { target c++20_down } }
+}

Reply via email to