forked from OSchip/llvm-project
[Clang][Sema][OpenMP] Sema support for `atomic compare`
This patch adds the Sema support for `atomic compare`. Reviewed By: ABataev Differential Revision: https://reviews.llvm.org/D116637
This commit is contained in:
parent
679c77ede3
commit
b35be6fe98
|
@ -10516,6 +10516,15 @@ def err_omp_atomic_capture_not_compound_statement : Error<
|
|||
" where x is an lvalue expression with scalar type">;
|
||||
def note_omp_atomic_capture: Note<
|
||||
"%select{expected assignment expression|expected compound statement|expected exactly two expression statements|expected in right hand side of the first expression}0">;
|
||||
def err_omp_atomic_compare : Error<
|
||||
"the statement for 'atomic compare' must be a compound statement of form '{x = expr ordop x ? expr : x;}', '{x = x ordop expr? expr : x;}',"
|
||||
" '{x = x == e ? d : x;}', '{x = e == x ? d : x;}', or 'if(expr ordop x) {x = expr;}', 'if(x ordop expr) {x = expr;}', 'if(x == e) {x = d;}',"
|
||||
" 'if(e == x) {x = d;}' where 'x' is an lvalue expression with scalar type, 'expr', 'e', and 'd' are expressions with scalar type,"
|
||||
" and 'ordop' is one of '<' or '>'.">;
|
||||
def note_omp_atomic_compare: Note<
|
||||
"%select{expected compound statement|expected exactly one expression statement|expected assignment statement|expected conditional operator|expect result value to be at false expression|"
|
||||
"expect binary operator in conditional expression|expect '<', '>' or '==' as order operator|expect comparison in a form of 'x == e', 'e == x', 'x ordop expr', or 'expr ordop x'|"
|
||||
"expect lvalue for result value|expect scalar value|expect integer value}0">;
|
||||
def err_omp_atomic_several_clauses : Error<
|
||||
"directive '#pragma omp atomic' cannot contain more than one 'read', 'write', 'update', 'capture', or 'compare' clause">;
|
||||
def err_omp_several_mem_order_clauses : Error<
|
||||
|
|
|
@ -6031,9 +6031,13 @@ static void emitOMPAtomicExpr(CodeGenFunction &CGF, OpenMPClauseKind Kind,
|
|||
emitOMPAtomicCaptureExpr(CGF, AO, IsPostfixUpdate, V, X, E, UE,
|
||||
IsXLHSInRHSPart, Loc);
|
||||
break;
|
||||
case OMPC_compare:
|
||||
// Do nothing here as we already emit an error.
|
||||
case OMPC_compare: {
|
||||
// Emit an error here.
|
||||
unsigned DiagID = CGF.CGM.getDiags().getCustomDiagID(
|
||||
DiagnosticsEngine::Error, "'atomic compare' is not supported for now");
|
||||
CGF.CGM.getDiags().Report(DiagID);
|
||||
break;
|
||||
}
|
||||
case OMPC_if:
|
||||
case OMPC_final:
|
||||
case OMPC_num_threads:
|
||||
|
|
|
@ -10925,6 +10925,357 @@ bool OpenMPAtomicUpdateChecker::checkStatement(Stmt *S, unsigned DiagId,
|
|||
}
|
||||
return ErrorFound != NoError;
|
||||
}
|
||||
|
||||
/// Get the node id of the fixed point of an expression \a S.
|
||||
llvm::FoldingSetNodeID getNodeId(ASTContext &Context, const Expr *S) {
|
||||
llvm::FoldingSetNodeID Id;
|
||||
S->IgnoreParenImpCasts()->Profile(Id, Context, true);
|
||||
return Id;
|
||||
}
|
||||
|
||||
/// Check if two expressions are same.
|
||||
bool checkIfTwoExprsAreSame(ASTContext &Context, const Expr *LHS,
|
||||
const Expr *RHS) {
|
||||
return getNodeId(Context, LHS) == getNodeId(Context, RHS);
|
||||
}
|
||||
|
||||
class OpenMPAtomicCompareChecker {
|
||||
public:
|
||||
/// All kinds of errors that can occur in `atomic compare`
|
||||
enum ErrorTy {
|
||||
/// Empty compound statement.
|
||||
NoStmt = 0,
|
||||
/// More than one statement in a compound statement.
|
||||
MoreThanOneStmt,
|
||||
/// Not an assignment binary operator.
|
||||
NotAnAssignment,
|
||||
/// Not a conditional operator.
|
||||
NotCondOp,
|
||||
/// Wrong false expr. According to the spec, 'x' should be at the false
|
||||
/// expression of a conditional expression.
|
||||
WrongFalseExpr,
|
||||
/// The condition of a conditional expression is not a binary operator.
|
||||
NotABinaryOp,
|
||||
/// Invalid binary operator (not <, >, or ==).
|
||||
InvalidBinaryOp,
|
||||
/// Invalid comparison (not x == e, e == x, x ordop expr, or expr ordop x).
|
||||
InvalidComparison,
|
||||
/// X is not a lvalue.
|
||||
XNotLValue,
|
||||
/// Not a scalar.
|
||||
NotScalar,
|
||||
/// Not an integer.
|
||||
NotInteger,
|
||||
/// No error.
|
||||
NoError,
|
||||
};
|
||||
|
||||
struct ErrorInfoTy {
|
||||
ErrorTy Error;
|
||||
SourceLocation ErrorLoc;
|
||||
SourceRange ErrorRange;
|
||||
SourceLocation NoteLoc;
|
||||
SourceRange NoteRange;
|
||||
};
|
||||
|
||||
OpenMPAtomicCompareChecker(Sema &S) : ContextRef(S.getASTContext()) {}
|
||||
|
||||
/// Check if statement \a S is valid for <tt>atomic compare</tt>.
|
||||
bool checkStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
|
||||
|
||||
Expr *getX() const { return X; }
|
||||
Expr *getE() const { return E; }
|
||||
Expr *getD() const { return D; }
|
||||
Expr *getCond() const { return C; }
|
||||
bool isXBinopExpr() const { return IsXBinopExpr; }
|
||||
|
||||
private:
|
||||
/// Reference to ASTContext
|
||||
ASTContext &ContextRef;
|
||||
/// 'x' lvalue part of the source atomic expression.
|
||||
Expr *X = nullptr;
|
||||
/// 'expr' or 'e' rvalue part of the source atomic expression.
|
||||
Expr *E = nullptr;
|
||||
/// 'd' rvalue part of the source atomic expression.
|
||||
Expr *D = nullptr;
|
||||
/// 'cond' part of the source atomic expression. It is in one of the following
|
||||
/// forms:
|
||||
/// expr ordop x
|
||||
/// x ordop expr
|
||||
/// x == e
|
||||
/// e == x
|
||||
Expr *C = nullptr;
|
||||
/// True if the cond expr is in the form of 'x ordop expr'.
|
||||
bool IsXBinopExpr = true;
|
||||
/// The atomic compare operator.
|
||||
OMPAtomicCompareOp Op;
|
||||
|
||||
/// Check if it is a valid conditional update statement (cond-update-stmt).
|
||||
bool checkCondUpdateStmt(IfStmt *S, ErrorInfoTy &ErrorInfo);
|
||||
|
||||
/// Check if it is a valid conditional expression statement (cond-expr-stmt).
|
||||
bool checkCondExprStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
|
||||
|
||||
/// Check if all captured values have right type.
|
||||
bool checkType(ErrorInfoTy &ErrorInfo) const;
|
||||
};
|
||||
|
||||
bool OpenMPAtomicCompareChecker::checkCondUpdateStmt(IfStmt *S,
|
||||
ErrorInfoTy &ErrorInfo) {
|
||||
auto *Then = S->getThen();
|
||||
if (auto *CS = dyn_cast<CompoundStmt>(Then)) {
|
||||
if (CS->body_empty()) {
|
||||
ErrorInfo.Error = ErrorTy::NoStmt;
|
||||
ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
|
||||
ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
|
||||
return false;
|
||||
}
|
||||
if (CS->size() > 1) {
|
||||
ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
|
||||
ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
|
||||
ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
|
||||
return false;
|
||||
}
|
||||
Then = CS->body_front();
|
||||
}
|
||||
|
||||
auto *BO = dyn_cast<BinaryOperator>(Then);
|
||||
if (!BO) {
|
||||
ErrorInfo.Error = ErrorTy::NotAnAssignment;
|
||||
ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Then->getBeginLoc();
|
||||
ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Then->getSourceRange();
|
||||
return false;
|
||||
}
|
||||
if (BO->getOpcode() != BO_Assign) {
|
||||
ErrorInfo.Error = ErrorTy::NotAnAssignment;
|
||||
ErrorInfo.ErrorLoc = BO->getExprLoc();
|
||||
ErrorInfo.NoteLoc = BO->getOperatorLoc();
|
||||
ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
|
||||
return false;
|
||||
}
|
||||
|
||||
X = BO->getLHS();
|
||||
|
||||
auto *Cond = dyn_cast<BinaryOperator>(S->getCond());
|
||||
if (!Cond) {
|
||||
ErrorInfo.Error = ErrorTy::NotABinaryOp;
|
||||
ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
|
||||
ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
|
||||
return false;
|
||||
}
|
||||
if (Cond->getOpcode() != BO_EQ && Cond->getOpcode() != BO_LT &&
|
||||
Cond->getOpcode() != BO_GT) {
|
||||
ErrorInfo.Error = ErrorTy::InvalidBinaryOp;
|
||||
ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
|
||||
ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Cond->getOpcode() == BO_EQ) {
|
||||
C = Cond;
|
||||
D = BO->getRHS();
|
||||
if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS())) {
|
||||
E = Cond->getRHS();
|
||||
} else if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getRHS())) {
|
||||
E = Cond->getLHS();
|
||||
} else {
|
||||
ErrorInfo.Error = ErrorTy::InvalidComparison;
|
||||
ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
|
||||
ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
E = BO->getRHS();
|
||||
if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS()) &&
|
||||
checkIfTwoExprsAreSame(ContextRef, E, Cond->getRHS())) {
|
||||
C = Cond;
|
||||
} else if (checkIfTwoExprsAreSame(ContextRef, E, Cond->getLHS()) &&
|
||||
checkIfTwoExprsAreSame(ContextRef, X, Cond->getRHS())) {
|
||||
C = Cond;
|
||||
IsXBinopExpr = false;
|
||||
} else {
|
||||
ErrorInfo.Error = ErrorTy::InvalidComparison;
|
||||
ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
|
||||
ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OpenMPAtomicCompareChecker::checkCondExprStmt(Stmt *S,
|
||||
ErrorInfoTy &ErrorInfo) {
|
||||
auto *BO = dyn_cast<BinaryOperator>(S);
|
||||
if (!BO) {
|
||||
ErrorInfo.Error = ErrorTy::NotAnAssignment;
|
||||
ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
|
||||
ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
|
||||
return false;
|
||||
}
|
||||
if (BO->getOpcode() != BO_Assign) {
|
||||
ErrorInfo.Error = ErrorTy::NotAnAssignment;
|
||||
ErrorInfo.ErrorLoc = BO->getExprLoc();
|
||||
ErrorInfo.NoteLoc = BO->getOperatorLoc();
|
||||
ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
|
||||
return false;
|
||||
}
|
||||
|
||||
X = BO->getLHS();
|
||||
|
||||
auto *CO = dyn_cast<ConditionalOperator>(BO->getRHS()->IgnoreParenImpCasts());
|
||||
if (!CO) {
|
||||
ErrorInfo.Error = ErrorTy::NotCondOp;
|
||||
ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = BO->getRHS()->getExprLoc();
|
||||
ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getRHS()->getSourceRange();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!checkIfTwoExprsAreSame(ContextRef, X, CO->getFalseExpr())) {
|
||||
ErrorInfo.Error = ErrorTy::WrongFalseExpr;
|
||||
ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getFalseExpr()->getExprLoc();
|
||||
ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
|
||||
CO->getFalseExpr()->getSourceRange();
|
||||
return false;
|
||||
}
|
||||
|
||||
auto *Cond = dyn_cast<BinaryOperator>(CO->getCond());
|
||||
if (!Cond) {
|
||||
ErrorInfo.Error = ErrorTy::NotABinaryOp;
|
||||
ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
|
||||
ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
|
||||
CO->getCond()->getSourceRange();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Cond->getOpcode() != BO_EQ && Cond->getOpcode() != BO_LT &&
|
||||
Cond->getOpcode() != BO_GT) {
|
||||
ErrorInfo.Error = ErrorTy::InvalidBinaryOp;
|
||||
ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
|
||||
ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Cond->getOpcode() == BO_EQ) {
|
||||
C = Cond;
|
||||
D = CO->getTrueExpr();
|
||||
if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS())) {
|
||||
E = Cond->getRHS();
|
||||
} else if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getRHS())) {
|
||||
E = Cond->getLHS();
|
||||
} else {
|
||||
ErrorInfo.Error = ErrorTy::InvalidComparison;
|
||||
ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
|
||||
ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
E = CO->getTrueExpr();
|
||||
if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS()) &&
|
||||
checkIfTwoExprsAreSame(ContextRef, E, Cond->getRHS())) {
|
||||
C = Cond;
|
||||
} else if (checkIfTwoExprsAreSame(ContextRef, E, Cond->getLHS()) &&
|
||||
checkIfTwoExprsAreSame(ContextRef, X, Cond->getRHS())) {
|
||||
C = Cond;
|
||||
IsXBinopExpr = false;
|
||||
} else {
|
||||
ErrorInfo.Error = ErrorTy::InvalidComparison;
|
||||
ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
|
||||
ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OpenMPAtomicCompareChecker::checkType(ErrorInfoTy &ErrorInfo) const {
|
||||
// 'x' and 'e' cannot be nullptr
|
||||
assert(X && E && "X and E cannot be nullptr");
|
||||
|
||||
auto CheckValue = [&ErrorInfo](const Expr *E, OMPAtomicCompareOp Op,
|
||||
bool ShouldBeLValue) {
|
||||
if (ShouldBeLValue && !E->isLValue()) {
|
||||
ErrorInfo.Error = ErrorTy::XNotLValue;
|
||||
ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
|
||||
ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!E->isInstantiationDependent()) {
|
||||
QualType QTy = E->getType();
|
||||
if (!QTy->isScalarType()) {
|
||||
ErrorInfo.Error = ErrorTy::NotScalar;
|
||||
ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
|
||||
ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Op != OMPAtomicCompareOp::EQ && !QTy->isIntegerType()) {
|
||||
ErrorInfo.Error = ErrorTy::NotInteger;
|
||||
ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
|
||||
ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
if (!CheckValue(X, Op, true))
|
||||
return false;
|
||||
|
||||
if (!CheckValue(E, Op, false))
|
||||
return false;
|
||||
|
||||
if (D && !CheckValue(D, Op, false))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OpenMPAtomicCompareChecker::checkStmt(
|
||||
Stmt *S, OpenMPAtomicCompareChecker::ErrorInfoTy &ErrorInfo) {
|
||||
auto *CS = dyn_cast<CompoundStmt>(S);
|
||||
if (CS) {
|
||||
if (CS->body_empty()) {
|
||||
ErrorInfo.Error = ErrorTy::NoStmt;
|
||||
ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
|
||||
ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (CS->size() != 1) {
|
||||
ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
|
||||
ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
|
||||
ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
|
||||
return false;
|
||||
}
|
||||
S = CS->body_front();
|
||||
}
|
||||
|
||||
auto Res = false;
|
||||
|
||||
if (auto *IS = dyn_cast<IfStmt>(S)) {
|
||||
// Check if the statement is in one of the following forms
|
||||
// (cond-update-stmt):
|
||||
// if (expr ordop x) { x = expr; }
|
||||
// if (x ordop expr) { x = expr; }
|
||||
// if (x == e) { x = d; }
|
||||
Res = checkCondUpdateStmt(IS, ErrorInfo);
|
||||
} else {
|
||||
// Check if the statement is in one of the following forms (cond-expr-stmt):
|
||||
// x = expr ordop x ? expr : x;
|
||||
// x = x ordop expr ? expr : x;
|
||||
// x = x == e ? d : x;
|
||||
Res = checkCondExprStmt(S, ErrorInfo);
|
||||
}
|
||||
|
||||
if (!Res)
|
||||
return false;
|
||||
|
||||
return checkType(ErrorInfo);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,
|
||||
|
@ -11018,6 +11369,8 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,
|
|||
Expr *V = nullptr;
|
||||
Expr *E = nullptr;
|
||||
Expr *UE = nullptr;
|
||||
Expr *D = nullptr;
|
||||
Expr *CE = nullptr;
|
||||
bool IsXLHSInRHSPart = false;
|
||||
bool IsPostfixUpdate = false;
|
||||
// OpenMP [2.12.6, atomic Construct]
|
||||
|
@ -11405,11 +11758,17 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,
|
|||
if (CurContext->isDependentContext())
|
||||
UE = V = E = X = nullptr;
|
||||
} else if (AtomicKind == OMPC_compare) {
|
||||
// TODO: For now we emit an error here and in emitOMPAtomicExpr we ignore
|
||||
// code gen.
|
||||
unsigned DiagID = Diags.getCustomDiagID(
|
||||
DiagnosticsEngine::Error, "atomic compare is not supported for now");
|
||||
Diag(AtomicKindLoc, DiagID);
|
||||
OpenMPAtomicCompareChecker::ErrorInfoTy ErrorInfo;
|
||||
OpenMPAtomicCompareChecker Checker(*this);
|
||||
if (!Checker.checkStmt(Body, ErrorInfo)) {
|
||||
Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_compare)
|
||||
<< ErrorInfo.ErrorRange;
|
||||
Diag(ErrorInfo.NoteLoc, diag::note_omp_atomic_compare)
|
||||
<< ErrorInfo.Error << ErrorInfo.NoteRange;
|
||||
return StmtError();
|
||||
}
|
||||
// TODO: We don't set X, D, E, etc. here because in code gen we will emit
|
||||
// error directly.
|
||||
}
|
||||
|
||||
setFunctionHasBranchProtectedScope();
|
||||
|
|
|
@ -5,6 +5,14 @@
|
|||
// RUN: %clang_cc1 -verify -fopenmp-simd -ast-print %s | FileCheck %s
|
||||
// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -emit-pch -o %t %s
|
||||
// RUN: %clang_cc1 -fopenmp-simd -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
|
||||
|
||||
// RUN: %clang_cc1 -DOMP51 -verify -fopenmp -fopenmp-version=51 -ast-print %s | FileCheck --check-prefixes=CHECK,CHECK-51 %s
|
||||
// RUN: %clang_cc1 -DOMP51 -fopenmp -fopenmp-version=51 -x c++ -std=c++11 -emit-pch -o %t %s
|
||||
// RUN: %clang_cc1 -DOMP51 -fopenmp -fopenmp-version=51 -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck --check-prefixes=CHECK,CHECK-51 %s
|
||||
|
||||
// RUN: %clang_cc1 -DOMP51 -verify -fopenmp-simd -fopenmp-version=51 -ast-print %s | FileCheck --check-prefixes=CHECK,CHECK-51 %s
|
||||
// RUN: %clang_cc1 -DOMP51 -fopenmp-simd -fopenmp-version=51 -x c++ -std=c++11 -emit-pch -o %t %s
|
||||
// RUN: %clang_cc1 -DOMP51 -fopenmp-simd -fopenmp-version=51 -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck --check-prefixes=CHECK,CHECK-51 %s
|
||||
// expected-no-diagnostics
|
||||
|
||||
#ifndef HEADER
|
||||
|
@ -12,6 +20,7 @@
|
|||
|
||||
template <class T>
|
||||
T foo(T argc) {
|
||||
T c = T();
|
||||
T b = T();
|
||||
T a = T();
|
||||
#pragma omp atomic
|
||||
|
@ -29,6 +38,14 @@ T foo(T argc) {
|
|||
a = b;
|
||||
b++;
|
||||
}
|
||||
#ifdef OMP51
|
||||
#pragma omp atomic compare
|
||||
{ a = a > b ? b : a; }
|
||||
#pragma omp atomic compare
|
||||
{ a = a < b ? b : a; }
|
||||
#pragma omp atomic compare
|
||||
{ a = a == b ? c : a; }
|
||||
#endif
|
||||
#pragma omp atomic seq_cst
|
||||
a++;
|
||||
#pragma omp atomic read seq_cst
|
||||
|
@ -44,6 +61,14 @@ T foo(T argc) {
|
|||
a = b;
|
||||
b++;
|
||||
}
|
||||
#ifdef OMP51
|
||||
#pragma omp atomic compare seq_cst
|
||||
{ a = a > b ? b : a; }
|
||||
#pragma omp atomic seq_cst compare
|
||||
{ a = a < b ? b : a; }
|
||||
#pragma omp atomic compare seq_cst
|
||||
{ a = a == b ? c : a; }
|
||||
#endif
|
||||
#pragma omp atomic
|
||||
a++;
|
||||
#pragma omp atomic read
|
||||
|
@ -59,6 +84,14 @@ T foo(T argc) {
|
|||
a = b;
|
||||
b++;
|
||||
}
|
||||
#ifdef OMP51
|
||||
#pragma omp atomic compare acq_rel
|
||||
{ a = a > b ? b : a; }
|
||||
#pragma omp atomic acq_rel compare
|
||||
{ a = a < b ? b : a; }
|
||||
#pragma omp atomic compare acq_rel
|
||||
{ a = a == b ? c : a; }
|
||||
#endif
|
||||
#pragma omp atomic
|
||||
a++;
|
||||
#pragma omp atomic read acquire
|
||||
|
@ -74,6 +107,14 @@ T foo(T argc) {
|
|||
a = b;
|
||||
b++;
|
||||
}
|
||||
#ifdef OMP51
|
||||
#pragma omp atomic compare acquire
|
||||
{ a = a > b ? b : a; }
|
||||
#pragma omp atomic acquire compare
|
||||
{ a = a < b ? b : a; }
|
||||
#pragma omp atomic compare acquire
|
||||
{ a = a == b ? c : a; }
|
||||
#endif
|
||||
#pragma omp atomic release
|
||||
a++;
|
||||
#pragma omp atomic read
|
||||
|
@ -89,6 +130,14 @@ T foo(T argc) {
|
|||
a = b;
|
||||
b++;
|
||||
}
|
||||
#ifdef OMP51
|
||||
#pragma omp atomic compare release
|
||||
{ a = a > b ? b : a; }
|
||||
#pragma omp atomic release compare
|
||||
{ a = a < b ? b : a; }
|
||||
#pragma omp atomic compare release
|
||||
{ a = a == b ? c : a; }
|
||||
#endif
|
||||
#pragma omp atomic relaxed
|
||||
a++;
|
||||
#pragma omp atomic read
|
||||
|
@ -104,6 +153,14 @@ T foo(T argc) {
|
|||
a = b;
|
||||
b++;
|
||||
}
|
||||
#ifdef OMP51
|
||||
#pragma omp atomic compare relaxed
|
||||
{ a = a > b ? b : a; }
|
||||
#pragma omp atomic relaxed compare
|
||||
{ a = a < b ? b : a; }
|
||||
#pragma omp atomic compare relaxed
|
||||
{ a = a == b ? c : a; }
|
||||
#endif
|
||||
#pragma omp atomic hint(6)
|
||||
a++;
|
||||
#pragma omp atomic read hint(6)
|
||||
|
@ -119,6 +176,14 @@ T foo(T argc) {
|
|||
a = b;
|
||||
b++;
|
||||
}
|
||||
#ifdef OMP51
|
||||
#pragma omp atomic compare hint(6)
|
||||
{ a = a > b ? b : a; }
|
||||
#pragma omp atomic hint(6) compare
|
||||
{ a = a < b ? b : a; }
|
||||
#pragma omp atomic compare hint(6)
|
||||
{ a = a == b ? c : a; }
|
||||
#endif
|
||||
return T();
|
||||
}
|
||||
|
||||
|
@ -138,6 +203,18 @@ T foo(T argc) {
|
|||
// CHECK-NEXT: a = b;
|
||||
// CHECK-NEXT: b++;
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-51-NEXT: #pragma omp atomic compare
|
||||
// CHECK-51-NEXT: {
|
||||
// CHECK-51-NEXT: a = a > b ? b : a;
|
||||
// CHECK-51-NEXT: }
|
||||
// CHECK-51-NEXT: #pragma omp atomic compare
|
||||
// CHECK-51-NEXT: {
|
||||
// CHECK-51-NEXT: a = a < b ? b : a;
|
||||
// CHECK-51-NEXT: }
|
||||
// CHECK-51-NEXT: #pragma omp atomic compare
|
||||
// CHECK-51-NEXT: {
|
||||
// CHECK-51-NEXT: a = a == b ? c : a;
|
||||
// CHECK-51-NEXT: }
|
||||
// CHECK-NEXT: #pragma omp atomic seq_cst
|
||||
// CHECK-NEXT: a++;
|
||||
// CHECK-NEXT: #pragma omp atomic read seq_cst
|
||||
|
@ -153,6 +230,18 @@ T foo(T argc) {
|
|||
// CHECK-NEXT: a = b;
|
||||
// CHECK-NEXT: b++;
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-51-NEXT: #pragma omp atomic compare seq_cst
|
||||
// CHECK-51-NEXT: {
|
||||
// CHECK-51-NEXT: a = a > b ? b : a;
|
||||
// CHECK-51-NEXT: }
|
||||
// CHECK-51-NEXT: #pragma omp atomic seq_cst compare
|
||||
// CHECK-51-NEXT: {
|
||||
// CHECK-51-NEXT: a = a < b ? b : a;
|
||||
// CHECK-51-NEXT: }
|
||||
// CHECK-51-NEXT: #pragma omp atomic compare seq_cst
|
||||
// CHECK-51-NEXT: {
|
||||
// CHECK-51-NEXT: a = a == b ? c : a;
|
||||
// CHECK-51-NEXT: }
|
||||
// CHECK-NEXT: #pragma omp atomic
|
||||
// CHECK-NEXT: a++;
|
||||
// CHECK-NEXT: #pragma omp atomic read
|
||||
|
@ -168,6 +257,18 @@ T foo(T argc) {
|
|||
// CHECK-NEXT: a = b;
|
||||
// CHECK-NEXT: b++;
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-51-NEXT: #pragma omp atomic compare acq_rel
|
||||
// CHECK-51-NEXT: {
|
||||
// CHECK-51-NEXT: a = a > b ? b : a;
|
||||
// CHECK-51-NEXT: }
|
||||
// CHECK-51-NEXT: #pragma omp atomic acq_rel compare
|
||||
// CHECK-51-NEXT: {
|
||||
// CHECK-51-NEXT: a = a < b ? b : a;
|
||||
// CHECK-51-NEXT: }
|
||||
// CHECK-51-NEXT: #pragma omp atomic compare acq_rel
|
||||
// CHECK-51-NEXT: {
|
||||
// CHECK-51-NEXT: a = a == b ? c : a;
|
||||
// CHECK-51-NEXT: }
|
||||
// CHECK-NEXT: #pragma omp atomic
|
||||
// CHECK-NEXT: a++;
|
||||
// CHECK-NEXT: #pragma omp atomic read acquire
|
||||
|
@ -183,6 +284,18 @@ T foo(T argc) {
|
|||
// CHECK-NEXT: a = b;
|
||||
// CHECK-NEXT: b++;
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-51-NEXT: #pragma omp atomic compare acquire
|
||||
// CHECK-51-NEXT: {
|
||||
// CHECK-51-NEXT: a = a > b ? b : a;
|
||||
// CHECK-51-NEXT: }
|
||||
// CHECK-51-NEXT: #pragma omp atomic acquire compare
|
||||
// CHECK-51-NEXT: {
|
||||
// CHECK-51-NEXT: a = a < b ? b : a;
|
||||
// CHECK-51-NEXT: }
|
||||
// CHECK-51-NEXT: #pragma omp atomic compare acquire
|
||||
// CHECK-51-NEXT: {
|
||||
// CHECK-51-NEXT: a = a == b ? c : a;
|
||||
// CHECK-51-NEXT: }
|
||||
// CHECK-NEXT: #pragma omp atomic release
|
||||
// CHECK-NEXT: a++;
|
||||
// CHECK-NEXT: #pragma omp atomic read
|
||||
|
@ -198,6 +311,18 @@ T foo(T argc) {
|
|||
// CHECK-NEXT: a = b;
|
||||
// CHECK-NEXT: b++;
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-51-NEXT: #pragma omp atomic compare release
|
||||
// CHECK-51-NEXT: {
|
||||
// CHECK-51-NEXT: a = a > b ? b : a;
|
||||
// CHECK-51-NEXT: }
|
||||
// CHECK-51-NEXT: #pragma omp atomic release compare
|
||||
// CHECK-51-NEXT: {
|
||||
// CHECK-51-NEXT: a = a < b ? b : a;
|
||||
// CHECK-51-NEXT: }
|
||||
// CHECK-51-NEXT: #pragma omp atomic compare release
|
||||
// CHECK-51-NEXT: {
|
||||
// CHECK-51-NEXT: a = a == b ? c : a;
|
||||
// CHECK-51-NEXT: }
|
||||
// CHECK-NEXT: #pragma omp atomic relaxed
|
||||
// CHECK-NEXT: a++;
|
||||
// CHECK-NEXT: #pragma omp atomic read
|
||||
|
@ -213,6 +338,18 @@ T foo(T argc) {
|
|||
// CHECK-NEXT: a = b;
|
||||
// CHECK-NEXT: b++;
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-51-NEXT: #pragma omp atomic compare relaxed
|
||||
// CHECK-51-NEXT: {
|
||||
// CHECK-51-NEXT: a = a > b ? b : a;
|
||||
// CHECK-51-NEXT: }
|
||||
// CHECK-51-NEXT: #pragma omp atomic relaxed compare
|
||||
// CHECK-51-NEXT: {
|
||||
// CHECK-51-NEXT: a = a < b ? b : a;
|
||||
// CHECK-51-NEXT: }
|
||||
// CHECK-51-NEXT: #pragma omp atomic compare relaxed
|
||||
// CHECK-51-NEXT: {
|
||||
// CHECK-51-NEXT: a = a == b ? c : a;
|
||||
// CHECK-51-NEXT: }
|
||||
// CHECK-NEXT: #pragma omp atomic hint(6)
|
||||
// CHECK-NEXT: a++;
|
||||
// CHECK-NEXT: #pragma omp atomic read hint(6)
|
||||
|
@ -228,6 +365,18 @@ T foo(T argc) {
|
|||
// CHECK-NEXT: a = b;
|
||||
// CHECK-NEXT: b++;
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-51-NEXT: #pragma omp atomic compare hint(6)
|
||||
// CHECK-51-NEXT: {
|
||||
// CHECK-51-NEXT: a = a > b ? b : a;
|
||||
// CHECK-51-NEXT: }
|
||||
// CHECK-51-NEXT: #pragma omp atomic hint(6) compare
|
||||
// CHECK-51-NEXT: {
|
||||
// CHECK-51-NEXT: a = a < b ? b : a;
|
||||
// CHECK-51-NEXT: }
|
||||
// CHECK-51-NEXT: #pragma omp atomic compare hint(6)
|
||||
// CHECK-51-NEXT: {
|
||||
// CHECK-51-NEXT: a = a == b ? c : a;
|
||||
// CHECK-51-NEXT: }
|
||||
// CHECK: int a = int();
|
||||
// CHECK-NEXT: #pragma omp atomic
|
||||
// CHECK-NEXT: a++;
|
||||
|
@ -244,6 +393,18 @@ T foo(T argc) {
|
|||
// CHECK-NEXT: a = b;
|
||||
// CHECK-NEXT: b++;
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-51-NEXT: #pragma omp atomic compare
|
||||
// CHECK-51-NEXT: {
|
||||
// CHECK-51-NEXT: a = a > b ? b : a;
|
||||
// CHECK-51-NEXT: }
|
||||
// CHECK-51-NEXT: #pragma omp atomic compare
|
||||
// CHECK-51-NEXT: {
|
||||
// CHECK-51-NEXT: a = a < b ? b : a;
|
||||
// CHECK-51-NEXT: }
|
||||
// CHECK-51-NEXT: #pragma omp atomic compare
|
||||
// CHECK-51-NEXT: {
|
||||
// CHECK-51-NEXT: a = a == b ? c : a;
|
||||
// CHECK-51-NEXT: }
|
||||
// CHECK-NEXT: #pragma omp atomic seq_cst
|
||||
// CHECK-NEXT: a++;
|
||||
// CHECK-NEXT: #pragma omp atomic read seq_cst
|
||||
|
@ -259,6 +420,18 @@ T foo(T argc) {
|
|||
// CHECK-NEXT: a = b;
|
||||
// CHECK-NEXT: b++;
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-51-NEXT: #pragma omp atomic compare seq_cst
|
||||
// CHECK-51-NEXT: {
|
||||
// CHECK-51-NEXT: a = a > b ? b : a;
|
||||
// CHECK-51-NEXT: }
|
||||
// CHECK-51-NEXT: #pragma omp atomic seq_cst compare
|
||||
// CHECK-51-NEXT: {
|
||||
// CHECK-51-NEXT: a = a < b ? b : a;
|
||||
// CHECK-51-NEXT: }
|
||||
// CHECK-51-NEXT: #pragma omp atomic compare seq_cst
|
||||
// CHECK-51-NEXT: {
|
||||
// CHECK-51-NEXT: a = a == b ? c : a;
|
||||
// CHECK-51-NEXT: }
|
||||
// CHECK-NEXT: #pragma omp atomic
|
||||
// CHECK-NEXT: a++;
|
||||
// CHECK-NEXT: #pragma omp atomic read
|
||||
|
@ -274,6 +447,18 @@ T foo(T argc) {
|
|||
// CHECK-NEXT: a = b;
|
||||
// CHECK-NEXT: b++;
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-51-NEXT: #pragma omp atomic compare acq_rel
|
||||
// CHECK-51-NEXT: {
|
||||
// CHECK-51-NEXT: a = a > b ? b : a;
|
||||
// CHECK-51-NEXT: }
|
||||
// CHECK-51-NEXT: #pragma omp atomic acq_rel compare
|
||||
// CHECK-51-NEXT: {
|
||||
// CHECK-51-NEXT: a = a < b ? b : a;
|
||||
// CHECK-51-NEXT: }
|
||||
// CHECK-51-NEXT: #pragma omp atomic compare acq_rel
|
||||
// CHECK-51-NEXT: {
|
||||
// CHECK-51-NEXT: a = a == b ? c : a;
|
||||
// CHECK-51-NEXT: }
|
||||
// CHECK-NEXT: #pragma omp atomic
|
||||
// CHECK-NEXT: a++;
|
||||
// CHECK-NEXT: #pragma omp atomic read acquire
|
||||
|
@ -289,6 +474,18 @@ T foo(T argc) {
|
|||
// CHECK-NEXT: a = b;
|
||||
// CHECK-NEXT: b++;
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-51-NEXT: #pragma omp atomic compare acquire
|
||||
// CHECK-51-NEXT: {
|
||||
// CHECK-51-NEXT: a = a > b ? b : a;
|
||||
// CHECK-51-NEXT: }
|
||||
// CHECK-51-NEXT: #pragma omp atomic acquire compare
|
||||
// CHECK-51-NEXT: {
|
||||
// CHECK-51-NEXT: a = a < b ? b : a;
|
||||
// CHECK-51-NEXT: }
|
||||
// CHECK-51-NEXT: #pragma omp atomic compare acquire
|
||||
// CHECK-51-NEXT: {
|
||||
// CHECK-51-NEXT: a = a == b ? c : a;
|
||||
// CHECK-51-NEXT: }
|
||||
// CHECK-NEXT: #pragma omp atomic release
|
||||
// CHECK-NEXT: a++;
|
||||
// CHECK-NEXT: #pragma omp atomic read
|
||||
|
@ -304,6 +501,18 @@ T foo(T argc) {
|
|||
// CHECK-NEXT: a = b;
|
||||
// CHECK-NEXT: b++;
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-51-NEXT: #pragma omp atomic compare release
|
||||
// CHECK-51-NEXT: {
|
||||
// CHECK-51-NEXT: a = a > b ? b : a;
|
||||
// CHECK-51-NEXT: }
|
||||
// CHECK-51-NEXT: #pragma omp atomic release compare
|
||||
// CHECK-51-NEXT: {
|
||||
// CHECK-51-NEXT: a = a < b ? b : a;
|
||||
// CHECK-51-NEXT: }
|
||||
// CHECK-51-NEXT: #pragma omp atomic compare release
|
||||
// CHECK-51-NEXT: {
|
||||
// CHECK-51-NEXT: a = a == b ? c : a;
|
||||
// CHECK-51-NEXT: }
|
||||
// CHECK-NEXT: #pragma omp atomic relaxed
|
||||
// CHECK-NEXT: a++;
|
||||
// CHECK-NEXT: #pragma omp atomic read
|
||||
|
@ -319,6 +528,18 @@ T foo(T argc) {
|
|||
// CHECK-NEXT: a = b;
|
||||
// CHECK-NEXT: b++;
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-51-NEXT: #pragma omp atomic compare relaxed
|
||||
// CHECK-51-NEXT: {
|
||||
// CHECK-51-NEXT: a = a > b ? b : a;
|
||||
// CHECK-51-NEXT: }
|
||||
// CHECK-51-NEXT: #pragma omp atomic relaxed compare
|
||||
// CHECK-51-NEXT: {
|
||||
// CHECK-51-NEXT: a = a < b ? b : a;
|
||||
// CHECK-51-NEXT: }
|
||||
// CHECK-51-NEXT: #pragma omp atomic compare relaxed
|
||||
// CHECK-51-NEXT: {
|
||||
// CHECK-51-NEXT: a = a == b ? c : a;
|
||||
// CHECK-51-NEXT: }
|
||||
// CHECK-NEXT: #pragma omp atomic hint(6)
|
||||
// CHECK-NEXT: a++;
|
||||
// CHECK-NEXT: #pragma omp atomic read hint(6)
|
||||
|
@ -334,8 +555,21 @@ T foo(T argc) {
|
|||
// CHECK-NEXT: a = b;
|
||||
// CHECK-NEXT: b++;
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-51-NEXT: #pragma omp atomic compare hint(6)
|
||||
// CHECK-51-NEXT: {
|
||||
// CHECK-51-NEXT: a = a > b ? b : a;
|
||||
// CHECK-51-NEXT: }
|
||||
// CHECK-51-NEXT: #pragma omp atomic hint(6) compare
|
||||
// CHECK-51-NEXT: {
|
||||
// CHECK-51-NEXT: a = a < b ? b : a;
|
||||
// CHECK-51-NEXT: }
|
||||
// CHECK-51-NEXT: #pragma omp atomic compare hint(6)
|
||||
// CHECK-51-NEXT: {
|
||||
// CHECK-51-NEXT: a = a == b ? c : a;
|
||||
// CHECK-51-NEXT: }
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int c = 0;
|
||||
int b = 0;
|
||||
int a = 0;
|
||||
// CHECK: int a = 0;
|
||||
|
@ -354,6 +588,14 @@ int main(int argc, char **argv) {
|
|||
a = b;
|
||||
b++;
|
||||
}
|
||||
#ifdef OMP51
|
||||
#pragma omp atomic compare
|
||||
{ a = a > b ? b : a; }
|
||||
#pragma omp atomic compare
|
||||
{ a = a < b ? b : a; }
|
||||
#pragma omp atomic compare
|
||||
{ a = a == b ? c : a; }
|
||||
#endif
|
||||
#pragma omp atomic seq_cst
|
||||
a++;
|
||||
#pragma omp atomic read seq_cst
|
||||
|
@ -369,6 +611,14 @@ int main(int argc, char **argv) {
|
|||
a = b;
|
||||
b++;
|
||||
}
|
||||
#ifdef OMP51
|
||||
#pragma omp atomic compare seq_cst
|
||||
{ a = a > b ? b : a; }
|
||||
#pragma omp atomic seq_cst compare
|
||||
{ a = a < b ? b : a; }
|
||||
#pragma omp atomic compare seq_cst
|
||||
{ a = a == b ? c : a; }
|
||||
#endif
|
||||
#pragma omp atomic
|
||||
a++;
|
||||
#pragma omp atomic read
|
||||
|
@ -384,6 +634,14 @@ int main(int argc, char **argv) {
|
|||
a = b;
|
||||
b++;
|
||||
}
|
||||
#ifdef OMP51
|
||||
#pragma omp atomic compare acq_rel
|
||||
{ a = a > b ? b : a; }
|
||||
#pragma omp atomic acq_rel compare
|
||||
{ a = a < b ? b : a; }
|
||||
#pragma omp atomic compare acq_rel
|
||||
{ a = a == b ? c : a; }
|
||||
#endif
|
||||
#pragma omp atomic
|
||||
a++;
|
||||
#pragma omp atomic read acquire
|
||||
|
@ -399,6 +657,14 @@ int main(int argc, char **argv) {
|
|||
a = b;
|
||||
b++;
|
||||
}
|
||||
#ifdef OMP51
|
||||
#pragma omp atomic compare acquire
|
||||
{ a = a > b ? b : a; }
|
||||
#pragma omp atomic acquire compare
|
||||
{ a = a < b ? b : a; }
|
||||
#pragma omp atomic compare acquire
|
||||
{ a = a == b ? c : a; }
|
||||
#endif
|
||||
#pragma omp atomic release
|
||||
a++;
|
||||
#pragma omp atomic read
|
||||
|
@ -414,6 +680,14 @@ int main(int argc, char **argv) {
|
|||
a = b;
|
||||
b++;
|
||||
}
|
||||
#ifdef OMP51
|
||||
#pragma omp atomic compare release
|
||||
{ a = a > b ? b : a; }
|
||||
#pragma omp atomic release compare
|
||||
{ a = a < b ? b : a; }
|
||||
#pragma omp atomic compare release
|
||||
{ a = a == b ? c : a; }
|
||||
#endif
|
||||
#pragma omp atomic relaxed
|
||||
a++;
|
||||
#pragma omp atomic read
|
||||
|
@ -429,6 +703,14 @@ int main(int argc, char **argv) {
|
|||
a = b;
|
||||
b++;
|
||||
}
|
||||
#ifdef OMP51
|
||||
#pragma omp atomic compare relaxed
|
||||
{ a = a > b ? b : a; }
|
||||
#pragma omp atomic relaxed compare
|
||||
{ a = a < b ? b : a; }
|
||||
#pragma omp atomic compare relaxed
|
||||
{ a = a == b ? c : a; }
|
||||
#endif
|
||||
#pragma omp atomic hint(6)
|
||||
a++;
|
||||
#pragma omp atomic read hint(6)
|
||||
|
@ -444,6 +726,14 @@ int main(int argc, char **argv) {
|
|||
a = b;
|
||||
b++;
|
||||
}
|
||||
#ifdef OMP51
|
||||
#pragma omp atomic compare hint(6)
|
||||
{ a = a > b ? b : a; }
|
||||
#pragma omp atomic hint(6) compare
|
||||
{ a = a < b ? b : a; }
|
||||
#pragma omp atomic compare hint(6)
|
||||
{ a = a == b ? c : a; }
|
||||
#endif
|
||||
// CHECK-NEXT: #pragma omp atomic
|
||||
// CHECK-NEXT: a++;
|
||||
// CHECK-NEXT: #pragma omp atomic read
|
||||
|
@ -459,6 +749,18 @@ int main(int argc, char **argv) {
|
|||
// CHECK-NEXT: a = b;
|
||||
// CHECK-NEXT: b++;
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-51-NEXT: #pragma omp atomic compare
|
||||
// CHECK-51-NEXT: {
|
||||
// CHECK-51-NEXT: a = a > b ? b : a;
|
||||
// CHECK-51-NEXT: }
|
||||
// CHECK-51-NEXT: #pragma omp atomic compare
|
||||
// CHECK-51-NEXT: {
|
||||
// CHECK-51-NEXT: a = a < b ? b : a;
|
||||
// CHECK-51-NEXT: }
|
||||
// CHECK-51-NEXT: #pragma omp atomic compare
|
||||
// CHECK-51-NEXT: {
|
||||
// CHECK-51-NEXT: a = a == b ? c : a;
|
||||
// CHECK-51-NEXT: }
|
||||
// CHECK-NEXT: #pragma omp atomic seq_cst
|
||||
// CHECK-NEXT: a++;
|
||||
// CHECK-NEXT: #pragma omp atomic read seq_cst
|
||||
|
@ -474,6 +776,18 @@ int main(int argc, char **argv) {
|
|||
// CHECK-NEXT: a = b;
|
||||
// CHECK-NEXT: b++;
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-51-NEXT: #pragma omp atomic compare seq_cst
|
||||
// CHECK-51-NEXT: {
|
||||
// CHECK-51-NEXT: a = a > b ? b : a;
|
||||
// CHECK-51-NEXT: }
|
||||
// CHECK-51-NEXT: #pragma omp atomic seq_cst compare
|
||||
// CHECK-51-NEXT: {
|
||||
// CHECK-51-NEXT: a = a < b ? b : a;
|
||||
// CHECK-51-NEXT: }
|
||||
// CHECK-51-NEXT: #pragma omp atomic compare seq_cst
|
||||
// CHECK-51-NEXT: {
|
||||
// CHECK-51-NEXT: a = a == b ? c : a;
|
||||
// CHECK-51-NEXT: }
|
||||
// CHECK-NEXT: #pragma omp atomic
|
||||
// CHECK-NEXT: a++;
|
||||
// CHECK-NEXT: #pragma omp atomic read
|
||||
|
@ -489,6 +803,18 @@ int main(int argc, char **argv) {
|
|||
// CHECK-NEXT: a = b;
|
||||
// CHECK-NEXT: b++;
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-51-NEXT: #pragma omp atomic compare acq_rel
|
||||
// CHECK-51-NEXT: {
|
||||
// CHECK-51-NEXT: a = a > b ? b : a;
|
||||
// CHECK-51-NEXT: }
|
||||
// CHECK-51-NEXT: #pragma omp atomic acq_rel compare
|
||||
// CHECK-51-NEXT: {
|
||||
// CHECK-51-NEXT: a = a < b ? b : a;
|
||||
// CHECK-51-NEXT: }
|
||||
// CHECK-51-NEXT: #pragma omp atomic compare acq_rel
|
||||
// CHECK-51-NEXT: {
|
||||
// CHECK-51-NEXT: a = a == b ? c : a;
|
||||
// CHECK-51-NEXT: }
|
||||
// CHECK-NEXT: #pragma omp atomic
|
||||
// CHECK-NEXT: a++;
|
||||
// CHECK-NEXT: #pragma omp atomic read acquire
|
||||
|
@ -504,6 +830,18 @@ int main(int argc, char **argv) {
|
|||
// CHECK-NEXT: a = b;
|
||||
// CHECK-NEXT: b++;
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-51-NEXT: #pragma omp atomic compare acquire
|
||||
// CHECK-51-NEXT: {
|
||||
// CHECK-51-NEXT: a = a > b ? b : a;
|
||||
// CHECK-51-NEXT: }
|
||||
// CHECK-51-NEXT: #pragma omp atomic acquire compare
|
||||
// CHECK-51-NEXT: {
|
||||
// CHECK-51-NEXT: a = a < b ? b : a;
|
||||
// CHECK-51-NEXT: }
|
||||
// CHECK-51-NEXT: #pragma omp atomic compare acquire
|
||||
// CHECK-51-NEXT: {
|
||||
// CHECK-51-NEXT: a = a == b ? c : a;
|
||||
// CHECK-51-NEXT: }
|
||||
// CHECK-NEXT: #pragma omp atomic release
|
||||
// CHECK-NEXT: a++;
|
||||
// CHECK-NEXT: #pragma omp atomic read
|
||||
|
@ -519,6 +857,18 @@ int main(int argc, char **argv) {
|
|||
// CHECK-NEXT: a = b;
|
||||
// CHECK-NEXT: b++;
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-51-NEXT: #pragma omp atomic compare release
|
||||
// CHECK-51-NEXT: {
|
||||
// CHECK-51-NEXT: a = a > b ? b : a;
|
||||
// CHECK-51-NEXT: }
|
||||
// CHECK-51-NEXT: #pragma omp atomic release compare
|
||||
// CHECK-51-NEXT: {
|
||||
// CHECK-51-NEXT: a = a < b ? b : a;
|
||||
// CHECK-51-NEXT: }
|
||||
// CHECK-51-NEXT: #pragma omp atomic compare release
|
||||
// CHECK-51-NEXT: {
|
||||
// CHECK-51-NEXT: a = a == b ? c : a;
|
||||
// CHECK-51-NEXT: }
|
||||
// CHECK-NEXT: #pragma omp atomic relaxed
|
||||
// CHECK-NEXT: a++;
|
||||
// CHECK-NEXT: #pragma omp atomic read
|
||||
|
@ -534,6 +884,18 @@ int main(int argc, char **argv) {
|
|||
// CHECK-NEXT: a = b;
|
||||
// CHECK-NEXT: b++;
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-51-NEXT: #pragma omp atomic compare relaxed
|
||||
// CHECK-51-NEXT: {
|
||||
// CHECK-51-NEXT: a = a > b ? b : a;
|
||||
// CHECK-51-NEXT: }
|
||||
// CHECK-51-NEXT: #pragma omp atomic relaxed compare
|
||||
// CHECK-51-NEXT: {
|
||||
// CHECK-51-NEXT: a = a < b ? b : a;
|
||||
// CHECK-51-NEXT: }
|
||||
// CHECK-51-NEXT: #pragma omp atomic compare relaxed
|
||||
// CHECK-51-NEXT: {
|
||||
// CHECK-51-NEXT: a = a == b ? c : a;
|
||||
// CHECK-51-NEXT: }
|
||||
// CHECK-NEXT: #pragma omp atomic hint(6)
|
||||
// CHECK-NEXT: a++;
|
||||
// CHECK-NEXT: #pragma omp atomic read hint(6)
|
||||
|
@ -549,6 +911,19 @@ int main(int argc, char **argv) {
|
|||
// CHECK-NEXT: a = b;
|
||||
// CHECK-NEXT: b++;
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-51-NEXT: #pragma omp atomic compare hint(6)
|
||||
// CHECK-51-NEXT: {
|
||||
// CHECK-51-NEXT: a = a > b ? b : a;
|
||||
// CHECK-51-NEXT: }
|
||||
// CHECK-51-NEXT: #pragma omp atomic hint(6) compare
|
||||
// CHECK-51-NEXT: {
|
||||
// CHECK-51-NEXT: a = a < b ? b : a;
|
||||
// CHECK-51-NEXT: }
|
||||
// CHECK-51-NEXT: #pragma omp atomic compare hint(6)
|
||||
// CHECK-51-NEXT: {
|
||||
// CHECK-51-NEXT: a = a == b ? c : a;
|
||||
// CHECK-51-NEXT: }
|
||||
// expect-note@+1 {{in instantiation of function template specialization 'foo<int>' requested here}}
|
||||
return foo(a);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
// RUN: %clang_cc1 -verify=expected,omp45 -fopenmp -fopenmp-version=45 -ferror-limit 100 %s -Wuninitialized
|
||||
// RUN: %clang_cc1 -verify=expected,omp50 -fopenmp -ferror-limit 100 %s -Wuninitialized
|
||||
// RUN: %clang_cc1 -DOMP51 -verify=expected,omp50,omp51 -fopenmp -fopenmp-version=51 -ferror-limit 100 %s -Wuninitialized
|
||||
|
||||
// RUN: %clang_cc1 -verify=expected,omp45 -fopenmp-simd -fopenmp-version=45 -ferror-limit 100 %s -Wuninitialized
|
||||
// RUN: %clang_cc1 -verify=expected,omp50 -fopenmp-simd -ferror-limit 100 %s -Wuninitialized
|
||||
// RUN: %clang_cc1 -DOMP51 -verify=expected,omp50,omp51 -fopenmp-simd -fopenmp-version=51 -ferror-limit 100 %s -Wuninitialized
|
||||
|
||||
void xxx(int argc) {
|
||||
int x; // expected-note {{initialize the variable 'x' to silence this warning}}
|
||||
|
@ -394,3 +396,92 @@ void hint() {
|
|||
#pragma omp atomic hint(1) hint(1) // omp45-error 2 {{unexpected OpenMP clause 'hint' in directive '#pragma omp atomic'}} expected-error {{directive '#pragma omp atomic' cannot contain more than one 'hint' clause}}
|
||||
a += 1;
|
||||
}
|
||||
|
||||
#ifdef OMP51
|
||||
extern void bbar();
|
||||
extern int ffoo();
|
||||
|
||||
void compare() {
|
||||
int x = 0;
|
||||
int d = 0;
|
||||
int e = 0;
|
||||
// omp51-error@+3 {{the statement for 'atomic compare' must be a compound statement of form '{x = expr ordop x ? expr : x;}', '{x = x ordop expr? expr : x;}', '{x = x == e ? d : x;}', '{x = e == x ? d : x;}', or 'if(expr ordop x) {x = expr;}', 'if(x ordop expr) {x = expr;}', 'if(x == e) {x = d;}', 'if(e == x) {x = d;}' where 'x' is an lvalue expression with scalar type, 'expr', 'e', and 'd' are expressions with scalar type, and 'ordop' is one of '<' or '>'.}}
|
||||
// omp51-note@+2 {{expected compound statement}}
|
||||
#pragma omp atomic compare
|
||||
{}
|
||||
// omp51-error@+3 {{the statement for 'atomic compare' must be a compound statement of form '{x = expr ordop x ? expr : x;}', '{x = x ordop expr? expr : x;}', '{x = x == e ? d : x;}', '{x = e == x ? d : x;}', or 'if(expr ordop x) {x = expr;}', 'if(x ordop expr) {x = expr;}', 'if(x == e) {x = d;}', 'if(e == x) {x = d;}' where 'x' is an lvalue expression with scalar type, 'expr', 'e', and 'd' are expressions with scalar type, and 'ordop' is one of '<' or '>'.}}
|
||||
// omp51-note@+2 {{expected exactly one expression statement}}
|
||||
#pragma omp atomic compare
|
||||
{
|
||||
x = d;
|
||||
x = e;
|
||||
}
|
||||
// omp51-error@+3 {{the statement for 'atomic compare' must be a compound statement of form '{x = expr ordop x ? expr : x;}', '{x = x ordop expr? expr : x;}', '{x = x == e ? d : x;}', '{x = e == x ? d : x;}', or 'if(expr ordop x) {x = expr;}', 'if(x ordop expr) {x = expr;}', 'if(x == e) {x = d;}', 'if(e == x) {x = d;}' where 'x' is an lvalue expression with scalar type, 'expr', 'e', and 'd' are expressions with scalar type, and 'ordop' is one of '<' or '>'.}}
|
||||
// omp51-note@+2 {{expected assignment statement}}
|
||||
#pragma omp atomic compare
|
||||
{ x += d; }
|
||||
// omp51-error@+3 {{the statement for 'atomic compare' must be a compound statement of form '{x = expr ordop x ? expr : x;}', '{x = x ordop expr? expr : x;}', '{x = x == e ? d : x;}', '{x = e == x ? d : x;}', or 'if(expr ordop x) {x = expr;}', 'if(x ordop expr) {x = expr;}', 'if(x == e) {x = d;}', 'if(e == x) {x = d;}' where 'x' is an lvalue expression with scalar type, 'expr', 'e', and 'd' are expressions with scalar type, and 'ordop' is one of '<' or '>'.}}
|
||||
// omp51-note@+2 {{expected assignment statement}}
|
||||
#pragma omp atomic compare
|
||||
{ bbar(); }
|
||||
// omp51-error@+3 {{the statement for 'atomic compare' must be a compound statement of form '{x = expr ordop x ? expr : x;}', '{x = x ordop expr? expr : x;}', '{x = x == e ? d : x;}', '{x = e == x ? d : x;}', or 'if(expr ordop x) {x = expr;}', 'if(x ordop expr) {x = expr;}', 'if(x == e) {x = d;}', 'if(e == x) {x = d;}' where 'x' is an lvalue expression with scalar type, 'expr', 'e', and 'd' are expressions with scalar type, and 'ordop' is one of '<' or '>'.}}
|
||||
// omp51-note@+2 {{expected conditional operator}}
|
||||
#pragma omp atomic compare
|
||||
{ x = d; }
|
||||
// omp51-error@+3 {{the statement for 'atomic compare' must be a compound statement of form '{x = expr ordop x ? expr : x;}', '{x = x ordop expr? expr : x;}', '{x = x == e ? d : x;}', '{x = e == x ? d : x;}', or 'if(expr ordop x) {x = expr;}', 'if(x ordop expr) {x = expr;}', 'if(x == e) {x = d;}', 'if(e == x) {x = d;}' where 'x' is an lvalue expression with scalar type, 'expr', 'e', and 'd' are expressions with scalar type, and 'ordop' is one of '<' or '>'.}}
|
||||
// omp51-note@+2 {{expect binary operator in conditional expression}}
|
||||
#pragma omp atomic compare
|
||||
{ x = ffoo() ? e : x; }
|
||||
// omp51-error@+3 {{the statement for 'atomic compare' must be a compound statement of form '{x = expr ordop x ? expr : x;}', '{x = x ordop expr? expr : x;}', '{x = x == e ? d : x;}', '{x = e == x ? d : x;}', or 'if(expr ordop x) {x = expr;}', 'if(x ordop expr) {x = expr;}', 'if(x == e) {x = d;}', 'if(e == x) {x = d;}' where 'x' is an lvalue expression with scalar type, 'expr', 'e', and 'd' are expressions with scalar type, and 'ordop' is one of '<' or '>'.}}
|
||||
// omp51-note@+2 {{expect '<', '>' or '==' as order operator}}
|
||||
#pragma omp atomic compare
|
||||
{ x = x >= e ? e : x; }
|
||||
// omp51-error@+3 {{the statement for 'atomic compare' must be a compound statement of form '{x = expr ordop x ? expr : x;}', '{x = x ordop expr? expr : x;}', '{x = x == e ? d : x;}', '{x = e == x ? d : x;}', or 'if(expr ordop x) {x = expr;}', 'if(x ordop expr) {x = expr;}', 'if(x == e) {x = d;}', 'if(e == x) {x = d;}' where 'x' is an lvalue expression with scalar type, 'expr', 'e', and 'd' are expressions with scalar type, and 'ordop' is one of '<' or '>'.}}
|
||||
// omp51-note@+2 {{expect comparison in a form of 'x == e', 'e == x', 'x ordop expr', or 'expr ordop x'}}
|
||||
#pragma omp atomic compare
|
||||
{ x = d > e ? e : x; }
|
||||
// omp51-error@+3 {{the statement for 'atomic compare' must be a compound statement of form '{x = expr ordop x ? expr : x;}', '{x = x ordop expr? expr : x;}', '{x = x == e ? d : x;}', '{x = e == x ? d : x;}', or 'if(expr ordop x) {x = expr;}', 'if(x ordop expr) {x = expr;}', 'if(x == e) {x = d;}', 'if(e == x) {x = d;}' where 'x' is an lvalue expression with scalar type, 'expr', 'e', and 'd' are expressions with scalar type, and 'ordop' is one of '<' or '>'.}}
|
||||
// omp51-note@+2 {{expect result value to be at false expression}}
|
||||
#pragma omp atomic compare
|
||||
{ x = d > x ? e : d; }
|
||||
// omp51-error@+4 {{the statement for 'atomic compare' must be a compound statement of form '{x = expr ordop x ? expr : x;}', '{x = x ordop expr? expr : x;}', '{x = x == e ? d : x;}', '{x = e == x ? d : x;}', or 'if(expr ordop x) {x = expr;}', 'if(x ordop expr) {x = expr;}', 'if(x == e) {x = d;}', 'if(e == x) {x = d;}' where 'x' is an lvalue expression with scalar type, 'expr', 'e', and 'd' are expressions with scalar type, and 'ordop' is one of '<' or '>'.}}
|
||||
// omp51-note@+3 {{expect binary operator in conditional expression}}
|
||||
#pragma omp atomic compare
|
||||
{
|
||||
if (foo())
|
||||
x = d;
|
||||
}
|
||||
// omp51-error@+4 {{the statement for 'atomic compare' must be a compound statement of form '{x = expr ordop x ? expr : x;}', '{x = x ordop expr? expr : x;}', '{x = x == e ? d : x;}', '{x = e == x ? d : x;}', or 'if(expr ordop x) {x = expr;}', 'if(x ordop expr) {x = expr;}', 'if(x == e) {x = d;}', 'if(e == x) {x = d;}' where 'x' is an lvalue expression with scalar type, 'expr', 'e', and 'd' are expressions with scalar type, and 'ordop' is one of '<' or '>'.}}
|
||||
// omp51-note@+3 {{expect '<', '>' or '==' as order operator}}
|
||||
#pragma omp atomic compare
|
||||
{
|
||||
if (x >= d)
|
||||
x = d;
|
||||
}
|
||||
// omp51-error@+4 {{the statement for 'atomic compare' must be a compound statement of form '{x = expr ordop x ? expr : x;}', '{x = x ordop expr? expr : x;}', '{x = x == e ? d : x;}', '{x = e == x ? d : x;}', or 'if(expr ordop x) {x = expr;}', 'if(x ordop expr) {x = expr;}', 'if(x == e) {x = d;}', 'if(e == x) {x = d;}' where 'x' is an lvalue expression with scalar type, 'expr', 'e', and 'd' are expressions with scalar type, and 'ordop' is one of '<' or '>'.}}
|
||||
// omp51-note@+3 {{expect comparison in a form of 'x == e', 'e == x', 'x ordop expr', or 'expr ordop x'}}
|
||||
#pragma omp atomic compare
|
||||
{
|
||||
if (e > d)
|
||||
x = d;
|
||||
}
|
||||
// omp51-error@+3 {{the statement for 'atomic compare' must be a compound statement of form '{x = expr ordop x ? expr : x;}', '{x = x ordop expr? expr : x;}', '{x = x == e ? d : x;}', '{x = e == x ? d : x;}', or 'if(expr ordop x) {x = expr;}', 'if(x ordop expr) {x = expr;}', 'if(x == e) {x = d;}', 'if(e == x) {x = d;}' where 'x' is an lvalue expression with scalar type, 'expr', 'e', and 'd' are expressions with scalar type, and 'ordop' is one of '<' or '>'.}}
|
||||
// omp51-note@+2 {{expected exactly one expression statement}}
|
||||
#pragma omp atomic compare
|
||||
{
|
||||
if (x > d)
|
||||
x = e;
|
||||
d = e;
|
||||
}
|
||||
float fx = 0.0f;
|
||||
float fd = 0.0f;
|
||||
float fe = 0.0f;
|
||||
// omp51-error@+5 {{the statement for 'atomic compare' must be a compound statement of form '{x = expr ordop x ? expr : x;}', '{x = x ordop expr? expr : x;}', '{x = x == e ? d : x;}', '{x = e == x ? d : x;}', or 'if(expr ordop x) {x = expr;}', 'if(x ordop expr) {x = expr;}', 'if(x == e) {x = d;}', 'if(e == x) {x = d;}' where 'x' is an lvalue expression with scalar type, 'expr', 'e', and 'd' are expressions with scalar type, and 'ordop' is one of '<' or '>'.}}
|
||||
// omp51-note@+4 {{expect integer value}}
|
||||
#pragma omp atomic compare
|
||||
{
|
||||
if (fx > fe)
|
||||
fx = fe;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
// RUN: %clang_cc1 -verify=expected,omp45 -fopenmp -fopenmp-version=45 -ferror-limit 150 %s -Wuninitialized
|
||||
// RUN: %clang_cc1 -verify=expected,omp50 -fopenmp -ferror-limit 150 %s -Wuninitialized
|
||||
// RUN: %clang_cc1 -verify=expected,omp50,omp51 -fopenmp -fopenmp-version=51 -ferror-limit 150 %s -Wuninitialized
|
||||
// RUN: %clang_cc1 -DOMP51 -verify=expected,omp50,omp51 -fopenmp -fopenmp-version=51 -ferror-limit 150 %s -Wuninitialized
|
||||
|
||||
// RUN: %clang_cc1 -verify=expected,omp45 -fopenmp-simd -fopenmp-version=45 -ferror-limit 150 %s -Wuninitialized
|
||||
// RUN: %clang_cc1 -verify=expected,omp50 -fopenmp-simd -ferror-limit 150 %s -Wuninitialized
|
||||
// RUN: %clang_cc1 -verify=expected,omp50,omp51 -fopenmp-simd -fopenmp-version=51 -ferror-limit 150 %s -Wuninitialized
|
||||
// RUN: %clang_cc1 -DOMP51 -verify=expected,omp50,omp51 -fopenmp-simd -fopenmp-version=51 -ferror-limit 150 %s -Wuninitialized
|
||||
|
||||
int foo() {
|
||||
L1:
|
||||
|
@ -914,6 +914,16 @@ T mixed() {
|
|||
// expected-note@+1 2 {{'capture' clause used here}}
|
||||
#pragma omp atomic capture read
|
||||
a = ++b;
|
||||
#ifdef OMP51
|
||||
// expected-error@+2 2 {{directive '#pragma omp atomic' cannot contain more than one 'read', 'write', 'update', 'capture', or 'compare' clause}}
|
||||
// expected-note@+1 2 {{'write' clause used here}}
|
||||
#pragma omp atomic write compare
|
||||
a = b;
|
||||
// expected-error@+2 2 {{directive '#pragma omp atomic' cannot contain more than one 'read', 'write', 'update', 'capture', or 'compare' clause}}
|
||||
// expected-note@+1 2 {{'read' clause used here}}
|
||||
#pragma omp atomic read compare
|
||||
a = b;
|
||||
#endif
|
||||
return T();
|
||||
}
|
||||
|
||||
|
@ -935,18 +945,16 @@ int mixed() {
|
|||
// expected-note@+1 {{'write' clause used here}}
|
||||
#pragma omp atomic write capture
|
||||
a = b;
|
||||
#ifdef OMP51
|
||||
// expected-error@+2 {{directive '#pragma omp atomic' cannot contain more than one 'read', 'write', 'update', 'capture', or 'compare' clause}}
|
||||
// expected-note@+1 {{'write' clause used here}}
|
||||
#pragma omp atomic write compare
|
||||
a = b;
|
||||
// expected-error@+2 {{directive '#pragma omp atomic' cannot contain more than one 'read', 'write', 'update', 'capture', or 'compare' clause}}
|
||||
// expected-note@+1 {{'read' clause used here}}
|
||||
#pragma omp atomic read compare
|
||||
a = b;
|
||||
#endif
|
||||
// expected-note@+1 {{in instantiation of function template specialization 'mixed<int>' requested here}}
|
||||
return mixed<int>();
|
||||
}
|
||||
|
||||
#if _OPENMP >= 202011
|
||||
int compare() {
|
||||
int a, b, c;
|
||||
// omp51-error@+1 {{atomic compare is not supported for now}}
|
||||
#pragma omp atomic compare
|
||||
{
|
||||
if (a == b)
|
||||
a = c;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue