[C++/83739] bogus error tsubsting range for in generic lambda
authorNathan Sidwell <nathan@acm.org>
Wed, 17 Jan 2018 15:39:35 +0000 (15:39 +0000)
committerNathan Sidwell <nathan@gcc.gnu.org>
Wed, 17 Jan 2018 15:39:35 +0000 (15:39 +0000)
https://gcc.gnu.org/ml/gcc-patches/2018-01/msg01554.html
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.

From-SVN: r256795

gcc/cp/ChangeLog
gcc/cp/pt.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp1y/pr83739.C [new file with mode: 0644]

index d378cb2ff3fb144252624990f360cd303b6442eb..9a48abab6af198889b77f21d94e29950edeb0093 100644 (file)
@@ -1,3 +1,9 @@
+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.
+
 2018-01-16  Jason Merrill  <jason@redhat.com>
 
        PR c++/83714 - ICE checking return in template.
index 322408d92ec286a9a19de5dd28d2725ac0e491fb..01778820793a4fa90b47a732487eafa8060b06ce 100644 (file)
@@ -16153,26 +16153,40 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
 
     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 a577e6f88d50fa2dca439c34653c7ad347ff7dd2..04a1ffcc8824a806320e18a7732c0d0383d1aeb8 100644 (file)
@@ -1,3 +1,8 @@
+2018-01-17  Nathan Sidwell  <nathan@acm.org>
+
+       PR c++/83739
+       * g++.dg/cpp1y/pr83739.C: New.
+
 2018-01-17  Eric Botcazou  <ebotcazou@adacore.com>
 
        * gcc.target/visium/overflow8.c: Pass -fno-if-conversion.
diff --git a/gcc/testsuite/g++.dg/cpp1y/pr83739.C b/gcc/testsuite/g++.dg/cpp1y/pr83739.C
new file mode 100644 (file)
index 0000000..4761220
--- /dev/null
@@ -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>();
+}