c++: Fix late-parsed default arg context
authorJason Merrill <jason@redhat.com>
Wed, 2 Dec 2020 19:35:50 +0000 (14:35 -0500)
committerJason Merrill <jason@redhat.com>
Thu, 3 Dec 2020 03:15:48 +0000 (22:15 -0500)
Jakub noticed that we weren't recognizing a default argument for a consteval
member function as being in immediate function context because there was no
function parameter scope to look at.

Note that this patch doesn't actually push the parameters into the scope,
that happens in a separate commit.

gcc/cp/ChangeLog:

* name-lookup.c (begin_scope): Set immediate_fn_ctx_p.
* parser.c (cp_parser_late_parsing_default_args): Push
sk_function_parms scope.

gcc/testsuite/ChangeLog:

* g++.dg/cpp2a/consteval-defarg1.C: New test.

gcc/cp/name-lookup.c
gcc/cp/parser.c
gcc/testsuite/g++.dg/cpp2a/consteval-defarg1.C [new file with mode: 0644]

index 837c0ea89af40f07fa164ff5193d9dbc70150c82..c87d151b4418c226b13e6bce9cd7eeffdb34d21e 100644 (file)
@@ -3291,12 +3291,17 @@ begin_scope (scope_kind kind, tree entity)
     case sk_cond:
     case sk_class:
     case sk_scoped_enum:
-    case sk_function_parms:
     case sk_transaction:
     case sk_omp:
       scope->keep = keep_next_level_flag;
       break;
 
+    case sk_function_parms:
+      scope->keep = keep_next_level_flag;
+      if (entity)
+       scope->immediate_fn_ctx_p = DECL_IMMEDIATE_FUNCTION_P (entity);
+      break;
+
     case sk_namespace:
       NAMESPACE_LEVEL (entity) = scope;
       break;
index 52743b03be29146d2604003f3e373d030a4b0b2f..a8e86cf250db980790decd79e0d177e29e5c8f01 100644 (file)
@@ -30566,6 +30566,8 @@ cp_parser_late_parsing_default_args (cp_parser *parser, tree fn)
 
   push_defarg_context (fn);
 
+  begin_scope (sk_function_parms, fn);
+
   for (parm = TYPE_ARG_TYPES (TREE_TYPE (fn)),
         parmdecl = DECL_ARGUMENTS (fn);
        parm && parm != void_list_node;
@@ -30598,6 +30600,8 @@ cp_parser_late_parsing_default_args (cp_parser *parser, tree fn)
        TREE_PURPOSE (copy) = parsed_arg;
     }
 
+  pop_bindings_and_leave_scope ();
+
   pop_defarg_context ();
 
   /* Make sure no default arg is missing.  */
diff --git a/gcc/testsuite/g++.dg/cpp2a/consteval-defarg1.C b/gcc/testsuite/g++.dg/cpp2a/consteval-defarg1.C
new file mode 100644 (file)
index 0000000..826ee25
--- /dev/null
@@ -0,0 +1,11 @@
+// Test that late-parsed default args have the same consteval semantics.
+// { dg-do compile { target c++20 } }
+
+consteval bool foo (bool x) { if (x) throw 1; return false; }
+consteval bool bar (bool x = foo (true)) { return true; }
+struct S
+{
+  consteval static bool baz (bool x = foo (true)) { return true; }
+};
+constexpr bool a = bar (true);
+constexpr bool b = S::baz (true);