Hi! During template instantiation, it is hard to find out if the inner combined loop construct is invalid and to remove the outer construct in that case too. So, this patch instead deals with that during gimplification.
Bootstrapped/regtested on x86_64-linux and i686-linux, committed to trunk and 5 branch. 2015-09-10 Jakub Jelinek <ja...@redhat.com> PR c++/67523 * gimplify.c (gimplify_omp_for): If inner stmt is not found for combined loop, assert seen_error () and return GS_ERROR. * g++.dg/gomp/pr67523.C: New test. --- gcc/gimplify.c.jj 2015-09-09 16:23:24.000000000 +0200 +++ gcc/gimplify.c 2015-09-09 18:11:18.541834564 +0200 @@ -7001,7 +7001,7 @@ find_combined_omp_for (tree *tp, int *wa static enum gimplify_status gimplify_omp_for (tree *expr_p, gimple_seq *pre_p) { - tree for_stmt, orig_for_stmt, decl, var, t; + tree for_stmt, orig_for_stmt, inner_for_stmt = NULL_TREE, decl, var, t; enum gimplify_status ret = GS_ALL_DONE; enum gimplify_status tret; gomp_for *gfor; @@ -7044,6 +7044,19 @@ gimplify_omp_for (tree *expr_p, gimple_s } } + if (OMP_FOR_INIT (for_stmt) == NULL_TREE) + { + gcc_assert (TREE_CODE (for_stmt) != OACC_LOOP); + inner_for_stmt = walk_tree (&OMP_FOR_BODY (for_stmt), + find_combined_omp_for, NULL, NULL); + if (inner_for_stmt == NULL_TREE) + { + gcc_assert (seen_error ()); + *expr_p = NULL_TREE; + return GS_ERROR; + } + } + gimplify_scan_omp_clauses (&OMP_FOR_CLAUSES (for_stmt), pre_p, simd ? ORT_SIMD : ORT_WORKSHARE); if (TREE_CODE (for_stmt) == OMP_DISTRIBUTE) @@ -7079,10 +7092,7 @@ gimplify_omp_for (tree *expr_p, gimple_s if (OMP_FOR_INIT (for_stmt) == NULL_TREE) { - gcc_assert (TREE_CODE (for_stmt) != OACC_LOOP); - for_stmt = walk_tree (&OMP_FOR_BODY (for_stmt), find_combined_omp_for, - NULL, NULL); - gcc_assert (for_stmt != NULL_TREE); + for_stmt = inner_for_stmt; gimplify_omp_ctxp->combined_loop = true; } --- gcc/testsuite/g++.dg/gomp/pr67523.C.jj 2015-09-09 18:35:45.333308064 +0200 +++ gcc/testsuite/g++.dg/gomp/pr67523.C 2015-09-09 18:35:24.000000000 +0200 @@ -0,0 +1,29 @@ +// PR c++/67523 +// { dg-do compile } +// { dg-options "-fopenmp" } + +struct S { int s; }; + +template <typename T> +void foo (T &x, T &y) +{ +#pragma omp for simd + for (T i = x; i < y; i++) // { dg-error "used with class iteration variable" } + ; +#pragma omp parallel for simd + for (T i = x; i < y; i++) // { dg-error "used with class iteration variable" } + ; +#pragma omp target teams distribute parallel for simd + for (T i = x; i < y; i++) // { dg-error "used with class iteration variable" } + ; +#pragma omp target teams distribute simd + for (T i = x; i < y; i++) // { dg-error "used with class iteration variable" } + ; +} + +void +bar () +{ + S x, y; + foo <S> (x, y); +} Jakub