]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
'omp scan' struct block seq update for OpenMP 5.x
authorTobias Burnus <tobias@codesourcery.com>
Tue, 25 Apr 2023 14:29:14 +0000 (16:29 +0200)
committerTobias Burnus <tobias@codesourcery.com>
Tue, 25 Apr 2023 14:29:14 +0000 (16:29 +0200)
While OpenMP 5.0 required a single structured block before and after the
'omp scan' directive, OpenMP 5.1 changed this to a 'structured block sequence,
denoting 2 or more executable statements in OpenMP 5.1 (whoops!) and zero or
more in OpenMP 5.2. This commit updates C/C++ to accept zero statements (but
till requires the '{' ... '}' for the final-loop-body) and updates Fortran
to accept zero or more than one statements.

If there is no preceeding or succeeding executable statement, a warning is
shown.

gcc/c/ChangeLog:

* c-parser.cc (c_parser_omp_scan_loop_body): Handle
zero exec statements before/after 'omp scan'.

gcc/cp/ChangeLog:

* parser.cc (cp_parser_omp_scan_loop_body): Handle
zero exec statements before/after 'omp scan'.

gcc/fortran/ChangeLog:

* openmp.cc (gfc_resolve_omp_do_blocks): Handle zero
or more than one exec statements before/after 'omp scan'.
* trans-openmp.cc (gfc_trans_omp_do): Likewise.

libgomp/ChangeLog:

* testsuite/libgomp.c-c++-common/scan-1.c: New test.
* testsuite/libgomp.c/scan-23.c: New test.
* testsuite/libgomp.fortran/scan-2.f90: New test.

gcc/testsuite/ChangeLog:

* g++.dg/gomp/attrs-7.C: Update dg-error/dg-warning.
* gfortran.dg/gomp/loop-2.f90: Likewise.
* gfortran.dg/gomp/reduction5.f90: Likewise.
* gfortran.dg/gomp/reduction6.f90: Likewise.
* gfortran.dg/gomp/scan-1.f90: Likewise.
* gfortran.dg/gomp/taskloop-2.f90: Likewise.
* c-c++-common/gomp/scan-6.c: New test.
* gfortran.dg/gomp/scan-8.f90: New test.

15 files changed:
gcc/c/c-parser.cc
gcc/cp/parser.cc
gcc/fortran/openmp.cc
gcc/fortran/trans-openmp.cc
gcc/testsuite/c-c++-common/gomp/scan-6.c [new file with mode: 0644]
gcc/testsuite/g++.dg/gomp/attrs-7.C
gcc/testsuite/gfortran.dg/gomp/loop-2.f90
gcc/testsuite/gfortran.dg/gomp/reduction5.f90
gcc/testsuite/gfortran.dg/gomp/reduction6.f90
gcc/testsuite/gfortran.dg/gomp/scan-1.f90
gcc/testsuite/gfortran.dg/gomp/scan-8.f90 [new file with mode: 0644]
gcc/testsuite/gfortran.dg/gomp/taskloop-2.f90
libgomp/testsuite/libgomp.c-c++-common/scan-1.c [new file with mode: 0644]
libgomp/testsuite/libgomp.c/scan-23.c [new file with mode: 0644]
libgomp/testsuite/libgomp.fortran/scan-2.f90 [new file with mode: 0644]

index 21bc3167ce224823c214efc064be399f2da9c787..9398c7a5271501332a1b8b09e26002ba33c0feb2 100644 (file)
@@ -20112,6 +20112,7 @@ c_parser_omp_scan_loop_body (c_parser *parser, bool open_brace_parsed)
   tree substmt;
   location_t loc;
   tree clauses = NULL_TREE;
+  bool found_scan = false;
 
   loc = c_parser_peek_token (parser)->location;
   if (!open_brace_parsed
@@ -20122,7 +20123,15 @@ c_parser_omp_scan_loop_body (c_parser *parser, bool open_brace_parsed)
       return;
     }
 
-  substmt = c_parser_omp_structured_block_sequence (parser, PRAGMA_OMP_SCAN);
+  if (c_parser_peek_token (parser)->pragma_kind != PRAGMA_OMP_SCAN)
+    substmt = c_parser_omp_structured_block_sequence (parser, PRAGMA_OMP_SCAN);
+  else
+    {
+      warning_at (c_parser_peek_token (parser)->location, 0,
+                 "%<#pragma omp scan%> with zero preceding executable "
+                 "statements");
+      substmt = build_empty_stmt (loc);
+    }
   substmt = build2 (OMP_SCAN, void_type_node, substmt, NULL_TREE);
   SET_EXPR_LOCATION (substmt, loc);
   add_stmt (substmt);
@@ -20131,6 +20140,7 @@ c_parser_omp_scan_loop_body (c_parser *parser, bool open_brace_parsed)
   if (c_parser_peek_token (parser)->pragma_kind == PRAGMA_OMP_SCAN)
     {
       enum omp_clause_code clause = OMP_CLAUSE_ERROR;
+      found_scan = true;
 
       c_parser_consume_pragma (parser);
 
@@ -20160,7 +20170,15 @@ c_parser_omp_scan_loop_body (c_parser *parser, bool open_brace_parsed)
     error ("expected %<#pragma omp scan%>");
 
   clauses = c_finish_omp_clauses (clauses, C_ORT_OMP);
-  substmt = c_parser_omp_structured_block_sequence (parser, PRAGMA_NONE);
+  if (!c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
+    substmt = c_parser_omp_structured_block_sequence (parser, PRAGMA_NONE);
+  else
+    {
+      if (found_scan)
+       warning_at (loc, 0, "%<#pragma omp scan%> with zero succeeding "
+                           "executable statements");
+      substmt = build_empty_stmt (loc);
+    }
   substmt = build2 (OMP_SCAN, void_type_node, substmt, clauses);
   SET_EXPR_LOCATION (substmt, loc);
   add_stmt (substmt);
index e5f032f2330b629374b553e87366ccd9aae9bdd9..d89553e7da81d64a6390c385e009b4ff07b5da58 100644 (file)
@@ -43553,19 +43553,29 @@ static void
 cp_parser_omp_scan_loop_body (cp_parser *parser)
 {
   tree substmt, clauses = NULL_TREE;
+  bool found_scan = false;
 
   matching_braces braces;
   if (!braces.require_open (parser))
     return;
 
-  substmt = cp_parser_omp_structured_block_sequence (parser, PRAGMA_OMP_SCAN);
+  cp_token *tok = cp_lexer_peek_token (parser->lexer);
+  if (cp_parser_pragma_kind (tok) != PRAGMA_OMP_SCAN)
+    substmt = cp_parser_omp_structured_block_sequence (parser, PRAGMA_OMP_SCAN);
+  else
+    {
+      warning_at (tok->location, 0, "%<#pragma omp scan%> with zero preceding "
+                                   "executable statements");
+      substmt = build_empty_stmt (tok->location);
+    }
   substmt = build2 (OMP_SCAN, void_type_node, substmt, NULL_TREE);
   add_stmt (substmt);
 
-  cp_token *tok = cp_lexer_peek_token (parser->lexer);
+  tok = cp_lexer_peek_token (parser->lexer);
   if (cp_parser_pragma_kind (tok) == PRAGMA_OMP_SCAN)
     {
       enum omp_clause_code clause = OMP_CLAUSE_ERROR;
+      found_scan = true;
 
       cp_lexer_consume_token (parser->lexer);
 
@@ -43596,7 +43606,15 @@ cp_parser_omp_scan_loop_body (cp_parser *parser)
     error ("expected %<#pragma omp scan%>");
 
   clauses = finish_omp_clauses (clauses, C_ORT_OMP);
-  substmt = cp_parser_omp_structured_block_sequence (parser, PRAGMA_NONE);
+  if (!cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_BRACE))
+    substmt = cp_parser_omp_structured_block_sequence (parser, PRAGMA_NONE);
+  else
+    {
+      if (found_scan)
+       warning_at (tok->location, 0, "%<#pragma omp scan%> with zero "
+                                     "succeeding executable statements");
+      substmt = build_empty_stmt (tok->location);
+    }
   substmt = build2_loc (tok->location, OMP_SCAN, void_type_node, substmt,
                        clauses);
   add_stmt (substmt);
index b8b66869908e20cce00858c30091f9c1bfc69b8e..86e451531a6c5fab756b478efa687c8d611c4299 100644 (file)
@@ -9067,17 +9067,34 @@ gfc_resolve_omp_do_blocks (gfc_code *code, gfc_namespace *ns)
          if (code->ext.omp_clauses->sched_kind != OMP_SCHED_NONE)
            gfc_error ("SCHEDULE clause specified together with %<inscan%> "
                       "REDUCTION clause at %L", loc);
-         if (!c->block
-             || !c->block->next
-             || !c->block->next->next
-             || c->block->next->next->op != EXEC_OMP_SCAN
-             || !c->block->next->next->next
-             || c->block->next->next->next->next)
+         gfc_code *block = c->block ? c->block->next : NULL;
+         if (block && block->op != EXEC_OMP_SCAN)
+           while (block && block->next && block->next->op != EXEC_OMP_SCAN)
+             block = block->next;
+         if (!block
+             || (block->op != EXEC_OMP_SCAN
+                 && (!block->next || block->next->op != EXEC_OMP_SCAN)))
            gfc_error ("With INSCAN at %L, expected loop body with !$OMP SCAN "
-                      "between two structured-block-sequences", loc);
+                      "between two structured block sequences", loc);
          else
-           /* Mark as checked; flag will be unset later.  */
-           c->block->next->next->ext.omp_clauses->if_present = true;
+           {
+             if (block->op == EXEC_OMP_SCAN)
+               gfc_warning (0, "!$OMP SCAN at %L with zero executable "
+                               "statements in preceding structured block "
+                               "sequence", &block->loc);
+             if ((block->op == EXEC_OMP_SCAN && !block->next)
+                 || (block->next && block->next->op == EXEC_OMP_SCAN
+                     && !block->next->next))
+               gfc_warning (0, "!$OMP SCAN at %L with zero executable "
+                               "statements in succeeding structured block "
+                               "sequence", block->op == EXEC_OMP_SCAN
+                                           ? &block->loc : &block->next->loc);
+           }
+         if (block && block->op != EXEC_OMP_SCAN)
+           block = block->next;
+         if (block && block->op == EXEC_OMP_SCAN)
+           /* Mark 'omp scan' as checked; flag will be unset later.  */
+           block->ext.omp_clauses->if_present = true;
        }
     }
   gfc_resolve_blocks (code->block, ns);
index 84c0184f48efd46ae51c8498d255c3bbcd34a59b..4ff9c59df5cba30c337773594e17564ac850ba62 100644 (file)
@@ -5603,26 +5603,29 @@ gfc_trans_omp_do (gfc_code *code, gfc_exec_op op, stmtblock_t *pblock,
   /* Main loop body.  */
   if (clauses->lists[OMP_LIST_REDUCTION_INSCAN])
     {
-      gcc_assert (code->block->next->next->op == EXEC_OMP_SCAN);
-      gcc_assert (code->block->next->next->next->next == NULL);
-      locus *cloc = &code->block->next->next->loc;
-      location_t loc = gfc_get_location (cloc);
-
-      gfc_code code2 = *code->block->next;
-      code2.next = NULL;
-      tmp = gfc_trans_code (&code2);
+      gfc_code *code1, *scan, *code2, *tmpcode;
+      code1 = tmpcode = code->block->next;
+      if (tmpcode && tmpcode->op != EXEC_OMP_SCAN)
+       while (tmpcode && tmpcode->next && tmpcode->next->op != EXEC_OMP_SCAN)
+         tmpcode = tmpcode->next;
+      scan = tmpcode->op == EXEC_OMP_SCAN ? tmpcode : tmpcode->next;
+      if (code1 != scan)
+       tmpcode->next = NULL;
+      code2 = scan->next;
+      gcc_assert (scan->op == EXEC_OMP_SCAN);
+      location_t loc = gfc_get_location (&scan->loc);
+
+      tmp = code1 != scan ? gfc_trans_code (code1) : build_empty_stmt (loc);
       tmp = build2 (OMP_SCAN, void_type_node, tmp, NULL_TREE);
       SET_EXPR_LOCATION (tmp, loc);
       gfc_add_expr_to_block (&body, tmp);
       input_location = loc;
-      tree c = gfc_trans_omp_clauses (&body,
-                                     code->block->next->next->ext.omp_clauses,
-                                     *cloc);
-      code2 = *code->block->next->next->next;
-      code2.next = NULL;
-      tmp = gfc_trans_code (&code2);
+      tree c = gfc_trans_omp_clauses (&body, scan->ext.omp_clauses, scan->loc);
+      tmp = code2 ? gfc_trans_code (code2) : build_empty_stmt (loc);
       tmp = build2 (OMP_SCAN, void_type_node, tmp, c);
       SET_EXPR_LOCATION (tmp, loc);
+      if (code1 != scan)
+       tmpcode->next = scan;
     }
   else
     tmp = gfc_trans_omp_code (code->block->next, true);
diff --git a/gcc/testsuite/c-c++-common/gomp/scan-6.c b/gcc/testsuite/c-c++-common/gomp/scan-6.c
new file mode 100644 (file)
index 0000000..0fdf66b
--- /dev/null
@@ -0,0 +1,95 @@
+void f1 (int, int, int);
+int iii (int, int, int);
+
+int
+s1 (int a1, int a2, int a3)
+{
+  int r = 0;
+  #pragma omp simd collapse(3) reduction (inscan, +:r)
+  for (int i = 0; i < a1; i++)
+    for (int j = 0; j < a2; j++)
+      for (int k = 0; k < a3; k++)
+       {
+         #pragma omp scan exclusive (r)  /* { dg-warning "'#pragma omp scan' with zero preceding executable statements" } */
+         f1 (2, k, r);
+       }
+
+  #pragma omp simd collapse(3) reduction (inscan, +:r)
+  for (int i = 0; i < a1; i++)
+    for (int j = 0; j < a2; j++)
+      for (int k = 0; k < a3; k++)
+       {
+         r += iii (i, j, k);
+         #pragma omp scan exclusive (r)  /* { dg-warning "'#pragma omp scan' with zero succeeding executable statements" } */
+       }
+
+  #pragma omp simd collapse(3) reduction (inscan, +:r)
+  for (int i = 0; i < a1; i++)
+    for (int j = 0; j < a2; j++)
+      for (int k = 0; k < a3; k++)
+       {
+         #pragma omp scan inclusive (r)
+           /* { dg-warning "'#pragma omp scan' with zero preceding executable statements" "" { target *-*-* } .-1 } */
+           /* { dg-warning "'#pragma omp scan' with zero succeeding executable statements" "" { target *-*-* } .-2 } */
+       }
+  return r;
+}
+
+int
+s2 (int a1, int a2, int a3)
+{
+  int r = 0;
+  #pragma omp simd collapse(3) reduction (inscan, +:r)  /* { dg-error "'r' specified in 'inscan' 'reduction' clause but not in 'scan' directive clause" } */
+  for (int i = 0; i < a1; i++)
+    for (int j = 0; j < a2; j++)
+      for (int k = 0; k < a3; k++)
+       {
+         f1 (2, k, r);
+         r += iii (i, j, k);  /* { dg-error "expected '#pragma omp scan'" "" { target c++ } } */
+       }  /* { dg-error "expected '#pragma omp scan'" "" { target c } } */
+
+  r = 0;
+  #pragma omp simd collapse(3) reduction (inscan, +:r)  /* { dg-error "'r' specified in 'inscan' 'reduction' clause but not in 'scan' directive clause" } */
+  for (int i = 0; i < a1; i++)
+    for (int j = 0; j < a2; j++)
+      for (int k = 0; k < a3; k++)
+       ;  /* { dg-error "expected '\{' before ';' token" } */
+
+  #pragma omp simd collapse(3) reduction (inscan, +:r)  /* { dg-error "'r' specified in 'inscan' 'reduction' clause but not in 'scan' directive clause" } */
+  for (int i = 0; i < a1; i++)
+    for (int j = 0; j < a2; j++)
+      for (int k = 0; k < a3; k++)
+       {
+       }  /* { dg-error "expected expression before '\}' token" "" { target c } } */
+           /* { dg-error "expected primary-expression before '\}' token" "" { target c++ } .-1 } */
+          /* { dg-error "expected '#pragma omp scan'" "" { target *-*-* } .-2 } */
+
+
+  r = 0;
+  #pragma omp simd collapse(3) reduction (inscan, +:r)
+  for (int i = 0; i < a1; i++)
+    for (int j = 0; j < a2; j++)
+      for (int k = 0; k < a3; k++)
+       {
+         f1 (2, k, r);
+         #pragma omp scan inclusive (r)
+         #pragma omp scan inclusive (r)  /* { dg-error "'#pragma omp scan' may only be used in a loop construct with 'inscan' 'reduction' clause" } */
+         r += iii (i, j, k);
+       }
+
+  #pragma omp scan inclusive (r)  /* { dg-error "'#pragma omp scan' may only be used in a loop construct with 'inscan' 'reduction' clause" } */
+
+  r = 0;
+  #pragma omp simd collapse(3) reduction (inscan, +:r)  /* { dg-error "'r' specified in 'inscan' 'reduction' clause but not in 'scan' directive clause" } */
+  for (int i = 0; i < a1; i++)
+    for (int j = 0; j < a2; j++)
+      for (int k = 0; k < a3; k++)
+       {
+         f1 (2, k, r);
+         {
+           #pragma omp scan inclusive (r)  /* { dg-error "'#pragma omp scan' may only be used in a loop construct with 'inscan' 'reduction' clause" } */
+         }
+         r += iii (i, j, k);  /* { dg-error "expected '#pragma omp scan'" "" { target c++ } }  */
+       }  /* { dg-error "expected '#pragma omp scan'" "" { target c } }  */
+  return r;
+}
index 900ef664957bf13ba7f10ee03b36e291313a0f80..59f992c516c571c03426c1622b1e6f9cdfce1e1d 100644 (file)
@@ -31,7 +31,7 @@ bar (int a, int *c, int *d, int *e, int *f)
       [[omp::sequence (omp::directive (parallel), omp::directive (scan, exclusive (a)))]]      // { dg-error "must be the only specified attribute on a statement" }
                                                                                        // { dg-error "#pragma omp scan" "" { target *-*-* } .-1 }
       a += c[i];                                                                       // { dg-error "expected" }
-    }                                                                                  // { dg-error "expected" }
+    }
   [[omp::directive (parallel for reduction (inscan, +: a))]]                           // { dg-error "'a' specified in 'inscan' 'reduction' clause but not in 'scan' directive clause" }
   for (i = 0; i < 64; i++)
     {
@@ -39,7 +39,7 @@ bar (int a, int *c, int *d, int *e, int *f)
       [[omp::sequence (directive (scan inclusive (a)), directive (critical))]]         // { dg-error "must be the only specified attribute on a statement" }
                                                                                        // { dg-error "#pragma omp scan" "" { target *-*-* } .-1 }
       d[i] = a;                                                                                // { dg-error "expected" }
-    }                                                                                  // { dg-error "expected" }
+    }
   [[omp::directive (parallel for reduction (inscan, +: a))]]                           // { dg-error "'a' specified in 'inscan' 'reduction' clause but not in 'scan' directive clause" }
   for (i = 0; i < 64; i++)
     {
@@ -47,7 +47,7 @@ bar (int a, int *c, int *d, int *e, int *f)
       [[gnu::cold]] [[omp::directive (scan, exclusive (a))]]                           // { dg-error "must be the only specified attribute on a statement" }
                                                                                        // { dg-error "#pragma omp scan" "" { target *-*-* } .-1 }
       a += c[i];                                                                       // { dg-error "expected" }
-    }                                                                                  // { dg-error "expected" }
+    }
   [[omp::directive (parallel for reduction (inscan, +: a))]]                           // { dg-error "'a' specified in 'inscan' 'reduction' clause but not in 'scan' directive clause" }
   for (i = 0; i < 64; i++)
     {
@@ -55,7 +55,7 @@ bar (int a, int *c, int *d, int *e, int *f)
       [[omp::directive (scan, exclusive (a)), gnu::cold]]                              // { dg-error "must be the only specified attribute on a statement" }
                                                                                        // { dg-error "#pragma omp scan" "" { target *-*-* } .-1 }
       a += c[i];                                                                       // { dg-error "expected" }
-    }                                                                                  // { dg-error "expected" }
+    }
   [[omp::directive (parallel for reduction (inscan, +: a))]]                           // { dg-error "'a' specified in 'inscan' 'reduction' clause but not in 'scan' directive clause" }
   for (i = 0; i < 64; i++)
     {
index 2d83e3a750733c4a92183301698edce0fae30e12..92a17b247bb969bace5db7c9f028b82780298c32 100644 (file)
@@ -18,23 +18,23 @@ do i = 1, 64
 end do
 
 !$omp loop reduction(inscan, +: r)  ! { dg-error "'inscan' REDUCTION clause on construct other than DO, SIMD, DO SIMD, PARALLEL DO, PARALLEL DO SIMD" }
-  ! { dg-error "With INSCAN at .1., expected loop body with ..OMP SCAN between two structured-block-sequences" "" { target *-*-* } .-1 }
+  ! { dg-error "With INSCAN at .1., expected loop body with ..OMP SCAN between two structured block sequences" "" { target *-*-* } .-1 }
 do i = 1, 64
 end do
 !$omp teams loop reduction(inscan, +: r)  ! { dg-error "'inscan' REDUCTION clause on construct other than DO, SIMD, DO SIMD, PARALLEL DO, PARALLEL DO SIMD" }
-  ! { dg-error "With INSCAN at .1., expected loop body with ..OMP SCAN between two structured-block-sequences" "" { target *-*-* } .-1 }
+  ! { dg-error "With INSCAN at .1., expected loop body with ..OMP SCAN between two structured block sequences" "" { target *-*-* } .-1 }
 do i = 1, 64
 end do
 !$omp parallel loop reduction(inscan, +: r) ! { dg-error "'inscan' REDUCTION clause on construct other than DO, SIMD, DO SIMD, PARALLEL DO, PARALLEL DO SIMD" }
-  ! { dg-error "With INSCAN at .1., expected loop body with ..OMP SCAN between two structured-block-sequences" "" { target *-*-* } .-1 }
+  ! { dg-error "With INSCAN at .1., expected loop body with ..OMP SCAN between two structured block sequences" "" { target *-*-* } .-1 }
 do i = 1, 64
 end do
 !$omp target teams loop reduction(inscan, +: r)  ! { dg-error "'inscan' REDUCTION clause on construct other than DO, SIMD, DO SIMD, PARALLEL DO, PARALLEL DO SIMD" }
-  ! { dg-error "With INSCAN at .1., expected loop body with ..OMP SCAN between two structured-block-sequences" "" { target *-*-* } .-1 }
+  ! { dg-error "With INSCAN at .1., expected loop body with ..OMP SCAN between two structured block sequences" "" { target *-*-* } .-1 }
 do i = 1, 64
 end do
 !$omp target parallel loop reduction(inscan, +: r)  ! { dg-error "'inscan' REDUCTION clause on construct other than DO, SIMD, DO SIMD, PARALLEL DO, PARALLEL DO SIMD" }
-  ! { dg-error "With INSCAN at .1., expected loop body with ..OMP SCAN between two structured-block-sequences" "" { target *-*-* } .-1 }
+  ! { dg-error "With INSCAN at .1., expected loop body with ..OMP SCAN between two structured block sequences" "" { target *-*-* } .-1 }
 do i = 1, 64
 end do
 
index 44f89d84c786e5c3a8b7c5b6c5f18bb42f54f09e..85491f0b643cc583fac211d6f6ad46651754b713 100644 (file)
@@ -21,7 +21,7 @@ end do
 !$omp end task  ! { dg-error "Unexpected !.OMP END TASK statement" }
 
 !$omp taskloop reduction(inscan,+:a) in_reduction(+:b) ! { dg-error "'inscan' REDUCTION clause on construct other than DO, SIMD, DO SIMD, PARALLEL DO, PARALLEL DO SIMD" }
-  ! { dg-error "34: With INSCAN at .1., expected loop body with ..OMP SCAN between two structured-block-sequences" "" { target *-*-* } .-1 }
+  ! { dg-error "34: With INSCAN at .1., expected loop body with ..OMP SCAN between two structured block sequences" "" { target *-*-* } .-1 }
   ! { dg-error "'inscan' and non-'inscan' 'reduction' clauses on the same construct" "" { target *-*-* } .-2 }
 do i=1,10
   a = a + 1
index 6bf685130ab7d0d45929f158baced43aff39a3f3..321f096e02bd35ed310364247f8d4a68594dd8a3 100644 (file)
@@ -4,13 +4,13 @@ implicit none
 integer :: a, b, i
 a = 0
 
-!$omp simd reduction(inscan,+:a)  ! { dg-error "30: With INSCAN at .1., expected loop body with ..OMP SCAN between two structured-block-sequences" }
+!$omp simd reduction(inscan,+:a)  ! { dg-error "30: With INSCAN at .1., expected loop body with ..OMP SCAN between two structured block sequences" }
 do i=1,10
   a = a + 1
 end do
 
 !$omp parallel
-!$omp do reduction(inscan,+:a)  ! { dg-error "28: With INSCAN at .1., expected loop body with ..OMP SCAN between two structured-block-sequences" }
+!$omp do reduction(inscan,+:a)  ! { dg-error "28: With INSCAN at .1., expected loop body with ..OMP SCAN between two structured block sequences" }
 do i=1,10
   a = a + 1
 end do
index f91c7fae09d3db126779ea07486d32d66e577735..a4f712f0d2fce501ecaa420327aea98fe76d798a 100644 (file)
@@ -176,7 +176,7 @@ subroutine f8 (c, d, e, f)
   use m
   implicit none
   integer i, c(64), d(64), e(64), f(64)
-  !$omp do reduction (inscan, +: a, b)   ! { dg-error "With INSCAN at .1., expected loop body with ..OMP SCAN between two structured-block-sequences" }
+  !$omp do reduction (inscan, +: a, b)   ! { dg-error "With INSCAN at .1., expected loop body with ..OMP SCAN between two structured block sequences" }
   do i = 1, 64
     block
       a = a + c(i)
@@ -189,7 +189,7 @@ subroutine f8 (c, d, e, f)
     end block
   end do
 
-  !$omp do reduction (inscan, +: a, b)  ! { dg-error "With INSCAN at .1., expected loop body with ..OMP SCAN between two structured-block-sequences" }
+  !$omp do reduction (inscan, +: a, b)  ! { dg-error "With INSCAN at .1., expected loop body with ..OMP SCAN between two structured block sequences" }
   do i = 1, 64
     block
       a = a + c(i)
@@ -207,12 +207,11 @@ subroutine f9
   use m
   implicit none
   integer i
-! The first error (exit) causes two follow-up errors:
-  !$omp simd reduction (inscan, +: a)  ! { dg-error "With INSCAN at .1., expected loop body with ..OMP SCAN between two structured-block-sequences" }
+  !$omp simd reduction (inscan, +: a)
   do i = 1, 64
     if (i == 23) &
       exit  ! { dg-error "EXIT statement at .1. terminating ..OMP DO loop" } */
-    !$omp scan exclusive (a) ! { dg-error "Unexpected ..OMP SCAN at .1. outside loop construct with 'inscan' REDUCTION clause" }
+    !$omp scan exclusive (a)  ! { dg-warning "!.OMP SCAN at .1. with zero executable statements in preceding structured block sequence" }
     a = a + 1
   end do
 end
diff --git a/gcc/testsuite/gfortran.dg/gomp/scan-8.f90 b/gcc/testsuite/gfortran.dg/gomp/scan-8.f90
new file mode 100644 (file)
index 0000000..b706bbb
--- /dev/null
@@ -0,0 +1,96 @@
+integer function s1 (a1, a2, a3) result(r)
+  implicit none
+  integer :: a1, a2, a3
+  integer :: i, j, k
+  procedure(integer) :: iii
+  
+  r = 0
+  !$omp simd collapse(3) reduction (inscan, +:r)
+  do i = 1, a1
+    do j = 1, a2
+      do k = 1, a3
+        !$omp scan exclusive (r)  ! { dg-warning "!.OMP SCAN at .1. with zero executable statements in preceding structured block sequence" }
+        call f1 (2, k, r)
+      end do
+    end do 
+  end do
+
+  !$omp simd collapse(3) reduction (inscan, +:r)
+  do i = 1, a1
+    do j = 1, a2
+      do k = 1, a3
+        r = r + iii (i, j, k)
+        !$omp scan exclusive (r)  ! { dg-warning "!.OMP SCAN at .1. with zero executable statements in succeeding structured block sequence" }
+      end do
+    end do 
+  end do
+
+  !$omp simd collapse(3) reduction (inscan, +:r)
+  do i = 1, a1
+    do j = 1, a2
+      do k = 1, a3
+        !$omp scan inclusive (r)
+           ! { dg-warning "!.OMP SCAN at .1. with zero executable statements in preceding structured block sequence" "" { target *-*-* } .-1 }
+           ! { dg-warning "!.OMP SCAN at .1. with zero executable statements in succeeding structured block sequence" "" { target *-*-* } .-2 }
+      end do
+    end do 
+  end do
+end function
+
+integer function s2 (a1, a2, a3) result(r)
+  implicit none
+  integer :: a1, a2, a3
+  integer :: i, j, k
+  procedure(integer) :: iii
+  
+  r = 0
+  !$omp simd collapse(3) reduction (inscan, +:r)  ! { dg-error "With INSCAN at .1., expected loop body with !.OMP SCAN between two structured block sequences" }
+  do i = 1, a1
+    do j = 1, a2
+      do k = 1, a3
+        call f1 (2, k, r)
+        r = r + iii (i, j, k)
+      end do
+    end do 
+  end do
+
+  r = 0
+  !$omp simd collapse(3) reduction (inscan, +:r)  ! { dg-error "With INSCAN at .1., expected loop body with !.OMP SCAN between two structured block sequences" }
+  do i = 1, a1
+    do j = 1, a2
+      do k = 1, a3
+      end do
+    end do 
+  end do
+
+  r = 0
+  !$omp simd collapse(3) reduction (inscan, +:r)
+  do i = 1, a1
+    do j = 1, a2
+      do k = 1, a3
+        call f1 (2, k, r)
+        !$omp scan inclusive (r)
+        !$omp scan inclusive (r)  ! { dg-error "Unexpected !.OMP SCAN at .1. outside loop construct with 'inscan' REDUCTION clause" }
+        r = r + iii (i, j, k)
+      end do
+    end do 
+  end do
+
+  !$omp scan inclusive (r)  ! { dg-error "Unexpected !.OMP SCAN at .1. outside loop construct with 'inscan' REDUCTION clause" }
+
+  r = 0
+  !$omp simd collapse(3) reduction (inscan, +:r)  ! { dg-error "With INSCAN at .1., expected loop body with !.OMP SCAN between two structured block sequences" }
+  do i = 1, a1
+    do j = 1, a2
+      do k = 1, a3
+        call f1 (2, k, r)
+        block
+          !$omp scan inclusive (r)  ! { dg-error "Unexpected !.OMP SCAN at .1. outside loop construct with 'inscan' REDUCTION clause" }
+        end block
+        r = r + iii (i, j, k)
+      end do
+    end do 
+  end do
+
+
+end function
index 41b4d6d21913c5fcdf5d9a977f29512eeaedf3db..d200a93bb4fa1518de68c8f93c52a49de58ae93a 100644 (file)
@@ -21,24 +21,24 @@ do i = 1, 64
 end do
 
 !$omp taskloop reduction(inscan, +: r)  ! { dg-error "'inscan' REDUCTION clause on construct other than DO, SIMD, DO SIMD, PARALLEL DO, PARALLEL DO SIMD" }
-do i = 1, 64                            ! { dg-error "OMP SCAN between two structured-block-sequences" "" { target *-*-* } .-1 }
+do i = 1, 64                            ! { dg-error "OMP SCAN between two structured block sequences" "" { target *-*-* } .-1 }
 end do
 !$omp taskloop simd reduction(inscan, +: r)  ! { dg-error "'inscan' REDUCTION clause on construct other than DO, SIMD, DO SIMD, PARALLEL DO, PARALLEL DO SIMD" }
-do i = 1, 64                                 ! { dg-error "OMP SCAN between two structured-block-sequences" "" { target *-*-* } .-1 }
+do i = 1, 64                                 ! { dg-error "OMP SCAN between two structured block sequences" "" { target *-*-* } .-1 }
 end do
 !$omp master taskloop reduction(inscan, +: r) ! { dg-error "'inscan' REDUCTION clause on construct other than DO, SIMD, DO SIMD, PARALLEL DO, PARALLEL DO SIMD" }
-  ! { dg-error "With INSCAN at .1., expected loop body with ..OMP SCAN between two structured-block-sequences" "" { target *-*-* } .-1 }
+  ! { dg-error "With INSCAN at .1., expected loop body with ..OMP SCAN between two structured block sequences" "" { target *-*-* } .-1 }
 do i = 1, 64
 end do
 !$omp master taskloop simd reduction(inscan, +: r)  ! { dg-error "'inscan' REDUCTION clause on construct other than DO, SIMD, DO SIMD, PARALLEL DO, PARALLEL DO SIMD" }
-  ! { dg-error "With INSCAN at .1., expected loop body with ..OMP SCAN between two structured-block-sequences" "" { target *-*-* } .-1 }
+  ! { dg-error "With INSCAN at .1., expected loop body with ..OMP SCAN between two structured block sequences" "" { target *-*-* } .-1 }
 do i = 1, 64
 end do
 !$omp parallel master taskloop reduction(inscan, +: r)  ! { dg-error "'inscan' REDUCTION clause on construct other than DO, SIMD, DO SIMD, PARALLEL DO, PARALLEL DO SIMD" }
-do i = 1, 64                                 ! { dg-error "OMP SCAN between two structured-block-sequences" "" { target *-*-* } .-1 }
+do i = 1, 64                                 ! { dg-error "OMP SCAN between two structured block sequences" "" { target *-*-* } .-1 }
 end do
 !$omp parallel master taskloop simd reduction(inscan, +: r)   ! { dg-error "'inscan' REDUCTION clause on construct other than DO, SIMD, DO SIMD, PARALLEL DO, PARALLEL DO SIMD" }
-do i = 1, 64                                 ! { dg-error "OMP SCAN between two structured-block-sequences" "" { target *-*-* } .-1 }
+do i = 1, 64                                 ! { dg-error "OMP SCAN between two structured block sequences" "" { target *-*-* } .-1 }
 end do
 end
 
diff --git a/libgomp/testsuite/libgomp.c-c++-common/scan-1.c b/libgomp/testsuite/libgomp.c-c++-common/scan-1.c
new file mode 100644 (file)
index 0000000..d1951a3
--- /dev/null
@@ -0,0 +1,68 @@
+#define N 30
+#define M 3
+
+int a[N][M], b[N][M], c[N][M];
+
+int
+main()
+{
+  int x, y, shift;
+  int j = 0;
+  for (int i = 0; i < N; i++)
+    {
+      a[i][0] = (i+1)*32;
+      a[i][1] = (i+1)*17;
+      a[i][2] = (i+1)*11;
+      b[i][0] = (i+1)*7;
+      b[i][1] = (i+1)*5;
+      b[i][2] = (i+1)*3;
+    }
+
+  x = 0;
+  #pragma omp parallel for simd collapse(2) reduction(inscan,+: x) private(shift)
+  for (int i = 0; i < N; i++)
+    for (int j = 0; j < M; j++)
+      {
+       x += a[i][j];
+       x += b[i][j];
+        #pragma omp scan inclusive(x)
+        shift = i + 29*j;
+        c[i][j] = x + shift;
+      }
+
+  y = 0;
+  for (int i = 0; i < N; i++)
+    for (int j = 0; j < M; j++)
+      {
+       y += a[i][j] + b[i][j];
+       if (c[i][j] != y + i + 29*j)
+         __builtin_abort ();
+      }
+  if (x != y)
+    __builtin_abort ();
+
+  x = 0;
+  #pragma omp parallel for simd collapse(2) reduction(inscan,+: x) private(shift)
+  for (int i = 0; i < N; i++)
+    for (int j = 0; j < M; j++)
+      {
+       shift = i + 29*j;
+       c[i][j] = x + shift;
+       #pragma omp scan exclusive(x)
+       x += a[i][j];
+       x += b[i][j];
+      }
+
+  y = 0;
+  for (int i = 0; i < N; i++)
+    for (int j = 0; j < M; j++)
+      {
+       if (c[i][j] != y + i + 29*j)
+         __builtin_abort ();
+       y += a[i][j] + b[i][j];
+      }
+  if (x != y)
+    __builtin_abort ();
+
+  return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c/scan-23.c b/libgomp/testsuite/libgomp.c/scan-23.c
new file mode 100644 (file)
index 0000000..e7681ad
--- /dev/null
@@ -0,0 +1,121 @@
+/* { dg-require-effective-target size32plus } */
+/* Same as scan-9.c, instead of using { ... } it simply uses multiple
+   executable stmt before 'omp scan'.  */
+
+extern void abort (void);
+int r, a[1024], b[1024], x, y, z;
+
+__attribute__((noipa)) void
+foo (int *a, int *b)
+{
+  #pragma omp for reduction (inscan, +:r) lastprivate (conditional: z) firstprivate (x) private (y)
+  for (int i = 0; i < 1024; i++)
+    {
+      y = a[i];
+      r += y + x + 12;
+      #pragma omp scan inclusive(r)
+      b[i] = r;
+      if ((i & 1) == 0 && i < 937)
+        z = r;
+    }
+}
+
+__attribute__((noipa)) int
+bar (void)
+{
+  int s = 0;
+  #pragma omp parallel
+  #pragma omp for reduction (inscan, +:s) firstprivate (x) private (y) lastprivate (z)
+  for (int i = 0; i < 1024; i++)
+    {
+      y = 2 * a[i]; s += y; z = y;
+      #pragma omp scan inclusive(s)
+      y = s; b[i] = y + x + 12;
+    }
+  return s;
+}
+
+__attribute__((noipa)) void
+baz (int *a, int *b)
+{
+  #pragma omp parallel for reduction (inscan, +:r) firstprivate (x) lastprivate (x)
+  for (int i = 0; i < 1024; i++)
+    {
+      r += a[i] + x + 12; if (i == 1023) x = 29;
+      #pragma omp scan inclusive(r)
+      b[i] = r;
+    }
+}
+
+__attribute__((noipa)) int
+qux (void)
+{
+  int s = 0;
+  #pragma omp parallel for reduction (inscan, +:s) lastprivate (conditional: x, y)
+  for (int i = 0; i < 1024; i++)
+    {
+      s += 2 * a[i]; if ((a[i] & 1) == 1 && i < 825) x = a[i];
+      #pragma omp scan inclusive(s)
+      b[i] = s; if ((a[i] & 1) == 0 && i < 829) y = a[i];
+    }
+  return s;
+}
+
+int
+main ()
+{
+  int s = 0;
+  x = -12;
+  for (int i = 0; i < 1024; ++i)
+    {
+      a[i] = i;
+      b[i] = -1;
+      asm ("" : "+g" (i));
+    }
+  #pragma omp parallel
+  foo (a, b);
+  if (r != 1024 * 1023 / 2 || x != -12 || z != b[936])
+    abort ();
+  for (int i = 0; i < 1024; ++i)
+    {
+      s += i;
+      if (b[i] != s)
+       abort ();
+      else
+       b[i] = 25;
+    }
+  if (bar () != 1024 * 1023 || x != -12 || z != 2 * 1023)
+    abort ();
+  s = 0;
+  for (int i = 0; i < 1024; ++i)
+    {
+      s += 2 * i;
+      if (b[i] != s)
+       abort ();
+      else
+       b[i] = -1;
+    }
+  r = 0;
+  baz (a, b);
+  if (r != 1024 * 1023 / 2 || x != 29)
+    abort ();
+  s = 0;
+  for (int i = 0; i < 1024; ++i)
+    {
+      s += i;
+      if (b[i] != s)
+       abort ();
+      else
+       b[i] = -25;
+    }
+  if (qux () != 1024 * 1023 || x != 823 || y != 828)
+    abort ();
+  s = 0;
+  for (int i = 0; i < 1024; ++i)
+    {
+      s += 2 * i;
+      if (b[i] != s)
+       abort ();
+    }
+  return 0;
+}
diff --git a/libgomp/testsuite/libgomp.fortran/scan-2.f90 b/libgomp/testsuite/libgomp.fortran/scan-2.f90
new file mode 100644 (file)
index 0000000..2815ec7
--- /dev/null
@@ -0,0 +1,59 @@
+implicit none
+integer, parameter :: N = 30
+integer, parameter :: M = 3
+
+integer :: a(M,N), b(M,N), c(M,N)
+integer :: x, y, shift
+integer :: i, j
+
+do i = 1, N
+  a(1,i) = i*32
+  a(2,i) = i*17
+  a(3,i) = i*11
+  b(1,i) = i*7
+  b(2,i) = i*5
+  b(3,i) = i*3
+end do
+
+x = 0
+!$omp parallel do simd collapse(2) reduction(inscan,+: x) private(shift)
+do i = 1, N
+  do j = 1, M
+    x = x + a(j,i)
+    x = x + b(j,i)
+    !$omp scan inclusive(x)
+    shift = i + 29*j
+    c(j,i) = x + shift;
+  end do
+end do
+
+y = 0
+do i = 1, N
+  do j = 1, M
+    y = y +  a(j,i) + b(j,i)
+    if (c(j,i) /= y + i + 29*j) error stop 1
+  end do
+end do
+if (x /= y) error stop 2
+
+x = 0
+!$omp parallel do simd collapse(2) reduction(inscan,+: x) private(shift)
+do i = 1, N
+  do j = 1, M
+    shift = i + 29*j
+    c(j,i) = x + shift;
+    !$omp scan exclusive(x)
+    x = x + a(j,i)
+    x = x + b(j,i)
+  end do
+end do
+
+y = 0
+do i = 1, N
+  do j = 1, M
+    if (c(j,i) /= y + i + 29*j) error stop 1
+    y = y + a(j,i) + b(j,i)
+  end do
+end do
+if (x /= y) error stop 2
+end