A recent change of mine caused auto to persist until instantiation time
in more cases, and the OMP for instantiation code wasn't prepared to
deal with that. This patch simplifies the handling of the for-init-expr
in an OMP loop by processing the DECL_EXPR right away, rather than
trying to split handling it between tsubst_omp_for_iterator and tsubst_expr.
All the tests in the libgomp and gcc testsuites pass with this patch,
but I'm not very confident about it because I don't fully understand
what the code is doing. In particular, I'm not sure what the condition
controlling the code in tsubst_omp_for_iterator that looks at the
clauses should be; init can never be a DECL_EXPR at that point anymore.
I'm also not sure whether moving the begin_omp_structured_block is
necessary, but it seemed like a good idea since we're handling the
DECL_EXPR earlier.
Does this make sense to you?
commit a31dd0fa43b7d0d75e18b566501c3dad6f477e2b
Author: Jason Merrill <ja...@redhat.com>
Date: Wed Jun 20 19:16:01 2012 -0700
PR c++/53565
* pt.c (tsubst_omp_for_iterator): Simplify DECL_EXPR handling.
(tsubst_expr) [OMP_FOR]: Here, too.
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 5e02c8c..cec244a 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -12659,22 +12659,23 @@ tsubst_omp_for_iterator (tree t, int i, tree declv, tree initv,
#define RECUR(NODE) \
tsubst_expr ((NODE), args, complain, in_decl, \
integral_constant_expression_p)
- tree decl, init, cond, incr, auto_node;
+ 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 = RECUR (TREE_OPERAND (init, 0));
+ decl = TREE_OPERAND (init, 0);
init = TREE_OPERAND (init, 1);
- auto_node = type_uses_auto (TREE_TYPE (decl));
- if (auto_node && init)
+ init_decl = (init && TREE_CODE (init) == DECL_EXPR);
+ /* Do this before substituting into decl to handle 'auto'. */
+ init = RECUR (init);
+ decl = RECUR (decl);
+ if (init_decl)
{
- tree init_expr = init;
- if (TREE_CODE (init_expr) == DECL_EXPR)
- init_expr = DECL_INITIAL (DECL_EXPR_DECL (init_expr));
- init_expr = RECUR (init_expr);
- TREE_TYPE (decl)
- = do_auto_deduction (TREE_TYPE (decl), init_expr, auto_node);
+ gcc_assert (!processing_template_decl);
+ init = DECL_INITIAL (decl);
}
+
gcc_assert (!type_dependent_expression_p (decl));
if (!CLASS_TYPE_P (TREE_TYPE (decl)))
@@ -13189,34 +13190,13 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
condv = make_tree_vec (TREE_VEC_LENGTH (OMP_FOR_INIT (t)));
incrv = make_tree_vec (TREE_VEC_LENGTH (OMP_FOR_INIT (t)));
+ stmt = begin_omp_structured_block ();
+
for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (t)); i++)
tsubst_omp_for_iterator (t, i, declv, initv, condv, incrv,
&clauses, args, complain, in_decl,
integral_constant_expression_p);
- stmt = begin_omp_structured_block ();
-
- for (i = 0; i < TREE_VEC_LENGTH (initv); i++)
- if (TREE_VEC_ELT (initv, i) == NULL
- || TREE_CODE (TREE_VEC_ELT (initv, i)) != DECL_EXPR)
- TREE_VEC_ELT (initv, i) = RECUR (TREE_VEC_ELT (initv, i));
- else if (CLASS_TYPE_P (TREE_TYPE (TREE_VEC_ELT (initv, i))))
- {
- tree init = RECUR (TREE_VEC_ELT (initv, i));
- gcc_assert (init == TREE_VEC_ELT (declv, i));
- TREE_VEC_ELT (initv, i) = NULL_TREE;
- }
- else
- {
- tree decl_expr = TREE_VEC_ELT (initv, i);
- tree init = DECL_INITIAL (DECL_EXPR_DECL (decl_expr));
- gcc_assert (init != NULL);
- TREE_VEC_ELT (initv, i) = RECUR (init);
- DECL_INITIAL (DECL_EXPR_DECL (decl_expr)) = NULL;
- RECUR (decl_expr);
- DECL_INITIAL (DECL_EXPR_DECL (decl_expr)) = init;
- }
-
pre_body = push_stmt_list ();
RECUR (OMP_FOR_PRE_BODY (t));
pre_body = pop_stmt_list (pre_body);
diff --git a/gcc/testsuite/g++.dg/gomp/for-19.C b/gcc/testsuite/g++.dg/gomp/for-19.C
index 7c56719..4441a29 100644
--- a/gcc/testsuite/g++.dg/gomp/for-19.C
+++ b/gcc/testsuite/g++.dg/gomp/for-19.C
@@ -26,8 +26,8 @@ template <typename T>
void
f3 (void)
{
-#pragma omp for // { dg-error "forbids incrementing a pointer of type" }
- for (T q = T (p); q < T (p + 4); q++)
+#pragma omp for
+ for (T q = T (p); q < T (p + 4); q++) // { dg-error "forbids incrementing a pointer of type" }
;
}