]> git.ipfire.org Git - people/ms/gcc.git/commitdiff
c++: generic lambda in template fn with DMI [PR100054]
authorJason Merrill <jason@redhat.com>
Tue, 13 Apr 2021 16:33:39 +0000 (12:33 -0400)
committerJason Merrill <jason@redhat.com>
Tue, 13 Apr 2021 18:01:50 +0000 (14:01 -0400)
get_nsdmi instantiates default member initializers on demand.  It tries to
push into the context of the class before doing so, so access checking works
properly, but since my patch for 90479 not for local classes.  We should
only be doing this when any template parameters have arguments.  But in this
case, we get here while regenerating a generic lambda, so
processing_template_decl is true, even though the class and its DMI are
non-dependent at this point.  And so we crashed.  So let's do more of the
pushing into the context of the class even for local classes.

gcc/cp/ChangeLog:

PR c++/100054
PR c++/90479
* init.c (get_nsdmi): Do more context adjustment for local classes.

gcc/testsuite/ChangeLog:

PR c++/100054
* g++.dg/cpp1y/lambda-generic-local-class1.C: New test.

gcc/cp/init.c
gcc/testsuite/g++.dg/cpp1y/lambda-generic-local-class1.C [new file with mode: 0644]

index 91b45a1a69511600ac4da7e1705af5e167cb190b..a85f4d507501bec257e1f4ea1dd2526e2922491d 100644 (file)
@@ -586,17 +586,21 @@ get_nsdmi (tree member, bool in_ctor, tsubst_flags_t complain)
 
          bool pushed = false;
          tree ctx = DECL_CONTEXT (member);
-         if (!currently_open_class (ctx)
-             && !LOCAL_CLASS_P (ctx))
+
+         processing_template_decl_sentinel ptds (/*reset*/false);
+         if (!currently_open_class (ctx))
            {
-             push_to_top_level ();
+             if (!LOCAL_CLASS_P (ctx))
+               push_to_top_level ();
+             else
+               /* push_to_top_level would lose the necessary function context,
+                  just reset processing_template_decl.  */
+               processing_template_decl = 0;
              push_nested_class (ctx);
              push_deferring_access_checks (dk_no_deferred);
              pushed = true;
            }
 
-         gcc_checking_assert (!processing_template_decl);
-
          inject_this_parameter (ctx, TYPE_UNQUALIFIED);
 
          start_lambda_scope (member);
@@ -619,7 +623,8 @@ get_nsdmi (tree member, bool in_ctor, tsubst_flags_t complain)
            {
              pop_deferring_access_checks ();
              pop_nested_class ();
-             pop_from_top_level ();
+             if (!LOCAL_CLASS_P (ctx))
+               pop_from_top_level ();
            }
 
          input_location = sloc;
diff --git a/gcc/testsuite/g++.dg/cpp1y/lambda-generic-local-class1.C b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-local-class1.C
new file mode 100644 (file)
index 0000000..7498327
--- /dev/null
@@ -0,0 +1,10 @@
+// PR c++/100054
+// { dg-do compile { target c++14 } }
+
+template <class T>
+void f() {
+  struct A { T m{}; };
+  [](auto){ return A{}; };
+}
+
+template void f<int>();