From c6e24cf840a55e6f0c83daa510b7b5c11a9fcabd Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Sat, 1 Mar 2014 13:43:24 -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. Conflicts: gcc/cp/pt.c From-SVN: r208244 --- gcc/cp/ChangeLog | 6 +++++ gcc/cp/pt.c | 42 +++++++++++++++++++++++------- gcc/testsuite/g++.dg/gomp/for-20.C | 16 ++++++++++++ 3 files changed, 54 insertions(+), 10 deletions(-) create mode 100644 gcc/testsuite/g++.dg/gomp/for-20.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 1f45ee80c2bd..f4d3b653a546 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +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. + 2014-02-24 Fabien Chêne PR c++/37140 * parser.c (cp_parser_nonclass_name): Call strip_using_decl and diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index b63b3d9cab19..e99dbfff7760 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -12703,27 +12703,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 (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) @@ -12740,7 +12756,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 000000000000..7b57b16b85f9 --- /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.47.2