Tested x86_64-pc-linux-gnu, applying to trunk.

-- 8< --

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                           |  3 ++
 gcc/cp/decl.cc                                | 28 +++++++++++--------
 gcc/cp/parser.cc                              |  7 +++--
 .../g++.dg/cpp1z/constexpr-lambda29.C         | 19 +++++++++++++
 4 files changed, 43 insertions(+), 14 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp1z/constexpr-lambda29.C

diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index fa754b9a176..272fab32896 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 a9ef28bfd80..ec4b6298b11 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 3e39bf33fab..091873cbe3a 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 00000000000..9e661b6a55d
--- /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 } }
+}

base-commit: c69afa2f1bd7455457ab4e028a6bc51211b2dd20
-- 
2.49.0

Reply via email to