diff mbox

C++ PATCH for c++/67041 (auto variable template and lambda)

Message ID 55EF3769.8070902@redhat.com
State New
Headers show

Commit Message

Jason Merrill Sept. 8, 2015, 7:30 p.m. UTC
If the lambda mangling scope is a variable, we don't want to call 
tsubst_copy on it, as that will call mark_used.  Use plain tsubst instead.

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

Patch

commit 60cf545572ad4214d70e99808f53312db592e341
Author: Jason Merrill <jason@redhat.com>
Date:   Tue Sep 8 09:47:18 2015 -0400

    	PR c++/67350
    	* pt.c (tsubst_copy_and_build): Handle variables like functions.

diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index ec32c5a..16ed1b5 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -16320,15 +16320,14 @@  tsubst_copy_and_build (tree t,
 	LAMBDA_EXPR_MUTABLE_P (r) = LAMBDA_EXPR_MUTABLE_P (t);
 	LAMBDA_EXPR_DISCRIMINATOR (r)
 	  = (LAMBDA_EXPR_DISCRIMINATOR (t));
-	/* For a function scope, we want to use tsubst so that we don't
-	   complain about referring to an auto function before its return
-	   type has been deduced.  Otherwise, we want to use tsubst_copy so
-	   that we look up the existing field/parameter/variable rather
-	   than build a new one.  */
 	tree scope = LAMBDA_EXPR_EXTRA_SCOPE (t);
-	if (scope && TREE_CODE (scope) == FUNCTION_DECL)
+	if (!scope)
+	  /* No substitution needed.  */;
+	else if (VAR_OR_FUNCTION_DECL_P (scope))
+	  /* For a function or variable scope, we want to use tsubst so that we
+	     don't complain about referring to an auto before deduction.  */
 	  scope = tsubst (scope, args, complain, in_decl);
-	else if (scope && TREE_CODE (scope) == PARM_DECL)
+	else if (TREE_CODE (scope) == PARM_DECL)
 	  {
 	    /* Look up the parameter we want directly, as tsubst_copy
 	       doesn't do what we need.  */
@@ -16341,8 +16340,12 @@  tsubst_copy_and_build (tree t,
 	    if (DECL_CONTEXT (scope) == NULL_TREE)
 	      DECL_CONTEXT (scope) = fn;
 	  }
-	else
+	else if (TREE_CODE (scope) == FIELD_DECL)
+	  /* For a field, use tsubst_copy so that we look up the existing field
+	     rather than build a new one.  */
 	  scope = RECUR (scope);
+	else
+	  gcc_unreachable ();
 	LAMBDA_EXPR_EXTRA_SCOPE (r) = scope;
 	LAMBDA_EXPR_RETURN_TYPE (r)
 	  = tsubst (LAMBDA_EXPR_RETURN_TYPE (t), args, complain, in_decl);
diff --git a/gcc/testsuite/g++.dg/cpp1y/lambda-var-templ1.C b/gcc/testsuite/g++.dg/cpp1y/lambda-var-templ1.C
new file mode 100644
index 0000000..adc1af1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/lambda-var-templ1.C
@@ -0,0 +1,11 @@ 
+// PR c++/67350
+// { dg-do compile { target c++14 } }
+
+template<typename T>
+auto test = [](){
+    return T{};
+};
+
+int main() {
+    test<int>();
+}