Commit 9a3740c3 authored by Alexey Bataev's avatar Alexey Bataev
Browse files

[OPENMP50]Add restrictions for memory order clauses in atomic directive.

Added restrictions for atomic directive.
1. If atomic-clause is read then memory-order-clause must not be acq_rel or release.
2. If atomic-clause is write then memory-order-clause must not be
   acq_rel or acquire.
3. If atomic-clause is update or not present then memory-order-clause
   must not be acq_rel or acquire.
parent b04885a5
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -9697,6 +9697,8 @@ def err_omp_atomic_several_clauses : Error<
  "directive '#pragma omp atomic' cannot contain more than one 'read', 'write', 'update' or 'capture' clause">;
def err_omp_several_mem_order_clauses : Error<
  "directive '#pragma omp %0' cannot contain more than one %select{'seq_cst', |}1'acq_rel', 'acquire' or 'release' clause">;
def err_omp_atomic_incompatible_mem_order_clause : Error<
  "directive '#pragma omp atomic%select{ %0|}1' cannot be used with '%2' clause">;
def note_omp_previous_mem_order_clause : Note<
  "'%0' clause used here">;
def err_omp_target_contains_not_only_teams : Error<
+22 −0
Original line number Diff line number Diff line
@@ -8968,6 +8968,28 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,
      }
    }
  }
  // OpenMP 5.0, 2.17.7 atomic Construct, Restrictions
  // If atomic-clause is read then memory-order-clause must not be acq_rel or
  // release.
  // If atomic-clause is write then memory-order-clause must not be acq_rel or
  // acquire.
  // If atomic-clause is update or not present then memory-order-clause must not
  // be acq_rel or acquire.
  if ((AtomicKind == OMPC_read &&
       (MemOrderKind == OMPC_acq_rel || MemOrderKind == OMPC_release)) ||
      ((AtomicKind == OMPC_write || AtomicKind == OMPC_update ||
        AtomicKind == OMPC_unknown) &&
       (MemOrderKind == OMPC_acq_rel || MemOrderKind == OMPC_acquire))) {
    SourceLocation Loc = AtomicKindLoc;
    if (AtomicKind == OMPC_unknown)
      Loc = StartLoc;
    Diag(Loc, diag::err_omp_atomic_incompatible_mem_order_clause)
        << getOpenMPClauseName(AtomicKind)
        << (AtomicKind == OMPC_unknown ? 1 : 0)
        << getOpenMPClauseName(MemOrderKind);
    Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
        << getOpenMPClauseName(MemOrderKind);
  }
  Stmt *Body = CS->getCapturedStmt();
  if (auto *EWC = dyn_cast<ExprWithCleanups>(Body))
+40 −40
Original line number Diff line number Diff line
@@ -44,13 +44,13 @@ T foo(T argc) {
    a = b;
    b++;
  }
#pragma omp atomic acq_rel
#pragma omp atomic
  a++;
#pragma omp atomic read acq_rel
#pragma omp atomic read
  a = argc;
#pragma omp atomic acq_rel write
#pragma omp atomic write
  a = argc + argc;
#pragma omp atomic update acq_rel
#pragma omp atomic update
  a = a + argc;
#pragma omp atomic acq_rel capture
  a = b++;
@@ -59,13 +59,13 @@ T foo(T argc) {
    a = b;
    b++;
  }
#pragma omp atomic acquire
#pragma omp atomic
  a++;
#pragma omp atomic read acquire
  a = argc;
#pragma omp atomic acquire write
#pragma omp atomic write
  a = argc + argc;
#pragma omp atomic update acquire
#pragma omp atomic update
  a = a + argc;
#pragma omp atomic acquire capture
  a = b++;
@@ -76,7 +76,7 @@ T foo(T argc) {
  }
#pragma omp atomic release
  a++;
#pragma omp atomic read release
#pragma omp atomic read
  a = argc;
#pragma omp atomic release write
  a = argc + argc;
@@ -123,13 +123,13 @@ T foo(T argc) {
// CHECK-NEXT: a = b;
// CHECK-NEXT: b++;
// CHECK-NEXT: }
// CHECK-NEXT: #pragma omp atomic acq_rel
// CHECK-NEXT: #pragma omp atomic
// CHECK-NEXT: a++;
// CHECK-NEXT: #pragma omp atomic read acq_rel
// CHECK-NEXT: #pragma omp atomic read
// CHECK-NEXT: a = argc;
// CHECK-NEXT: #pragma omp atomic acq_rel write
// CHECK-NEXT: #pragma omp atomic write
// CHECK-NEXT: a = argc + argc;
// CHECK-NEXT: #pragma omp atomic update acq_rel
// CHECK-NEXT: #pragma omp atomic update
// CHECK-NEXT: a = a + argc;
// CHECK-NEXT: #pragma omp atomic acq_rel capture
// CHECK-NEXT: a = b++;
@@ -138,13 +138,13 @@ T foo(T argc) {
// CHECK-NEXT: a = b;
// CHECK-NEXT: b++;
// CHECK-NEXT: }
// CHECK-NEXT: #pragma omp atomic acquire
// CHECK-NEXT: #pragma omp atomic
// CHECK-NEXT: a++;
// CHECK-NEXT: #pragma omp atomic read acquire
// CHECK-NEXT: a = argc;
// CHECK-NEXT: #pragma omp atomic acquire write
// CHECK-NEXT: #pragma omp atomic write
// CHECK-NEXT: a = argc + argc;
// CHECK-NEXT: #pragma omp atomic update acquire
// CHECK-NEXT: #pragma omp atomic update
// CHECK-NEXT: a = a + argc;
// CHECK-NEXT: #pragma omp atomic acquire capture
// CHECK-NEXT: a = b++;
@@ -155,7 +155,7 @@ T foo(T argc) {
// CHECK-NEXT: }
// CHECK-NEXT: #pragma omp atomic release
// CHECK-NEXT: a++;
// CHECK-NEXT: #pragma omp atomic read release
// CHECK-NEXT: #pragma omp atomic read
// CHECK-NEXT: a = argc;
// CHECK-NEXT: #pragma omp atomic release write
// CHECK-NEXT: a = argc + argc;
@@ -199,13 +199,13 @@ T foo(T argc) {
// CHECK-NEXT: a = b;
// CHECK-NEXT: b++;
// CHECK-NEXT: }
// CHECK-NEXT: #pragma omp atomic acq_rel
// CHECK-NEXT: #pragma omp atomic
// CHECK-NEXT: a++;
// CHECK-NEXT: #pragma omp atomic read acq_rel
// CHECK-NEXT: #pragma omp atomic read
// CHECK-NEXT: a = argc;
// CHECK-NEXT: #pragma omp atomic acq_rel write
// CHECK-NEXT: #pragma omp atomic write
// CHECK-NEXT: a = argc + argc;
// CHECK-NEXT: #pragma omp atomic update acq_rel
// CHECK-NEXT: #pragma omp atomic update
// CHECK-NEXT: a = a + argc;
// CHECK-NEXT: #pragma omp atomic acq_rel capture
// CHECK-NEXT: a = b++;
@@ -214,13 +214,13 @@ T foo(T argc) {
// CHECK-NEXT: a = b;
// CHECK-NEXT: b++;
// CHECK-NEXT: }
// CHECK-NEXT: #pragma omp atomic acquire
// CHECK-NEXT: #pragma omp atomic
// CHECK-NEXT: a++;
// CHECK-NEXT: #pragma omp atomic read acquire
// CHECK-NEXT: a = argc;
// CHECK-NEXT: #pragma omp atomic acquire write
// CHECK-NEXT: #pragma omp atomic write
// CHECK-NEXT: a = argc + argc;
// CHECK-NEXT: #pragma omp atomic update acquire
// CHECK-NEXT: #pragma omp atomic update
// CHECK-NEXT: a = a + argc;
// CHECK-NEXT: #pragma omp atomic acquire capture
// CHECK-NEXT: a = b++;
@@ -231,7 +231,7 @@ T foo(T argc) {
// CHECK-NEXT: }
// CHECK-NEXT: #pragma omp atomic release
// CHECK-NEXT: a++;
// CHECK-NEXT: #pragma omp atomic read release
// CHECK-NEXT: #pragma omp atomic read
// CHECK-NEXT: a = argc;
// CHECK-NEXT: #pragma omp atomic release write
// CHECK-NEXT: a = argc + argc;
@@ -279,13 +279,13 @@ int main(int argc, char **argv) {
    a = b;
    b++;
  }
#pragma omp atomic acq_rel
#pragma omp atomic
  a++;
#pragma omp atomic read acq_rel
#pragma omp atomic read
  a = argc;
#pragma omp atomic acq_rel write
#pragma omp atomic write
  a = argc + argc;
#pragma omp atomic update acq_rel
#pragma omp atomic update
  a = a + argc;
#pragma omp atomic acq_rel capture
  a = b++;
@@ -294,13 +294,13 @@ int main(int argc, char **argv) {
    a = b;
    b++;
  }
#pragma omp atomic acquire
#pragma omp atomic
  a++;
#pragma omp atomic read acquire
  a = argc;
#pragma omp atomic acquire write
#pragma omp atomic write
  a = argc + argc;
#pragma omp atomic update acquire
#pragma omp atomic update
  a = a + argc;
#pragma omp atomic acquire capture
  a = b++;
@@ -311,7 +311,7 @@ int main(int argc, char **argv) {
  }
#pragma omp atomic release
  a++;
#pragma omp atomic read release
#pragma omp atomic read
  a = argc;
#pragma omp atomic release write
  a = argc + argc;
@@ -354,13 +354,13 @@ int main(int argc, char **argv) {
  // CHECK-NEXT: a = b;
  // CHECK-NEXT: b++;
  // CHECK-NEXT: }
  // CHECK-NEXT: #pragma omp atomic acq_rel
  // CHECK-NEXT: #pragma omp atomic
  // CHECK-NEXT: a++;
  // CHECK-NEXT: #pragma omp atomic read acq_rel
  // CHECK-NEXT: #pragma omp atomic read
  // CHECK-NEXT: a = argc;
  // CHECK-NEXT: #pragma omp atomic acq_rel write
  // CHECK-NEXT: #pragma omp atomic write
  // CHECK-NEXT: a = argc + argc;
  // CHECK-NEXT: #pragma omp atomic update acq_rel
  // CHECK-NEXT: #pragma omp atomic update
  // CHECK-NEXT: a = a + argc;
  // CHECK-NEXT: #pragma omp atomic acq_rel capture
  // CHECK-NEXT: a = b++;
@@ -369,13 +369,13 @@ int main(int argc, char **argv) {
  // CHECK-NEXT: a = b;
  // CHECK-NEXT: b++;
  // CHECK-NEXT: }
  // CHECK-NEXT: #pragma omp atomic acquire
  // CHECK-NEXT: #pragma omp atomic
  // CHECK-NEXT: a++;
  // CHECK-NEXT: #pragma omp atomic read acquire
  // CHECK-NEXT: a = argc;
  // CHECK-NEXT: #pragma omp atomic acquire write
  // CHECK-NEXT: #pragma omp atomic write
  // CHECK-NEXT: a = argc + argc;
  // CHECK-NEXT: #pragma omp atomic update acquire
  // CHECK-NEXT: #pragma omp atomic update
  // CHECK-NEXT: a = a + argc;
  // CHECK-NEXT: #pragma omp atomic acquire capture
  // CHECK-NEXT: a = b++;
@@ -386,7 +386,7 @@ int main(int argc, char **argv) {
  // CHECK-NEXT: }
  // CHECK-NEXT: #pragma omp atomic release
  // CHECK-NEXT: a++;
  // CHECK-NEXT: #pragma omp atomic read release
  // CHECK-NEXT: #pragma omp atomic read
  // CHECK-NEXT: a = argc;
  // CHECK-NEXT: #pragma omp atomic release write
  // CHECK-NEXT: a = argc + argc;
+19 −19
Original line number Diff line number Diff line
@@ -728,16 +728,16 @@ int seq_cst() {
template <class T>
T acq_rel() {
  T a = 0, b = 0;
// omp45-error@+1 {{unexpected OpenMP clause 'acq_rel' in directive '#pragma omp atomic'}}
// omp45-error@+1 {{unexpected OpenMP clause 'acq_rel' in directive '#pragma omp atomic'}} omp50-error@+1 {{directive '#pragma omp atomic' cannot be used with 'acq_rel' clause}} omp50-note@+1 {{'acq_rel' clause used here}}
#pragma omp atomic acq_rel
  // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}}
  // expected-note@+1 {{expected an expression statement}}
  ;
// omp50-error@+1 2 {{directive '#pragma omp atomic' cannot contain more than one 'seq_cst', 'acq_rel', 'acquire' or 'release' clause}} omp50-note@+1 2 {{'acq_rel' clause used here}} omp45-error@+1 {{unexpected OpenMP clause 'acq_rel' in directive '#pragma omp atomic'}}
#pragma omp atomic acq_rel seq_cst
  a += b;
// omp50-error@+1 2 {{directive '#pragma omp atomic' cannot contain more than one 'seq_cst', 'acq_rel', 'acquire' or 'release' clause}} omp50-note@+1 2 {{'acq_rel' clause used here}} omp45-error@+1 {{unexpected OpenMP clause 'acq_rel' in directive '#pragma omp atomic'}} omp50-error@+1 2 {{directive '#pragma omp atomic read' cannot be used with 'acq_rel' clause}} omp50-note@+1 2 {{'acq_rel' clause used here}}
#pragma omp atomic read acq_rel seq_cst
  a = b;

// omp45-error@+1 {{unexpected OpenMP clause 'acq_rel' in directive '#pragma omp atomic'}}
// omp45-error@+1 {{unexpected OpenMP clause 'acq_rel' in directive '#pragma omp atomic'}} omp50-error@+1 {{directive '#pragma omp atomic update' cannot be used with 'acq_rel' clause}} omp50-note@+1 {{'acq_rel' clause used here}}
#pragma omp atomic update acq_rel
  // expected-error@+2 {{the statement for 'atomic update' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}}
  // expected-note@+1 {{expected an expression statement}}
@@ -749,16 +749,16 @@ T acq_rel() {
int acq_rel() {
  int a = 0, b = 0;
// Test for atomic acq_rel
// omp45-error@+1 {{unexpected OpenMP clause 'acq_rel' in directive '#pragma omp atomic'}}
#pragma omp atomic acq_rel
  // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}}
// omp45-error@+1 {{unexpected OpenMP clause 'acq_rel' in directive '#pragma omp atomic'}} omp50-error@+1 {{directive '#pragma omp atomic write' cannot be used with 'acq_rel' clause}} omp50-note@+1 {{'acq_rel' clause used here}}
#pragma omp atomic acq_rel write
  // expected-error@+2 {{the statement for 'atomic write' must be an expression statement of form 'x = expr;', where x is a lvalue expression with scalar type}}
  // expected-note@+1 {{expected an expression statement}}
  ;
// omp50-error@+1 {{directive '#pragma omp atomic' cannot contain more than one 'seq_cst', 'acq_rel', 'acquire' or 'release' clause}} omp50-note@+1 {{'seq_cst' clause used here}} omp45-error@+1 {{unexpected OpenMP clause 'acq_rel' in directive '#pragma omp atomic'}}
#pragma omp atomic seq_cst acq_rel
  a += b;

// omp45-error@+1 {{unexpected OpenMP clause 'acq_rel' in directive '#pragma omp atomic'}}
// omp45-error@+1 {{unexpected OpenMP clause 'acq_rel' in directive '#pragma omp atomic'}} omp50-error@+1 {{directive '#pragma omp atomic update' cannot be used with 'acq_rel' clause}} omp50-note@+1 {{'acq_rel' clause used here}}
#pragma omp atomic update acq_rel
  // expected-error@+2 {{the statement for 'atomic update' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}}
  // expected-note@+1 {{expected an expression statement}}
@@ -770,16 +770,16 @@ int acq_rel() {
template <class T>
T acquire() {
  T a = 0, b = 0;
// omp45-error@+1 {{unexpected OpenMP clause 'acquire' in directive '#pragma omp atomic'}}
// omp45-error@+1 {{unexpected OpenMP clause 'acquire' in directive '#pragma omp atomic'}} omp50-error@+1 {{directive '#pragma omp atomic' cannot be used with 'acquire' clause}} omp50-note@+1 {{'acquire' clause used here}}
#pragma omp atomic acquire
  // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}}
  // expected-note@+1 {{expected an expression statement}}
  ;
// omp50-error@+1 2 {{directive '#pragma omp atomic' cannot contain more than one 'seq_cst', 'acq_rel', 'acquire' or 'release' clause}} omp50-note@+1 2 {{'acquire' clause used here}} omp45-error@+1 {{unexpected OpenMP clause 'acquire' in directive '#pragma omp atomic'}}
// omp50-error@+1 2 {{directive '#pragma omp atomic' cannot contain more than one 'seq_cst', 'acq_rel', 'acquire' or 'release' clause}} omp50-note@+1 2 {{'acquire' clause used here}} omp45-error@+1 {{unexpected OpenMP clause 'acquire' in directive '#pragma omp atomic'}} omp50-error@+1 2 {{directive '#pragma omp atomic' cannot be used with 'acquire' clause}} omp50-note@+1 2 {{'acquire' clause used here}}
#pragma omp atomic acquire seq_cst
  a += b;

// omp45-error@+1 {{unexpected OpenMP clause 'acquire' in directive '#pragma omp atomic'}}
// omp45-error@+1 {{unexpected OpenMP clause 'acquire' in directive '#pragma omp atomic'}} omp50-error@+1 {{directive '#pragma omp atomic update' cannot be used with 'acquire' clause}} omp50-note@+1 {{'acquire' clause used here}}
#pragma omp atomic update acquire
  // expected-error@+2 {{the statement for 'atomic update' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}}
  // expected-note@+1 {{expected an expression statement}}
@@ -791,16 +791,16 @@ T acquire() {
int acquire() {
  int a = 0, b = 0;
// Test for atomic acquire
// omp45-error@+1 {{unexpected OpenMP clause 'acquire' in directive '#pragma omp atomic'}}
#pragma omp atomic acquire
  // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}}
// omp45-error@+1 {{unexpected OpenMP clause 'acquire' in directive '#pragma omp atomic'}} omp50-error@+1 {{directive '#pragma omp atomic write' cannot be used with 'acquire' clause}} omp50-note@+1 {{'acquire' clause used here}}
#pragma omp atomic write acquire
  // expected-error@+2 {{the statement for 'atomic write' must be an expression statement of form 'x = expr;', where x is a lvalue expression with scalar type}}
  // expected-note@+1 {{expected an expression statement}}
  ;
// omp50-error@+1 {{directive '#pragma omp atomic' cannot contain more than one 'seq_cst', 'acq_rel', 'acquire' or 'release' clause}} omp50-note@+1 {{'seq_cst' clause used here}} omp45-error@+1 {{unexpected OpenMP clause 'acquire' in directive '#pragma omp atomic'}}
#pragma omp atomic seq_cst acquire
  a += b;

// omp45-error@+1 {{unexpected OpenMP clause 'acquire' in directive '#pragma omp atomic'}}
// omp45-error@+1 {{unexpected OpenMP clause 'acquire' in directive '#pragma omp atomic'}} omp50-error@+1 {{directive '#pragma omp atomic update' cannot be used with 'acquire' clause}} omp50-note@+1 {{'acquire' clause used here}}
#pragma omp atomic update acquire
  // expected-error@+2 {{the statement for 'atomic update' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}}
  // expected-note@+1 {{expected an expression statement}}
@@ -833,9 +833,9 @@ T release() {
int release() {
  int a = 0, b = 0;
// Test for atomic release
// omp45-error@+1 {{unexpected OpenMP clause 'release' in directive '#pragma omp atomic'}}
#pragma omp atomic release
  // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}}
// omp45-error@+1 {{unexpected OpenMP clause 'release' in directive '#pragma omp atomic'}} omp50-error@+1 {{directive '#pragma omp atomic read' cannot be used with 'release' clause}} omp50-note@+1 {{'release' clause used here}}
#pragma omp atomic read release
  // expected-error@+2 {{the statement for 'atomic read' must be an expression statement of form 'v = x;', where v and x are both lvalue expressions with scalar type}}
  // expected-note@+1 {{expected an expression statement}}
  ;
// omp50-error@+1 {{directive '#pragma omp atomic' cannot contain more than one 'seq_cst', 'acq_rel', 'acquire' or 'release' clause}} omp50-note@+1 {{'seq_cst' clause used here}} omp45-error@+1 {{unexpected OpenMP clause 'release' in directive '#pragma omp atomic'}}
+3 −4
Original line number Diff line number Diff line
@@ -312,7 +312,7 @@ int main() {
// CHECK: [[SHL:%.+]] = shl i64 [[LD]], 40
// CHECK: [[ASHR:%.+]] = ashr i64 [[SHL]], 57
// CHECK: store x86_fp80
#pragma omp atomic read release
#pragma omp atomic read
  ldv = bfx4.b;
// CHECK: [[LD:%.+]] = load atomic i8, i8* getelementptr inbounds (%struct.BitFields4_packed, %struct.BitFields4_packed* @bfx4_packed, i32 0, i32 0, i64 2) acquire
// CHECK: store i8 [[LD]], i8* [[LDTEMP:%.+]]
@@ -323,14 +323,13 @@ int main() {
// CHECK: store x86_fp80
#pragma omp atomic read acquire
  ldv = bfx4_packed.b;
// CHECK: [[LD:%.+]] = load atomic i64, i64* bitcast (<2 x float>* @{{.+}} to i64*) acquire
// CHECK: [[LD:%.+]] = load atomic i64, i64* bitcast (<2 x float>* @{{.+}} to i64*) monotonic
// CHECK: [[BITCAST:%.+]] = bitcast <2 x float>* [[LDTEMP:%.+]] to i64*
// CHECK: store i64 [[LD]], i64* [[BITCAST]]
// CHECK: [[LD:%.+]] = load <2 x float>, <2 x float>* [[LDTEMP]]
// CHECK: extractelement <2 x float> [[LD]]
// CHECK: call{{.*}} @__kmpc_flush(
// CHECK: store i64
#pragma omp atomic read acq_rel
#pragma omp atomic read
  ulv = float2x.x;
// CHECK: call{{.*}} i{{[0-9]+}} @llvm.read_register
// CHECK: call{{.*}} @__kmpc_flush(
Loading