re PR c++/60146 (ICE when compiling this code with -fopenmp)
authorJason Merrill <jason@redhat.com>
Mon, 24 Feb 2014 22:17:43 +0000 (17:17 -0500)
committerJason Merrill <jason@gcc.gnu.org>
Mon, 24 Feb 2014 22:17:43 +0000 (17:17 -0500)
PR c++/60146
* pt.c (tsubst_omp_for_iterator): Don't let substitution of the
DECL_EXPR initialize a non-class iterator.

From-SVN: r208094

gcc/cp/ChangeLog
gcc/cp/pt.c
gcc/testsuite/g++.dg/gomp/for-20.C [new file with mode: 0644]

index 5369ee6..20589c3 100644 (file)
@@ -1,5 +1,9 @@
 2014-02-24  Jason Merrill  <jason@redhat.com>
 
+       PR c++/60146
+       * pt.c (tsubst_omp_for_iterator): Don't let substitution of the
+       DECL_EXPR initialize a non-class iterator.
+
        PR c++/60312
        * parser.c (cp_parser_template_type_arg): Check for invalid 'auto'.
 
index 2dc5f32..bd59142 100644 (file)
@@ -13063,31 +13063,43 @@ tsubst_omp_for_iterator (tree t, int i, tree declv, tree initv,
   tsubst_expr ((NODE), args, complain, in_decl,        \
               integral_constant_expression_p)
   tree decl, init, cond, incr;
-  bool init_decl;
 
   init = TREE_VEC_ELT (OMP_FOR_INIT (t), i);
   gcc_assert (TREE_CODE (init) == MODIFY_EXPR);
   decl = TREE_OPERAND (init, 0);
   init = TREE_OPERAND (init, 1);
-  /* Do this before substituting into decl to handle 'auto'.  */
-  init_decl = (init && TREE_CODE (init) == DECL_EXPR);
-  init = RECUR (init);
-  decl = RECUR (decl);
-
-  if (decl == error_mark_node || init == error_mark_node)
-    return;
-
-  if (init_decl)
+  tree decl_expr = NULL_TREE;
+  if (init && TREE_CODE (init) == DECL_EXPR)
     {
-      gcc_assert (!processing_template_decl);
-      init = DECL_INITIAL (decl);
-      DECL_INITIAL (decl) = NULL_TREE;
+      /* We need to jump through some hoops to handle declarations in the
+        for-init-statement, since we might need to handle auto deduction,
+        but we need to keep control of initialization.  */
+      decl_expr = init;
+      init = DECL_INITIAL (DECL_EXPR_DECL (init));
+      decl = tsubst_decl (decl, args, complain);
     }
+  else
+    decl = RECUR (decl);
+  init = RECUR (init);
+
+  tree auto_node = type_uses_auto (TREE_TYPE (decl));
+  if (auto_node && init)
+    TREE_TYPE (decl)
+      = do_auto_deduction (TREE_TYPE (decl), init, auto_node);
 
   gcc_assert (!type_dependent_expression_p (decl));
 
   if (!CLASS_TYPE_P (TREE_TYPE (decl)))
     {
+      if (decl_expr)
+       {
+         /* Declare the variable, but don't let that initialize it.  */
+         tree init_sav = DECL_INITIAL (DECL_EXPR_DECL (decl_expr));
+         DECL_INITIAL (DECL_EXPR_DECL (decl_expr)) = NULL_TREE;
+         RECUR (decl_expr);
+         DECL_INITIAL (DECL_EXPR_DECL (decl_expr)) = init_sav;
+       }
+
       cond = RECUR (TREE_VEC_ELT (OMP_FOR_COND (t), i));
       incr = TREE_VEC_ELT (OMP_FOR_INCR (t), i);
       if (TREE_CODE (incr) == MODIFY_EXPR)
@@ -13104,7 +13116,13 @@ tsubst_omp_for_iterator (tree t, int i, tree declv, tree initv,
       return;
     }
 
-  if (init && !init_decl)
+  if (decl_expr)
+    {
+      /* Declare and initialize the variable.  */
+      RECUR (decl_expr);
+      init = NULL_TREE;
+    }
+  else if (init)
     {
       tree c;
       for (c = *clauses; c ; c = OMP_CLAUSE_CHAIN (c))
diff --git a/gcc/testsuite/g++.dg/gomp/for-20.C b/gcc/testsuite/g++.dg/gomp/for-20.C
new file mode 100644 (file)
index 0000000..7b57b16
--- /dev/null
@@ -0,0 +1,16 @@
+// PR c++/60146
+// { dg-do compile }
+// { dg-options -fopenmp }
+
+int foo() { return 0; }
+
+template<typename T> void bar()
+{
+#pragma omp parallel for
+  for (T i = foo(); i < 8; ++i) {}
+}
+
+void baz()
+{
+  bar<int>();
+}