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

Reply via email to