From 2105f1a796d2fa126313b6568b573af6e330ce80 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Mon, 24 Feb 2014 17:17:43 -0500 Subject: [PATCH] re PR c++/60146 (ICE when compiling this code with -fopenmp) 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 | 4 ++++ gcc/cp/pt.c | 46 ++++++++++++++++++++++++++------------ gcc/testsuite/g++.dg/gomp/for-20.C | 16 +++++++++++++ 3 files changed, 52 insertions(+), 14 deletions(-) create mode 100644 gcc/testsuite/g++.dg/gomp/for-20.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 5369ee6..20589c3 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,9 @@ 2014-02-24 Jason Merrill + 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'. diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 2dc5f32..bd59142 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -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 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 void bar() +{ +#pragma omp parallel for + for (T i = foo(); i < 8; ++i) {} +} + +void baz() +{ + bar(); +} -- 2.7.4