]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
c++: C++17 constexpr lambda and goto/static
authorJason Merrill <jason@redhat.com>
Thu, 29 May 2025 16:21:28 +0000 (12:21 -0400)
committerJason Merrill <jason@redhat.com>
Thu, 29 May 2025 17:46:00 +0000 (13:46 -0400)
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.

gcc/cp/constexpr.cc
gcc/cp/decl.cc
gcc/cp/parser.cc
gcc/testsuite/g++.dg/cpp1z/constexpr-lambda29.C [new file with mode: 0644]

index fa754b9a176a7b8068992fedbfe4ee2acce0d386..272fab328968e2efb9b373378c026ad85ea7f169 100644 (file)
@@ -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");
index a9ef28bfd80510538b793879902086310713a706..ec4b6298b11a8d7eec4f6c1ca58d982d257c9a76 100644 (file)
@@ -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)
index 3e39bf33fab0e695ce59001158a0d5b164f1ad16..091873cbe3a9fd33160810b5cf7770362d2f91ab 100644 (file)
@@ -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 (file)
index 0000000..9e661b6
--- /dev/null
@@ -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 } }
+}