Hi! For the way we implement task reductions, making it work with zero sized aggregates is impossible and those aren't really useful anyway. The patch also disallows reductions on variable sized structures for the same reason, but when trying to add test coverage for that I've discovered we don't handle them properly even in the privatization clauses, so ++todo for later.
Committed to gomp-5_0-branch. 2018-10-17 Jakub Jelinek <ja...@redhat.com> * c-parser.c (c_finish_taskloop_clauses): New function. (c_parser_omp_taskloop): Use it. * c-typeck.c (c_finish_omp_clauses): Call save_expr for whole array reduction sizes. Diagnose reductions with zero sized elements or variable length structures. * semantics.c (finish_omp_reduction_clause): Call save_expr for whole array reduction sizes. * gcc.dg/gomp/reduction-2.c: New test. --- gcc/c/c-parser.c.jj 2018-08-02 14:14:40.138818877 +0200 +++ gcc/c/c-parser.c 2018-10-17 11:49:04.527491213 +0200 @@ -18823,6 +18823,41 @@ c_parser_omp_requires (c_parser *parser) error_at (loc, "%<pragma omp requires%> requires at least one clause"); } +/* Helper function for c_parser_omp_taskloop. + Disallow zero sized or potentially zero sized task reductions. */ + +static tree +c_finish_taskloop_clauses (tree clauses) +{ + tree *pc = &clauses; + for (tree c = clauses; c; c = *pc) + { + bool remove = false; + if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION) + { + tree type = strip_array_types (TREE_TYPE (OMP_CLAUSE_DECL (c))); + if (integer_zerop (TYPE_SIZE_UNIT (type))) + { + error_at (OMP_CLAUSE_LOCATION (c), + "zero sized type %qT in %<reduction%> clause", type); + remove = true; + } + else if (TREE_CODE (TYPE_SIZE_UNIT (type)) != INTEGER_CST) + { + error_at (OMP_CLAUSE_LOCATION (c), + "variable sized type %qT in %<reduction%> clause", + type); + remove = true; + } + } + if (remove) + *pc = OMP_CLAUSE_CHAIN (c); + else + pc = &OMP_CLAUSE_CHAIN (c); + } + return clauses; +} + /* OpenMP 4.5: #pragma omp taskloop taskloop-clause[optseq] new-line for-loop @@ -18880,6 +18915,8 @@ c_parser_omp_taskloop (location_t loc, c TREE_TYPE (ret) = void_type_node; OMP_FOR_BODY (ret) = block; OMP_FOR_CLAUSES (ret) = cclauses[C_OMP_CLAUSE_SPLIT_TASKLOOP]; + OMP_FOR_CLAUSES (ret) + = c_finish_taskloop_clauses (OMP_FOR_CLAUSES (ret)); SET_EXPR_LOCATION (ret, loc); add_stmt (ret); return ret; @@ -18898,6 +18935,7 @@ c_parser_omp_taskloop (location_t loc, c clauses = cclauses[C_OMP_CLAUSE_SPLIT_TASKLOOP]; } + clauses = c_finish_taskloop_clauses (clauses); block = c_begin_compound_stmt (true); ret = c_parser_omp_for_loop (loc, parser, OMP_TASKLOOP, clauses, NULL, if_p); block = c_end_compound_stmt (loc, block, true); --- gcc/c/c-typeck.c.jj 2018-10-16 15:19:10.702681542 +0200 +++ gcc/c/c-typeck.c 2018-10-17 11:17:22.339930169 +0200 @@ -13343,6 +13343,7 @@ c_finish_omp_clauses (tree clauses, enum break; } size = size_binop (MINUS_EXPR, size, size_one_node); + size = save_expr (size); tree index_type = build_index_type (size); tree atype = build_array_type (type, index_type); tree ptype = build_pointer_type (type); @@ -13358,6 +13359,28 @@ c_finish_omp_clauses (tree clauses, enum remove = true; break; } + if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION + || OMP_CLAUSE_REDUCTION_TASK (c)) + { + /* Disallow zero sized or potentially zero sized task + reductions. */ + if (integer_zerop (TYPE_SIZE_UNIT (type))) + { + error_at (OMP_CLAUSE_LOCATION (c), + "zero sized type %qT in %qs clause", type, + omp_clause_code_name[OMP_CLAUSE_CODE (c)]); + remove = true; + break; + } + else if (TREE_CODE (TYPE_SIZE_UNIT (type)) != INTEGER_CST) + { + error_at (OMP_CLAUSE_LOCATION (c), + "variable sized type %qT in %qs clause", type, + omp_clause_code_name[OMP_CLAUSE_CODE (c)]); + remove = true; + break; + } + } if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) == NULL_TREE && (FLOAT_TYPE_P (type) || TREE_CODE (type) == COMPLEX_TYPE)) --- gcc/cp/semantics.c.jj 2018-10-16 15:29:14.154644851 +0200 +++ gcc/cp/semantics.c 2018-10-17 10:59:59.558752697 +0200 @@ -5567,6 +5567,7 @@ finish_omp_reduction_clause (tree c, boo return true; } size = size_binop (MINUS_EXPR, size, size_one_node); + size = save_expr (size); tree index_type = build_index_type (size); tree atype = build_array_type (type, index_type); tree ptype = build_pointer_type (type); --- gcc/testsuite/gcc.dg/gomp/reduction-2.c.jj 2018-10-17 12:39:16.031574352 +0200 +++ gcc/testsuite/gcc.dg/gomp/reduction-2.c 2018-10-17 12:07:28.163688735 +0200 @@ -0,0 +1,30 @@ +/* { dg-do compile } */ +/* { dg-options "-fopenmp" } */ + +struct S {}; +void foo (void *, void *); +void bar (void *, void *); +void baz (void *); +#pragma omp declare reduction(+:struct S:foo (&omp_out, &omp_in))initializer(bar(&omp_priv, &omp_orig)) + +void +test1 (void) +{ + struct S s; + int i; + #pragma omp parallel reduction(+:s) + baz (&s); + #pragma omp parallel reduction(task, +:s) /* { dg-error "zero sized type 'struct S' in 'reduction' clause" } */ + baz (&s); + #pragma omp taskloop reduction(+:s) /* { dg-error "zero sized type 'struct S' in 'reduction' clause" } */ + for (i = 0; i < 1; i++) + baz (&s); + #pragma omp taskloop simd reduction(+:s) /* { dg-error "zero sized type 'struct S' in 'reduction' clause" } */ + for (i = 0; i < 1; i++) + baz (&s); + #pragma omp taskgroup task_reduction(+:s) /* { dg-error "zero sized type 'struct S' in 'task_reduction' clause" } */ + { + #pragma omp task in_reduction(+:s) /* { dg-error "zero sized type 'struct S' in 'in_reduction' clause" } */ + baz (&s); + } +} Jakub