aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/fortran/openmp.cc57
-rw-r--r--gcc/fortran/parse.cc33
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/copyprivate-1.f9021
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/copyprivate-2.f9097
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/nowait-2.f90159
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/nowait-4.f90158
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/nowait-5.f90156
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/nowait-6.f90158
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/nowait-7.f90118
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/nowait-8.f9092
-rw-r--r--libgomp/libgomp.texi2
11 files changed, 857 insertions, 194 deletions
diff --git a/gcc/fortran/openmp.cc b/gcc/fortran/openmp.cc
index e0e3b52..862c649 100644
--- a/gcc/fortran/openmp.cc
+++ b/gcc/fortran/openmp.cc
@@ -4173,17 +4173,19 @@ cleanup:
(omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE \
| OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_REDUCTION \
| OMP_CLAUSE_SCHEDULE | OMP_CLAUSE_ORDERED | OMP_CLAUSE_COLLAPSE \
- | OMP_CLAUSE_LINEAR | OMP_CLAUSE_ORDER | OMP_CLAUSE_ALLOCATE)
+ | OMP_CLAUSE_LINEAR | OMP_CLAUSE_ORDER | OMP_CLAUSE_ALLOCATE \
+ | OMP_CLAUSE_NOWAIT)
#define OMP_LOOP_CLAUSES \
(omp_mask (OMP_CLAUSE_BIND) | OMP_CLAUSE_COLLAPSE | OMP_CLAUSE_ORDER \
| OMP_CLAUSE_PRIVATE | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_REDUCTION)
#define OMP_SCOPE_CLAUSES \
(omp_mask (OMP_CLAUSE_PRIVATE) |OMP_CLAUSE_FIRSTPRIVATE \
- | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_ALLOCATE)
+ | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_ALLOCATE | OMP_CLAUSE_NOWAIT)
#define OMP_SECTIONS_CLAUSES \
(omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE \
- | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_ALLOCATE)
+ | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_REDUCTION \
+ | OMP_CLAUSE_ALLOCATE | OMP_CLAUSE_NOWAIT)
#define OMP_SIMD_CLAUSES \
(omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_LASTPRIVATE \
| OMP_CLAUSE_REDUCTION | OMP_CLAUSE_COLLAPSE | OMP_CLAUSE_SAFELEN \
@@ -4233,7 +4235,7 @@ cleanup:
| OMP_CLAUSE_ORDER | OMP_CLAUSE_ALLOCATE)
#define OMP_SINGLE_CLAUSES \
(omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE \
- | OMP_CLAUSE_ALLOCATE)
+ | OMP_CLAUSE_ALLOCATE | OMP_CLAUSE_NOWAIT | OMP_CLAUSE_COPYPRIVATE)
#define OMP_ORDERED_CLAUSES \
(omp_mask (OMP_CLAUSE_THREADS) | OMP_CLAUSE_SIMD)
#define OMP_DECLARE_TARGET_CLAUSES \
@@ -4247,7 +4249,8 @@ cleanup:
(omp_mask (OMP_CLAUSE_FILTER))
#define OMP_ERROR_CLAUSES \
(omp_mask (OMP_CLAUSE_AT) | OMP_CLAUSE_MESSAGE | OMP_CLAUSE_SEVERITY)
-
+#define OMP_WORKSHARE_CLAUSES \
+ omp_mask (OMP_CLAUSE_NOWAIT)
static match
@@ -4458,8 +4461,8 @@ gfc_match_omp_distribute_parallel_do (void)
return match_omp (EXEC_OMP_DISTRIBUTE_PARALLEL_DO,
(OMP_DISTRIBUTE_CLAUSES | OMP_PARALLEL_CLAUSES
| OMP_DO_CLAUSES)
- & ~(omp_mask (OMP_CLAUSE_ORDERED))
- & ~(omp_mask (OMP_CLAUSE_LINEAR)));
+ & ~(omp_mask (OMP_CLAUSE_ORDERED)
+ | OMP_CLAUSE_LINEAR | OMP_CLAUSE_NOWAIT));
}
@@ -4469,7 +4472,7 @@ gfc_match_omp_distribute_parallel_do_simd (void)
return match_omp (EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD,
(OMP_DISTRIBUTE_CLAUSES | OMP_PARALLEL_CLAUSES
| OMP_DO_CLAUSES | OMP_SIMD_CLAUSES)
- & ~(omp_mask (OMP_CLAUSE_ORDERED)));
+ & ~(omp_mask (OMP_CLAUSE_ORDERED) | OMP_CLAUSE_NOWAIT));
}
@@ -5770,7 +5773,8 @@ match
gfc_match_omp_parallel_do (void)
{
return match_omp (EXEC_OMP_PARALLEL_DO,
- OMP_PARALLEL_CLAUSES | OMP_DO_CLAUSES);
+ (OMP_PARALLEL_CLAUSES | OMP_DO_CLAUSES)
+ & ~(omp_mask (OMP_CLAUSE_NOWAIT)));
}
@@ -5778,7 +5782,8 @@ match
gfc_match_omp_parallel_do_simd (void)
{
return match_omp (EXEC_OMP_PARALLEL_DO_SIMD,
- OMP_PARALLEL_CLAUSES | OMP_DO_CLAUSES | OMP_SIMD_CLAUSES);
+ (OMP_PARALLEL_CLAUSES | OMP_DO_CLAUSES | OMP_SIMD_CLAUSES)
+ & ~(omp_mask (OMP_CLAUSE_NOWAIT)));
}
@@ -5834,7 +5839,8 @@ match
gfc_match_omp_parallel_sections (void)
{
return match_omp (EXEC_OMP_PARALLEL_SECTIONS,
- OMP_PARALLEL_CLAUSES | OMP_SECTIONS_CLAUSES);
+ (OMP_PARALLEL_CLAUSES | OMP_SECTIONS_CLAUSES)
+ & ~(omp_mask (OMP_CLAUSE_NOWAIT)));
}
@@ -6320,8 +6326,8 @@ gfc_match_omp_teams_distribute_parallel_do (void)
return match_omp (EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO,
(OMP_TEAMS_CLAUSES | OMP_DISTRIBUTE_CLAUSES
| OMP_PARALLEL_CLAUSES | OMP_DO_CLAUSES)
- & ~(omp_mask (OMP_CLAUSE_ORDERED))
- & ~(omp_mask (OMP_CLAUSE_LINEAR)));
+ & ~(omp_mask (OMP_CLAUSE_ORDERED)
+ | OMP_CLAUSE_LINEAR | OMP_CLAUSE_NOWAIT));
}
@@ -6331,7 +6337,8 @@ gfc_match_omp_teams_distribute_parallel_do_simd (void)
return match_omp (EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD,
(OMP_TEAMS_CLAUSES | OMP_DISTRIBUTE_CLAUSES
| OMP_PARALLEL_CLAUSES | OMP_DO_CLAUSES
- | OMP_SIMD_CLAUSES) & ~(omp_mask (OMP_CLAUSE_ORDERED)));
+ | OMP_SIMD_CLAUSES)
+ & ~(omp_mask (OMP_CLAUSE_ORDERED) | OMP_CLAUSE_NOWAIT));
}
@@ -6347,14 +6354,7 @@ gfc_match_omp_teams_distribute_simd (void)
match
gfc_match_omp_workshare (void)
{
- if (gfc_match_omp_eos () != MATCH_YES)
- {
- gfc_error ("Unexpected junk after $OMP WORKSHARE statement at %C");
- return MATCH_ERROR;
- }
- new_st.op = EXEC_OMP_WORKSHARE;
- new_st.ext.omp_clauses = gfc_get_omp_clauses ();
- return MATCH_YES;
+ return match_omp (EXEC_OMP_WORKSHARE, OMP_WORKSHARE_CLAUSES);
}
@@ -6658,14 +6658,8 @@ match
gfc_match_omp_end_single (void)
{
gfc_omp_clauses *c;
- if (gfc_match ("% nowait") == MATCH_YES)
- {
- new_st.op = EXEC_OMP_END_NOWAIT;
- new_st.ext.omp_bool = true;
- return MATCH_YES;
- }
- if (gfc_match_omp_clauses (&c, omp_mask (OMP_CLAUSE_COPYPRIVATE))
- != MATCH_YES)
+ if (gfc_match_omp_clauses (&c, omp_mask (OMP_CLAUSE_COPYPRIVATE)
+ | OMP_CLAUSE_NOWAIT) != MATCH_YES)
return MATCH_ERROR;
new_st.op = EXEC_OMP_END_SINGLE;
new_st.ext.omp_clauses = c;
@@ -7406,6 +7400,9 @@ resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses,
}
break;
case OMP_LIST_COPYPRIVATE:
+ if (omp_clauses->nowait)
+ gfc_error ("NOWAIT clause must not be used with COPYPRIVATE "
+ "clause at %L", &n->where);
for (; n != NULL; n = n->next)
{
if (n->sym->as && n->sym->as->type == AS_ASSUMED_SIZE)
diff --git a/gcc/fortran/parse.cc b/gcc/fortran/parse.cc
index f04fd13..51ff0fc 100644
--- a/gcc/fortran/parse.cc
+++ b/gcc/fortran/parse.cc
@@ -942,7 +942,8 @@ decode_omp_directive (void)
matchs ("end ordered", gfc_match_omp_eos_error, ST_OMP_END_ORDERED);
matchs ("end parallel do simd", gfc_match_omp_eos_error,
ST_OMP_END_PARALLEL_DO_SIMD);
- matcho ("end parallel do", gfc_match_omp_eos_error, ST_OMP_END_PARALLEL_DO);
+ matcho ("end parallel do", gfc_match_omp_eos_error,
+ ST_OMP_END_PARALLEL_DO);
matcho ("end parallel loop", gfc_match_omp_eos_error,
ST_OMP_END_PARALLEL_LOOP);
matcho ("end parallel masked taskloop simd", gfc_match_omp_eos_error,
@@ -5305,7 +5306,13 @@ parse_omp_do (gfc_statement omp_st)
if (st == omp_end_st)
{
if (new_st.op == EXEC_OMP_END_NOWAIT)
- cp->ext.omp_clauses->nowait |= new_st.ext.omp_bool;
+ {
+ if (cp->ext.omp_clauses->nowait && new_st.ext.omp_bool)
+ gfc_error_now ("Duplicated NOWAIT clause on %s and %s at %C",
+ gfc_ascii_statement (omp_st),
+ gfc_ascii_statement (omp_end_st));
+ cp->ext.omp_clauses->nowait |= new_st.ext.omp_bool;
+ }
else
gcc_assert (new_st.op == EXEC_NOP);
gfc_clear_new_st ();
@@ -5745,6 +5752,10 @@ parse_omp_structured_block (gfc_statement omp_st, bool workshare_stmts_only)
switch (new_st.op)
{
case EXEC_OMP_END_NOWAIT:
+ if (cp->ext.omp_clauses->nowait && new_st.ext.omp_bool)
+ gfc_error_now ("Duplicated NOWAIT clause on %s and %s at %C",
+ gfc_ascii_statement (omp_st),
+ gfc_ascii_statement (omp_end_st));
cp->ext.omp_clauses->nowait |= new_st.ext.omp_bool;
break;
case EXEC_OMP_END_CRITICAL:
@@ -5759,8 +5770,22 @@ parse_omp_structured_block (gfc_statement omp_st, bool workshare_stmts_only)
new_st.ext.omp_name = NULL;
break;
case EXEC_OMP_END_SINGLE:
- cp->ext.omp_clauses->lists[OMP_LIST_COPYPRIVATE]
- = new_st.ext.omp_clauses->lists[OMP_LIST_COPYPRIVATE];
+ if (cp->ext.omp_clauses->nowait && new_st.ext.omp_clauses->nowait)
+ gfc_error_now ("Duplicated NOWAIT clause on %s and %s at %C",
+ gfc_ascii_statement (omp_st),
+ gfc_ascii_statement (omp_end_st));
+ cp->ext.omp_clauses->nowait |= new_st.ext.omp_clauses->nowait;
+ if (cp->ext.omp_clauses->lists[OMP_LIST_COPYPRIVATE])
+ {
+ gfc_omp_namelist *nl;
+ for (nl = cp->ext.omp_clauses->lists[OMP_LIST_COPYPRIVATE];
+ nl->next; nl = nl->next);
+ ;
+ nl->next = new_st.ext.omp_clauses->lists[OMP_LIST_COPYPRIVATE];
+ }
+ else
+ cp->ext.omp_clauses->lists[OMP_LIST_COPYPRIVATE]
+ = new_st.ext.omp_clauses->lists[OMP_LIST_COPYPRIVATE];
new_st.ext.omp_clauses->lists[OMP_LIST_COPYPRIVATE] = NULL;
gfc_free_omp_clauses (new_st.ext.omp_clauses);
break;
diff --git a/gcc/testsuite/gfortran.dg/gomp/copyprivate-1.f90 b/gcc/testsuite/gfortran.dg/gomp/copyprivate-1.f90
new file mode 100644
index 0000000..eb2c865
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/copyprivate-1.f90
@@ -0,0 +1,21 @@
+! based on pr59467.f90 but COPYPRIVATE on the directive
+! { dg-additional-options "-fdump-tree-original" }
+
+ FUNCTION t()
+ INTEGER :: a, b, t
+ a = 0
+ b = 0
+ t = b
+ b = 0
+ !$OMP PARALLEL REDUCTION(+:b)
+ !$OMP SINGLE COPYPRIVATE (b)
+ !$OMP ATOMIC WRITE
+ b = 6
+ !$OMP END SINGLE
+ !$OMP END PARALLEL
+ t = t + b
+ END FUNCTION
+
+! { dg-final { scan-tree-dump-times "#pragma omp parallel reduction\\(\\+:b\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp single copyprivate\\(b\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp atomic relaxed" 1 "original" } }
diff --git a/gcc/testsuite/gfortran.dg/gomp/copyprivate-2.f90 b/gcc/testsuite/gfortran.dg/gomp/copyprivate-2.f90
new file mode 100644
index 0000000..130f371
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/copyprivate-2.f90
@@ -0,0 +1,97 @@
+ FUNCTION t()
+ INTEGER :: a, b, t
+ a = 0
+ t = b
+ b = 0
+ !$OMP PARALLEL REDUCTION(+:b)
+ !$OMP SINGLE COPYPRIVATE (b) NOWAIT ! { dg-error "NOWAIT clause must not be used with COPYPRIVATE clause" }
+ !$OMP ATOMIC WRITE
+ b = 6
+ !$OMP END SINGLE
+ !$OMP END PARALLEL
+ t = t + b
+ END FUNCTION
+
+ FUNCTION t2()
+ INTEGER :: a, b, t2
+ a = 0
+ t2 = b
+ b = 0
+ !$OMP PARALLEL REDUCTION(+:b)
+ !$OMP SINGLE NOWAIT COPYPRIVATE (b) ! { dg-error "NOWAIT clause must not be used with COPYPRIVATE clause" }
+ !$OMP ATOMIC WRITE
+ b = 6
+ !$OMP END SINGLE
+ !$OMP END PARALLEL
+ t2 = t2 + b
+ END FUNCTION
+
+ FUNCTION t3()
+ INTEGER :: a, b, t3
+ a = 0
+ t3 = b
+ b = 0
+ !$OMP PARALLEL REDUCTION(+:b)
+ !$OMP SINGLE COPYPRIVATE (b) ! { dg-error "NOWAIT clause must not be used with COPYPRIVATE clause" }
+ !$OMP ATOMIC WRITE
+ b = 6
+ !$OMP END SINGLE NOWAIT
+ !$OMP END PARALLEL
+ t3 = t3 + b
+ END FUNCTION
+
+ FUNCTION t4()
+ INTEGER :: a, b, t4
+ a = 0
+ t4 = b
+ b = 0
+ !$OMP PARALLEL REDUCTION(+:b)
+ !$OMP SINGLE
+ !$OMP ATOMIC WRITE
+ b = 6
+ !$OMP END SINGLE NOWAIT COPYPRIVATE (b) ! { dg-error "NOWAIT clause must not be used with COPYPRIVATE clause" }
+ !$OMP END PARALLEL
+ t4 = t4 + b
+ END FUNCTION
+
+ FUNCTION t5()
+ INTEGER :: a, b, t5
+ a = 0
+ t5 = b
+ b = 0
+ !$OMP PARALLEL REDUCTION(+:b)
+ !$OMP SINGLE
+ !$OMP ATOMIC WRITE
+ b = 6
+ !$OMP END SINGLE COPYPRIVATE (b) NOWAIT ! { dg-error "NOWAIT clause must not be used with COPYPRIVATE clause" }
+ !$OMP END PARALLEL
+ t5 = t5 + b
+ END FUNCTION
+
+ FUNCTION t6()
+ INTEGER :: a, b, t6
+ a = 0
+ t6 = b
+ b = 0
+ !$OMP PARALLEL REDUCTION(+:b)
+ !$OMP SINGLE NOWAIT
+ !$OMP ATOMIC WRITE
+ b = 6
+ !$OMP END SINGLE COPYPRIVATE (b) ! { dg-error "NOWAIT clause must not be used with COPYPRIVATE clause" }
+ !$OMP END PARALLEL
+ t6 = t6 + b
+ END FUNCTION
+
+ FUNCTION t7()
+ INTEGER :: a, b, t7
+ a = 0
+ t7 = b
+ b = 0
+ !$OMP PARALLEL REDUCTION(+:b)
+ !$OMP SINGLE COPYPRIVATE (b)
+ !$OMP ATOMIC WRITE
+ b = 7
+ !$OMP END SINGLE COPYPRIVATE (b) ! { dg-error "Symbol 'b' present on multiple clauses" }
+ !$OMP END PARALLEL
+ t7 = t7 + b
+ END FUNCTION
diff --git a/gcc/testsuite/gfortran.dg/gomp/nowait-2.f90 b/gcc/testsuite/gfortran.dg/gomp/nowait-2.f90
index d18459b..c688117 100644
--- a/gcc/testsuite/gfortran.dg/gomp/nowait-2.f90
+++ b/gcc/testsuite/gfortran.dg/gomp/nowait-2.f90
@@ -154,162 +154,3 @@ end do
!$omp end target data
end
-
-! invalid nowait
-
-subroutine foo
-implicit none
-integer :: i, a(5)
-!$omp atomic write
-i = 5
-!$omp end atomic nowait ! { dg-error "Unexpected junk" }
-
-!$omp critical
-!$omp end critical nowait ! { dg-error "Unexpected junk" }
-
-!$omp distribute
-do i = 1, 5
-end do
-!$omp end distribute nowait ! { dg-error "Unexpected junk" }
-
-!$omp distribute parallel do
-do i = 1, 5
-end do
-!$omp end distribute parallel do nowait ! { dg-error "Unexpected junk" }
-
-!$omp distribute parallel do simd
-do i = 1, 5
-end do
-!$omp end distribute parallel do simd nowait ! { dg-error "Unexpected junk" }
-
-!$omp parallel sections
- !$omp section
- block; end block
-!$omp end parallel sections nowait ! { dg-error "Unexpected junk" }
-
-!$omp distribute simd
-do i = 1, 5
-end do
-!$omp end distribute simd nowait ! { dg-error "Unexpected junk" }
-
-!$omp masked
-!$omp end masked nowait ! { dg-error "Unexpected junk" }
-
-!$omp masked taskloop
-do i = 1, 5
-end do
-!$omp end masked taskloop nowait ! { dg-error "Unexpected junk" }
-
-!$omp masked taskloop simd
-do i = 1, 5
-end do
-!$omp end masked taskloop simd nowait ! { dg-error "Unexpected junk" }
-
-!$omp master
-!$omp end master nowait ! { dg-error "Unexpected junk" }
-
-!$omp master taskloop
-do i = 1, 5
-end do
-!$omp end master taskloop nowait ! { dg-error "Unexpected junk" }
-
-!$omp master taskloop simd
-do i = 1, 5
-end do
-!$omp end master taskloop simd nowait ! { dg-error "Unexpected junk" }
-
-!$omp ordered
-!$omp end ordered nowait ! { dg-error "Unexpected junk" }
-
-!$omp parallel
-!$omp end parallel nowait ! { dg-error "Unexpected junk" }
-
-!$omp parallel workshare
-a(:) = 5
-!$omp end parallel workshare nowait ! { dg-error "Unexpected junk" }
-
-!$omp parallel do
-do i = 1, 5
-end do
-!$omp end parallel do nowait ! { dg-error "Unexpected junk" }
-
-!$omp parallel do simd
-do i = 1, 5
-end do
-!$omp end parallel do simd nowait ! { dg-error "Unexpected junk" }
-
-!$omp parallel masked
-!$omp end parallel masked nowait ! { dg-error "Unexpected junk" }
-
-!$omp parallel masked taskloop
-do i = 1, 5
-end do
-!$omp end parallel masked taskloop nowait ! { dg-error "Unexpected junk" }
-
-!$omp parallel masked taskloop simd
-do i = 1, 5
-end do
-!$omp end parallel masked taskloop simd nowait ! { dg-error "Unexpected junk" }
-
-!$omp parallel master
-!$omp end parallel master nowait ! { dg-error "Unexpected junk" }
-
-!$omp parallel master taskloop
-do i = 1, 5
-end do
-!$omp end parallel master taskloop nowait ! { dg-error "Unexpected junk" }
-
-!$omp parallel master taskloop simd
-do i = 1, 5
-end do
-!$omp end parallel master taskloop simd nowait ! { dg-error "Unexpected junk" }
-
-!$omp simd
-do i = 1, 5
-end do
-!$omp end simd nowait ! { dg-error "Unexpected junk" }
-
-!$omp task
-!$omp end task nowait ! { dg-error "Unexpected junk" }
-
-!$omp taskgroup
-!$omp end taskgroup nowait ! { dg-error "Unexpected junk" }
-
-!$omp taskloop
-do i = 1, 5
-end do
-!$omp end taskloop nowait ! { dg-error "Unexpected junk" }
-
-!$omp taskloop simd
-do i = 1, 5
-end do
-!$omp end taskloop simd nowait ! { dg-error "Unexpected junk" }
-
-!$omp teams
-!$omp end teams nowait ! { dg-error "Unexpected junk" }
-
-!$omp teams distribute
-do i = 1, 5
-end do
-!$omp end teams distribute nowait ! { dg-error "Unexpected junk" }
-
-!$omp teams distribute parallel do
-do i = 1, 5
-end do
-!$omp end teams distribute parallel do nowait ! { dg-error "Unexpected junk" }
-
-!$omp teams distribute parallel do simd
-do i = 1, 5
-end do
-!$omp end teams distribute parallel do simd nowait ! { dg-error "Unexpected junk" }
-
-!$omp teams distribute simd
-do i = 1, 5
-end do
-!$omp end teams distribute simd nowait ! { dg-error "Unexpected junk" }
-
-!$omp target data map(tofrom:i)
-!$omp end target data nowait ! { dg-error "Unexpected junk" }
-
-end ! { dg-error "Unexpected END statement" }
-! { dg-prune-output "Unexpected end of file" }
diff --git a/gcc/testsuite/gfortran.dg/gomp/nowait-4.f90 b/gcc/testsuite/gfortran.dg/gomp/nowait-4.f90
new file mode 100644
index 0000000..bebb9d7
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/nowait-4.f90
@@ -0,0 +1,158 @@
+! invalid nowait
+
+subroutine foo
+implicit none
+integer :: i, a(5)
+!$omp atomic write
+i = 5
+!$omp end atomic nowait ! { dg-error "Unexpected junk" }
+
+!$omp critical
+!$omp end critical nowait ! { dg-error "Unexpected junk" }
+
+!$omp distribute
+do i = 1, 5
+end do
+!$omp end distribute nowait ! { dg-error "Unexpected junk" }
+
+!$omp distribute parallel do
+do i = 1, 5
+end do
+!$omp end distribute parallel do nowait ! { dg-error "Unexpected junk" }
+
+!$omp distribute parallel do simd
+do i = 1, 5
+end do
+!$omp end distribute parallel do simd nowait ! { dg-error "Unexpected junk" }
+
+!$omp parallel sections
+ !$omp section
+ block; end block
+!$omp end parallel sections nowait ! { dg-error "Unexpected junk" }
+
+!$omp distribute simd
+do i = 1, 5
+end do
+!$omp end distribute simd nowait ! { dg-error "Unexpected junk" }
+
+!$omp masked
+!$omp end masked nowait ! { dg-error "Unexpected junk" }
+
+!$omp masked taskloop
+do i = 1, 5
+end do
+!$omp end masked taskloop nowait ! { dg-error "Unexpected junk" }
+
+!$omp masked taskloop simd
+do i = 1, 5
+end do
+!$omp end masked taskloop simd nowait ! { dg-error "Unexpected junk" }
+
+!$omp master
+!$omp end master nowait ! { dg-error "Unexpected junk" }
+
+!$omp master taskloop
+do i = 1, 5
+end do
+!$omp end master taskloop nowait ! { dg-error "Unexpected junk" }
+
+!$omp master taskloop simd
+do i = 1, 5
+end do
+!$omp end master taskloop simd nowait ! { dg-error "Unexpected junk" }
+
+!$omp ordered
+!$omp end ordered nowait ! { dg-error "Unexpected junk" }
+
+!$omp parallel
+!$omp end parallel nowait ! { dg-error "Unexpected junk" }
+
+!$omp parallel workshare
+a(:) = 5
+!$omp end parallel workshare nowait ! { dg-error "Unexpected junk" }
+
+!$omp parallel do
+do i = 1, 5
+end do
+!$omp end parallel do nowait ! { dg-error "Unexpected junk" }
+
+!$omp parallel do simd
+do i = 1, 5
+end do
+!$omp end parallel do simd nowait ! { dg-error "Unexpected junk" }
+
+!$omp parallel masked
+!$omp end parallel masked nowait ! { dg-error "Unexpected junk" }
+
+!$omp parallel masked taskloop
+do i = 1, 5
+end do
+!$omp end parallel masked taskloop nowait ! { dg-error "Unexpected junk" }
+
+!$omp parallel masked taskloop simd
+do i = 1, 5
+end do
+!$omp end parallel masked taskloop simd nowait ! { dg-error "Unexpected junk" }
+
+!$omp parallel master
+!$omp end parallel master nowait ! { dg-error "Unexpected junk" }
+
+!$omp parallel master taskloop
+do i = 1, 5
+end do
+!$omp end parallel master taskloop nowait ! { dg-error "Unexpected junk" }
+
+!$omp parallel master taskloop simd
+do i = 1, 5
+end do
+!$omp end parallel master taskloop simd nowait ! { dg-error "Unexpected junk" }
+
+!$omp simd
+do i = 1, 5
+end do
+!$omp end simd nowait ! { dg-error "Unexpected junk" }
+
+!$omp task
+!$omp end task nowait ! { dg-error "Unexpected junk" }
+
+!$omp taskgroup
+!$omp end taskgroup nowait ! { dg-error "Unexpected junk" }
+
+!$omp taskloop
+do i = 1, 5
+end do
+!$omp end taskloop nowait ! { dg-error "Unexpected junk" }
+
+!$omp taskloop simd
+do i = 1, 5
+end do
+!$omp end taskloop simd nowait ! { dg-error "Unexpected junk" }
+
+!$omp teams
+!$omp end teams nowait ! { dg-error "Unexpected junk" }
+
+!$omp teams distribute
+do i = 1, 5
+end do
+!$omp end teams distribute nowait ! { dg-error "Unexpected junk" }
+
+!$omp teams distribute parallel do
+do i = 1, 5
+end do
+!$omp end teams distribute parallel do nowait ! { dg-error "Unexpected junk" }
+
+!$omp teams distribute parallel do simd
+do i = 1, 5
+end do
+!$omp end teams distribute parallel do simd nowait ! { dg-error "Unexpected junk" }
+
+!$omp teams distribute simd
+do i = 1, 5
+end do
+!$omp end teams distribute simd nowait ! { dg-error "Unexpected junk" }
+
+!$omp target data map(tofrom:i)
+!$omp end target data nowait ! { dg-error "Unexpected junk" }
+
+end ! { dg-error "Unexpected END statement" }
+! { dg-prune-output "Unexpected end of file" }
diff --git a/gcc/testsuite/gfortran.dg/gomp/nowait-5.f90 b/gcc/testsuite/gfortran.dg/gomp/nowait-5.f90
new file mode 100644
index 0000000..c688117
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/nowait-5.f90
@@ -0,0 +1,156 @@
+! Cross check that it is accepted without nowait
+subroutine bar()
+implicit none
+integer :: i, a(5)
+!$omp atomic write
+i = 5
+!$omp end atomic
+
+!$omp critical
+!$omp end critical
+
+!$omp distribute
+do i = 1, 5
+end do
+!$omp end distribute
+
+!$omp distribute parallel do
+do i = 1, 5
+end do
+!$omp end distribute parallel do
+
+!$omp distribute parallel do simd
+do i = 1, 5
+end do
+!$omp end distribute parallel do simd
+
+!$omp distribute simd
+do i = 1, 5
+end do
+!$omp end distribute simd
+
+!$omp masked
+!$omp end masked
+
+!$omp masked taskloop
+do i = 1, 5
+end do
+!$omp end masked taskloop
+
+!$omp masked taskloop simd
+do i = 1, 5
+end do
+!$omp end masked taskloop simd
+
+!$omp master
+!$omp end master
+
+!$omp master taskloop
+do i = 1, 5
+end do
+!$omp end master taskloop
+
+!$omp master taskloop simd
+do i = 1, 5
+end do
+!$omp end master taskloop simd
+
+!$omp ordered
+!$omp end ordered
+
+!$omp parallel
+!$omp end parallel
+
+!$omp parallel workshare
+a(:) = 5
+!$omp end parallel workshare
+
+!$omp parallel do
+do i = 1, 5
+end do
+!$omp end parallel do
+
+!$omp parallel do simd
+do i = 1, 5
+end do
+!$omp end parallel do simd
+
+!$omp parallel sections
+ !$omp section
+ block; end block
+!$omp end parallel sections
+
+!$omp parallel masked
+!$omp end parallel masked
+
+!$omp parallel masked taskloop
+do i = 1, 5
+end do
+!$omp end parallel masked taskloop
+
+!$omp parallel masked taskloop simd
+do i = 1, 5
+end do
+!$omp end parallel masked taskloop simd
+
+!$omp parallel master
+!$omp end parallel master
+
+!$omp parallel master taskloop
+do i = 1, 5
+end do
+!$omp end parallel master taskloop
+
+!$omp parallel master taskloop simd
+do i = 1, 5
+end do
+!$omp end parallel master taskloop simd
+
+!$omp simd
+do i = 1, 5
+end do
+!$omp end simd
+
+!$omp task
+!$omp end task
+
+!$omp taskgroup
+!$omp end taskgroup
+
+!$omp taskloop
+do i = 1, 5
+end do
+!$omp end taskloop
+
+!$omp taskloop simd
+do i = 1, 5
+end do
+!$omp end taskloop simd
+
+!$omp teams
+!$omp end teams
+
+!$omp teams distribute
+do i = 1, 5
+end do
+!$omp end teams distribute
+
+!$omp teams distribute parallel do
+do i = 1, 5
+end do
+!$omp end teams distribute parallel do
+
+!$omp teams distribute parallel do simd
+do i = 1, 5
+end do
+!$omp end teams distribute parallel do simd
+
+!$omp teams distribute simd
+do i = 1, 5
+end do
+!$omp end teams distribute simd
+
+!$omp target data map(tofrom:i)
+!$omp end target data
+
+end
diff --git a/gcc/testsuite/gfortran.dg/gomp/nowait-6.f90 b/gcc/testsuite/gfortran.dg/gomp/nowait-6.f90
new file mode 100644
index 0000000..5fe7d38
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/nowait-6.f90
@@ -0,0 +1,158 @@
+! invalid nowait
+
+subroutine foo
+implicit none
+integer :: i, a(5)
+!$omp atomic write nowait ! { dg-error "Failed to match clause" }
+i = 5
+!$omp end atomic ! { dg-error "Unexpected ..OMP END " }
+
+!$omp critical nowait ! { dg-error "Failed to match clause" }
+!$omp end critical ! { dg-error "Unexpected ..OMP END " }
+
+!$omp distribute nowait ! { dg-error "Failed to match clause" }
+do i = 1, 5
+end do
+!$omp end distribute ! { dg-error "Unexpected ..OMP END " }
+
+!$omp distribute parallel do nowait ! { dg-error "Failed to match clause" }
+do i = 1, 5
+end do
+!$omp end distribute parallel do ! { dg-error "Unexpected ..OMP END " }
+
+!$omp distribute parallel do simd nowait ! { dg-error "Failed to match clause" }
+do i = 1, 5
+end do
+!$omp end distribute parallel do simd ! { dg-error "Unexpected ..OMP END " }
+
+!$omp parallel sections nowait ! { dg-error "Failed to match clause" }
+ !$omp section ! { dg-error "Unexpected ..OMP SECTION statement" }
+ block; end block
+!$omp end parallel sections ! { dg-error "Unexpected ..OMP END " }
+
+!$omp distribute simd nowait ! { dg-error "Failed to match clause" }
+do i = 1, 5
+end do
+!$omp end distribute simd ! { dg-error "Unexpected ..OMP END " }
+
+!$omp masked nowait ! { dg-error "Failed to match clause" }
+!$omp end masked ! { dg-error "Unexpected ..OMP END " }
+
+!$omp masked taskloop nowait ! { dg-error "Failed to match clause" }
+do i = 1, 5
+end do
+!$omp end masked taskloop ! { dg-error "Unexpected ..OMP END " }
+
+!$omp masked taskloop simd nowait ! { dg-error "Failed to match clause" }
+do i = 1, 5
+end do
+!$omp end masked taskloop simd ! { dg-error "Unexpected ..OMP END " }
+
+!$omp master nowait ! { dg-error "Unexpected junk" }
+!$omp end master ! { dg-error "Unexpected ..OMP END " }
+
+!$omp master taskloop nowait ! { dg-error "Failed to match clause" }
+do i = 1, 5
+end do
+!$omp end master taskloop ! { dg-error "Unexpected ..OMP END " }
+
+!$omp master taskloop simd nowait ! { dg-error "Failed to match clause" }
+do i = 1, 5
+end do
+!$omp end master taskloop simd ! { dg-error "Unexpected ..OMP END " }
+
+!$omp ordered nowait ! { dg-error "Failed to match clause" }
+!$omp end ordered ! { dg-error "Unexpected ..OMP END " }
+
+!$omp parallel nowait ! { dg-error "Failed to match clause" }
+!$omp end parallel ! { dg-error "Unexpected ..OMP END " }
+
+!$omp parallel workshare nowait ! { dg-error "Failed to match clause" }
+a(:) = 5
+!$omp end parallel workshare ! { dg-error "Unexpected ..OMP END " }
+
+!$omp parallel do nowait ! { dg-error "Failed to match clause" }
+do i = 1, 5
+end do
+!$omp end parallel do ! { dg-error "Unexpected ..OMP END " }
+
+!$omp parallel do simd nowait ! { dg-error "Failed to match clause" }
+do i = 1, 5
+end do
+!$omp end parallel do simd ! { dg-error "Unexpected ..OMP END " }
+
+!$omp parallel masked nowait ! { dg-error "Failed to match clause" }
+!$omp end parallel masked ! { dg-error "Unexpected ..OMP END " }
+
+!$omp parallel masked taskloop nowait ! { dg-error "Failed to match clause" }
+do i = 1, 5
+end do
+!$omp end parallel masked taskloop ! { dg-error "Unexpected ..OMP END " }
+
+!$omp parallel masked taskloop simd nowait ! { dg-error "Failed to match clause" }
+do i = 1, 5
+end do
+!$omp end parallel masked taskloop simd ! { dg-error "Unexpected ..OMP END " }
+
+!$omp parallel master nowait ! { dg-error "Failed to match clause" }
+!$omp end parallel master ! { dg-error "Unexpected ..OMP END " }
+
+!$omp parallel master taskloop nowait ! { dg-error "Failed to match clause" }
+do i = 1, 5
+end do
+!$omp end parallel master taskloop ! { dg-error "Unexpected ..OMP END " }
+
+!$omp parallel master taskloop simd nowait ! { dg-error "Failed to match clause" }
+do i = 1, 5
+end do
+!$omp end parallel master taskloop simd ! { dg-error "Unexpected ..OMP END " }
+
+!$omp simd nowait ! { dg-error "Failed to match clause" }
+do i = 1, 5
+end do
+!$omp end simd ! { dg-error "Unexpected ..OMP END " }
+
+!$omp task nowait ! { dg-error "Failed to match clause" }
+!$omp end task ! { dg-error "Unexpected ..OMP END " }
+
+!$omp taskgroup nowait ! { dg-error "Failed to match clause" }
+!$omp end taskgroup ! { dg-error "Unexpected ..OMP END " }
+
+!$omp taskloop nowait ! { dg-error "Failed to match clause" }
+do i = 1, 5
+end do
+!$omp end taskloop ! { dg-error "Unexpected ..OMP END " }
+
+!$omp taskloop simd nowait ! { dg-error "Failed to match clause" }
+do i = 1, 5
+end do
+!$omp end taskloop simd ! { dg-error "Unexpected ..OMP END " }
+
+!$omp teams nowait ! { dg-error "Failed to match clause" }
+!$omp end teams ! { dg-error "Unexpected ..OMP END " }
+
+!$omp teams distribute nowait ! { dg-error "Failed to match clause" }
+do i = 1, 5
+end do
+!$omp end teams distribute ! { dg-error "Unexpected ..OMP END " }
+
+!$omp teams distribute parallel do nowait ! { dg-error "Failed to match clause" }
+do i = 1, 5
+end do
+!$omp end teams distribute parallel do ! { dg-error "Unexpected ..OMP END " }
+
+!$omp teams distribute parallel do simd nowait ! { dg-error "Failed to match clause" }
+do i = 1, 5
+end do
+!$omp end teams distribute parallel do simd ! { dg-error "Unexpected ..OMP END " }
+
+!$omp teams distribute simd nowait ! { dg-error "Failed to match clause" }
+do i = 1, 5
+end do
+!$omp end teams distribute simd ! { dg-error "Unexpected ..OMP END " }
+
+!$omp target data map(tofrom:i) nowait ! { dg-error "Failed to match clause" }
+!$omp end target data ! { dg-error "Unexpected ..OMP END " }
+
+end
+! { dg-prune-output "Unexpected end of file" }
diff --git a/gcc/testsuite/gfortran.dg/gomp/nowait-7.f90 b/gcc/testsuite/gfortran.dg/gomp/nowait-7.f90
new file mode 100644
index 0000000..41ead2f
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/nowait-7.f90
@@ -0,0 +1,118 @@
+! { dg-additional-options "-fdump-tree-original" }
+
+subroutine foo
+implicit none
+integer :: i, a(5)
+
+!$omp do nowait
+do i = 1, 5
+end do
+!$omp end do
+
+!$omp do simd nowait
+do i = 1, 5
+end do
+!$omp end do simd
+
+!$omp scope nowait
+!$omp end scope
+
+!$omp sections nowait
+ !$omp section
+ block; end block
+!$omp end sections
+
+!$omp single nowait
+!$omp end single
+
+!$omp target nowait
+!$omp end target
+
+!$omp target parallel nowait
+!$omp end target parallel
+
+!$omp target parallel do nowait
+do i = 1, 5
+end do
+!$omp end target parallel do
+
+!$omp target parallel do simd nowait
+do i = 1, 5
+end do
+!$omp end target parallel do simd
+
+!$omp target parallel loop nowait
+do i = 1, 5
+end do
+!$omp end target parallel loop
+
+!$omp target teams distribute parallel do nowait
+do i = 1, 5
+end do
+!$omp end target teams distribute parallel do
+
+!$omp target teams distribute parallel do simd nowait
+do i = 1, 5
+end do
+!$omp end target teams distribute parallel do simd
+
+!$omp target simd nowait
+do i = 1, 5
+end do
+!$omp end target simd
+
+!$omp target teams nowait
+!$omp end target teams
+
+!$omp target teams distribute nowait
+do i = 1, 5
+end do
+!$omp end target teams distribute
+
+!$omp target teams distribute simd nowait
+do i = 1, 5
+end do
+!$omp end target teams distribute simd
+
+!$omp target teams loop nowait
+do i = 1, 5
+end do
+!$omp end target teams loop
+
+!$omp workshare nowait
+A(:) = 5
+!$omp end workshare
+end
+
+! Note: internally, for '... parallel do ...', 'nowait' is always added
+! such that for 'omp end target parallel do nowait', 'nowait' is on both
+! 'target' as specified in the OpenMP spec and and on 'do' due to internal usage.
+
+! Expected with 'nowait'
+
+! { dg-final { scan-tree-dump-times "#pragma omp for nowait" 6 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp for schedule\\(static\\) nowait" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp sections nowait" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp single nowait" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp target nowait" 12 "original" } }
+
+! Never:
+
+! { dg-final { scan-tree-dump-not "#pragma omp distribute\[^\n\r]*nowait" "original" } }
+! { dg-final { scan-tree-dump-not "#pragma omp loop\[^\n\r]*nowait" "original" } }
+! { dg-final { scan-tree-dump-not "#pragma omp parallel\[^\n\r]*nowait" "original" } }
+! { dg-final { scan-tree-dump-not "#pragma omp section\[^s\]\[^\n\r]*nowait" "original" } }
+! { dg-final { scan-tree-dump-not "#pragma omp simd\[^\n\r]*nowait" "original" } }
+! { dg-final { scan-tree-dump-not "#pragma omp teams\[^\n\r]*nowait" "original" } }
+
+! Sometimes or never with nowait:
+
+! { dg-final { scan-tree-dump-times "#pragma omp distribute\[\n\r]" 4 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp loop\[\n\r]" 2 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp parallel\[\n\r]" 6 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp section\[\n\r]" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp simd linear\\(i:1\\)\[\n\r]" 5 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp teams\[\n\r]" 6 "original" } }
+
+! { dg-final { scan-tree-dump-times "#pragma omp target\[\n\r]" 0 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp for\[\n\r]" 0 "original" } }
diff --git a/gcc/testsuite/gfortran.dg/gomp/nowait-8.f90 b/gcc/testsuite/gfortran.dg/gomp/nowait-8.f90
new file mode 100644
index 0000000..5e666d1
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/nowait-8.f90
@@ -0,0 +1,92 @@
+subroutine foo
+implicit none
+integer :: i, a(5)
+
+!$omp do nowait nowait ! { dg-error "Duplicated 'nowait' clause" }
+do i = 1, 5
+end do
+
+!$omp do
+do i = 1, 5
+end do
+!$omp do nowait nowait ! { dg-error "Duplicated 'nowait' clause" }
+
+!$omp do nowait
+do i = 1, 5
+end do
+!$omp end do nowait ! { dg-error "Duplicated NOWAIT clause" }
+
+!$omp do simd nowait
+do i = 1, 5
+end do
+!$omp end do simd nowait ! { dg-error "Duplicated NOWAIT clause" }
+
+!$omp scope nowait
+!$omp end scope nowait ! { dg-error "Duplicated NOWAIT clause" }
+
+!$omp sections nowait
+ !$omp section
+ block; end block
+!$omp end sections nowait ! { dg-error "Duplicated NOWAIT clause" }
+
+!$omp single nowait
+!$omp end single nowait ! { dg-error "Duplicated NOWAIT clause" }
+
+!$omp target nowait
+!$omp end target nowait ! { dg-error "Duplicated NOWAIT clause" }
+
+!$omp target parallel nowait
+!$omp end target parallel nowait ! { dg-error "Duplicated NOWAIT clause" }
+
+!$omp target parallel do nowait
+do i = 1, 5
+end do
+!$omp end target parallel do nowait ! { dg-error "Duplicated NOWAIT clause" }
+
+!$omp target parallel do simd nowait
+do i = 1, 5
+end do
+!$omp end target parallel do simd nowait ! { dg-error "Duplicated NOWAIT clause" }
+
+!$omp target parallel loop nowait
+do i = 1, 5
+end do
+!$omp end target parallel loop nowait ! { dg-error "Duplicated NOWAIT clause" }
+
+!$omp target teams distribute parallel do nowait
+do i = 1, 5
+end do
+!$omp end target teams distribute parallel do nowait ! { dg-error "Duplicated NOWAIT clause" }
+
+!$omp target teams distribute parallel do simd nowait
+do i = 1, 5
+end do
+!$omp end target teams distribute parallel do simd nowait ! { dg-error "Duplicated NOWAIT clause" }
+
+!$omp target simd nowait
+do i = 1, 5
+end do
+!$omp end target simd nowait ! { dg-error "Duplicated NOWAIT clause" }
+
+!$omp target teams nowait
+!$omp end target teams nowait ! { dg-error "Duplicated NOWAIT clause" }
+
+!$omp target teams distribute nowait
+do i = 1, 5
+end do
+!$omp end target teams distribute nowait ! { dg-error "Duplicated NOWAIT clause" }
+
+!$omp target teams distribute simd nowait
+do i = 1, 5
+end do
+!$omp end target teams distribute simd nowait ! { dg-error "Duplicated NOWAIT clause" }
+
+!$omp target teams loop nowait
+do i = 1, 5
+end do
+!$omp end target teams loop nowait ! { dg-error "Duplicated NOWAIT clause" }
+
+!$omp workshare nowait
+A(:) = 5
+!$omp end workshare nowait ! { dg-error "Duplicated NOWAIT clause" }
+end
diff --git a/libgomp/libgomp.texi b/libgomp/libgomp.texi
index 584af45..85cae74 100644
--- a/libgomp/libgomp.texi
+++ b/libgomp/libgomp.texi
@@ -375,7 +375,7 @@ to address of matching mapped list item per 5.1, Sect. 2.21.7.2 @tab N @tab
a warning enabled by default and, for fixed-source code, the @code{omx}
sentinel is warned for with with @code{-Wsurprising} (enabled by
@code{-Wall}). Unknown clauses are always rejected with an error.}
-@item Clauses on @code{end} directive can be on directive @tab N @tab
+@item Clauses on @code{end} directive can be on directive @tab Y @tab
@item Deprecation of no-argument @code{destroy} clause on @code{depobj}
@tab N @tab
@item @code{linear} clause syntax changes and @code{step} modifier @tab Y @tab