r222913 - [OPENMP] Additional processing of 'omp atomic write' directive.
Alexey Bataev
a.bataev at hotmail.com
Thu Nov 27 23:21:40 PST 2014
Author: abataev
Date: Fri Nov 28 01:21:40 2014
New Revision: 222913
URL: http://llvm.org/viewvc/llvm-project?rev=222913&view=rev
Log:
[OPENMP] Additional processing of 'omp atomic write' directive.
According to OpenMP standard, Section 2.12.6, atomic Construct, '#pragma omp atomic write' is allowed to be used only for expression statements of form 'x = expr;', where x is a lvalue expression and expr is an expression with scalar type. Patch adds checks for it.
Modified:
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
cfe/trunk/lib/Sema/SemaOpenMP.cpp
cfe/trunk/test/OpenMP/atomic_messages.c
cfe/trunk/test/OpenMP/atomic_messages.cpp
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=222913&r1=222912&r2=222913&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Fri Nov 28 01:21:40 2014
@@ -7357,11 +7357,11 @@ def err_omp_parallel_reduction_in_task_f
def err_omp_atomic_read_not_expression_statement : Error<
"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">;
-def note_omp_atomic_read: Note<
+def note_omp_atomic_read_write: Note<
"%select{expected an expression statement|expected built-in assignment operator|expected expression of scalar type|expected lvalue expression}0">;
def err_omp_atomic_write_not_expression_statement : Error<
"the statement for 'atomic write' must be an expression statement of form 'x = expr;',"
- " where x is an l-value expression with scalar type">;
+ " where x is a lvalue expression with scalar type">;
def err_omp_atomic_update_not_expression_statement : Error<
"the statement for 'atomic%select{| update}0' 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">;
Modified: cfe/trunk/lib/Sema/SemaOpenMP.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOpenMP.cpp?rev=222913&r1=222912&r2=222913&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOpenMP.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOpenMP.cpp Fri Nov 28 01:21:40 2014
@@ -3222,14 +3222,14 @@ StmtResult Sema::ActOnOpenMPAtomicDirect
// expr or subexpressions of expr.
// * For forms that allow multiple occurrences of x, the number of times
// that x is evaluated is unspecified.
+ enum {
+ NotAnExpression,
+ NotAnAssignmentOp,
+ NotAScalarType,
+ NotAnLValue,
+ NoError
+ } ErrorFound = NoError;
if (AtomicKind == OMPC_read) {
- enum {
- NotAnExpression,
- NotAnAssignmentOp,
- NotAScalarType,
- NotAnLValue,
- NoError
- } ErrorFound = NoError;
SourceLocation ErrorLoc, NoteLoc;
SourceRange ErrorRange, NoteRange;
// If clause is read:
@@ -3279,16 +3279,65 @@ StmtResult Sema::ActOnOpenMPAtomicDirect
if (ErrorFound != NoError) {
Diag(ErrorLoc, diag::err_omp_atomic_read_not_expression_statement)
<< ErrorRange;
- Diag(NoteLoc, diag::note_omp_atomic_read) << ErrorFound << NoteRange;
+ Diag(NoteLoc, diag::note_omp_atomic_read_write) << ErrorFound
+ << NoteRange;
return StmtError();
} else if (CurContext->isDependentContext())
V = X = nullptr;
} else if (AtomicKind == OMPC_write) {
- if (!isa<Expr>(Body)) {
- Diag(Body->getLocStart(),
- diag::err_omp_atomic_write_not_expression_statement);
- return StmtError();
+ SourceLocation ErrorLoc, NoteLoc;
+ SourceRange ErrorRange, NoteRange;
+ // If clause is write:
+ // x = expr;
+ if (auto AtomicBody = dyn_cast<Expr>(Body)) {
+ auto AtomicBinOp =
+ dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
+ if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
+ X = AtomicBinOp->getLHS()->IgnoreParenImpCasts();
+ E = AtomicBinOp->getRHS()->IgnoreParenImpCasts();
+ if ((X->isInstantiationDependent() || X->getType()->isScalarType()) &&
+ (E->isInstantiationDependent() || E->getType()->isScalarType())) {
+ if (!X->isLValue()) {
+ ErrorFound = NotAnLValue;
+ ErrorLoc = AtomicBinOp->getExprLoc();
+ ErrorRange = AtomicBinOp->getSourceRange();
+ NoteLoc = X->getExprLoc();
+ NoteRange = X->getSourceRange();
+ }
+ } else if (!X->isInstantiationDependent() ||
+ !E->isInstantiationDependent()) {
+ auto NotScalarExpr =
+ (X->isInstantiationDependent() || X->getType()->isScalarType())
+ ? E
+ : X;
+ ErrorFound = NotAScalarType;
+ ErrorLoc = AtomicBinOp->getExprLoc();
+ ErrorRange = AtomicBinOp->getSourceRange();
+ NoteLoc = NotScalarExpr->getExprLoc();
+ NoteRange = NotScalarExpr->getSourceRange();
+ }
+ } else {
+ ErrorFound = NotAnAssignmentOp;
+ ErrorLoc = AtomicBody->getExprLoc();
+ ErrorRange = AtomicBody->getSourceRange();
+ NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
+ : AtomicBody->getExprLoc();
+ NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
+ : AtomicBody->getSourceRange();
+ }
+ } else {
+ ErrorFound = NotAnExpression;
+ NoteLoc = ErrorLoc = Body->getLocStart();
+ NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
}
+ if (ErrorFound != NoError) {
+ Diag(ErrorLoc, diag::err_omp_atomic_write_not_expression_statement)
+ << ErrorRange;
+ Diag(NoteLoc, diag::note_omp_atomic_read_write) << ErrorFound
+ << NoteRange;
+ return StmtError();
+ } else if (CurContext->isDependentContext())
+ E = X = nullptr;
} else if (AtomicKind == OMPC_update || AtomicKind == OMPC_unknown) {
if (!isa<Expr>(Body)) {
Diag(Body->getLocStart(),
Modified: cfe/trunk/test/OpenMP/atomic_messages.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/atomic_messages.c?rev=222913&r1=222912&r2=222913&view=diff
==============================================================================
--- cfe/trunk/test/OpenMP/atomic_messages.c (original)
+++ cfe/trunk/test/OpenMP/atomic_messages.c Fri Nov 28 01:21:40 2014
@@ -63,3 +63,40 @@ int readS() {
return a.a;
}
+
+int writeint() {
+ int a = 0, b = 0;
+// Test for atomic write
+#pragma omp atomic write
+ // expected-error at +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 at +1 {{expected an expression statement}}
+ ;
+#pragma omp atomic write
+ // expected-error at +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 at +1 {{expected built-in assignment operator}}
+ foo();
+#pragma omp atomic write
+ // expected-error at +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 at +1 {{expected built-in assignment operator}}
+ a += b;
+#pragma omp atomic write
+ a = 0;
+#pragma omp atomic write
+ a = b;
+ // expected-error at +1 {{directive '#pragma omp atomic' cannot contain more than one 'write' clause}}
+#pragma omp atomic write write
+ a = b;
+
+ return 0;
+}
+
+int writeS() {
+ struct S a, b;
+ // expected-error at +1 {{directive '#pragma omp atomic' cannot contain more than one 'write' clause}}
+#pragma omp atomic write write
+ // expected-error at +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 at +1 {{expected expression of scalar type}}
+ a = b;
+
+ return a.a;
+}
Modified: cfe/trunk/test/OpenMP/atomic_messages.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/atomic_messages.cpp?rev=222913&r1=222912&r2=222913&view=diff
==============================================================================
--- cfe/trunk/test/OpenMP/atomic_messages.cpp (original)
+++ cfe/trunk/test/OpenMP/atomic_messages.cpp Fri Nov 28 01:21:40 2014
@@ -100,11 +100,24 @@ T write() {
T a, b = 0;
// Test for atomic write
#pragma omp atomic write
- // expected-error at +1 {{the statement for 'atomic write' must be an expression statement of form 'x = expr;', where x is an l-value expression with scalar type}}
+ // expected-error at +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 at +1 {{expected an expression statement}}
;
// expected-error at +1 {{directive '#pragma omp atomic' cannot contain more than one 'write' clause}}
#pragma omp atomic write write
a = b;
+#pragma omp atomic write
+ // expected-error at +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 at +1 {{expected built-in assignment operator}}
+ foo();
+#pragma omp atomic write
+ // expected-error at +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 at +1 {{expected built-in assignment operator}}
+ a += b;
+#pragma omp atomic write
+ a = 0;
+#pragma omp atomic write
+ a = b;
return T();
}
@@ -113,11 +126,24 @@ int write() {
int a, b = 0;
// Test for atomic write
#pragma omp atomic write
- // expected-error at +1 {{the statement for 'atomic write' must be an expression statement of form 'x = expr;', where x is an l-value expression with scalar type}}
+ // expected-error at +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 at +1 {{expected an expression statement}}
;
// expected-error at +1 {{directive '#pragma omp atomic' cannot contain more than one 'write' clause}}
#pragma omp atomic write write
a = b;
+#pragma omp atomic write
+ // expected-error at +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 at +1 {{expected built-in assignment operator}}
+ foo();
+#pragma omp atomic write
+ // expected-error at +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 at +1 {{expected built-in assignment operator}}
+ a += b;
+#pragma omp atomic write
+ a = 0;
+#pragma omp atomic write
+ a = foo();
return write<int>();
}
More information about the cfe-commits
mailing list