OpenMP: Support acquires/release in 'omp require atomic_default_mem_order'
This is an OpenMP 5.2 feature.
gcc/c/ChangeLog:
* c-parser.cc (c_parser_omp_requires): Handle acquires/release
in atomic_default_mem_order clause.
(c_parser_omp_atomic): Update.
gcc/cp/ChangeLog:
* parser.cc (cp_parser_omp_requires): Handle acquires/release
in atomic_default_mem_order clause.
(cp_parser_omp_atomic): Update.
gcc/fortran/ChangeLog:
* gfortran.h (enum gfc_omp_requires_kind): Add
OMP_REQ_ATOMIC_MEM_ORDER_ACQUIRE and OMP_REQ_ATOMIC_MEM_ORDER_RELEASE.
(gfc_namespace): Add a 7th bit to omp_requires.
* module.cc (enum ab_attribute): Add AB_OMP_REQ_MEM_ORDER_ACQUIRE
and AB_OMP_REQ_MEM_ORDER_RELEASE
(mio_symbol_attribute): Handle it.
* openmp.cc (gfc_omp_requires_add_clause): Update for acquire/release.
(gfc_match_omp_requires): Likewise.
(gfc_match_omp_atomic): Handle them for atomic_default_mem_order.
* parse.cc: Likewise.
gcc/testsuite/ChangeLog:
* c-c++-common/gomp/requires-3.c: Update for now valid code.
* gfortran.dg/gomp/requires-3.f90: Likewise.
* gfortran.dg/gomp/requires-2.f90: Update dg-error.
* gfortran.dg/gomp/requires-5.f90: Likewise.
* c-c++-common/gomp/requires-5.c: New test.
* c-c++-common/gomp/requires-6.c: New test.
* c-c++-common/gomp/requires-7.c: New test.
* c-c++-common/gomp/requires-8.c: New test.
* gfortran.dg/gomp/requires-10.f90: New test.
* gfortran.dg/gomp/requires-11.f90: New test.
gcc/c/c-parser.cc | 32 +++++++++++++++-
gcc/cp/parser.cc | 32 +++++++++++++++-
gcc/fortran/gfortran.h | 22 ++++++-----
gcc/fortran/module.cc | 19 +++++++++
gcc/fortran/openmp.cc | 53 +++++++++++++++++++++-----
gcc/fortran/parse.cc | 8 ++++
gcc/testsuite/c-c++-common/gomp/requires-3.c | 8 ++--
gcc/testsuite/c-c++-common/gomp/requires-5.c | 23 +++++++++++
gcc/testsuite/c-c++-common/gomp/requires-6.c | 23 +++++++++++
gcc/testsuite/c-c++-common/gomp/requires-7.c | 11 ++++++
gcc/testsuite/c-c++-common/gomp/requires-8.c | 14 +++++++
gcc/testsuite/gfortran.dg/gomp/requires-10.f90 | 36 +++++++++++++++++
gcc/testsuite/gfortran.dg/gomp/requires-11.f90 | 31 +++++++++++++++
gcc/testsuite/gfortran.dg/gomp/requires-2.f90 | 2 +-
gcc/testsuite/gfortran.dg/gomp/requires-3.f90 | 7 ++--
gcc/testsuite/gfortran.dg/gomp/requires-5.f90 | 2 +-
16 files changed, 291 insertions(+), 32 deletions(-)
@@ -20896,6 +20896,28 @@ c_parser_omp_atomic (location_t loc, c_parser *parser, bool openacc)
case OMP_MEMORY_ORDER_SEQ_CST:
memory_order = OMP_MEMORY_ORDER_SEQ_CST;
break;
+ case OMP_MEMORY_ORDER_ACQUIRE:
+ if (code == NOP_EXPR) /* atomic write */
+ {
+ error_at (loc, "%<#pragma omp atomic write%> incompatible with "
+ "%<acquire%> clause implicitly provided by a "
+ "%<requires%> directive");
+ memory_order = OMP_MEMORY_ORDER_SEQ_CST;
+ }
+ else
+ memory_order = OMP_MEMORY_ORDER_ACQUIRE;
+ break;
+ case OMP_MEMORY_ORDER_RELEASE:
+ if (code == OMP_ATOMIC_READ)
+ {
+ error_at (loc, "%<#pragma omp atomic read%> incompatible with "
+ "%<release%> clause implicitly provided by a "
+ "%<requires%> directive");
+ memory_order = OMP_MEMORY_ORDER_SEQ_CST;
+ }
+ else
+ memory_order = OMP_MEMORY_ORDER_RELEASE;
+ break;
case OMP_MEMORY_ORDER_ACQ_REL:
switch (code)
{
@@ -25724,15 +25746,21 @@ c_parser_omp_requires (c_parser *parser)
else if (!strcmp (p, "relaxed"))
this_req
= (enum omp_requires) OMP_MEMORY_ORDER_RELAXED;
+ else if (!strcmp (p, "release"))
+ this_req
+ = (enum omp_requires) OMP_MEMORY_ORDER_RELEASE;
else if (!strcmp (p, "acq_rel"))
this_req
= (enum omp_requires) OMP_MEMORY_ORDER_ACQ_REL;
+ else if (!strcmp (p, "acquire"))
+ this_req
+ = (enum omp_requires) OMP_MEMORY_ORDER_ACQUIRE;
}
if (this_req == 0)
{
error_at (c_parser_peek_token (parser)->location,
- "expected %<seq_cst%>, %<relaxed%> or "
- "%<acq_rel%>");
+ "expected %<acq_rel%>, %<acquire%>, "
+ "%<relaxed%>, %<release%> or %<seq_cst%>");
switch (c_parser_peek_token (parser)->type)
{
case CPP_EOF:
@@ -42436,6 +42436,28 @@ cp_parser_omp_atomic (cp_parser *parser, cp_token *pragma_tok, bool openacc)
case OMP_MEMORY_ORDER_SEQ_CST:
memory_order = OMP_MEMORY_ORDER_SEQ_CST;
break;
+ case OMP_MEMORY_ORDER_ACQUIRE:
+ if (code == NOP_EXPR) /* atomic write */
+ {
+ error_at (loc, "%<#pragma omp atomic write%> incompatible with "
+ "%<acquire%> clause implicitly provided by a "
+ "%<requires%> directive");
+ memory_order = OMP_MEMORY_ORDER_SEQ_CST;
+ }
+ else
+ memory_order = OMP_MEMORY_ORDER_ACQUIRE;
+ break;
+ case OMP_MEMORY_ORDER_RELEASE:
+ if (code == OMP_ATOMIC_READ)
+ {
+ error_at (loc, "%<#pragma omp atomic read%> incompatible with "
+ "%<release%> clause implicitly provided by a "
+ "%<requires%> directive");
+ memory_order = OMP_MEMORY_ORDER_SEQ_CST;
+ }
+ else
+ memory_order = OMP_MEMORY_ORDER_RELEASE;
+ break;
case OMP_MEMORY_ORDER_ACQ_REL:
switch (code)
{
@@ -49126,15 +49148,21 @@ cp_parser_omp_requires (cp_parser *parser, cp_token *pragma_tok)
else if (!strcmp (p, "relaxed"))
this_req
= (enum omp_requires) OMP_MEMORY_ORDER_RELAXED;
+ else if (!strcmp (p, "release"))
+ this_req
+ = (enum omp_requires) OMP_MEMORY_ORDER_RELEASE;
else if (!strcmp (p, "acq_rel"))
this_req
= (enum omp_requires) OMP_MEMORY_ORDER_ACQ_REL;
+ else if (!strcmp (p, "acquire"))
+ this_req
+ = (enum omp_requires) OMP_MEMORY_ORDER_ACQUIRE;
}
if (this_req == 0)
{
error_at (cp_lexer_peek_token (parser->lexer)->location,
- "expected %<seq_cst%>, %<relaxed%> or "
- "%<acq_rel%>");
+ "expected %<acq_rel%>, %<acquire%>, "
+ "%<relaxed%>, %<release%> or %<seq_cst%>");
switch (cp_lexer_peek_token (parser->lexer)->type)
{
case CPP_EOF:
@@ -1496,19 +1496,23 @@ enum gfc_omp_atomic_op
enum gfc_omp_requires_kind
{
/* Keep in sync with gfc_namespace, esp. with omp_req_mem_order. */
- OMP_REQ_ATOMIC_MEM_ORDER_SEQ_CST = 1, /* 01 */
- OMP_REQ_ATOMIC_MEM_ORDER_ACQ_REL = 2, /* 10 */
- OMP_REQ_ATOMIC_MEM_ORDER_RELAXED = 3, /* 11 */
- OMP_REQ_REVERSE_OFFLOAD = (1 << 2),
- OMP_REQ_UNIFIED_ADDRESS = (1 << 3),
- OMP_REQ_UNIFIED_SHARED_MEMORY = (1 << 4),
- OMP_REQ_DYNAMIC_ALLOCATORS = (1 << 5),
+ OMP_REQ_ATOMIC_MEM_ORDER_SEQ_CST = 1, /* 001 */
+ OMP_REQ_ATOMIC_MEM_ORDER_ACQ_REL = 2, /* 010 */
+ OMP_REQ_ATOMIC_MEM_ORDER_RELAXED = 3, /* 011 */
+ OMP_REQ_ATOMIC_MEM_ORDER_ACQUIRE = 4, /* 100 */
+ OMP_REQ_ATOMIC_MEM_ORDER_RELEASE = 5, /* 101 */
+ OMP_REQ_REVERSE_OFFLOAD = (1 << 3),
+ OMP_REQ_UNIFIED_ADDRESS = (1 << 4),
+ OMP_REQ_UNIFIED_SHARED_MEMORY = (1 << 5),
+ OMP_REQ_DYNAMIC_ALLOCATORS = (1 << 6),
OMP_REQ_TARGET_MASK = (OMP_REQ_REVERSE_OFFLOAD
| OMP_REQ_UNIFIED_ADDRESS
| OMP_REQ_UNIFIED_SHARED_MEMORY),
OMP_REQ_ATOMIC_MEM_ORDER_MASK = (OMP_REQ_ATOMIC_MEM_ORDER_SEQ_CST
| OMP_REQ_ATOMIC_MEM_ORDER_ACQ_REL
- | OMP_REQ_ATOMIC_MEM_ORDER_RELAXED)
+ | OMP_REQ_ATOMIC_MEM_ORDER_RELAXED
+ | OMP_REQ_ATOMIC_MEM_ORDER_ACQUIRE
+ | OMP_REQ_ATOMIC_MEM_ORDER_RELEASE)
};
enum gfc_omp_memorder
@@ -2257,7 +2261,7 @@ typedef struct gfc_namespace
unsigned implicit_interface_calls:1;
/* OpenMP requires. */
- unsigned omp_requires:6;
+ unsigned omp_requires:7;
unsigned omp_target_seen:1;
/* Set to 1 if this is an implicit OMP structured block. */
@@ -2093,6 +2093,7 @@ enum ab_attribute
AB_OMP_REQ_REVERSE_OFFLOAD, AB_OMP_REQ_UNIFIED_ADDRESS,
AB_OMP_REQ_UNIFIED_SHARED_MEMORY, AB_OMP_REQ_DYNAMIC_ALLOCATORS,
AB_OMP_REQ_MEM_ORDER_SEQ_CST, AB_OMP_REQ_MEM_ORDER_ACQ_REL,
+ AB_OMP_REQ_MEM_ORDER_ACQUIRE, AB_OMP_REQ_MEM_ORDER_RELEASE,
AB_OMP_REQ_MEM_ORDER_RELAXED, AB_OMP_DEVICE_TYPE_NOHOST,
AB_OMP_DEVICE_TYPE_HOST, AB_OMP_DEVICE_TYPE_ANY
};
@@ -2175,7 +2176,9 @@ static const mstring attr_bits[] =
minit ("OMP_REQ_DYNAMIC_ALLOCATORS", AB_OMP_REQ_DYNAMIC_ALLOCATORS),
minit ("OMP_REQ_MEM_ORDER_SEQ_CST", AB_OMP_REQ_MEM_ORDER_SEQ_CST),
minit ("OMP_REQ_MEM_ORDER_ACQ_REL", AB_OMP_REQ_MEM_ORDER_ACQ_REL),
+ minit ("OMP_REQ_MEM_ORDER_ACQUIRE", AB_OMP_REQ_MEM_ORDER_ACQUIRE),
minit ("OMP_REQ_MEM_ORDER_RELAXED", AB_OMP_REQ_MEM_ORDER_RELAXED),
+ minit ("OMP_REQ_MEM_ORDER_RELEASE", AB_OMP_REQ_MEM_ORDER_RELEASE),
minit ("OMP_DEVICE_TYPE_HOST", AB_OMP_DEVICE_TYPE_HOST),
minit ("OMP_DEVICE_TYPE_NOHOST", AB_OMP_DEVICE_TYPE_NOHOST),
minit ("OMP_DEVICE_TYPE_ANYHOST", AB_OMP_DEVICE_TYPE_ANY),
@@ -2442,9 +2445,15 @@ mio_symbol_attribute (symbol_attribute *attr)
if ((gfc_current_ns->omp_requires & OMP_REQ_ATOMIC_MEM_ORDER_MASK)
== OMP_REQ_ATOMIC_MEM_ORDER_ACQ_REL)
MIO_NAME (ab_attribute) (AB_OMP_REQ_MEM_ORDER_ACQ_REL, attr_bits);
+ if ((gfc_current_ns->omp_requires & OMP_REQ_ATOMIC_MEM_ORDER_MASK)
+ == OMP_REQ_ATOMIC_MEM_ORDER_ACQUIRE)
+ MIO_NAME (ab_attribute) (AB_OMP_REQ_MEM_ORDER_ACQUIRE, attr_bits);
if ((gfc_current_ns->omp_requires & OMP_REQ_ATOMIC_MEM_ORDER_MASK)
== OMP_REQ_ATOMIC_MEM_ORDER_RELAXED)
MIO_NAME (ab_attribute) (AB_OMP_REQ_MEM_ORDER_RELAXED, attr_bits);
+ if ((gfc_current_ns->omp_requires & OMP_REQ_ATOMIC_MEM_ORDER_MASK)
+ == OMP_REQ_ATOMIC_MEM_ORDER_RELEASE)
+ MIO_NAME (ab_attribute) (AB_OMP_REQ_MEM_ORDER_RELEASE, attr_bits);
}
switch (attr->omp_device_type)
{
@@ -2724,11 +2733,21 @@ mio_symbol_attribute (symbol_attribute *attr)
"acq_rel", &gfc_current_locus,
module_name);
break;
+ case AB_OMP_REQ_MEM_ORDER_ACQUIRE:
+ gfc_omp_requires_add_clause (OMP_REQ_ATOMIC_MEM_ORDER_ACQUIRE,
+ "acquires", &gfc_current_locus,
+ module_name);
+ break;
case AB_OMP_REQ_MEM_ORDER_RELAXED:
gfc_omp_requires_add_clause (OMP_REQ_ATOMIC_MEM_ORDER_RELAXED,
"relaxed", &gfc_current_locus,
module_name);
break;
+ case AB_OMP_REQ_MEM_ORDER_RELEASE:
+ gfc_omp_requires_add_clause (OMP_REQ_ATOMIC_MEM_ORDER_RELEASE,
+ "release", &gfc_current_locus,
+ module_name);
+ break;
case AB_OMP_DEVICE_TYPE_HOST:
attr->omp_device_type = OMP_DEVICE_TYPE_HOST;
break;
@@ -6251,14 +6251,15 @@ gfc_omp_requires_add_clause (gfc_omp_requires_kind clause,
!= (int) clause)
{
const char *other;
- if (prog_unit->omp_requires & OMP_REQ_ATOMIC_MEM_ORDER_SEQ_CST)
- other = "seq_cst";
- else if (prog_unit->omp_requires & OMP_REQ_ATOMIC_MEM_ORDER_ACQ_REL)
- other = "acq_rel";
- else if (prog_unit->omp_requires & OMP_REQ_ATOMIC_MEM_ORDER_RELAXED)
- other = "relaxed";
- else
- gcc_unreachable ();
+ switch (prog_unit->omp_requires & OMP_REQ_ATOMIC_MEM_ORDER_MASK)
+ {
+ case OMP_REQ_ATOMIC_MEM_ORDER_SEQ_CST: other = "seq_cst"; break;
+ case OMP_REQ_ATOMIC_MEM_ORDER_ACQ_REL: other = "acq_rel"; break;
+ case OMP_REQ_ATOMIC_MEM_ORDER_ACQUIRE: other = "acquire"; break;
+ case OMP_REQ_ATOMIC_MEM_ORDER_RELAXED: other = "relaxed"; break;
+ case OMP_REQ_ATOMIC_MEM_ORDER_RELEASE: other = "release"; break;
+ default: gcc_unreachable ();
+ }
if (module_name)
gfc_error ("!$OMP REQUIRES clause %<atomic_default_mem_order(%s)%> "
@@ -6372,15 +6373,25 @@ gfc_match_omp_requires (void)
clause = "acq_rel";
requires_clause = OMP_REQ_ATOMIC_MEM_ORDER_ACQ_REL;
}
+ else if (gfc_match (" acquire )") == MATCH_YES)
+ {
+ clause = "acquire";
+ requires_clause = OMP_REQ_ATOMIC_MEM_ORDER_ACQUIRE;
+ }
else if (gfc_match (" relaxed )") == MATCH_YES)
{
clause = "relaxed";
requires_clause = OMP_REQ_ATOMIC_MEM_ORDER_RELAXED;
}
+ else if (gfc_match (" release )") == MATCH_YES)
+ {
+ clause = "release";
+ requires_clause = OMP_REQ_ATOMIC_MEM_ORDER_RELEASE;
+ }
else
{
- gfc_error ("Expected SEQ_CST, ACQ_REL or RELAXED for "
- "ATOMIC_DEFAULT_MEM_ORDER clause at %C");
+ gfc_error ("Expected ACQ_REL, ACQUIRE, RELAXED, RELEASE or "
+ "SEQ_CST for ATOMIC_DEFAULT_MEM_ORDER clause at %C");
goto error;
}
}
@@ -6827,6 +6838,28 @@ gfc_match_omp_atomic (void)
else
c->memorder = OMP_MEMORDER_RELEASE;
break;
+ case OMP_REQ_ATOMIC_MEM_ORDER_ACQUIRE:
+ if (c->atomic_op == GFC_OMP_ATOMIC_WRITE)
+ {
+ gfc_error ("!$OMP ATOMIC WRITE at %L incompatible with "
+ "ACQUIRES clause implicitly provided by a "
+ "REQUIRES directive", &loc);
+ c->memorder = OMP_MEMORDER_SEQ_CST;
+ }
+ else
+ c->memorder = OMP_MEMORDER_ACQUIRE;
+ break;
+ case OMP_REQ_ATOMIC_MEM_ORDER_RELEASE:
+ if (c->atomic_op == GFC_OMP_ATOMIC_READ)
+ {
+ gfc_error ("!$OMP ATOMIC READ at %L incompatible with "
+ "RELEASE clause implicitly provided by a "
+ "REQUIRES directive", &loc);
+ c->memorder = OMP_MEMORDER_SEQ_CST;
+ }
+ else
+ c->memorder = OMP_MEMORDER_RELEASE;
+ break;
default:
gcc_unreachable ();
}
@@ -7269,10 +7269,18 @@ done:
omp_requires_mask
= (enum omp_requires) (omp_requires_mask | OMP_MEMORY_ORDER_ACQ_REL);
break;
+ case OMP_REQ_ATOMIC_MEM_ORDER_ACQUIRE:
+ omp_requires_mask
+ = (enum omp_requires) (omp_requires_mask | OMP_MEMORY_ORDER_ACQUIRE);
+ break;
case OMP_REQ_ATOMIC_MEM_ORDER_RELAXED:
omp_requires_mask
= (enum omp_requires) (omp_requires_mask | OMP_MEMORY_ORDER_RELAXED);
break;
+ case OMP_REQ_ATOMIC_MEM_ORDER_RELEASE:
+ omp_requires_mask
+ = (enum omp_requires) (omp_requires_mask | OMP_MEMORY_ORDER_RELEASE);
+ break;
}
if (omp_target_seen)
@@ -1,6 +1,6 @@
-#pragma omp requires atomic_default_mem_order(acquire) /* { dg-error "expected 'seq_cst', 'relaxed' or 'acq_rel'" } */
-#pragma omp requires atomic_default_mem_order(release) /* { dg-error "expected 'seq_cst', 'relaxed' or 'acq_rel'" } */
-#pragma omp requires atomic_default_mem_order(foobar) /* { dg-error "expected 'seq_cst', 'relaxed' or 'acq_rel'" } */
-#pragma omp requires atomic_default_mem_order ( /* { dg-error "expected 'seq_cst', 'relaxed' or 'acq_rel'" } */
+#pragma omp requires atomic_default_mem_order(foobar) /* { dg-error "expected 'acq_rel', 'acquire', 'relaxed', 'release' or 'seq_cst'" } */
+#pragma omp requires atomic_default_mem_order ( /* { dg-error "expected 'acq_rel', 'acquire', 'relaxed', 'release' or 'seq_cst'" } */
/* { dg-error "expected '\\\)' before end of line" "" { target *-*-* } .-1 } */
#pragma omp requires atomic_default_mem_order(seq_cst), /* { dg-error "expected end of line before ',' token" } */
+/* Valid since since 5.2, but ... */
+#pragma omp requires atomic_default_mem_order(acquire) /* { dg-error "more than one 'atomic_default_mem_order' clause in a single compilation unit" } */
new file mode 100644
@@ -0,0 +1,23 @@
+/* { dg-additional-options "-fdump-tree-original" } */
+
+#pragma omp requires atomic_default_mem_order(release)
+
+int
+foo (int x, int y)
+{
+ int z;
+
+ #pragma omp atomic write
+ x = y;
+
+ #pragma omp atomic update
+ x += 1;
+
+ #pragma omp atomic read acquire
+ z = x;
+ return z;
+}
+
+/* { dg-final { scan-tree-dump "#pragma omp atomic release" "original" } } */
+/* { dg-final { scan-tree-dump "#pragma omp atomic release" "original" } } */
+/* { dg-final { scan-tree-dump "z = #pragma omp atomic read acquire" "original" } } */
new file mode 100644
@@ -0,0 +1,23 @@
+/* { dg-additional-options "-fdump-tree-original" } */
+
+#pragma omp requires atomic_default_mem_order(acquire)
+
+int
+bar (int a, int b)
+{
+ int c;
+
+ #pragma omp atomic write release
+ a = b;
+
+ #pragma omp atomic update
+ a += 1;
+
+ #pragma omp atomic read
+ c = a;
+ return c;
+}
+
+/* { dg-final { scan-tree-dump "#pragma omp atomic release" "original" } } */
+/* { dg-final { scan-tree-dump "#pragma omp atomic acquire" "original" } } */
+/* { dg-final { scan-tree-dump "c = #pragma omp atomic read acquire" "original" } } */
new file mode 100644
@@ -0,0 +1,11 @@
+#pragma omp requires atomic_default_mem_order(release)
+
+int
+foo (int x)
+{
+ int z;
+
+ #pragma omp atomic read /* { dg-error "'#pragma omp atomic read' incompatible with 'release' clause implicitly provided by a 'requires' directive" } */
+ z = x;
+ return z;
+}
new file mode 100644
@@ -0,0 +1,14 @@
+#pragma omp requires atomic_default_mem_order(acquire)
+
+int
+bar (int a, int b)
+{
+ int c;
+
+ #pragma omp atomic write /* { dg-error "'#pragma omp atomic write' incompatible with 'acquire' clause implicitly provided by a 'requires' directive" } */
+ a = b;
+
+ #pragma omp atomic read
+ c = a;
+ return c;
+}
new file mode 100644
@@ -0,0 +1,36 @@
+! { dg-additional-options "-fdump-tree-original" }
+
+function foo (x, y) result (z)
+ !$omp requires atomic_default_mem_order(release)
+ implicit none
+ real :: x, y, z
+
+ !$omp atomic write
+ x = y
+
+ !$omp atomic update
+ x = x + 1
+
+ !$omp atomic read acquire
+ z = x
+end
+
+function bar (a, b) result (c)
+ !$omp requires atomic_default_mem_order(acquire)
+ implicit none
+ real :: a, b, c
+
+ !$omp atomic write release
+ a = b
+
+ !$omp atomic update
+ a = a + 1
+
+ !$omp atomic read
+ c = a
+end
+
+! { dg-final { scan-tree-dump-times "#pragma omp atomic release" 3 "original" } } */
+! { dg-final { scan-tree-dump-times "#pragma omp atomic acquire" 1 "original" } } */
+! { dg-final { scan-tree-dump-times "z = #pragma omp atomic read acquire" 1 "original" } } */
+! { dg-final { scan-tree-dump-times "c = #pragma omp atomic read acquire" 1 "original" } } */
new file mode 100644
@@ -0,0 +1,31 @@
+function foo (x, y) result (z)
+ !$omp requires atomic_default_mem_order(release)
+ implicit none
+ real :: x, y, z
+
+ !$omp atomic write
+ x = y
+
+ !$omp atomic update
+ x = x + 1
+
+ !$omp atomic read ! { dg-error "!.OMP ATOMIC READ at .1. incompatible with RELEASE clause implicitly provided by a REQUIRES directive" }
+ z = x
+end
+
+function bar (a, b) result (c)
+ !$omp requires atomic_default_mem_order(acquire)
+ implicit none
+ real :: a, b, c
+
+ !$omp atomic write ! { dg-error "!.OMP ATOMIC WRITE at .1. incompatible with ACQUIRES clause implicitly provided by a REQUIRES directive" }
+ a = b
+
+ !$omp atomic update
+ a = a + 1
+
+ !$omp atomic read
+ c = a
+end
+
+
@@ -8,7 +8,7 @@
!$omp requires atomic_default_mem_order (seq_cst)
!$omp requires atomic_default_mem_order (seq_cst)
!$omp requires atomic_default_mem_order (acq_rel) ! { dg-error "overrides a previous 'atomic_default_mem_order\\(seq_cst\\)'" }
-!$omp requires atomic_default_mem_order (foo) ! { dg-error "Expected SEQ_CST, ACQ_REL or RELAXED for ATOMIC_DEFAULT_MEM_ORDER clause" }
+!$omp requires atomic_default_mem_order (foo) ! { dg-error "Expected ACQ_REL, ACQUIRE, RELAXED, RELEASE or SEQ_CST for ATOMIC_DEFAULT_MEM_ORDER clause" }
end
! { dg-prune-output "not yet supported" }
@@ -1,4 +1,5 @@
-!$omp requires atomic_default_mem_order(acquire) ! { dg-error "Expected SEQ_CST, ACQ_REL or RELAXED for ATOMIC_DEFAULT_MEM_ORDER clause" }
-!$omp requires atomic_default_mem_order(release) ! { dg-error "Expected SEQ_CST, ACQ_REL or RELAXED for ATOMIC_DEFAULT_MEM_ORDER clause" }
-!$omp requires atomic_default_mem_order(foobar) ! { dg-error "Expected SEQ_CST, ACQ_REL or RELAXED for ATOMIC_DEFAULT_MEM_ORDER clause" }
+!$omp requires atomic_default_mem_order(foobar) ! { dg-error "Expected ACQ_REL, ACQUIRE, RELAXED, RELEASE or SEQ_CST for ATOMIC_DEFAULT_MEM_ORDER clause" }
+
+!$omp requires atomic_default_mem_order(acquire) ! OK since OpenMP 5.2
+!$omp requires atomic_default_mem_order(release) ! { dg-error "!.OMP REQUIRES clause 'atomic_default_mem_order\\(release\\)' specified at .1. overrides a previous 'atomic_default_mem_order\\(acquire\\)' \\(which might be through using a module\\)" }
end
@@ -8,7 +8,7 @@ subroutine foo
!$omp requires unified_shared_memory
!$omp requires atomic_default_mem_order(relaxed)
!$omp requires atomic_default_mem_order(relaxed)
-!$omp requires atomic_default_mem_order(seq_cst) ! { dg-error "overrides a previous 'atomic_default_mem_order\\(seq_cst\\)'" }
+!$omp requires atomic_default_mem_order(seq_cst) ! { dg-error "overrides a previous 'atomic_default_mem_order\\(relaxed\\)'" }
!$omp target
!$omp end target
end