From: Alexey Bataev Date: Fri, 13 Mar 2015 12:27:31 +0000 (+0000) Subject: [OPENMP] Additional sema analysis for 'omp atomic[ update]'. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=0a77f5e5fb0534abecb6ffeb68a4b78644f3f67a;p=clang [OPENMP] Additional sema analysis for 'omp atomic[ update]'. Adds additional semantic analysis + generation of helper expressions for proper codegen. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@232164 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/StmtOpenMP.h b/include/clang/AST/StmtOpenMP.h index aed7691cf7..91c2c3ecc1 100644 --- a/include/clang/AST/StmtOpenMP.h +++ b/include/clang/AST/StmtOpenMP.h @@ -1557,6 +1557,8 @@ public: /// class OMPAtomicDirective : public OMPExecutableDirective { friend class ASTStmtReader; + /// \brief Binary operator for update and capture constructs. + BinaryOperatorKind OpKind; /// \brief Build directive with the given start and end location. /// /// \param StartLoc Starting location of the directive kind. @@ -1566,7 +1568,7 @@ class OMPAtomicDirective : public OMPExecutableDirective { OMPAtomicDirective(SourceLocation StartLoc, SourceLocation EndLoc, unsigned NumClauses) : OMPExecutableDirective(this, OMPAtomicDirectiveClass, OMPD_atomic, - StartLoc, EndLoc, NumClauses, 4) {} + StartLoc, EndLoc, NumClauses, 5) {} /// \brief Build an empty directive. /// @@ -1575,14 +1577,19 @@ class OMPAtomicDirective : public OMPExecutableDirective { explicit OMPAtomicDirective(unsigned NumClauses) : OMPExecutableDirective(this, OMPAtomicDirectiveClass, OMPD_atomic, SourceLocation(), SourceLocation(), NumClauses, - 4) {} + 5) {} + /// \brief Set operator kind for update and capture atomic constructs. + void setOpKind(const BinaryOperatorKind BOK) { OpKind = BOK; } /// \brief Set 'x' part of the associated expression/statement. void setX(Expr *X) { *std::next(child_begin()) = X; } + /// \brief Set 'x' rvalue used in update and capture atomic constructs for + /// proper update expression generation. + void setXRVal(Expr *XRVal) { *std::next(child_begin(), 2) = XRVal; } /// \brief Set 'v' part of the associated expression/statement. - void setV(Expr *V) { *std::next(child_begin(), 2) = V; } + void setV(Expr *V) { *std::next(child_begin(), 3) = V; } /// \brief Set 'expr' part of the associated expression/statement. - void setExpr(Expr *E) { *std::next(child_begin(), 3) = E; } + void setExpr(Expr *E) { *std::next(child_begin(), 4) = E; } public: /// \brief Creates directive with a list of \a Clauses and 'x', 'v' and 'expr' @@ -1594,14 +1601,19 @@ public: /// \param EndLoc Ending Location of the directive. /// \param Clauses List of clauses. /// \param AssociatedStmt Statement, associated with the directive. + /// \param OpKind Binary operator used for updating of 'x' part of the + /// expression in update and capture atomic constructs. /// \param X 'x' part of the associated expression/statement. + /// \param XRVal 'x' rvalue expression used in update and capture constructs + /// for proper update expression generation. Used to read original value of + /// the 'x' part of the expression. /// \param V 'v' part of the associated expression/statement. /// \param E 'expr' part of the associated expression/statement. /// static OMPAtomicDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, - ArrayRef Clauses, Stmt *AssociatedStmt, Expr *X, Expr *V, - Expr *E); + ArrayRef Clauses, Stmt *AssociatedStmt, + BinaryOperatorKind OpKind, Expr *X, Expr *XRVal, Expr *V, Expr *E); /// \brief Creates an empty directive with the place for \a NumClauses /// clauses. @@ -1612,20 +1624,28 @@ public: static OMPAtomicDirective *CreateEmpty(const ASTContext &C, unsigned NumClauses, EmptyShell); + /// \brief Get binary operation for update or capture atomic constructs. + BinaryOperatorKind getOpKind() const { return OpKind; } /// \brief Get 'x' part of the associated expression/statement. Expr *getX() { return cast_or_null(*std::next(child_begin())); } const Expr *getX() const { return cast_or_null(*std::next(child_begin())); } + /// \brief Get 'x' rvalue used in update and capture atomic constructs for + /// proper update expression generation. + Expr *getXRVal() { return cast_or_null(*std::next(child_begin(), 2)); } + const Expr *getXRVal() const { + return cast_or_null(*std::next(child_begin(), 2)); + } /// \brief Get 'v' part of the associated expression/statement. - Expr *getV() { return cast_or_null(*std::next(child_begin(), 2)); } + Expr *getV() { return cast_or_null(*std::next(child_begin(), 3)); } const Expr *getV() const { - return cast_or_null(*std::next(child_begin(), 2)); + return cast_or_null(*std::next(child_begin(), 3)); } /// \brief Get 'expr' part of the associated expression/statement. - Expr *getExpr() { return cast_or_null(*std::next(child_begin(), 3)); } + Expr *getExpr() { return cast_or_null(*std::next(child_begin(), 4)); } const Expr *getExpr() const { - return cast_or_null(*std::next(child_begin(), 3)); + return cast_or_null(*std::next(child_begin(), 4)); } static bool classof(const Stmt *T) { diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 5e9688bbec..085cafff78 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -7490,8 +7490,15 @@ def err_omp_atomic_write_not_expression_statement : Error< "the statement for 'atomic write' must be an expression statement of form 'x = expr;'," " where x is a lvalue expression with scalar type">; def err_omp_atomic_update_not_expression_statement : Error< - "the statement for 'atomic%select{| update}0' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x'," + "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">; +def err_omp_atomic_not_expression_statement : Error< + "the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x'," + " where x is an l-value expression with scalar type">; +def note_omp_atomic_update: Note< + "%select{expected an expression statement|expected built-in binary or unary operator|expected unary decrement/increment operation|" + "expected expression of scalar type|expected assignment expression|expected built-in binary operator|" + "expected one of '+', '*', '-', '/', '&', '^', '%|', '<<', or '>>' built-in operations|expected in right hand side of expression}0">; def err_omp_atomic_capture_not_expression_statement : Error< "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">; diff --git a/lib/AST/Stmt.cpp b/lib/AST/Stmt.cpp index 64b1897e0b..a48f4a3e15 100644 --- a/lib/AST/Stmt.cpp +++ b/lib/AST/Stmt.cpp @@ -1957,16 +1957,19 @@ OMPOrderedDirective *OMPOrderedDirective::CreateEmpty(const ASTContext &C, OMPAtomicDirective * OMPAtomicDirective::Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef Clauses, - Stmt *AssociatedStmt, Expr *X, Expr *V, Expr *E) { + Stmt *AssociatedStmt, BinaryOperatorKind OpKind, + Expr *X, Expr *XRVal, Expr *V, Expr *E) { unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPAtomicDirective), llvm::alignOf()); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + - 4 * sizeof(Stmt *)); + 5 * sizeof(Stmt *)); OMPAtomicDirective *Dir = new (Mem) OMPAtomicDirective(StartLoc, EndLoc, Clauses.size()); + Dir->setOpKind(OpKind); Dir->setClauses(Clauses); Dir->setAssociatedStmt(AssociatedStmt); Dir->setX(X); + Dir->setXRVal(X); Dir->setV(V); Dir->setExpr(E); return Dir; @@ -1978,7 +1981,7 @@ OMPAtomicDirective *OMPAtomicDirective::CreateEmpty(const ASTContext &C, unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPAtomicDirective), llvm::alignOf()); void *Mem = - C.Allocate(Size + sizeof(OMPClause *) * NumClauses + 4 * sizeof(Stmt *)); + C.Allocate(Size + sizeof(OMPClause *) * NumClauses + 5 * sizeof(Stmt *)); return new (Mem) OMPAtomicDirective(NumClauses); } diff --git a/lib/Sema/SemaOpenMP.cpp b/lib/Sema/SemaOpenMP.cpp index 9b66d2fd9f..7042399428 100644 --- a/lib/Sema/SemaOpenMP.cpp +++ b/lib/Sema/SemaOpenMP.cpp @@ -3236,6 +3236,211 @@ StmtResult Sema::ActOnOpenMPOrderedDirective(Stmt *AStmt, return OMPOrderedDirective::Create(Context, StartLoc, EndLoc, AStmt); } +namespace { +/// \brief Helper class for checking expression in 'omp atomic [update]' +/// construct. +class OpenMPAtomicUpdateChecker { + /// \brief Error results for atomic update expressions. + enum ExprAnalysisErrorCode { + /// \brief A statement is not an expression statement. + NotAnExpression, + /// \brief Expression is not builtin binary or unary operation. + NotABinaryOrUnaryExpression, + /// \brief Unary operation is not post-/pre- increment/decrement operation. + NotAnUnaryIncDecExpression, + /// \brief An expression is not of scalar type. + NotAScalarType, + /// \brief A binary operation is not an assignment operation. + NotAnAssignmentOp, + /// \brief RHS part of the binary operation is not a binary expression. + NotABinaryExpression, + /// \brief RHS part is not additive/multiplicative/shift/biwise binary + /// expression. + NotABinaryOperator, + /// \brief RHS binary operation does not have reference to the updated LHS + /// part. + NotAnUpdateExpression, + /// \brief No errors is found. + NoError + }; + /// \brief Reference to Sema. + Sema &SemaRef; + /// \brief A location for note diagnostics (when error is found). + SourceLocation NoteLoc; + /// \brief Atomic operation supposed to be performed on source expression. + BinaryOperatorKind OpKind; + /// \brief 'x' lvalue part of the source atomic expression. + Expr *X; + /// \brief 'x' rvalue part of the source atomic expression, used in the right + /// hand side of the expression. We need this to properly generate RHS part of + /// the source expression (x = x'rval' binop expr or x = expr binop x'rval'). + Expr *XRVal; + /// \brief 'expr' rvalue part of the source atomic expression. + Expr *E; + +public: + OpenMPAtomicUpdateChecker(Sema &SemaRef) + : SemaRef(SemaRef), OpKind(BO_PtrMemD), X(nullptr), XRVal(nullptr), + E(nullptr) {} + /// \brief Check specified statement that it is suitable for 'atomic update' + /// constructs and extract 'x', 'expr' and Operation from the original + /// expression. + /// \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); + /// \brief Return the 'x' lvalue part of the source atomic expression. + Expr *getX() const { return X; } + /// \brief Return the 'x' rvalue part of the source atomic expression, used in + /// the RHS part of the source expression. + Expr *getXRVal() const { return XRVal; } + /// \brief Return the 'expr' rvalue part of the source atomic expression. + Expr *getExpr() const { return E; } + /// \brief Return required atomic operation. + BinaryOperatorKind getOpKind() const {return OpKind;} +private: + bool checkBinaryOperation(BinaryOperator *AtomicBinOp, unsigned DiagId, + unsigned NoteId); +}; +} // namespace + +bool OpenMPAtomicUpdateChecker::checkBinaryOperation( + BinaryOperator *AtomicBinOp, unsigned DiagId, unsigned NoteId) { + ExprAnalysisErrorCode ErrorFound = NoError; + SourceLocation ErrorLoc, NoteLoc; + SourceRange ErrorRange, NoteRange; + // Allowed constructs are: + // x = x binop expr; + // x = expr binop x; + if (AtomicBinOp->getOpcode() == BO_Assign) { + X = AtomicBinOp->getLHS(); + if (auto *AtomicInnerBinOp = dyn_cast( + AtomicBinOp->getRHS()->IgnoreParenImpCasts())) { + if (AtomicInnerBinOp->isMultiplicativeOp() || + AtomicInnerBinOp->isAdditiveOp() || AtomicInnerBinOp->isShiftOp() || + AtomicInnerBinOp->isBitwiseOp()) { + OpKind = AtomicInnerBinOp->getOpcode(); + auto *LHS = AtomicInnerBinOp->getLHS(); + auto *RHS = AtomicInnerBinOp->getRHS(); + llvm::FoldingSetNodeID XId, LHSId, RHSId; + X->IgnoreParenImpCasts()->Profile(XId, SemaRef.getASTContext(), + /*Canonical=*/true); + LHS->IgnoreParenImpCasts()->Profile(LHSId, SemaRef.getASTContext(), + /*Canonical=*/true); + RHS->IgnoreParenImpCasts()->Profile(RHSId, SemaRef.getASTContext(), + /*Canonical=*/true); + if (XId == LHSId) { + E = RHS; + XRVal = LHS; + } else if (XId == RHSId) { + E = LHS; + XRVal = RHS; + } else { + ErrorLoc = AtomicInnerBinOp->getExprLoc(); + ErrorRange = AtomicInnerBinOp->getSourceRange(); + NoteLoc = X->getExprLoc(); + NoteRange = X->getSourceRange(); + ErrorFound = NotAnUpdateExpression; + } + } else { + ErrorLoc = AtomicInnerBinOp->getExprLoc(); + ErrorRange = AtomicInnerBinOp->getSourceRange(); + NoteLoc = AtomicInnerBinOp->getOperatorLoc(); + NoteRange = SourceRange(NoteLoc, NoteLoc); + ErrorFound = NotABinaryOperator; + } + } else { + NoteLoc = ErrorLoc = AtomicBinOp->getRHS()->getExprLoc(); + NoteRange = ErrorRange = AtomicBinOp->getRHS()->getSourceRange(); + ErrorFound = NotABinaryExpression; + } + } else { + ErrorLoc = AtomicBinOp->getExprLoc(); + ErrorRange = AtomicBinOp->getSourceRange(); + NoteLoc = AtomicBinOp->getOperatorLoc(); + NoteRange = SourceRange(NoteLoc, NoteLoc); + ErrorFound = NotAnAssignmentOp; + } + if (ErrorFound != NoError) { + SemaRef.Diag(ErrorLoc, DiagId) << ErrorRange; + SemaRef.Diag(NoteLoc, NoteId) << ErrorFound << NoteRange; + return true; + } else if (SemaRef.CurContext->isDependentContext()) + E = X = XRVal = nullptr; + return false; +} + +bool OpenMPAtomicUpdateChecker::checkStatement(Stmt *S, unsigned DiagId, + unsigned NoteId) { + ExprAnalysisErrorCode ErrorFound = NoError; + SourceLocation ErrorLoc, NoteLoc; + SourceRange ErrorRange, NoteRange; + // Allowed constructs are: + // x++; + // x--; + // ++x; + // --x; + // x binop= expr; + // x = x binop expr; + // x = expr binop x; + if (auto *AtomicBody = dyn_cast(S)) { + AtomicBody = AtomicBody->IgnoreParenImpCasts(); + if (AtomicBody->getType()->isScalarType() || + AtomicBody->isInstantiationDependent()) { + if (auto *AtomicCompAssignOp = dyn_cast( + AtomicBody->IgnoreParenImpCasts())) { + // Check for Compound Assignment Operation + OpKind = BinaryOperator::getOpForCompoundAssignment( + AtomicCompAssignOp->getOpcode()); + X = AtomicCompAssignOp->getLHS(); + XRVal = SemaRef.PerformImplicitConversion( + X, AtomicCompAssignOp->getComputationLHSType(), + Sema::AA_Casting, /*AllowExplicit=*/true).get(); + E = AtomicCompAssignOp->getRHS(); + } else if (auto *AtomicBinOp = dyn_cast( + AtomicBody->IgnoreParenImpCasts())) { + // Check for Binary Operation + return checkBinaryOperation(AtomicBinOp, DiagId, NoteId); + } else if (auto *AtomicUnaryOp = + // Check for Binary Operation + dyn_cast(AtomicBody->IgnoreParenImpCasts())) { + // Check for Unary Operation + if (AtomicUnaryOp->isIncrementDecrementOp()) { + OpKind = AtomicUnaryOp->isIncrementOp() ? BO_Add : BO_Sub; + XRVal = X = AtomicUnaryOp->getSubExpr(); + E = SemaRef.ActOnIntegerConstant(AtomicUnaryOp->getOperatorLoc(), 1) + .get(); + } else { + ErrorFound = NotAnUnaryIncDecExpression; + ErrorLoc = AtomicUnaryOp->getExprLoc(); + ErrorRange = AtomicUnaryOp->getSourceRange(); + NoteLoc = AtomicUnaryOp->getOperatorLoc(); + NoteRange = SourceRange(NoteLoc, NoteLoc); + } + } else { + ErrorFound = NotABinaryOrUnaryExpression; + NoteLoc = ErrorLoc = AtomicBody->getExprLoc(); + NoteRange = ErrorRange = AtomicBody->getSourceRange(); + } + } else { + ErrorFound = NotAScalarType; + NoteLoc = ErrorLoc = AtomicBody->getLocStart(); + NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc); + } + } else { + ErrorFound = NotAnExpression; + NoteLoc = ErrorLoc = S->getLocStart(); + NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc); + } + if (ErrorFound != NoError) { + SemaRef.Diag(ErrorLoc, DiagId) << ErrorRange; + SemaRef.Diag(NoteLoc, NoteId) << ErrorFound << NoteRange; + return true; + } else if (SemaRef.CurContext->isDependentContext()) + E = X = XRVal = nullptr; + return false; +} + StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc, @@ -3270,7 +3475,9 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef Clauses, if (auto *EWC = dyn_cast(Body)) Body = EWC->getSubExpr(); + BinaryOperatorKind OpKind = BO_PtrMemD; Expr *X = nullptr; + Expr *XRVal = nullptr; Expr *V = nullptr; Expr *E = nullptr; // OpenMP [2.12.6, atomic Construct] @@ -3412,11 +3619,26 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef Clauses, } else if (CurContext->isDependentContext()) E = X = nullptr; } else if (AtomicKind == OMPC_update || AtomicKind == OMPC_unknown) { - if (!isa(Body)) { - Diag(Body->getLocStart(), - diag::err_omp_atomic_update_not_expression_statement) - << (AtomicKind == OMPC_update); + // If clause is update: + // x++; + // x--; + // ++x; + // --x; + // x binop= expr; + // x = x binop expr; + // x = expr binop x; + OpenMPAtomicUpdateChecker Checker(*this); + if (Checker.checkStatement( + Body, (AtomicKind == OMPC_update) + ? diag::err_omp_atomic_update_not_expression_statement + : diag::err_omp_atomic_not_expression_statement, + diag::note_omp_atomic_update)) return StmtError(); + if (!CurContext->isDependentContext()) { + E = Checker.getExpr(); + X = Checker.getX(); + XRVal = Checker.getXRVal(); + OpKind = Checker.getOpKind(); } } else if (AtomicKind == OMPC_capture) { if (isa(Body) && !isa(Body)) { @@ -3433,7 +3655,7 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef Clauses, getCurFunction()->setHasBranchProtectedScope(); return OMPAtomicDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt, - X, V, E); + OpKind, X, XRVal, V, E); } StmtResult Sema::ActOnOpenMPTargetDirective(ArrayRef Clauses, diff --git a/lib/Serialization/ASTReaderStmt.cpp b/lib/Serialization/ASTReaderStmt.cpp index 4ef2e73062..a1b6c1bf2e 100644 --- a/lib/Serialization/ASTReaderStmt.cpp +++ b/lib/Serialization/ASTReaderStmt.cpp @@ -2132,7 +2132,9 @@ void ASTStmtReader::VisitOMPAtomicDirective(OMPAtomicDirective *D) { // The NumClauses field was read in ReadStmtFromStream. ++Idx; VisitOMPExecutableDirective(D); + D->setOpKind(static_cast(Record[Idx++])); D->setX(Reader.ReadSubExpr()); + D->setXRVal(Reader.ReadSubExpr()); D->setV(Reader.ReadSubExpr()); D->setExpr(Reader.ReadSubExpr()); } diff --git a/lib/Serialization/ASTWriterStmt.cpp b/lib/Serialization/ASTWriterStmt.cpp index e980ce783f..e8769c08d6 100644 --- a/lib/Serialization/ASTWriterStmt.cpp +++ b/lib/Serialization/ASTWriterStmt.cpp @@ -1987,7 +1987,9 @@ void ASTStmtWriter::VisitOMPAtomicDirective(OMPAtomicDirective *D) { VisitStmt(D); Record.push_back(D->getNumClauses()); VisitOMPExecutableDirective(D); + Record.push_back(D->getOpKind()); Writer.AddStmt(D->getX()); + Writer.AddStmt(D->getXRVal()); Writer.AddStmt(D->getV()); Writer.AddStmt(D->getExpr()); Code = serialization::STMT_OMP_ATOMIC_DIRECTIVE; diff --git a/test/OpenMP/atomic_messages.c b/test/OpenMP/atomic_messages.c index ae490ee084..8d4ade6fe0 100644 --- a/test/OpenMP/atomic_messages.c +++ b/test/OpenMP/atomic_messages.c @@ -4,14 +4,16 @@ int foo() { L1: foo(); #pragma omp atomic - // expected-error@+1 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-note@+1 {{expected an expression statement}} { foo(); goto L1; // expected-error {{use of undeclared label 'L1'}} } goto L2; // expected-error {{use of undeclared label 'L2'}} #pragma omp atomic - // expected-error@+1 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-note@+1 {{expected an expression statement}} { foo(); L2: @@ -100,3 +102,94 @@ int writeS() { return a.a; } + +int updateint() { + int a = 0, b = 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}} + // expected-note@+1 {{expected an expression statement}} + ; +#pragma omp atomic + // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-note@+1 {{expected built-in binary or unary operator}} + foo(); +#pragma omp atomic + // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-note@+1 {{expected built-in binary operator}} + a = b; +#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}} + // expected-note@+1 {{expected one of '+', '*', '-', '/', '&', '^', '|', '<<', or '>>' built-in operations}} + a = b || a; +#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}} + // expected-note@+1 {{expected one of '+', '*', '-', '/', '&', '^', '|', '<<', or '>>' built-in operations}} + a = a && b; +#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}} + // expected-note@+1 {{expected in right hand side of expression}} + a = (float)a + b; +#pragma omp atomic + // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-note@+1 {{expected in right hand side of expression}} + a = 2 * b; +#pragma omp atomic + // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-note@+1 {{expected in right hand side of expression}} + a = b + *&a; +#pragma omp atomic update + *&a = *&a + 2; +#pragma omp atomic update + a++; +#pragma omp atomic + ++a; +#pragma omp atomic update + a--; +#pragma omp atomic + --a; +#pragma omp atomic update + a += b; +#pragma omp atomic + a %= b; +#pragma omp atomic update + a *= b; +#pragma omp atomic + a -= b; +#pragma omp atomic update + a /= b; +#pragma omp atomic + a &= b; +#pragma omp atomic update + a ^= b; +#pragma omp atomic + a |= b; +#pragma omp atomic update + a <<= b; +#pragma omp atomic + a >>= b; +#pragma omp atomic update + a = b + a; +#pragma omp atomic + a = a * b; +#pragma omp atomic update + a = b - a; +#pragma omp atomic + a = a / b; +#pragma omp atomic update + a = b & a; +#pragma omp atomic + a = a ^ b; +#pragma omp atomic update + a = b | a; +#pragma omp atomic + a = a << b; +#pragma omp atomic + a = b >> a; + // expected-error@+1 {{directive '#pragma omp atomic' cannot contain more than one 'update' clause}} +#pragma omp atomic update update + a /= b; + + return 0; +} + diff --git a/test/OpenMP/atomic_messages.cpp b/test/OpenMP/atomic_messages.cpp index a6c07ad9e2..b47fbbc5c4 100644 --- a/test/OpenMP/atomic_messages.cpp +++ b/test/OpenMP/atomic_messages.cpp @@ -4,14 +4,16 @@ int foo() { L1: foo(); #pragma omp atomic - // expected-error@+1 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-note@+1 {{expected an expression statement}} { foo(); goto L1; // expected-error {{use of undeclared label 'L1'}} } goto L2; // expected-error {{use of undeclared label 'L2'}} #pragma omp atomic - // expected-error@+1 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-note@+1 {{expected an expression statement}} { foo(); L2: @@ -153,14 +155,88 @@ T update() { T a, b = 0; // Test for atomic update #pragma omp atomic update - // expected-error@+1 {{the statement for 'atomic update' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-error@+2 {{the statement for 'atomic update' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-note@+1 {{expected an expression statement}} ; // expected-error@+1 {{directive '#pragma omp atomic' cannot contain more than one 'update' clause}} #pragma omp atomic update update a += b; +#pragma omp atomic + // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-note@+1 {{expected built-in binary operator}} + a = b; +#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}} + // expected-note@+1 {{expected one of '+', '*', '-', '/', '&', '^', '|', '<<', or '>>' built-in operations}} + a = b || a; +#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}} + // expected-note@+1 {{expected one of '+', '*', '-', '/', '&', '^', '|', '<<', or '>>' built-in operations}} + a = a && b; +#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}} + // expected-note@+1 {{expected in right hand side of expression}} + a = float(a) + b; +#pragma omp atomic + // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-note@+1 {{expected in right hand side of expression}} + a = 2 * b; +#pragma omp atomic + // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-note@+1 {{expected in right hand side of expression}} + a = b + *&a; +#pragma omp atomic + *&a = b * *&a; +#pragma omp atomic update + a++; +#pragma omp atomic + ++a; +#pragma omp atomic update + a--; +#pragma omp atomic + --a; +#pragma omp atomic update + a += b; +#pragma omp atomic + a %= b; +#pragma omp atomic update + a *= b; +#pragma omp atomic + a -= b; +#pragma omp atomic update + a /= b; +#pragma omp atomic + a &= b; +#pragma omp atomic update + a ^= b; +#pragma omp atomic + a |= b; +#pragma omp atomic update + a <<= b; +#pragma omp atomic + a >>= b; +#pragma omp atomic update + a = b + a; +#pragma omp atomic + a = a * b; +#pragma omp atomic update + a = b - a; +#pragma omp atomic + a = a / b; +#pragma omp atomic update + a = b & a; +#pragma omp atomic + a = a ^ b; +#pragma omp atomic update + a = b | a; +#pragma omp atomic + a = a << b; +#pragma omp atomic + a = b >> a; #pragma omp atomic - // expected-error@+1 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-note@+1 {{expected an expression statement}} ; return T(); @@ -170,14 +246,85 @@ int update() { int a, b = 0; // Test for atomic update #pragma omp atomic update - // expected-error@+1 {{the statement for 'atomic update' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-error@+2 {{the statement for 'atomic update' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-note@+1 {{expected an expression statement}} ; // expected-error@+1 {{directive '#pragma omp atomic' cannot contain more than one 'update' clause}} #pragma omp atomic update update a += b; - #pragma omp atomic - // expected-error@+1 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-note@+1 {{expected built-in binary operator}} + a = b; +#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}} + // expected-note@+1 {{expected one of '+', '*', '-', '/', '&', '^', '|', '<<', or '>>' built-in operations}} + a = b || a; +#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}} + // expected-note@+1 {{expected one of '+', '*', '-', '/', '&', '^', '|', '<<', or '>>' built-in operations}} + a = a && b; +#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}} + // expected-note@+1 {{expected in right hand side of expression}} + a = float(a) + b; +#pragma omp atomic + // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-note@+1 {{expected in right hand side of expression}} + a = 2 * b; +#pragma omp atomic + // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-note@+1 {{expected in right hand side of expression}} + a = b + *&a; +#pragma omp atomic update + a++; +#pragma omp atomic + ++a; +#pragma omp atomic update + a--; +#pragma omp atomic + --a; +#pragma omp atomic update + a += b; +#pragma omp atomic + a %= b; +#pragma omp atomic update + a *= b; +#pragma omp atomic + a -= b; +#pragma omp atomic update + a /= b; +#pragma omp atomic + a &= b; +#pragma omp atomic update + a ^= b; +#pragma omp atomic + a |= b; +#pragma omp atomic update + a <<= b; +#pragma omp atomic + a >>= b; +#pragma omp atomic update + a = b + a; +#pragma omp atomic + a = a * b; +#pragma omp atomic update + a = b - a; +#pragma omp atomic + a = a / b; +#pragma omp atomic update + a = b & a; +#pragma omp atomic + a = a ^ b; +#pragma omp atomic update + a = b | a; +#pragma omp atomic + a = a << b; +#pragma omp atomic + a = b >> a; +#pragma omp atomic + // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-note@+1 {{expected an expression statement}} ; return update(); @@ -221,14 +368,16 @@ T seq_cst() { T a, b = 0; // Test for atomic seq_cst #pragma omp atomic seq_cst - // expected-error@+1 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-note@+1 {{expected an expression statement}} ; // expected-error@+1 {{directive '#pragma omp atomic' cannot contain more than one 'seq_cst' clause}} #pragma omp atomic seq_cst seq_cst a += b; #pragma omp atomic update seq_cst - // expected-error@+1 {{the statement for 'atomic update' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-error@+2 {{the statement for 'atomic update' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-note@+1 {{expected an expression statement}} ; return T(); @@ -238,14 +387,16 @@ int seq_cst() { int a, b = 0; // Test for atomic seq_cst #pragma omp atomic seq_cst - // expected-error@+1 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-note@+1 {{expected an expression statement}} ; // expected-error@+1 {{directive '#pragma omp atomic' cannot contain more than one 'seq_cst' clause}} #pragma omp atomic seq_cst seq_cst a += b; #pragma omp atomic update seq_cst - // expected-error@+1 {{the statement for 'atomic update' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-error@+2 {{the statement for 'atomic update' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-note@+1 {{expected an expression statement}} ; return seq_cst(); diff --git a/test/OpenMP/nesting_of_regions.cpp b/test/OpenMP/nesting_of_regions.cpp index a948ca3e3b..dd81f88c3e 100644 --- a/test/OpenMP/nesting_of_regions.cpp +++ b/test/OpenMP/nesting_of_regions.cpp @@ -1979,35 +1979,40 @@ void foo() { // ATOMIC DIRECTIVE #pragma omp atomic - // expected-error@+1 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-note@+1 {{expected an expression statement}} { #pragma omp for // expected-error {{OpenMP constructs may not be nested inside an atomic region}} for (int i = 0; i < 10; ++i) ; } #pragma omp atomic - // expected-error@+1 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-note@+1 {{expected an expression statement}} { #pragma omp simd // expected-error {{OpenMP constructs may not be nested inside an atomic region}} for (int i = 0; i < 10; ++i) ; } #pragma omp atomic - // expected-error@+1 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-note@+1 {{expected an expression statement}} { #pragma omp for simd // expected-error {{OpenMP constructs may not be nested inside an atomic region}} for (int i = 0; i < 10; ++i) ; } #pragma omp atomic - // expected-error@+1 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-note@+1 {{expected an expression statement}} { #pragma omp parallel // expected-error {{OpenMP constructs may not be nested inside an atomic region}} for (int i = 0; i < 10; ++i) ; } #pragma omp atomic - // expected-error@+1 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-note@+1 {{expected an expression statement}} { #pragma omp sections // expected-error {{OpenMP constructs may not be nested inside an atomic region}} { @@ -2015,7 +2020,8 @@ void foo() { } } #pragma omp atomic - // expected-error@+1 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-note@+1 {{expected an expression statement}} { #pragma omp section // expected-error {{OpenMP constructs may not be nested inside an atomic region}} { @@ -2023,7 +2029,8 @@ void foo() { } } #pragma omp atomic - // expected-error@+1 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-note@+1 {{expected an expression statement}} { #pragma omp single // expected-error {{OpenMP constructs may not be nested inside an atomic region}} { @@ -2031,7 +2038,8 @@ void foo() { } } #pragma omp atomic - // expected-error@+1 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-note@+1 {{expected an expression statement}} { #pragma omp master // expected-error {{OpenMP constructs may not be nested inside an atomic region}} { @@ -2039,7 +2047,8 @@ void foo() { } } #pragma omp atomic - // expected-error@+1 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-note@+1 {{expected an expression statement}} { #pragma omp critical // expected-error {{OpenMP constructs may not be nested inside an atomic region}} { @@ -2047,21 +2056,24 @@ void foo() { } } #pragma omp atomic - // expected-error@+1 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-note@+1 {{expected an expression statement}} { #pragma omp parallel for // expected-error {{OpenMP constructs may not be nested inside an atomic region}} for (int i = 0; i < 10; ++i) ; } #pragma omp atomic - // expected-error@+1 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-note@+1 {{expected an expression statement}} { #pragma omp parallel for simd // expected-error {{OpenMP constructs may not be nested inside an atomic region}} for (int i = 0; i < 10; ++i) ; } #pragma omp atomic - // expected-error@+1 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-note@+1 {{expected an expression statement}} { #pragma omp parallel sections // expected-error {{OpenMP constructs may not be nested inside an atomic region}} { @@ -2069,7 +2081,8 @@ void foo() { } } #pragma omp atomic - // expected-error@+1 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-note@+1 {{expected an expression statement}} { #pragma omp task // expected-error {{OpenMP constructs may not be nested inside an atomic region}} { @@ -2077,49 +2090,57 @@ void foo() { } } #pragma omp atomic - // expected-error@+1 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-note@+1 {{expected an expression statement}} { #pragma omp taskyield // expected-error {{OpenMP constructs may not be nested inside an atomic region}} bar(); } #pragma omp atomic - // expected-error@+1 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-note@+1 {{expected an expression statement}} { #pragma omp barrier // expected-error {{OpenMP constructs may not be nested inside an atomic region}} bar(); } #pragma omp atomic - // expected-error@+1 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-note@+1 {{expected an expression statement}} { #pragma omp taskwait // expected-error {{OpenMP constructs may not be nested inside an atomic region}} bar(); } #pragma omp atomic - // expected-error@+1 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-note@+1 {{expected an expression statement}} { #pragma omp flush // expected-error {{OpenMP constructs may not be nested inside an atomic region}} bar(); } #pragma omp atomic - // expected-error@+1 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-note@+1 {{expected an expression statement}} { #pragma omp ordered // expected-error {{OpenMP constructs may not be nested inside an atomic region}} bar(); } #pragma omp atomic - // expected-error@+1 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-note@+1 {{expected an expression statement}} { #pragma omp atomic // expected-error {{OpenMP constructs may not be nested inside an atomic region}} ++a; } #pragma omp atomic - // expected-error@+1 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-note@+1 {{expected an expression statement}} { #pragma omp target // expected-error {{OpenMP constructs may not be nested inside an atomic region}} ++a; } #pragma omp atomic - // expected-error@+1 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-note@+1 {{expected an expression statement}} { #pragma omp teams // expected-error {{OpenMP constructs may not be nested inside an atomic region}} ++a; @@ -4134,35 +4155,40 @@ void foo() { // ATOMIC DIRECTIVE #pragma omp atomic - // expected-error@+1 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-note@+1 {{expected an expression statement}} { #pragma omp for // expected-error {{OpenMP constructs may not be nested inside an atomic region}} for (int i = 0; i < 10; ++i) ; } #pragma omp atomic - // expected-error@+1 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-note@+1 {{expected an expression statement}} { #pragma omp simd // expected-error {{OpenMP constructs may not be nested inside an atomic region}} for (int i = 0; i < 10; ++i) ; } #pragma omp atomic - // expected-error@+1 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-note@+1 {{expected an expression statement}} { #pragma omp for simd // expected-error {{OpenMP constructs may not be nested inside an atomic region}} for (int i = 0; i < 10; ++i) ; } #pragma omp atomic - // expected-error@+1 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-note@+1 {{expected an expression statement}} { #pragma omp parallel // expected-error {{OpenMP constructs may not be nested inside an atomic region}} for (int i = 0; i < 10; ++i) ; } #pragma omp atomic - // expected-error@+1 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-note@+1 {{expected an expression statement}} { #pragma omp sections // expected-error {{OpenMP constructs may not be nested inside an atomic region}} { @@ -4170,7 +4196,8 @@ void foo() { } } #pragma omp atomic - // expected-error@+1 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-note@+1 {{expected an expression statement}} { #pragma omp section // expected-error {{OpenMP constructs may not be nested inside an atomic region}} { @@ -4178,7 +4205,8 @@ void foo() { } } #pragma omp atomic - // expected-error@+1 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-note@+1 {{expected an expression statement}} { #pragma omp single // expected-error {{OpenMP constructs may not be nested inside an atomic region}} { @@ -4186,7 +4214,8 @@ void foo() { } } #pragma omp atomic - // expected-error@+1 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-note@+1 {{expected an expression statement}} { #pragma omp master // expected-error {{OpenMP constructs may not be nested inside an atomic region}} { @@ -4194,7 +4223,8 @@ void foo() { } } #pragma omp atomic - // expected-error@+1 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-note@+1 {{expected an expression statement}} { #pragma omp critical // expected-error {{OpenMP constructs may not be nested inside an atomic region}} { @@ -4202,21 +4232,24 @@ void foo() { } } #pragma omp atomic - // expected-error@+1 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-note@+1 {{expected an expression statement}} { #pragma omp parallel for // expected-error {{OpenMP constructs may not be nested inside an atomic region}} for (int i = 0; i < 10; ++i) ; } #pragma omp atomic - // expected-error@+1 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-note@+1 {{expected an expression statement}} { #pragma omp parallel for simd // expected-error {{OpenMP constructs may not be nested inside an atomic region}} for (int i = 0; i < 10; ++i) ; } #pragma omp atomic - // expected-error@+1 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-note@+1 {{expected an expression statement}} { #pragma omp parallel sections // expected-error {{OpenMP constructs may not be nested inside an atomic region}} { @@ -4224,7 +4257,8 @@ void foo() { } } #pragma omp atomic - // expected-error@+1 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-note@+1 {{expected an expression statement}} { #pragma omp task // expected-error {{OpenMP constructs may not be nested inside an atomic region}} { @@ -4232,49 +4266,57 @@ void foo() { } } #pragma omp atomic - // expected-error@+1 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-note@+1 {{expected an expression statement}} { #pragma omp taskyield // expected-error {{OpenMP constructs may not be nested inside an atomic region}} bar(); } #pragma omp atomic - // expected-error@+1 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-note@+1 {{expected an expression statement}} { #pragma omp barrier // expected-error {{OpenMP constructs may not be nested inside an atomic region}} bar(); } #pragma omp atomic - // expected-error@+1 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-note@+1 {{expected an expression statement}} { #pragma omp taskwait // expected-error {{OpenMP constructs may not be nested inside an atomic region}} bar(); } #pragma omp atomic - // expected-error@+1 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-note@+1 {{expected an expression statement}} { #pragma omp flush // expected-error {{OpenMP constructs may not be nested inside an atomic region}} bar(); } #pragma omp atomic - // expected-error@+1 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-note@+1 {{expected an expression statement}} { #pragma omp ordered // expected-error {{OpenMP constructs may not be nested inside an atomic region}} bar(); } #pragma omp atomic - // expected-error@+1 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-note@+1 {{expected an expression statement}} { #pragma omp atomic // expected-error {{OpenMP constructs may not be nested inside an atomic region}} ++a; } #pragma omp atomic - // expected-error@+1 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-note@+1 {{expected an expression statement}} { #pragma omp target // expected-error {{OpenMP constructs may not be nested inside an atomic region}} ++a; } #pragma omp atomic - // expected-error@+1 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-note@+1 {{expected an expression statement}} { #pragma omp teams // expected-error {{OpenMP constructs may not be nested inside an atomic region}} ++a;