My earlier patch to simplify DECL_EXPR handling simplified things too
far, since the omp_for code really wants to keep control of initializing
non-class iterators. So I needed to re-complexify the code a bit.
Tested x86_64-pc-linux-gnu, applying to trunk.
commit 4929fd87044013cb0987ba95a00c01e29bdfa3a7
Author: Jason Merrill <ja...@redhat.com>
Date: Mon Feb 24 15:51:35 2014 -0500
PR c++/60146
* pt.c (tsubst_omp_for_iterator): Don't let substitution of the
DECL_EXPR initialize a non-class iterator.
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 2dc5f32..d6198c0 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -13063,31 +13063,40 @@ 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);
+ tree decl_expr = NULL_TREE;
+ if (init && TREE_CODE (init) == DECL_EXPR)
+ {
+ decl_expr = init;
+ init = DECL_INITIAL (DECL_EXPR_DECL (init));
+ decl = tsubst_decl (decl, args, complain);
+ }
+ else
+ decl = RECUR (decl);
init = RECUR (init);
- decl = RECUR (decl);
- if (decl == error_mark_node || init == error_mark_node)
- return;
-
- if (init_decl)
- {
- gcc_assert (!processing_template_decl);
- init = DECL_INITIAL (decl);
- DECL_INITIAL (decl) = NULL_TREE;
- }
+ 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 +13113,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
index 0000000..7b57b16
--- /dev/null
+++ b/gcc/testsuite/g++.dg/gomp/for-20.C
@@ -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>();
+}