This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[C++/83739] bogus error tsubsting range for in generic lambda


When a generic lambda contains a range_for, and we're instantiating the containing function, we must rebuild a range_for. We should only convert to a regular for when tsubsting the resulting generic lambda itself.

This patch looks at processing_template_decl to determine that.

Applying to trunk.

nathan

--
Nathan Sidwell
2018-01-17  Nathan Sidwell  <nathan@acm.org>

	PR c++/83739
	* pt.c (tsubst_expr) <case RANGE_FOR_STMT>: Rebuild a range_for if
	this not a final instantiation.

	PR c++/83739
	* g++.dg/cpp1y/pr83739.C: New.

Index: cp/pt.c
===================================================================
--- cp/pt.c	(revision 256794)
+++ cp/pt.c	(working copy)
@@ -16153,26 +16153,40 @@ tsubst_expr (tree t, tree args, tsubst_f
 
     case RANGE_FOR_STMT:
       {
+	/* Construct another range_for, if this is not a final
+	   substitution (for inside inside a generic lambda of a
+	   template).  Otherwise convert to a regular for.  */
         tree decl, expr;
-        stmt = begin_for_stmt (NULL_TREE, NULL_TREE);
+        stmt = (processing_template_decl
+		? begin_range_for_stmt (NULL_TREE, NULL_TREE)
+		: begin_for_stmt (NULL_TREE, NULL_TREE));
         decl = RANGE_FOR_DECL (t);
         decl = tsubst (decl, args, complain, in_decl);
         maybe_push_decl (decl);
         expr = RECUR (RANGE_FOR_EXPR (t));
-	const unsigned short unroll
-	  = RANGE_FOR_UNROLL (t) ? tree_to_uhwi (RANGE_FOR_UNROLL (t)) : 0;
+
+	tree decomp_first = NULL_TREE;
+	unsigned decomp_cnt = 0;
 	if (VAR_P (decl) && DECL_DECOMPOSITION_P (decl))
+	  decl = tsubst_decomp_names (decl, RANGE_FOR_DECL (t), args,
+				      complain, in_decl,
+				      &decomp_first, &decomp_cnt);
+
+	if (processing_template_decl)
 	  {
-	    unsigned int cnt;
-	    tree first;
-	    decl = tsubst_decomp_names (decl, RANGE_FOR_DECL (t), args,
-					complain, in_decl, &first, &cnt);
-	    stmt = cp_convert_range_for (stmt, decl, expr, first, cnt,
-					 RANGE_FOR_IVDEP (t), unroll);
+	    RANGE_FOR_IVDEP (stmt) = RANGE_FOR_IVDEP (t);
+	    RANGE_FOR_UNROLL (stmt) = RANGE_FOR_UNROLL (t);
+	    finish_range_for_decl (stmt, decl, expr);
 	  }
 	else
-	  stmt = cp_convert_range_for (stmt, decl, expr, NULL_TREE, 0,
-				       RANGE_FOR_IVDEP (t), unroll);
+	  {
+	    unsigned short unroll = (RANGE_FOR_UNROLL (t)
+				     ? tree_to_uhwi (RANGE_FOR_UNROLL (t)) : 0);
+	    stmt = cp_convert_range_for (stmt, decl, expr,
+					 decomp_first, decomp_cnt,
+					 RANGE_FOR_IVDEP (t), unroll);
+	  }
+
 	bool prev = note_iteration_stmt_body_start ();
         RECUR (RANGE_FOR_BODY (t));
 	note_iteration_stmt_body_end (prev);
Index: testsuite/g++.dg/cpp1y/pr83739.C
===================================================================
--- testsuite/g++.dg/cpp1y/pr83739.C	(revision 0)
+++ testsuite/g++.dg/cpp1y/pr83739.C	(working copy)
@@ -0,0 +1,16 @@
+// { dg-do compile { target c++14 } }
+
+// PR 83739, deduced range-for in lambda in template
+
+template <bool> void f()
+{
+  int x[2];
+  auto delegate = [](auto & foo)
+  {
+    for (auto bar : foo);
+  };
+  delegate(x);
+}
+int main() {
+  f<true>();
+}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]