Hi! I've committed (yesterday already) the following patch to trunk and 5 branch to fix an issue where tsubst_expr on OMP_CLAUSE_DECL, when a decl had non-reference dependent type, got a reference type after instantiation and tsubst_expr added convert_from_reference around it.
Bootstrapped/regtested on x86_64-linux and i686-linux. 2015-06-17 Jakub Jelinek <ja...@redhat.com> PR c++/66571 * pt.c (tsubst_omp_clause_decl): New function. (tsubst_omp_clauses): Use it or tsubst_copy instead of tsubst_expr on OMP_CLAUSE_DECL. * g++.dg/gomp/pr66571-1.C: New test. --- gcc/cp/pt.c.jj 2015-06-17 15:18:40.000000000 +0200 +++ gcc/cp/pt.c 2015-06-17 17:39:01.793799371 +0200 @@ -13490,6 +13490,32 @@ tsubst_copy (tree t, tree args, tsubst_f } } +/* Helper function for tsubst_omp_clauses, used for instantiation of + OMP_CLAUSE_DECL of clauses that handles also OpenMP array sections + represented with TREE_LIST. */ + +static tree +tsubst_omp_clause_decl (tree decl, tree args, tsubst_flags_t complain, + tree in_decl) +{ + if (TREE_CODE (decl) == TREE_LIST) + { + tree low_bound + = tsubst_expr (TREE_PURPOSE (decl), args, complain, in_decl, + /*integral_constant_expression_p=*/false); + tree length = tsubst_expr (TREE_VALUE (decl), args, complain, in_decl, + /*integral_constant_expression_p=*/false); + tree chain = tsubst_omp_clause_decl (TREE_CHAIN (decl), args, complain, + in_decl); + if (TREE_PURPOSE (decl) == low_bound + && TREE_VALUE (decl) == length + && TREE_CHAIN (decl) == chain) + return decl; + return tree_cons (low_bound, length, chain); + } + return tsubst_copy (decl, args, complain, in_decl); +} + /* Like tsubst_copy, but specifically for OpenMP clauses. */ static tree @@ -13521,16 +13547,23 @@ tsubst_omp_clauses (tree clauses, bool d case OMP_CLAUSE_FIRSTPRIVATE: case OMP_CLAUSE_COPYIN: case OMP_CLAUSE_COPYPRIVATE: + case OMP_CLAUSE_UNIFORM: + OMP_CLAUSE_DECL (nc) = tsubst_copy (OMP_CLAUSE_DECL (oc), args, + complain, in_decl); + break; + case OMP_CLAUSE_DEPEND: + case OMP_CLAUSE_FROM: + case OMP_CLAUSE_TO: + case OMP_CLAUSE_MAP: + OMP_CLAUSE_DECL (nc) + = tsubst_omp_clause_decl (OMP_CLAUSE_DECL (oc), args, complain, + in_decl); + break; case OMP_CLAUSE_IF: case OMP_CLAUSE_NUM_THREADS: case OMP_CLAUSE_SCHEDULE: case OMP_CLAUSE_COLLAPSE: case OMP_CLAUSE_FINAL: - case OMP_CLAUSE_DEPEND: - case OMP_CLAUSE_FROM: - case OMP_CLAUSE_TO: - case OMP_CLAUSE_UNIFORM: - case OMP_CLAUSE_MAP: case OMP_CLAUSE_DEVICE: case OMP_CLAUSE_DIST_SCHEDULE: case OMP_CLAUSE_NUM_TEAMS: @@ -13557,20 +13590,17 @@ tsubst_omp_clauses (tree clauses, bool d else gcc_assert (identifier_p (placeholder)); } - OMP_CLAUSE_OPERAND (nc, 0) - = tsubst_expr (OMP_CLAUSE_OPERAND (oc, 0), args, complain, - in_decl, /*integral_constant_expression_p=*/false); + OMP_CLAUSE_DECL (nc) = tsubst_copy (OMP_CLAUSE_DECL (oc), args, + complain, in_decl); break; case OMP_CLAUSE_LINEAR: case OMP_CLAUSE_ALIGNED: - OMP_CLAUSE_OPERAND (nc, 0) - = tsubst_expr (OMP_CLAUSE_OPERAND (oc, 0), args, complain, - in_decl, /*integral_constant_expression_p=*/false); + OMP_CLAUSE_DECL (nc) = tsubst_copy (OMP_CLAUSE_DECL (oc), args, + complain, in_decl); OMP_CLAUSE_OPERAND (nc, 1) = tsubst_expr (OMP_CLAUSE_OPERAND (oc, 1), args, complain, in_decl, /*integral_constant_expression_p=*/false); break; - case OMP_CLAUSE_NOWAIT: case OMP_CLAUSE_ORDERED: case OMP_CLAUSE_DEFAULT: --- gcc/testsuite/g++.dg/gomp/pr66571-1.C.jj 2015-06-17 16:44:26.401206652 +0200 +++ gcc/testsuite/g++.dg/gomp/pr66571-1.C 2015-06-17 16:44:44.487927628 +0200 @@ -0,0 +1,37 @@ +// PR c++/66571 +// { dg-do compile } +// { dg-options "-fopenmp" } + +template <typename T, typename U> +extern void bar (T, T, U); + +template <typename T, typename U> +void +foo (T a, T b, U c) +{ + #pragma omp parallel for simd shared (a, c) reduction (+:b) + for (int i = 0; i < 10; i++) + bar<T> (a, b, c); + #pragma omp target map(tofrom:a, c[0:5]) + ; + #pragma omp task depend(inout:c[4:2]) + ; + T d = a; + T e = b; + U f = c; + #pragma omp parallel for simd shared (d, f) reduction (+:e) + for (int i = 0; i < 10; i++) + bar<T> (d, e, f); + #pragma omp target map(tofrom:d, f[0:5]) + ; + #pragma omp task depend(inout:f[4:2]) + ; +} + +void +baz () +{ + int a = 0, b = 0, cb[10] = {}, *c = cb; + foo <int, int *> (a, b, c); + foo <int &, int *&> (a, b, c); +} Jakub