diff mbox series

c++: generic lambdas and local-externs from outer scopes [PR 99030]

Message ID 41bad01b-d0eb-f659-93d7-3e1cf7bedc82@acm.org
State New
Headers show
Series c++: generic lambdas and local-externs from outer scopes [PR 99030] | expand

Commit Message

Nathan Sidwell Feb. 10, 2021, 1:34 p.m. UTC
Lambdas	can refer to local externs from	their enclosing	scope.	When
the lambda's generic but the containing function is not a temploid,
we'll never have tsubsted the declaring decl so	won't have a local
specialization.	 But in	that case we can just use the decl we
tsubsting directly -- it's not dependent.

	PR c++/99030
	gcc/cp
         * pt.c (tsubst_copy) [VAR_DECL]: For a DECL_LOCAL_DECL_P T is the
         answer if there's no local specialization.
	gcc/testsuite/
         * g++.dg/lookup/pr99030.C: New.
diff mbox series

Patch

diff --git c/gcc/cp/pt.c w/gcc/cp/pt.c
index f73deb3aee3..d8574f649b2 100644
--- c/gcc/cp/pt.c
+++ w/gcc/cp/pt.c
@@ -16650,11 +16650,16 @@  tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
 	r = tsubst (t, args, complain, in_decl);
       else if (DECL_LOCAL_DECL_P (t))
 	{
-	  /* Local specialization will have been created when we
-	     instantiated the DECL_EXPR_DECL. */
+	  /* Local specialization will usually have been created when
+	     we instantiated the DECL_EXPR_DECL. */
 	  r = retrieve_local_specialization (t);
 	  if (!r)
-	    r = error_mark_node;
+	    {
+	      /* We're in a generic lambda referencing a local extern
+		 from an outer block-scope of a non-template.  */
+	      gcc_checking_assert (LAMBDA_FUNCTION_P (current_function_decl));
+	      r = t;
+	    }
 	}
       else if (local_variable_p (t)
 	       && uses_template_parms (DECL_CONTEXT (t)))
diff --git c/gcc/testsuite/g++.dg/lookup/pr99030.C w/gcc/testsuite/g++.dg/lookup/pr99030.C
new file mode 100644
index 00000000000..080847ca11c
--- /dev/null
+++ w/gcc/testsuite/g++.dg/lookup/pr99030.C
@@ -0,0 +1,16 @@ 
+// PR 99030 ICE with generic lambda accessing local extern
+// { dg-do compile { target c++14 } }
+
+void foo ()
+{
+  extern int a;
+  [] (auto b) { a; } (1);
+}
+
+template<typename T> void bar ()
+{
+  extern T a;
+  [] (auto b) { a; } (1);
+}
+
+template void bar<int> ();