diff options
author | Alexey Bataev <a.bataev@hotmail.com> | 2015-04-01 03:33:17 +0000 |
---|---|---|
committer | Alexey Bataev <a.bataev@hotmail.com> | 2015-04-01 03:33:17 +0000 |
commit | b78ca83d3b9f86efea1b5d9e618e8dd1c27de2da (patch) | |
tree | f9316bcc26eade320af03bf566c47afce3c7f381 | |
parent | 506cf09c6f641b7c06eb3b6bba8e2c388a27c144 (diff) | |
download | bcm5719-llvm-b78ca83d3b9f86efea1b5d9e618e8dd1c27de2da.tar.gz bcm5719-llvm-b78ca83d3b9f86efea1b5d9e618e8dd1c27de2da.zip |
[OPENMP] Sema analysis for 'atomic capture' construct.
Added sema checks for forms of expressions/statements allowed under control of 'atomic capture' directive + generation of helper objects for future codegen.
llvm-svn: 233785
-rw-r--r-- | clang/include/clang/AST/StmtOpenMP.h | 20 | ||||
-rw-r--r-- | clang/include/clang/Basic/DiagnosticSemaKinds.td | 2 | ||||
-rw-r--r-- | clang/lib/AST/Stmt.cpp | 10 | ||||
-rw-r--r-- | clang/lib/Sema/SemaOpenMP.cpp | 261 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTReaderStmt.cpp | 1 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTWriterStmt.cpp | 1 | ||||
-rw-r--r-- | clang/test/OpenMP/atomic_messages.c | 172 | ||||
-rw-r--r-- | clang/test/OpenMP/atomic_messages.cpp | 343 |
8 files changed, 763 insertions, 47 deletions
diff --git a/clang/include/clang/AST/StmtOpenMP.h b/clang/include/clang/AST/StmtOpenMP.h index d3b76f775f3..2238e3483b9 100644 --- a/clang/include/clang/AST/StmtOpenMP.h +++ b/clang/include/clang/AST/StmtOpenMP.h @@ -1592,6 +1592,15 @@ class OMPAtomicDirective : public OMPExecutableDirective { /// second. Required for correct codegen of non-associative operations (like /// << or >>). bool IsXLHSInRHSPart; + /// \brief Used for 'atomic update' or 'atomic capture' constructs. They may + /// have atomic expressions of forms + /// \code + /// v = x; <update x>; + /// <update x>; v = x; + /// \endcode + /// This field is true for the first(postfix) form of the expression and false + /// otherwise. + bool IsPostfixUpdate; /// \brief Build directive with the given start and end location. /// @@ -1603,7 +1612,7 @@ class OMPAtomicDirective : public OMPExecutableDirective { unsigned NumClauses) : OMPExecutableDirective(this, OMPAtomicDirectiveClass, OMPD_atomic, StartLoc, EndLoc, NumClauses, 5), - IsXLHSInRHSPart(false) {} + IsXLHSInRHSPart(false), IsPostfixUpdate(false) {} /// \brief Build an empty directive. /// @@ -1613,7 +1622,7 @@ class OMPAtomicDirective : public OMPExecutableDirective { : OMPExecutableDirective(this, OMPAtomicDirectiveClass, OMPD_atomic, SourceLocation(), SourceLocation(), NumClauses, 5), - IsXLHSInRHSPart(false) {} + IsXLHSInRHSPart(false), IsPostfixUpdate(false) {} /// \brief Set 'x' part of the associated expression/statement. void setX(Expr *X) { *std::next(child_begin()) = X; } @@ -1644,10 +1653,12 @@ public: /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'. /// \param IsXLHSInRHSPart true if \a UE has the first form and false if the /// second. + /// \param IsPostfixUpdate true if original value of 'x' must be stored in + /// 'v', not an updated one. static OMPAtomicDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, Expr *X, Expr *V, - Expr *E, Expr *UE, bool IsXLHSInRHSPart); + Expr *E, Expr *UE, bool IsXLHSInRHSPart, bool IsPostfixUpdate); /// \brief Creates an empty directive with the place for \a NumClauses /// clauses. @@ -1676,6 +1687,9 @@ public: /// 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' and false if it has form /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'. bool isXLHSInRHSPart() const { return IsXLHSInRHSPart; } + /// \brief Return true if 'v' expression must be updated to original value of + /// 'x', false if 'v' must be updated to the new value of 'x'. + bool isPostfixUpdate() const { return IsPostfixUpdate; } /// \brief Get 'v' part of the associated expression/statement. Expr *getV() { return cast_or_null<Expr>(*std::next(child_begin(), 3)); } const Expr *getV() const { diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index e02271c9023..7866e5471e2 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -7495,6 +7495,8 @@ def err_omp_atomic_capture_not_compound_statement : Error< " '{v = x; x = x binop expr;}', '{v = x; x = expr binop x;}', '{x = x binop expr; v = x;}', '{x = expr binop x; v = x;}' or '{v = x; x = expr;}'," " '{v = x; x++;}', '{v = x; ++x;}', '{++x; v = x;}', '{x++; v = x;}', '{v = x; x--;}', '{v = x; --x;}', '{--x; v = x;}', '{x--; v = x;}'" " where x is an l-value 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_several_clauses : Error< "directive '#pragma omp atomic' cannot contain more than one 'read', 'write', 'update' or 'capture' clause">; def note_omp_atomic_previous_clause : Note< diff --git a/clang/lib/AST/Stmt.cpp b/clang/lib/AST/Stmt.cpp index 4262dc39ea5..f5d8213ded6 100644 --- a/clang/lib/AST/Stmt.cpp +++ b/clang/lib/AST/Stmt.cpp @@ -2007,11 +2007,10 @@ OMPOrderedDirective *OMPOrderedDirective::CreateEmpty(const ASTContext &C, return new (Mem) OMPOrderedDirective(); } -OMPAtomicDirective * -OMPAtomicDirective::Create(const ASTContext &C, SourceLocation StartLoc, - SourceLocation EndLoc, ArrayRef<OMPClause *> Clauses, - Stmt *AssociatedStmt, Expr *X, Expr *V, Expr *E, - Expr *UE, bool IsXLHSInRHSPart) { +OMPAtomicDirective *OMPAtomicDirective::Create( + const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, Expr *X, Expr *V, + Expr *E, Expr *UE, bool IsXLHSInRHSPart, bool IsPostfixUpdate) { unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPAtomicDirective), llvm::alignOf<OMPClause *>()); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + @@ -2025,6 +2024,7 @@ OMPAtomicDirective::Create(const ASTContext &C, SourceLocation StartLoc, Dir->setExpr(E); Dir->setUpdateExpr(UE); Dir->IsXLHSInRHSPart = IsXLHSInRHSPart; + Dir->IsPostfixUpdate = IsPostfixUpdate; return Dir; } diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index 54dc8861b7a..80ca072e2dd 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -3295,18 +3295,22 @@ class OpenMPAtomicUpdateChecker { bool IsXLHSInRHSPart; BinaryOperatorKind Op; SourceLocation OpLoc; + /// \brief true if the source expression is a postfix unary operation, false + /// if it is a prefix unary operation. + bool IsPostfixUpdate; public: OpenMPAtomicUpdateChecker(Sema &SemaRef) : SemaRef(SemaRef), X(nullptr), E(nullptr), UpdateExpr(nullptr), - IsXLHSInRHSPart(false), Op(BO_PtrMemD) {} + IsXLHSInRHSPart(false), Op(BO_PtrMemD), IsPostfixUpdate(false) {} /// \brief Check specified statement that it is suitable for 'atomic update' /// constructs and extract 'x', 'expr' and Operation from the original - /// expression. + /// expression. If DiagId and NoteId == 0, then only check is performed + /// without error notification. /// \param DiagId Diagnostic which should be emitted if error is found. /// \param NoteId Diagnostic note for the main error message. /// \return true if statement is not an update expression, false otherwise. - bool checkStatement(Stmt *S, unsigned DiagId, unsigned NoteId); + bool checkStatement(Stmt *S, unsigned DiagId = 0, unsigned NoteId = 0); /// \brief Return the 'x' lvalue part of the source atomic expression. Expr *getX() const { return X; } /// \brief Return the 'expr' rvalue part of the source atomic expression. @@ -3319,9 +3323,13 @@ public: /// false otherwise. bool isXLHSInRHSPart() const { return IsXLHSInRHSPart; } + /// \brief true if the source expression is a postfix unary operation, false + /// if it is a prefix unary operation. + bool isPostfixUpdate() const { return IsPostfixUpdate; } + private: - bool checkBinaryOperation(BinaryOperator *AtomicBinOp, unsigned DiagId, - unsigned NoteId); + bool checkBinaryOperation(BinaryOperator *AtomicBinOp, unsigned DiagId = 0, + unsigned NoteId = 0); }; } // namespace @@ -3383,7 +3391,7 @@ bool OpenMPAtomicUpdateChecker::checkBinaryOperation( NoteRange = SourceRange(NoteLoc, NoteLoc); ErrorFound = NotAnAssignmentOp; } - if (ErrorFound != NoError) { + if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) { SemaRef.Diag(ErrorLoc, DiagId) << ErrorRange; SemaRef.Diag(NoteLoc, NoteId) << ErrorFound << NoteRange; return true; @@ -3427,6 +3435,7 @@ bool OpenMPAtomicUpdateChecker::checkStatement(Stmt *S, unsigned DiagId, dyn_cast<UnaryOperator>(AtomicBody->IgnoreParenImpCasts())) { // Check for Unary Operation if (AtomicUnaryOp->isIncrementDecrementOp()) { + IsPostfixUpdate = AtomicUnaryOp->isPostfix(); Op = AtomicUnaryOp->isIncrementOp() ? BO_Add : BO_Sub; OpLoc = AtomicUnaryOp->getOperatorLoc(); X = AtomicUnaryOp->getSubExpr(); @@ -3454,7 +3463,7 @@ bool OpenMPAtomicUpdateChecker::checkStatement(Stmt *S, unsigned DiagId, NoteLoc = ErrorLoc = S->getLocStart(); NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc); } - if (ErrorFound != NoError) { + if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) { SemaRef.Diag(ErrorLoc, DiagId) << ErrorRange; SemaRef.Diag(NoteLoc, NoteId) << ErrorFound << NoteRange; return true; @@ -3493,7 +3502,6 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses, // top and a single exit at the bottom. // The point of exit cannot be a branch out of the structured block. // longjmp() and throw() must not violate the entry/exit criteria. - // TODO further analysis of associated statements and clauses. OpenMPClauseKind AtomicKind = OMPC_unknown; SourceLocation AtomicKindLoc; for (auto *C : Clauses) { @@ -3521,6 +3529,7 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses, Expr *E = nullptr; Expr *UE = nullptr; bool IsXLHSInRHSPart = false; + bool IsPostfixUpdate = false; // OpenMP [2.12.6, atomic Construct] // In the next expressions: // * x and v (as applicable) are both l-value expressions with scalar type. @@ -3543,14 +3552,14 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses, // 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: @@ -3606,6 +3615,13 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses, } else if (CurContext->isDependentContext()) V = X = nullptr; } else if (AtomicKind == OMPC_write) { + enum { + NotAnExpression, + NotAnAssignmentOp, + NotAScalarType, + NotAnLValue, + NoError + } ErrorFound = NoError; SourceLocation ErrorLoc, NoteLoc; SourceRange ErrorRange, NoteRange; // If clause is write: @@ -3682,21 +3698,218 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses, IsXLHSInRHSPart = Checker.isXLHSInRHSPart(); } } else if (AtomicKind == OMPC_capture) { - if (isa<Expr>(Body) && !isa<BinaryOperator>(Body)) { - Diag(Body->getLocStart(), - diag::err_omp_atomic_capture_not_expression_statement); - return StmtError(); - } else if (!isa<Expr>(Body) && !isa<CompoundStmt>(Body)) { - Diag(Body->getLocStart(), - diag::err_omp_atomic_capture_not_compound_statement); - return StmtError(); + enum { + NotAnAssignmentOp, + NotACompoundStatement, + NotTwoSubstatements, + NotASpecificExpression, + NoError + } ErrorFound = NoError; + SourceLocation ErrorLoc, NoteLoc; + SourceRange ErrorRange, NoteRange; + if (auto *AtomicBody = dyn_cast<Expr>(Body)) { + // If clause is a capture: + // v = x++; + // v = x--; + // v = ++x; + // v = --x; + // v = x binop= expr; + // v = x = x binop expr; + // v = x = expr binop x; + auto *AtomicBinOp = + dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts()); + if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) { + V = AtomicBinOp->getLHS(); + Body = AtomicBinOp->getRHS()->IgnoreParenImpCasts(); + OpenMPAtomicUpdateChecker Checker(*this); + if (Checker.checkStatement( + Body, diag::err_omp_atomic_capture_not_expression_statement, + diag::note_omp_atomic_update)) + return StmtError(); + E = Checker.getExpr(); + X = Checker.getX(); + UE = Checker.getUpdateExpr(); + IsXLHSInRHSPart = Checker.isXLHSInRHSPart(); + IsPostfixUpdate = Checker.isPostfixUpdate(); + } else { + ErrorLoc = AtomicBody->getExprLoc(); + ErrorRange = AtomicBody->getSourceRange(); + NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc() + : AtomicBody->getExprLoc(); + NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange() + : AtomicBody->getSourceRange(); + ErrorFound = NotAnAssignmentOp; + } + if (ErrorFound != NoError) { + Diag(ErrorLoc, diag::err_omp_atomic_capture_not_expression_statement) + << ErrorRange; + Diag(NoteLoc, diag::note_omp_atomic_capture) << ErrorFound << NoteRange; + return StmtError(); + } else if (CurContext->isDependentContext()) { + UE = V = E = X = nullptr; + } + } else { + // If clause is a capture: + // { v = x; x = expr; } + // { v = x; x++; } + // { v = x; x--; } + // { v = x; ++x; } + // { v = x; --x; } + // { v = x; x binop= expr; } + // { v = x; x = x binop expr; } + // { v = x; x = expr binop x; } + // { x++; v = x; } + // { x--; v = x; } + // { ++x; v = x; } + // { --x; v = x; } + // { x binop= expr; v = x; } + // { x = x binop expr; v = x; } + // { x = expr binop x; v = x; } + if (auto *CS = dyn_cast<CompoundStmt>(Body)) { + // Check that this is { expr1; expr2; } + if (CS->size() == 2) { + auto *First = CS->body_front(); + auto *Second = CS->body_back(); + if (auto *EWC = dyn_cast<ExprWithCleanups>(First)) + First = EWC->getSubExpr()->IgnoreParenImpCasts(); + if (auto *EWC = dyn_cast<ExprWithCleanups>(Second)) + Second = EWC->getSubExpr()->IgnoreParenImpCasts(); + // Need to find what subexpression is 'v' and what is 'x'. + OpenMPAtomicUpdateChecker Checker(*this); + bool IsUpdateExprFound = !Checker.checkStatement(Second); + BinaryOperator *BinOp = nullptr; + if (IsUpdateExprFound) { + BinOp = dyn_cast<BinaryOperator>(First); + IsUpdateExprFound = BinOp && BinOp->getOpcode() == BO_Assign; + } + if (IsUpdateExprFound && !CurContext->isDependentContext()) { + // { v = x; x++; } + // { v = x; x--; } + // { v = x; ++x; } + // { v = x; --x; } + // { v = x; x binop= expr; } + // { v = x; x = x binop expr; } + // { v = x; x = expr binop x; } + // Check that the first expression has form v = x. + auto *PossibleX = BinOp->getRHS()->IgnoreParenImpCasts(); + llvm::FoldingSetNodeID XId, PossibleXId; + Checker.getX()->Profile(XId, Context, /*Canonical=*/true); + PossibleX->Profile(PossibleXId, Context, /*Canonical=*/true); + IsUpdateExprFound = XId == PossibleXId; + if (IsUpdateExprFound) { + V = BinOp->getLHS(); + X = Checker.getX(); + E = Checker.getExpr(); + UE = Checker.getUpdateExpr(); + IsXLHSInRHSPart = Checker.isXLHSInRHSPart(); + IsPostfixUpdate = Checker.isPostfixUpdate(); + } + } + if (!IsUpdateExprFound) { + IsUpdateExprFound = !Checker.checkStatement(First); + BinOp = nullptr; + if (IsUpdateExprFound) { + BinOp = dyn_cast<BinaryOperator>(Second); + IsUpdateExprFound = BinOp && BinOp->getOpcode() == BO_Assign; + } + if (IsUpdateExprFound && !CurContext->isDependentContext()) { + // { x++; v = x; } + // { x--; v = x; } + // { ++x; v = x; } + // { --x; v = x; } + // { x binop= expr; v = x; } + // { x = x binop expr; v = x; } + // { x = expr binop x; v = x; } + // Check that the second expression has form v = x. + auto *PossibleX = BinOp->getRHS()->IgnoreParenImpCasts(); + llvm::FoldingSetNodeID XId, PossibleXId; + Checker.getX()->Profile(XId, Context, /*Canonical=*/true); + PossibleX->Profile(PossibleXId, Context, /*Canonical=*/true); + IsUpdateExprFound = XId == PossibleXId; + if (IsUpdateExprFound) { + V = BinOp->getLHS(); + X = Checker.getX(); + E = Checker.getExpr(); + UE = Checker.getUpdateExpr(); + IsXLHSInRHSPart = Checker.isXLHSInRHSPart(); + IsPostfixUpdate = Checker.isPostfixUpdate(); + } + } + } + if (!IsUpdateExprFound) { + // { v = x; x = expr; } + auto *FirstBinOp = dyn_cast<BinaryOperator>(First); + if (!FirstBinOp || FirstBinOp->getOpcode() != BO_Assign) { + ErrorFound = NotAnAssignmentOp; + NoteLoc = ErrorLoc = FirstBinOp ? FirstBinOp->getOperatorLoc() + : First->getLocStart(); + NoteRange = ErrorRange = FirstBinOp + ? FirstBinOp->getSourceRange() + : SourceRange(ErrorLoc, ErrorLoc); + } else { + auto *SecondBinOp = dyn_cast<BinaryOperator>(Second); + if (!SecondBinOp || SecondBinOp->getOpcode() != BO_Assign) { + ErrorFound = NotAnAssignmentOp; + NoteLoc = ErrorLoc = SecondBinOp ? SecondBinOp->getOperatorLoc() + : Second->getLocStart(); + NoteRange = ErrorRange = SecondBinOp + ? SecondBinOp->getSourceRange() + : SourceRange(ErrorLoc, ErrorLoc); + } else { + auto *PossibleXRHSInFirst = + FirstBinOp->getRHS()->IgnoreParenImpCasts(); + auto *PossibleXLHSInSecond = + SecondBinOp->getLHS()->IgnoreParenImpCasts(); + llvm::FoldingSetNodeID X1Id, X2Id; + PossibleXRHSInFirst->Profile(X1Id, Context, /*Canonical=*/true); + PossibleXLHSInSecond->Profile(X2Id, Context, + /*Canonical=*/true); + IsUpdateExprFound = X1Id == X2Id; + if (IsUpdateExprFound) { + V = FirstBinOp->getLHS(); + X = SecondBinOp->getLHS(); + E = SecondBinOp->getRHS(); + UE = nullptr; + IsXLHSInRHSPart = false; + IsPostfixUpdate = true; + } else { + ErrorFound = NotASpecificExpression; + ErrorLoc = FirstBinOp->getExprLoc(); + ErrorRange = FirstBinOp->getSourceRange(); + NoteLoc = SecondBinOp->getLHS()->getExprLoc(); + NoteRange = SecondBinOp->getRHS()->getSourceRange(); + } + } + } + } + } else { + NoteLoc = ErrorLoc = Body->getLocStart(); + NoteRange = ErrorRange = + SourceRange(Body->getLocStart(), Body->getLocStart()); + ErrorFound = NotTwoSubstatements; + } + } else { + NoteLoc = ErrorLoc = Body->getLocStart(); + NoteRange = ErrorRange = + SourceRange(Body->getLocStart(), Body->getLocStart()); + ErrorFound = NotACompoundStatement; + } + if (ErrorFound != NoError) { + Diag(ErrorLoc, diag::err_omp_atomic_capture_not_compound_statement) + << ErrorRange; + Diag(NoteLoc, diag::note_omp_atomic_capture) << ErrorFound << NoteRange; + return StmtError(); + } else if (CurContext->isDependentContext()) { + UE = V = E = X = nullptr; + } } } getCurFunction()->setHasBranchProtectedScope(); return OMPAtomicDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt, - X, V, E, UE, IsXLHSInRHSPart); + X, V, E, UE, IsXLHSInRHSPart, + IsPostfixUpdate); } StmtResult Sema::ActOnOpenMPTargetDirective(ArrayRef<OMPClause *> Clauses, diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp index b31d9e756a6..e40b1d9599e 100644 --- a/clang/lib/Serialization/ASTReaderStmt.cpp +++ b/clang/lib/Serialization/ASTReaderStmt.cpp @@ -2162,6 +2162,7 @@ void ASTStmtReader::VisitOMPAtomicDirective(OMPAtomicDirective *D) { D->setExpr(Reader.ReadSubExpr()); D->setUpdateExpr(Reader.ReadSubExpr()); D->IsXLHSInRHSPart = Record[Idx++] != 0; + D->IsPostfixUpdate = Record[Idx++] != 0; } void ASTStmtReader::VisitOMPTargetDirective(OMPTargetDirective *D) { diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp index daebc52c96b..97ed06ff638 100644 --- a/clang/lib/Serialization/ASTWriterStmt.cpp +++ b/clang/lib/Serialization/ASTWriterStmt.cpp @@ -2010,6 +2010,7 @@ void ASTStmtWriter::VisitOMPAtomicDirective(OMPAtomicDirective *D) { Writer.AddStmt(D->getExpr()); Writer.AddStmt(D->getUpdateExpr()); Record.push_back(D->isXLHSInRHSPart() ? 1 : 0); + Record.push_back(D->isPostfixUpdate() ? 1 : 0); Code = serialization::STMT_OMP_ATOMIC_DIRECTIVE; } diff --git a/clang/test/OpenMP/atomic_messages.c b/clang/test/OpenMP/atomic_messages.c index 8d4ade6fe0c..294ce7e6b21 100644 --- a/clang/test/OpenMP/atomic_messages.c +++ b/clang/test/OpenMP/atomic_messages.c @@ -193,3 +193,175 @@ int updateint() { return 0; } +int captureint() { + int a = 0, b = 0, c = 0; +// Test for atomic capture +#pragma omp atomic capture + // expected-error@+2 {{the statement for 'atomic capture' must be a compound statement of form '{v = x; x binop= expr;}', '{x binop= expr; v = x;}', '{v = x; x = x binop expr;}', '{v = x; x = expr binop x;}', '{x = x binop expr; v = x;}', '{x = expr binop x; v = x;}' or '{v = x; x = expr;}', '{v = x; x++;}', '{v = x; ++x;}', '{++x; v = x;}', '{x++; v = x;}', '{v = x; x--;}', '{v = x; --x;}', '{--x; v = x;}', '{x--; v = x;}' where x is an l-value expression with scalar type}} + // expected-note@+1 {{expected compound statement}} + ; +#pragma omp atomic capture + // expected-error@+2 {{the statement for 'atomic capture' must be an expression statement of form 'v = ++x;', 'v = --x;', 'v = x++;', 'v = x--;', 'v = x binop= expr;', 'v = x = x binop expr' or 'v = x = expr binop x', where x and v are both l-value expressions with scalar type}} + // expected-note@+1 {{expected assignment expression}} + foo(); +#pragma omp atomic capture + // expected-error@+2 {{the statement for 'atomic capture' must be an expression statement of form 'v = ++x;', 'v = --x;', 'v = x++;', 'v = x--;', 'v = x binop= expr;', 'v = x = x binop expr' or 'v = x = expr binop x', where x and v are both l-value expressions with scalar type}} + // expected-note@+1 {{expected built-in binary or unary operator}} + a = b; +#pragma omp atomic capture + // expected-error@+2 {{the statement for 'atomic capture' must be an expression statement of form 'v = ++x;', 'v = --x;', 'v = x++;', 'v = x--;', 'v = x binop= expr;', 'v = x = x binop expr' or 'v = x = expr binop x', where x and v are both l-value expressions with scalar type}} + // expected-note@+1 {{expected assignment expression}} + a = b || a; +#pragma omp atomic capture + // expected-error@+2 {{the statement for 'atomic capture' must be an expression statement of form 'v = ++x;', 'v = --x;', 'v = x++;', 'v = x--;', 'v = x binop= expr;', 'v = x = x binop expr' or 'v = x = expr binop x', where x and v are both l-value expressions with scalar type}} + // expected-note@+1 {{expected one of '+', '*', '-', '/', '&', '^', '|', '<<', or '>>' built-in operations}} + b = a = a && b; +#pragma omp atomic capture + // expected-error@+2 {{the statement for 'atomic capture' must be an expression statement of form 'v = ++x;', 'v = --x;', 'v = x++;', 'v = x--;', 'v = x binop= expr;', 'v = x = x binop expr' or 'v = x = expr binop x', where x and v are both l-value expressions with scalar type}} + // expected-note@+1 {{expected assignment expression}} + a = (float)a + b; +#pragma omp atomic capture + // expected-error@+2 {{the statement for 'atomic capture' must be an expression statement of form 'v = ++x;', 'v = --x;', 'v = x++;', 'v = x--;', 'v = x binop= expr;', 'v = x = x binop expr' or 'v = x = expr binop x', where x and v are both l-value expressions with scalar type}} + // expected-note@+1 {{expected assignment expression}} + a = 2 * b; +#pragma omp atomic capture + // expected-error@+2 {{the statement for 'atomic capture' must be an expression statement of form 'v = ++x;', 'v = --x;', 'v = x++;', 'v = x--;', 'v = x binop= expr;', 'v = x = x binop expr' or 'v = x = expr binop x', where x and v are both l-value expressions with scalar type}} + // expected-note@+1 {{expected assignment expression}} + a = b + *&a; +#pragma omp atomic capture + // expected-error@+2 {{the statement for 'atomic capture' must be a compound statement of form '{v = x; x binop= expr;}', '{x binop= expr; v = x;}', '{v = x; x = x binop expr;}', '{v = x; x = expr binop x;}', '{x = x binop expr; v = x;}', '{x = expr binop x; v = x;}' or '{v = x; x = expr;}', '{v = x; x++;}', '{v = x; ++x;}', '{++x; v = x;}', '{x++; v = x;}', '{v = x; x--;}', '{v = x; --x;}', '{--x; v = x;}', '{x--; v = x;}' where x is an l-value expression with scalar type}} + // expected-note@+1 {{expected exactly two expression statements}} + { a = b; } +#pragma omp atomic capture + // expected-error@+2 {{the statement for 'atomic capture' must be a compound statement of form '{v = x; x binop= expr;}', '{x binop= expr; v = x;}', '{v = x; x = x binop expr;}', '{v = x; x = expr binop x;}', '{x = x binop expr; v = x;}', '{x = expr binop x; v = x;}' or '{v = x; x = expr;}', '{v = x; x++;}', '{v = x; ++x;}', '{++x; v = x;}', '{x++; v = x;}', '{v = x; x--;}', '{v = x; --x;}', '{--x; v = x;}', '{x--; v = x;}' where x is an l-value expression with scalar type}} + // expected-note@+1 {{expected exactly two expression statements}} + {} +#pragma omp atomic capture + // expected-error@+2 {{the statement for 'atomic capture' must be a compound statement of form '{v = x; x binop= expr;}', '{x binop= expr; v = x;}', '{v = x; x = x binop expr;}', '{v = x; x = expr binop x;}', '{x = x binop expr; v = x;}', '{x = expr binop x; v = x;}' or '{v = x; x = expr;}', '{v = x; x++;}', '{v = x; ++x;}', '{++x; v = x;}', '{x++; v = x;}', '{v = x; x--;}', '{v = x; --x;}', '{--x; v = x;}', '{x--; v = x;}' where x is an l-value expression with scalar type}} + // expected-note@+1 {{expected in right hand side of the first expression}} + {a = b;a = b;} +#pragma omp atomic capture + // expected-error@+2 {{the statement for 'atomic capture' must be a compound statement of form '{v = x; x binop= expr;}', '{x binop= expr; v = x;}', '{v = x; x = x binop expr;}', '{v = x; x = expr binop x;}', '{x = x binop expr; v = x;}', '{x = expr binop x; v = x;}' or '{v = x; x = expr;}', '{v = x; x++;}', '{v = x; ++x;}', '{++x; v = x;}', '{x++; v = x;}', '{v = x; x--;}', '{v = x; --x;}', '{--x; v = x;}', '{x--; v = x;}' where x is an l-value expression with scalar type}} + // expected-note@+1 {{expected in right hand side of the first expression}} + {a = b; a = b || a;} +#pragma omp atomic capture + {b = a; a = a && b;} +#pragma omp atomic capture + // expected-error@+2 {{the statement for 'atomic capture' must be an expression statement of form 'v = ++x;', 'v = --x;', 'v = x++;', 'v = x--;', 'v = x binop= expr;', 'v = x = x binop expr' or 'v = x = expr binop x', where x and v are both l-value expressions with scalar type}} + // expected-note@+1 {{expected in right hand side of expression}} + b = a = (float)a + b; +#pragma omp atomic capture + // expected-error@+2 {{the statement for 'atomic capture' must be an expression statement of form 'v = ++x;', 'v = --x;', 'v = x++;', 'v = x--;', 'v = x binop= expr;', 'v = x = x binop expr' or 'v = x = expr binop x', where x and v are both l-value expressions with scalar type}} + // expected-note@+1 {{expected in right hand side of expression}} + b = a = 2 * b; +#pragma omp atomic capture + // expected-error@+2 {{the statement for 'atomic capture' must be an expression statement of form 'v = ++x;', 'v = --x;', 'v = x++;', 'v = x--;', 'v = x binop= expr;', 'v = x = x binop expr' or 'v = x = expr binop x', where x and v are both l-value expressions with scalar type}} + // expected-note@+1 {{expected in right hand side of expression}} + b = a = b + *&a; +#pragma omp atomic capture + c = *&a = *&a + 2; +#pragma omp atomic capture + c = a++; +#pragma omp atomic capture + c = ++a; +#pragma omp atomic capture + c = a--; +#pragma omp atomic capture + c = --a; +#pragma omp atomic capture + c = a += b; +#pragma omp atomic capture + c = a %= b; +#pragma omp atomic capture + c = a *= b; +#pragma omp atomic capture + c = a -= b; +#pragma omp atomic capture + c = a /= b; +#pragma omp atomic capture + c = a &= b; +#pragma omp atomic capture + c = a ^= b; +#pragma omp atomic capture + c = a |= b; +#pragma omp atomic capture + c = a <<= b; +#pragma omp atomic capture + c = a >>= b; +#pragma omp atomic capture + c = a = b + a; +#pragma omp atomic capture + c = a = a * b; +#pragma omp atomic capture + c = a = b - a; +#pragma omp atomic capture + c = a = a / b; +#pragma omp atomic capture + c = a = b & a; +#pragma omp atomic capture + c = a = a ^ b; +#pragma omp atomic capture + c = a = b | a; +#pragma omp atomic capture + c = a = a << b; +#pragma omp atomic capture + c = a = b >> a; +#pragma omp atomic capture + { c = *&a; *&a = *&a + 2;} +#pragma omp atomic capture + { *&a = *&a + 2; c = *&a;} +#pragma omp atomic capture + {c = a; a++;} +#pragma omp atomic capture + {++a;c = a;} +#pragma omp atomic capture + {c = a;a--;} +#pragma omp atomic capture + {--a;c = a;} +#pragma omp atomic capture + {c = a; a += b;} +#pragma omp atomic capture + {a %= b; c = a;} +#pragma omp atomic capture + {c = a; a *= b;} +#pragma omp atomic capture + {a -= b;c = a;} +#pragma omp atomic capture + {c = a; a /= b;} +#pragma omp atomic capture + {a &= b; c = a;} +#pragma omp atomic capture + {c = a; a ^= b;} +#pragma omp atomic capture + {a |= b; c = a;} +#pragma omp atomic capture + {c = a; a <<= b;} +#pragma omp atomic capture + {a >>= b; c = a;} +#pragma omp atomic capture + {c = a; a = b + a;} +#pragma omp atomic capture + {a = a * b; c = a;} +#pragma omp atomic capture + {c = a; a = b - a;} +#pragma omp atomic capture + {a = a / b; c = a;} +#pragma omp atomic capture + {c = a; a = b & a;} +#pragma omp atomic capture + {a = a ^ b; c = a;} +#pragma omp atomic capture + {c = a; a = b | a;} +#pragma omp atomic capture + {a = a << b; c = a;} +#pragma omp atomic capture + {c = a; a = b >> a;} +#pragma omp atomic capture + {c = a; a = foo();} + // expected-error@+1 {{directive '#pragma omp atomic' cannot contain more than one 'capture' clause}} +#pragma omp atomic capture capture + b = a /= b; + + return 0; +} + diff --git a/clang/test/OpenMP/atomic_messages.cpp b/clang/test/OpenMP/atomic_messages.cpp index b47fbbc5c41..7466509b275 100644 --- a/clang/test/OpenMP/atomic_messages.cpp +++ b/clang/test/OpenMP/atomic_messages.cpp @@ -152,7 +152,7 @@ int write() { template <class T> T update() { - T a, b = 0; + T a = 0, b = 0, c = 0; // Test for atomic update #pragma omp atomic update // 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}} @@ -332,34 +332,347 @@ int update() { template <class T> T capture() { - T a, b = 0; + T a = 0, b = 0, c = 0; // Test for atomic capture #pragma omp atomic capture - // expected-error@+1 {{the statement for 'atomic capture' must be an expression statement of form 'v = ++x;', 'v = --x;', 'v = x++;', 'v = x--;', 'v = x binop= expr;', 'v = x = x binop expr' or 'v = x = expr binop x', where x and v are both l-value expressions with scalar type}} - ++a; -#pragma omp atomic capture - // expected-error@+1 {{the statement for 'atomic capture' must be a compound statement of form '{v = x; x binop= expr;}', '{x binop= expr; v = x;}', '{v = x; x = x binop expr;}', '{v = x; x = expr binop x;}', '{x = x binop expr; v = x;}', '{x = expr binop x; v = x;}' or '{v = x; x = expr;}', '{v = x; x++;}', '{v = x; ++x;}', '{++x; v = x;}', '{x++; v = x;}', '{v = x; x--;}', '{v = x; --x;}', '{--x; v = x;}', '{x--; v = x;}' where x is an l-value expression with scalar type}} + // expected-error@+2 {{the statement for 'atomic capture' must be a compound statement of form '{v = x; x binop= expr;}', '{x binop= expr; v = x;}', '{v = x; x = x binop expr;}', '{v = x; x = expr binop x;}', '{x = x binop expr; v = x;}', '{x = expr binop x; v = x;}' or '{v = x; x = expr;}', '{v = x; x++;}', '{v = x; ++x;}', '{++x; v = x;}', '{x++; v = x;}', '{v = x; x--;}', '{v = x; --x;}', '{--x; v = x;}', '{x--; v = x;}' where x is an l-value expression with scalar type}} + // expected-note@+1 {{expected compound statement}} ; -// expected-error@+1 {{directive '#pragma omp atomic' cannot contain more than one 'capture' clause}} +#pragma omp atomic capture + // expected-error@+2 {{the statement for 'atomic capture' must be an expression statement of form 'v = ++x;', 'v = --x;', 'v = x++;', 'v = x--;', 'v = x binop= expr;', 'v = x = x binop expr' or 'v = x = expr binop x', where x and v are both l-value expressions with scalar type}} + // expected-note@+1 {{expected assignment expression}} + foo(); +#pragma omp atomic capture + // expected-error@+2 {{the statement for 'atomic capture' must be an expression statement of form 'v = ++x;', 'v = --x;', 'v = x++;', 'v = x--;', 'v = x binop= expr;', 'v = x = x binop expr' or 'v = x = expr binop x', where x and v are both l-value expressions with scalar type}} + // expected-note@+1 {{expected built-in binary or unary operator}} + a = b; +#pragma omp atomic capture + // expected-error@+2 {{the statement for 'atomic capture' must be an expression statement of form 'v = ++x;', 'v = --x;', 'v = x++;', 'v = x--;', 'v = x binop= expr;', 'v = x = x binop expr' or 'v = x = expr binop x', where x and v are both l-value expressions with scalar type}} + // expected-note@+1 {{expected assignment expression}} + a = b || a; +#pragma omp atomic capture + // expected-error@+2 {{the statement for 'atomic capture' must be an expression statement of form 'v = ++x;', 'v = --x;', 'v = x++;', 'v = x--;', 'v = x binop= expr;', 'v = x = x binop expr' or 'v = x = expr binop x', where x and v are both l-value expressions with scalar type}} + // expected-note@+1 {{expected one of '+', '*', '-', '/', '&', '^', '|', '<<', or '>>' built-in operations}} + b = a = a && b; +#pragma omp atomic capture + // expected-error@+2 {{the statement for 'atomic capture' must be an expression statement of form 'v = ++x;', 'v = --x;', 'v = x++;', 'v = x--;', 'v = x binop= expr;', 'v = x = x binop expr' or 'v = x = expr binop x', where x and v are both l-value expressions with scalar type}} + // expected-note@+1 {{expected assignment expression}} + a = (float)a + b; +#pragma omp atomic capture + // expected-error@+2 {{the statement for 'atomic capture' must be an expression statement of form 'v = ++x;', 'v = --x;', 'v = x++;', 'v = x--;', 'v = x binop= expr;', 'v = x = x binop expr' or 'v = x = expr binop x', where x and v are both l-value expressions with scalar type}} + // expected-note@+1 {{expected assignment expression}} + a = 2 * b; +#pragma omp atomic capture + // expected-error@+2 {{the statement for 'atomic capture' must be an expression statement of form 'v = ++x;', 'v = --x;', 'v = x++;', 'v = x--;', 'v = x binop= expr;', 'v = x = x binop expr' or 'v = x = expr binop x', where x and v are both l-value expressions with scalar type}} + // expected-note@+1 {{expected assignment expression}} + a = b + *&a; +#pragma omp atomic capture + // expected-error@+2 {{the statement for 'atomic capture' must be a compound statement of form '{v = x; x binop= expr;}', '{x binop= expr; v = x;}', '{v = x; x = x binop expr;}', '{v = x; x = expr binop x;}', '{x = x binop expr; v = x;}', '{x = expr binop x; v = x;}' or '{v = x; x = expr;}', '{v = x; x++;}', '{v = x; ++x;}', '{++x; v = x;}', '{x++; v = x;}', '{v = x; x--;}', '{v = x; --x;}', '{--x; v = x;}', '{x--; v = x;}' where x is an l-value expression with scalar type}} + // expected-note@+1 {{expected exactly two expression statements}} + { a = b; } +#pragma omp atomic capture + // expected-error@+2 {{the statement for 'atomic capture' must be a compound statement of form '{v = x; x binop= expr;}', '{x binop= expr; v = x;}', '{v = x; x = x binop expr;}', '{v = x; x = expr binop x;}', '{x = x binop expr; v = x;}', '{x = expr binop x; v = x;}' or '{v = x; x = expr;}', '{v = x; x++;}', '{v = x; ++x;}', '{++x; v = x;}', '{x++; v = x;}', '{v = x; x--;}', '{v = x; --x;}', '{--x; v = x;}', '{x--; v = x;}' where x is an l-value expression with scalar type}} + // expected-note@+1 {{expected exactly two expression statements}} + {} +#pragma omp atomic capture + // expected-error@+2 {{the statement for 'atomic capture' must be a compound statement of form '{v = x; x binop= expr;}', '{x binop= expr; v = x;}', '{v = x; x = x binop expr;}', '{v = x; x = expr binop x;}', '{x = x binop expr; v = x;}', '{x = expr binop x; v = x;}' or '{v = x; x = expr;}', '{v = x; x++;}', '{v = x; ++x;}', '{++x; v = x;}', '{x++; v = x;}', '{v = x; x--;}', '{v = x; --x;}', '{--x; v = x;}', '{x--; v = x;}' where x is an l-value expression with scalar type}} + // expected-note@+1 {{expected in right hand side of the first expression}} + {a = b;a = b;} +#pragma omp atomic capture + // expected-error@+2 {{the statement for 'atomic capture' must be a compound statement of form '{v = x; x binop= expr;}', '{x binop= expr; v = x;}', '{v = x; x = x binop expr;}', '{v = x; x = expr binop x;}', '{x = x binop expr; v = x;}', '{x = expr binop x; v = x;}' or '{v = x; x = expr;}', '{v = x; x++;}', '{v = x; ++x;}', '{++x; v = x;}', '{x++; v = x;}', '{v = x; x--;}', '{v = x; --x;}', '{--x; v = x;}', '{x--; v = x;}' where x is an l-value expression with scalar type}} + // expected-note@+1 {{expected in right hand side of the first expression}} + {a = b; a = b || a;} +#pragma omp atomic capture + {b = a; a = a && b;} +#pragma omp atomic capture + // expected-error@+2 {{the statement for 'atomic capture' must be an expression statement of form 'v = ++x;', 'v = --x;', 'v = x++;', 'v = x--;', 'v = x binop= expr;', 'v = x = x binop expr' or 'v = x = expr binop x', where x and v are both l-value expressions with scalar type}} + // expected-note@+1 {{expected in right hand side of expression}} + b = a = (float)a + b; +#pragma omp atomic capture + // expected-error@+2 {{the statement for 'atomic capture' must be an expression statement of form 'v = ++x;', 'v = --x;', 'v = x++;', 'v = x--;', 'v = x binop= expr;', 'v = x = x binop expr' or 'v = x = expr binop x', where x and v are both l-value expressions with scalar type}} + // expected-note@+1 {{expected in right hand side of expression}} + b = a = 2 * b; +#pragma omp atomic capture + // expected-error@+2 {{the statement for 'atomic capture' must be an expression statement of form 'v = ++x;', 'v = --x;', 'v = x++;', 'v = x--;', 'v = x binop= expr;', 'v = x = x binop expr' or 'v = x = expr binop x', where x and v are both l-value expressions with scalar type}} + // expected-note@+1 {{expected in right hand side of expression}} + b = a = b + *&a; +#pragma omp atomic capture + c = *&a = *&a + 2; +#pragma omp atomic capture + c = a++; +#pragma omp atomic capture + c = ++a; +#pragma omp atomic capture + c = a--; +#pragma omp atomic capture + c = --a; +#pragma omp atomic capture + c = a += b; +#pragma omp atomic capture + c = a %= b; +#pragma omp atomic capture + c = a *= b; +#pragma omp atomic capture + c = a -= b; +#pragma omp atomic capture + c = a /= b; +#pragma omp atomic capture + c = a &= b; +#pragma omp atomic capture + c = a ^= b; +#pragma omp atomic capture + c = a |= b; +#pragma omp atomic capture + c = a <<= b; +#pragma omp atomic capture + c = a >>= b; +#pragma omp atomic capture + c = a = b + a; +#pragma omp atomic capture + c = a = a * b; +#pragma omp atomic capture + c = a = b - a; +#pragma omp atomic capture + c = a = a / b; +#pragma omp atomic capture + c = a = b & a; +#pragma omp atomic capture + c = a = a ^ b; +#pragma omp atomic capture + c = a = b | a; +#pragma omp atomic capture + c = a = a << b; +#pragma omp atomic capture + c = a = b >> a; +#pragma omp atomic capture + { c = *&a; *&a = *&a + 2;} +#pragma omp atomic capture + { *&a = *&a + 2; c = *&a;} +#pragma omp atomic capture + {c = a; a++;} +#pragma omp atomic capture + {++a;c = a;} +#pragma omp atomic capture + {c = a;a--;} +#pragma omp atomic capture + {--a;c = a;} +#pragma omp atomic capture + {c = a; a += b;} +#pragma omp atomic capture + {a %= b; c = a;} +#pragma omp atomic capture + {c = a; a *= b;} +#pragma omp atomic capture + {a -= b;c = a;} +#pragma omp atomic capture + {c = a; a /= b;} +#pragma omp atomic capture + {a &= b; c = a;} +#pragma omp atomic capture + {c = a; a ^= b;} +#pragma omp atomic capture + {a |= b; c = a;} +#pragma omp atomic capture + {c = a; a <<= b;} +#pragma omp atomic capture + {a >>= b; c = a;} +#pragma omp atomic capture + {c = a; a = b + a;} +#pragma omp atomic capture + {a = a * b; c = a;} +#pragma omp atomic capture + {c = a; a = b - a;} +#pragma omp atomic capture + {a = a / b; c = a;} +#pragma omp atomic capture + {c = a; a = b & a;} +#pragma omp atomic capture + {a = a ^ b; c = a;} +#pragma omp atomic capture + {c = a; a = b | a;} +#pragma omp atomic capture + {a = a << b; c = a;} +#pragma omp atomic capture + {c = a; a = b >> a;} +#pragma omp atomic capture + {c = a; a = foo();} + // expected-error@+1 {{directive '#pragma omp atomic' cannot contain more than one 'capture' clause}} #pragma omp atomic capture capture - a = ++b; + b = a /= b; return T(); } int capture() { - int a, b = 0; + int a = 0, b = 0, c = 0; // Test for atomic capture #pragma omp atomic capture - // expected-error@+1 {{the statement for 'atomic capture' must be an expression statement of form 'v = ++x;', 'v = --x;', 'v = x++;', 'v = x--;', 'v = x binop= expr;', 'v = x = x binop expr' or 'v = x = expr binop x', where x and v are both l-value expressions with scalar type}} - ++a; -#pragma omp atomic capture - // expected-error@+1 {{the statement for 'atomic capture' must be a compound statement of form '{v = x; x binop= expr;}', '{x binop= expr; v = x;}', '{v = x; x = x binop expr;}', '{v = x; x = expr binop x;}', '{x = x binop expr; v = x;}', '{x = expr binop x; v = x;}' or '{v = x; x = expr;}', '{v = x; x++;}', '{v = x; ++x;}', '{++x; v = x;}', '{x++; v = x;}', '{v = x; x--;}', '{v = x; --x;}', '{--x; v = x;}', '{x--; v = x;}' where x is an l-value expression with scalar type}} + // expected-error@+2 {{the statement for 'atomic capture' must be a compound statement of form '{v = x; x binop= expr;}', '{x binop= expr; v = x;}', '{v = x; x = x binop expr;}', '{v = x; x = expr binop x;}', '{x = x binop expr; v = x;}', '{x = expr binop x; v = x;}' or '{v = x; x = expr;}', '{v = x; x++;}', '{v = x; ++x;}', '{++x; v = x;}', '{x++; v = x;}', '{v = x; x--;}', '{v = x; --x;}', '{--x; v = x;}', '{x--; v = x;}' where x is an l-value expression with scalar type}} + // expected-note@+1 {{expected compound statement}} ; -// expected-error@+1 {{directive '#pragma omp atomic' cannot contain more than one 'capture' clause}} +#pragma omp atomic capture + // expected-error@+2 {{the statement for 'atomic capture' must be an expression statement of form 'v = ++x;', 'v = --x;', 'v = x++;', 'v = x--;', 'v = x binop= expr;', 'v = x = x binop expr' or 'v = x = expr binop x', where x and v are both l-value expressions with scalar type}} + // expected-note@+1 {{expected assignment expression}} + foo(); +#pragma omp atomic capture + // expected-error@+2 {{the statement for 'atomic capture' must be an expression statement of form 'v = ++x;', 'v = --x;', 'v = x++;', 'v = x--;', 'v = x binop= expr;', 'v = x = x binop expr' or 'v = x = expr binop x', where x and v are both l-value expressions with scalar type}} + // expected-note@+1 {{expected built-in binary or unary operator}} + a = b; +#pragma omp atomic capture + // expected-error@+2 {{the statement for 'atomic capture' must be an expression statement of form 'v = ++x;', 'v = --x;', 'v = x++;', 'v = x--;', 'v = x binop= expr;', 'v = x = x binop expr' or 'v = x = expr binop x', where x and v are both l-value expressions with scalar type}} + // expected-note@+1 {{expected assignment expression}} + a = b || a; +#pragma omp atomic capture + // expected-error@+2 {{the statement for 'atomic capture' must be an expression statement of form 'v = ++x;', 'v = --x;', 'v = x++;', 'v = x--;', 'v = x binop= expr;', 'v = x = x binop expr' or 'v = x = expr binop x', where x and v are both l-value expressions with scalar type}} + // expected-note@+1 {{expected one of '+', '*', '-', '/', '&', '^', '|', '<<', or '>>' built-in operations}} + b = a = a && b; +#pragma omp atomic capture + // expected-error@+2 {{the statement for 'atomic capture' must be an expression statement of form 'v = ++x;', 'v = --x;', 'v = x++;', 'v = x--;', 'v = x binop= expr;', 'v = x = x binop expr' or 'v = x = expr binop x', where x and v are both l-value expressions with scalar type}} + // expected-note@+1 {{expected assignment expression}} + a = (float)a + b; +#pragma omp atomic capture + // expected-error@+2 {{the statement for 'atomic capture' must be an expression statement of form 'v = ++x;', 'v = --x;', 'v = x++;', 'v = x--;', 'v = x binop= expr;', 'v = x = x binop expr' or 'v = x = expr binop x', where x and v are both l-value expressions with scalar type}} + // expected-note@+1 {{expected assignment expression}} + a = 2 * b; +#pragma omp atomic capture + // expected-error@+2 {{the statement for 'atomic capture' must be an expression statement of form 'v = ++x;', 'v = --x;', 'v = x++;', 'v = x--;', 'v = x binop= expr;', 'v = x = x binop expr' or 'v = x = expr binop x', where x and v are both l-value expressions with scalar type}} + // expected-note@+1 {{expected assignment expression}} + a = b + *&a; +#pragma omp atomic capture + // expected-error@+2 {{the statement for 'atomic capture' must be a compound statement of form '{v = x; x binop= expr;}', '{x binop= expr; v = x;}', '{v = x; x = x binop expr;}', '{v = x; x = expr binop x;}', '{x = x binop expr; v = x;}', '{x = expr binop x; v = x;}' or '{v = x; x = expr;}', '{v = x; x++;}', '{v = x; ++x;}', '{++x; v = x;}', '{x++; v = x;}', '{v = x; x--;}', '{v = x; --x;}', '{--x; v = x;}', '{x--; v = x;}' where x is an l-value expression with scalar type}} + // expected-note@+1 {{expected exactly two expression statements}} + { a = b; } +#pragma omp atomic capture + // expected-error@+2 {{the statement for 'atomic capture' must be a compound statement of form '{v = x; x binop= expr;}', '{x binop= expr; v = x;}', '{v = x; x = x binop expr;}', '{v = x; x = expr binop x;}', '{x = x binop expr; v = x;}', '{x = expr binop x; v = x;}' or '{v = x; x = expr;}', '{v = x; x++;}', '{v = x; ++x;}', '{++x; v = x;}', '{x++; v = x;}', '{v = x; x--;}', '{v = x; --x;}', '{--x; v = x;}', '{x--; v = x;}' where x is an l-value expression with scalar type}} + // expected-note@+1 {{expected exactly two expression statements}} + {} +#pragma omp atomic capture + // expected-error@+2 {{the statement for 'atomic capture' must be a compound statement of form '{v = x; x binop= expr;}', '{x binop= expr; v = x;}', '{v = x; x = x binop expr;}', '{v = x; x = expr binop x;}', '{x = x binop expr; v = x;}', '{x = expr binop x; v = x;}' or '{v = x; x = expr;}', '{v = x; x++;}', '{v = x; ++x;}', '{++x; v = x;}', '{x++; v = x;}', '{v = x; x--;}', '{v = x; --x;}', '{--x; v = x;}', '{x--; v = x;}' where x is an l-value expression with scalar type}} + // expected-note@+1 {{expected in right hand side of the first expression}} + {a = b;a = b;} +#pragma omp atomic capture + // expected-error@+2 {{the statement for 'atomic capture' must be a compound statement of form '{v = x; x binop= expr;}', '{x binop= expr; v = x;}', '{v = x; x = x binop expr;}', '{v = x; x = expr binop x;}', '{x = x binop expr; v = x;}', '{x = expr binop x; v = x;}' or '{v = x; x = expr;}', '{v = x; x++;}', '{v = x; ++x;}', '{++x; v = x;}', '{x++; v = x;}', '{v = x; x--;}', '{v = x; --x;}', '{--x; v = x;}', '{x--; v = x;}' where x is an l-value expression with scalar type}} + // expected-note@+1 {{expected in right hand side of the first expression}} + {a = b; a = b || a;} +#pragma omp atomic capture + {b = a; a = a && b;} +#pragma omp atomic capture + // expected-error@+2 {{the statement for 'atomic capture' must be an expression statement of form 'v = ++x;', 'v = --x;', 'v = x++;', 'v = x--;', 'v = x binop= expr;', 'v = x = x binop expr' or 'v = x = expr binop x', where x and v are both l-value expressions with scalar type}} + // expected-note@+1 {{expected in right hand side of expression}} + b = a = (float)a + b; +#pragma omp atomic capture + // expected-error@+2 {{the statement for 'atomic capture' must be an expression statement of form 'v = ++x;', 'v = --x;', 'v = x++;', 'v = x--;', 'v = x binop= expr;', 'v = x = x binop expr' or 'v = x = expr binop x', where x and v are both l-value expressions with scalar type}} + // expected-note@+1 {{expected in right hand side of expression}} + b = a = 2 * b; +#pragma omp atomic capture + // expected-error@+2 {{the statement for 'atomic capture' must be an expression statement of form 'v = ++x;', 'v = --x;', 'v = x++;', 'v = x--;', 'v = x binop= expr;', 'v = x = x binop expr' or 'v = x = expr binop x', where x and v are both l-value expressions with scalar type}} + // expected-note@+1 {{expected in right hand side of expression}} + b = a = b + *&a; +#pragma omp atomic capture + c = *&a = *&a + 2; +#pragma omp atomic capture + c = a++; +#pragma omp atomic capture + c = ++a; +#pragma omp atomic capture + c = a--; +#pragma omp atomic capture + c = --a; +#pragma omp atomic capture + c = a += b; +#pragma omp atomic capture + c = a %= b; +#pragma omp atomic capture + c = a *= b; +#pragma omp atomic capture + c = a -= b; +#pragma omp atomic capture + c = a /= b; +#pragma omp atomic capture + c = a &= b; +#pragma omp atomic capture + c = a ^= b; +#pragma omp atomic capture + c = a |= b; +#pragma omp atomic capture + c = a <<= b; +#pragma omp atomic capture + c = a >>= b; +#pragma omp atomic capture + c = a = b + a; +#pragma omp atomic capture + c = a = a * b; +#pragma omp atomic capture + c = a = b - a; +#pragma omp atomic capture + c = a = a / b; +#pragma omp atomic capture + c = a = b & a; +#pragma omp atomic capture + c = a = a ^ b; +#pragma omp atomic capture + c = a = b | a; +#pragma omp atomic capture + c = a = a << b; +#pragma omp atomic capture + c = a = b >> a; +#pragma omp atomic capture + { c = *&a; *&a = *&a + 2;} +#pragma omp atomic capture + { *&a = *&a + 2; c = *&a;} +#pragma omp atomic capture + {c = a; a++;} +#pragma omp atomic capture + {++a;c = a;} +#pragma omp atomic capture + {c = a;a--;} +#pragma omp atomic capture + {--a;c = a;} +#pragma omp atomic capture + {c = a; a += b;} +#pragma omp atomic capture + {a %= b; c = a;} +#pragma omp atomic capture + {c = a; a *= b;} +#pragma omp atomic capture + {a -= b;c = a;} +#pragma omp atomic capture + {c = a; a /= b;} +#pragma omp atomic capture + {a &= b; c = a;} +#pragma omp atomic capture + {c = a; a ^= b;} +#pragma omp atomic capture + {a |= b; c = a;} +#pragma omp atomic capture + {c = a; a <<= b;} +#pragma omp atomic capture + {a >>= b; c = a;} +#pragma omp atomic capture + {c = a; a = b + a;} +#pragma omp atomic capture + {a = a * b; c = a;} +#pragma omp atomic capture + {c = a; a = b - a;} +#pragma omp atomic capture + {a = a / b; c = a;} +#pragma omp atomic capture + {c = a; a = b & a;} +#pragma omp atomic capture + {a = a ^ b; c = a;} +#pragma omp atomic capture + {c = a; a = b | a;} +#pragma omp atomic capture + {a = a << b; c = a;} +#pragma omp atomic capture + {c = a; a = b >> a;} +#pragma omp atomic capture + {c = a; a = foo();} + // expected-error@+1 {{directive '#pragma omp atomic' cannot contain more than one 'capture' clause}} #pragma omp atomic capture capture - a = ++b; + b = a /= b; + // expected-note@+1 {{in instantiation of function template specialization 'capture<int>' requested here}} return capture<int>(); } |