diff --git a/include/clang/AST/DataRecursiveASTVisitor.h b/include/clang/AST/DataRecursiveASTVisitor.h index c776603c6b4eed785db358ddcd8ab7a69093c73c..c1e98e757e18176433919d5b35adfd441643cbb6 100644 --- a/include/clang/AST/DataRecursiveASTVisitor.h +++ b/include/clang/AST/DataRecursiveASTVisitor.h @@ -2480,7 +2480,8 @@ RecursiveASTVisitor<Derived>::VisitOMPScheduleClause(OMPScheduleClause *C) { } template <typename Derived> -bool RecursiveASTVisitor<Derived>::VisitOMPOrderedClause(OMPOrderedClause *) { +bool RecursiveASTVisitor<Derived>::VisitOMPOrderedClause(OMPOrderedClause *C) { + TRY_TO(TraverseStmt(C->getNumForLoops())); return true; } diff --git a/include/clang/AST/OpenMPClause.h b/include/clang/AST/OpenMPClause.h index 7d3fcf0423633f740a2b59f8d01a39b8b8188278..03104be18374d11af681f3d2f0dfe49008467377 100644 --- a/include/clang/AST/OpenMPClause.h +++ b/include/clang/AST/OpenMPClause.h @@ -694,32 +694,53 @@ public: /// \brief This represents 'ordered' clause in the '#pragma omp ...' directive. /// /// \code -/// #pragma omp for ordered +/// #pragma omp for ordered (2) /// \endcode -/// In this example directive '#pragma omp for' has 'ordered' clause. +/// In this example directive '#pragma omp for' has 'ordered' clause with +/// parameter 2. /// class OMPOrderedClause : public OMPClause { + friend class OMPClauseReader; + /// \brief Location of '('. + SourceLocation LParenLoc; + /// \brief Number of for-loops. + Stmt *NumForLoops; + + /// \brief Set the number of associated for-loops. + void setNumForLoops(Expr *Num) { NumForLoops = Num; } + public: /// \brief Build 'ordered' clause. /// + /// \param Num Expression, possibly associated with this clause. /// \param StartLoc Starting location of the clause. + /// \param LParenLoc Location of '('. /// \param EndLoc Ending location of the clause. /// - OMPOrderedClause(SourceLocation StartLoc, SourceLocation EndLoc) - : OMPClause(OMPC_ordered, StartLoc, EndLoc) {} + OMPOrderedClause(Expr *Num, SourceLocation StartLoc, + SourceLocation LParenLoc, SourceLocation EndLoc) + : OMPClause(OMPC_ordered, StartLoc, EndLoc), LParenLoc(LParenLoc), + NumForLoops(Num) {} /// \brief Build an empty clause. /// - OMPOrderedClause() - : OMPClause(OMPC_ordered, SourceLocation(), SourceLocation()) {} + explicit OMPOrderedClause() + : OMPClause(OMPC_ordered, SourceLocation(), SourceLocation()), + LParenLoc(SourceLocation()), NumForLoops(nullptr) {} + + /// \brief Sets the location of '('. + void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } + /// \brief Returns the location of '('. + SourceLocation getLParenLoc() const { return LParenLoc; } + + /// \brief Return the number of associated for-loops. + Expr *getNumForLoops() const { return cast_or_null<Expr>(NumForLoops); } static bool classof(const OMPClause *T) { return T->getClauseKind() == OMPC_ordered; } - child_range children() { - return child_range(child_iterator(), child_iterator()); - } + child_range children() { return child_range(&NumForLoops, &NumForLoops + 1); } }; /// \brief This represents 'nowait' clause in the '#pragma omp ...' directive. diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h index 99f5e56cf407eb12a441ecb65274a6de6f91af9c..e0a48e86b8514405d12caaedb30aa1bf60dd42a2 100644 --- a/include/clang/AST/RecursiveASTVisitor.h +++ b/include/clang/AST/RecursiveASTVisitor.h @@ -2512,7 +2512,8 @@ RecursiveASTVisitor<Derived>::VisitOMPScheduleClause(OMPScheduleClause *C) { } template <typename Derived> -bool RecursiveASTVisitor<Derived>::VisitOMPOrderedClause(OMPOrderedClause *) { +bool RecursiveASTVisitor<Derived>::VisitOMPOrderedClause(OMPOrderedClause *C) { + TRY_TO(TraverseStmt(C->getNumForLoops())); return true; } diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 51e069a9ae1bd575be62ba4ac62cc83770a2300f..44508d59024a4dba63d3e19ae2884921821fee24 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -7501,8 +7501,8 @@ def err_omp_loop_var_dsa : Error< def err_omp_not_for : Error< "%select{statement after '#pragma omp %1' must be a for loop|" "expected %2 for loops after '#pragma omp %1'%select{|, but found only %4}3}0">; -def note_omp_collapse_expr : Note< - "as specified in 'collapse' clause">; +def note_omp_collapse_ordered_expr : Note< + "as specified in %select{'collapse'|'ordered'|'collapse' and 'ordered'}0 clause%select{||s}0">; def err_omp_negative_expression_in_clause : Error< "argument to '%0' clause must be a positive integer value">; def err_omp_not_integral : Error< diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 575f705542134dd7ca910d7fe88a7fc0bf2a6afb..edd7b2576fa27fca291701355e75b8b07d2bf80c 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -7903,6 +7903,11 @@ public: SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc); + /// \brief Called on well-formed 'ordered' clause. + OMPClause * + ActOnOpenMPOrderedClause(SourceLocation StartLoc, SourceLocation EndLoc, + SourceLocation LParenLoc = SourceLocation(), + Expr *NumForLoops = nullptr); OMPClause *ActOnOpenMPSimpleClause(OpenMPClauseKind Kind, unsigned Argument, @@ -7940,9 +7945,6 @@ public: OMPClause *ActOnOpenMPClause(OpenMPClauseKind Kind, SourceLocation StartLoc, SourceLocation EndLoc); - /// \brief Called on well-formed 'ordered' clause. - OMPClause *ActOnOpenMPOrderedClause(SourceLocation StartLoc, - SourceLocation EndLoc); /// \brief Called on well-formed 'nowait' clause. OMPClause *ActOnOpenMPNowaitClause(SourceLocation StartLoc, SourceLocation EndLoc); diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp index 30f15e037baa2606d672363cd6873f2fe5cade4a..57187ca8620517be11bfa6cbc395969b5dd5e22f 100644 --- a/lib/AST/StmtPrinter.cpp +++ b/lib/AST/StmtPrinter.cpp @@ -651,8 +651,13 @@ void OMPClausePrinter::VisitOMPScheduleClause(OMPScheduleClause *Node) { OS << ")"; } -void OMPClausePrinter::VisitOMPOrderedClause(OMPOrderedClause *) { +void OMPClausePrinter::VisitOMPOrderedClause(OMPOrderedClause *Node) { OS << "ordered"; + if (auto *Num = Node->getNumForLoops()) { + OS << "("; + Num->printPretty(OS, nullptr, Policy, 0); + OS << ")"; + } } void OMPClausePrinter::VisitOMPNowaitClause(OMPNowaitClause *) { diff --git a/lib/AST/StmtProfile.cpp b/lib/AST/StmtProfile.cpp index f2fa53d25cdbe45c60955ba997ca0a61bcfe72e8..091682ad7ffd81abfadafd1779938873710db69c 100644 --- a/lib/AST/StmtProfile.cpp +++ b/lib/AST/StmtProfile.cpp @@ -306,7 +306,10 @@ void OMPClauseProfiler::VisitOMPScheduleClause(const OMPScheduleClause *C) { } } -void OMPClauseProfiler::VisitOMPOrderedClause(const OMPOrderedClause *) {} +void OMPClauseProfiler::VisitOMPOrderedClause(const OMPOrderedClause *C) { + if (auto *Num = C->getNumForLoops()) + Profiler->VisitStmt(Num); +} void OMPClauseProfiler::VisitOMPNowaitClause(const OMPNowaitClause *) {} diff --git a/lib/Parse/ParseOpenMP.cpp b/lib/Parse/ParseOpenMP.cpp index 2234f1396d5dfaaaf113959ee300986a9619a71c..1266e447fca3184ee2eaecd1c9457ad0cbf6b5a9 100644 --- a/lib/Parse/ParseOpenMP.cpp +++ b/lib/Parse/ParseOpenMP.cpp @@ -415,6 +415,7 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, case OMPC_num_threads: case OMPC_safelen: case OMPC_collapse: + case OMPC_ordered: // OpenMP [2.5, Restrictions] // At most one if clause can appear on the directive. // At most one num_threads clause can appear on the directive. @@ -430,7 +431,10 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, ErrorFound = true; } - Clause = ParseOpenMPSingleExprClause(CKind); + if (CKind == OMPC_ordered && PP.LookAhead(/*N=*/0).isNot(tok::l_paren)) + Clause = ParseOpenMPClause(CKind); + else + Clause = ParseOpenMPSingleExprClause(CKind); break; case OMPC_default: case OMPC_proc_bind: @@ -458,7 +462,6 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, Clause = ParseOpenMPSingleExprWithArgClause(CKind); break; - case OMPC_ordered: case OMPC_nowait: case OMPC_untied: case OMPC_mergeable: diff --git a/lib/Sema/SemaOpenMP.cpp b/lib/Sema/SemaOpenMP.cpp index 88a705056a2ccb96299d9d72ce1a661214f36486..422e0e4ca337f31c56dbf0a76cd59a7b29a28753 100644 --- a/lib/Sema/SemaOpenMP.cpp +++ b/lib/Sema/SemaOpenMP.cpp @@ -2751,7 +2751,7 @@ void Sema::ActOnOpenMPLoopInitialization(SourceLocation ForLoc, Stmt *Init) { static bool CheckOpenMPIterationSpace( OpenMPDirectiveKind DKind, Stmt *S, Sema &SemaRef, DSAStackTy &DSA, unsigned CurrentNestedLoopCount, unsigned NestedLoopCount, - Expr *NestedLoopCountExpr, + Expr *CollapseLoopCountExpr, Expr *OrderedLoopCountExpr, llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA, LoopIterationSpace &ResultIterSpace) { // OpenMP [2.6, Canonical Loop Form] @@ -2759,13 +2759,24 @@ static bool CheckOpenMPIterationSpace( auto For = dyn_cast_or_null<ForStmt>(S); if (!For) { SemaRef.Diag(S->getLocStart(), diag::err_omp_not_for) - << (NestedLoopCountExpr != nullptr) << getOpenMPDirectiveName(DKind) - << NestedLoopCount << (CurrentNestedLoopCount > 0) - << CurrentNestedLoopCount; - if (NestedLoopCount > 1) - SemaRef.Diag(NestedLoopCountExpr->getExprLoc(), - diag::note_omp_collapse_expr) - << NestedLoopCountExpr->getSourceRange(); + << (CollapseLoopCountExpr != nullptr || OrderedLoopCountExpr != nullptr) + << getOpenMPDirectiveName(DKind) << NestedLoopCount + << (CurrentNestedLoopCount > 0) << CurrentNestedLoopCount; + if (NestedLoopCount > 1) { + if (CollapseLoopCountExpr && OrderedLoopCountExpr) + SemaRef.Diag(DSA.getConstructLoc(), + diag::note_omp_collapse_ordered_expr) + << 2 << CollapseLoopCountExpr->getSourceRange() + << OrderedLoopCountExpr->getSourceRange(); + else if (CollapseLoopCountExpr) + SemaRef.Diag(CollapseLoopCountExpr->getExprLoc(), + diag::note_omp_collapse_ordered_expr) + << 0 << CollapseLoopCountExpr->getSourceRange(); + else + SemaRef.Diag(OrderedLoopCountExpr->getExprLoc(), + diag::note_omp_collapse_ordered_expr) + << 1 << OrderedLoopCountExpr->getSourceRange(); + } return true; } assert(For->getBody()); @@ -2840,7 +2851,8 @@ static bool CheckOpenMPIterationSpace( } else if (LoopVarRefExpr != nullptr) { // Make the loop iteration variable private (for worksharing constructs), // linear (for simd directives with the only one associated loop) or - // lastprivate (for simd directives with several collapsed loops). + // lastprivate (for simd directives with several collapsed or ordered + // loops). if (DVar.CKind == OMPC_unknown) DVar = DSA.hasDSA(Var, isOpenMPPrivate, MatchesAlways(), /*FromParent=*/false); @@ -2942,16 +2954,23 @@ static bool FitsInto(unsigned Bits, bool Signed, Expr *E, Sema &SemaRef) { /// \return Returns 0 if one of the collapsed stmts is not canonical for loop, /// number of collapsed loops otherwise. static unsigned -CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *NestedLoopCountExpr, - Stmt *AStmt, Sema &SemaRef, DSAStackTy &DSA, +CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, + Expr *OrderedLoopCountExpr, Stmt *AStmt, Sema &SemaRef, + DSAStackTy &DSA, llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA, OMPLoopDirective::HelperExprs &Built) { unsigned NestedLoopCount = 1; - if (NestedLoopCountExpr) { + if (CollapseLoopCountExpr) { // Found 'collapse' clause - calculate collapse number. llvm::APSInt Result; - if (NestedLoopCountExpr->EvaluateAsInt(Result, SemaRef.getASTContext())) - NestedLoopCount = Result.getLimitedValue(); + if (CollapseLoopCountExpr->EvaluateAsInt(Result, SemaRef.getASTContext())) + NestedLoopCount += Result.getLimitedValue() - 1; + } + if (OrderedLoopCountExpr) { + // Found 'ordered' clause - calculate collapse number. + llvm::APSInt Result; + if (OrderedLoopCountExpr->EvaluateAsInt(Result, SemaRef.getASTContext())) + NestedLoopCount += Result.getLimitedValue() - 1; } // This is helper routine for loop directives (e.g., 'for', 'simd', // 'for simd', etc.). @@ -2960,8 +2979,9 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *NestedLoopCountExpr, Stmt *CurStmt = AStmt->IgnoreContainers(/* IgnoreCaptured */ true); for (unsigned Cnt = 0; Cnt < NestedLoopCount; ++Cnt) { if (CheckOpenMPIterationSpace(DKind, CurStmt, SemaRef, DSA, Cnt, - NestedLoopCount, NestedLoopCountExpr, - VarsWithImplicitDSA, IterSpaces[Cnt])) + NestedLoopCount, CollapseLoopCountExpr, + OrderedLoopCountExpr, VarsWithImplicitDSA, + IterSpaces[Cnt])) return 0; // Move on to the next nested for loop, or to the loop body. // OpenMP [2.8.1, simd construct, Restrictions] @@ -2978,11 +2998,12 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *NestedLoopCountExpr, // An example of what is generated for the following code: // - // #pragma omp simd collapse(2) + // #pragma omp simd collapse(2) ordered(2) // for (i = 0; i < NI; ++i) - // for (j = J0; j < NJ; j+=2) { - // <loop body> - // } + // for (k = 0; k < NK; ++k) + // for (j = J0; j < NJ; j+=2) { + // <loop body> + // } // // We generate the code below. // Note: the loop body may be outlined in CodeGen. @@ -3292,7 +3313,7 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *NestedLoopCountExpr, return NestedLoopCount; } -static Expr *GetCollapseNumberExpr(ArrayRef<OMPClause *> Clauses) { +static Expr *getCollapseNumberExpr(ArrayRef<OMPClause *> Clauses) { auto &&CollapseFilter = [](const OMPClause *C) -> bool { return C->getClauseKind() == OMPC_collapse; }; @@ -3303,15 +3324,27 @@ static Expr *GetCollapseNumberExpr(ArrayRef<OMPClause *> Clauses) { return nullptr; } +static Expr *getOrderedNumberExpr(ArrayRef<OMPClause *> Clauses) { + auto &&OrderedFilter = [](const OMPClause *C) -> bool { + return C->getClauseKind() == OMPC_ordered; + }; + OMPExecutableDirective::filtered_clause_iterator<decltype(OrderedFilter)> I( + Clauses, std::move(OrderedFilter)); + if (I) + return cast<OMPOrderedClause>(*I)->getNumForLoops(); + return nullptr; +} + StmtResult Sema::ActOnOpenMPSimdDirective( ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA) { OMPLoopDirective::HelperExprs B; - // In presence of clause 'collapse', it will define the nested loops number. - unsigned NestedLoopCount = - CheckOpenMPLoop(OMPD_simd, GetCollapseNumberExpr(Clauses), AStmt, *this, - *DSAStack, VarsWithImplicitDSA, B); + // In presence of clause 'collapse' or 'ordered' with number of loops, it will + // define the nested loops number. + unsigned NestedLoopCount = CheckOpenMPLoop( + OMPD_simd, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses), + AStmt, *this, *DSAStack, VarsWithImplicitDSA, B); if (NestedLoopCount == 0) return StmtError(); @@ -3338,10 +3371,11 @@ StmtResult Sema::ActOnOpenMPForDirective( SourceLocation EndLoc, llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA) { OMPLoopDirective::HelperExprs B; - // In presence of clause 'collapse', it will define the nested loops number. - unsigned NestedLoopCount = - CheckOpenMPLoop(OMPD_for, GetCollapseNumberExpr(Clauses), AStmt, *this, - *DSAStack, VarsWithImplicitDSA, B); + // In presence of clause 'collapse' or 'ordered' with number of loops, it will + // define the nested loops number. + unsigned NestedLoopCount = CheckOpenMPLoop( + OMPD_for, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses), + AStmt, *this, *DSAStack, VarsWithImplicitDSA, B); if (NestedLoopCount == 0) return StmtError(); @@ -3358,10 +3392,12 @@ StmtResult Sema::ActOnOpenMPForSimdDirective( SourceLocation EndLoc, llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA) { OMPLoopDirective::HelperExprs B; - // In presence of clause 'collapse', it will define the nested loops number. + // In presence of clause 'collapse' or 'ordered' with number of loops, it will + // define the nested loops number. unsigned NestedLoopCount = - CheckOpenMPLoop(OMPD_for_simd, GetCollapseNumberExpr(Clauses), AStmt, - *this, *DSAStack, VarsWithImplicitDSA, B); + CheckOpenMPLoop(OMPD_for_simd, getCollapseNumberExpr(Clauses), + getOrderedNumberExpr(Clauses), AStmt, *this, *DSAStack, + VarsWithImplicitDSA, B); if (NestedLoopCount == 0) return StmtError(); @@ -3490,10 +3526,12 @@ StmtResult Sema::ActOnOpenMPParallelForDirective( CS->getCapturedDecl()->setNothrow(); OMPLoopDirective::HelperExprs B; - // In presence of clause 'collapse', it will define the nested loops number. + // In presence of clause 'collapse' or 'ordered' with number of loops, it will + // define the nested loops number. unsigned NestedLoopCount = - CheckOpenMPLoop(OMPD_parallel_for, GetCollapseNumberExpr(Clauses), AStmt, - *this, *DSAStack, VarsWithImplicitDSA, B); + CheckOpenMPLoop(OMPD_parallel_for, getCollapseNumberExpr(Clauses), + getOrderedNumberExpr(Clauses), AStmt, *this, *DSAStack, + VarsWithImplicitDSA, B); if (NestedLoopCount == 0) return StmtError(); @@ -3519,10 +3557,12 @@ StmtResult Sema::ActOnOpenMPParallelForSimdDirective( CS->getCapturedDecl()->setNothrow(); OMPLoopDirective::HelperExprs B; - // In presence of clause 'collapse', it will define the nested loops number. + // In presence of clause 'collapse' or 'ordered' with number of loops, it will + // define the nested loops number. unsigned NestedLoopCount = - CheckOpenMPLoop(OMPD_parallel_for_simd, GetCollapseNumberExpr(Clauses), - AStmt, *this, *DSAStack, VarsWithImplicitDSA, B); + CheckOpenMPLoop(OMPD_parallel_for_simd, getCollapseNumberExpr(Clauses), + getOrderedNumberExpr(Clauses), AStmt, *this, *DSAStack, + VarsWithImplicitDSA, B); if (NestedLoopCount == 0) return StmtError(); @@ -4426,6 +4466,9 @@ OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr, case OMPC_collapse: Res = ActOnOpenMPCollapseClause(Expr, StartLoc, LParenLoc, EndLoc); break; + case OMPC_ordered: + Res = ActOnOpenMPOrderedClause(StartLoc, EndLoc, LParenLoc, Expr); + break; case OMPC_default: case OMPC_proc_bind: case OMPC_schedule: @@ -4438,7 +4481,6 @@ OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr, case OMPC_aligned: case OMPC_copyin: case OMPC_copyprivate: - case OMPC_ordered: case OMPC_nowait: case OMPC_untied: case OMPC_mergeable: @@ -4588,7 +4630,11 @@ ExprResult Sema::VerifyPositiveIntegerConstantInClause(Expr *E, return ExprError(); } if (CKind == OMPC_collapse) { - DSAStack->setCollapseNumber(Result.getExtValue()); + DSAStack->setCollapseNumber(DSAStack->getCollapseNumber() - 1 + + Result.getExtValue()); + } else if (CKind == OMPC_ordered) { + DSAStack->setCollapseNumber(DSAStack->getCollapseNumber() - 1 + + Result.getExtValue()); } return ICE; } @@ -4623,6 +4669,27 @@ OMPClause *Sema::ActOnOpenMPCollapseClause(Expr *NumForLoops, OMPCollapseClause(NumForLoopsResult.get(), StartLoc, LParenLoc, EndLoc); } +OMPClause *Sema::ActOnOpenMPOrderedClause(SourceLocation StartLoc, + SourceLocation EndLoc, + SourceLocation LParenLoc, + Expr *NumForLoops) { + DSAStack->setOrderedRegion(); + // OpenMP [2.7.1, loop construct, Description] + // OpenMP [2.8.1, simd construct, Description] + // OpenMP [2.9.6, distribute construct, Description] + // The parameter of the ordered clause must be a constant + // positive integer expression if any. + if (NumForLoops && LParenLoc.isValid()) { + ExprResult NumForLoopsResult = + VerifyPositiveIntegerConstantInClause(NumForLoops, OMPC_ordered); + if (NumForLoopsResult.isInvalid()) + return nullptr; + NumForLoops = NumForLoopsResult.get(); + } + return new (Context) + OMPOrderedClause(NumForLoops, StartLoc, LParenLoc, EndLoc); +} + OMPClause *Sema::ActOnOpenMPSimpleClause( OpenMPClauseKind Kind, unsigned Argument, SourceLocation ArgumentLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) { @@ -4915,12 +4982,6 @@ OMPClause *Sema::ActOnOpenMPClause(OpenMPClauseKind Kind, return Res; } -OMPClause *Sema::ActOnOpenMPOrderedClause(SourceLocation StartLoc, - SourceLocation EndLoc) { - DSAStack->setOrderedRegion(); - return new (Context) OMPOrderedClause(StartLoc, EndLoc); -} - OMPClause *Sema::ActOnOpenMPNowaitClause(SourceLocation StartLoc, SourceLocation EndLoc) { DSAStack->setNowaitRegion(); diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index 35408acdad3dbcac0bfdf96f468644a46f3882f4..885dba778f1a427ed340fe2e1d095d73161903c2 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -1447,6 +1447,16 @@ public: Kind, ChunkSize, StartLoc, LParenLoc, KindLoc, CommaLoc, EndLoc); } + /// \brief Build a new OpenMP 'ordered' clause. + /// + /// By default, performs semantic analysis to build the new OpenMP clause. + /// Subclasses may override this routine to provide different behavior. + OMPClause *RebuildOMPOrderedClause(SourceLocation StartLoc, + SourceLocation EndLoc, + SourceLocation LParenLoc, Expr *Num) { + return getSema().ActOnOpenMPOrderedClause(StartLoc, EndLoc, LParenLoc, Num); + } + /// \brief Build a new OpenMP 'private' clause. /// /// By default, performs semantic analysis to build the new OpenMP clause. @@ -7237,8 +7247,14 @@ TreeTransform<Derived>::TransformOMPScheduleClause(OMPScheduleClause *C) { template <typename Derived> OMPClause * TreeTransform<Derived>::TransformOMPOrderedClause(OMPOrderedClause *C) { - // No need to rebuild this clause, no template-dependent parameters. - return C; + ExprResult E; + if (auto *Num = C->getNumForLoops()) { + E = getDerived().TransformExpr(Num); + if (E.isInvalid()) + return nullptr; + } + return getDerived().RebuildOMPOrderedClause(C->getLocStart(), C->getLocEnd(), + C->getLParenLoc(), E.get()); } template <typename Derived> diff --git a/lib/Serialization/ASTReaderStmt.cpp b/lib/Serialization/ASTReaderStmt.cpp index f8aac551e1abd865943020d08c692c523b797733..83c462535476b9f82139795f9e12700520d4e011 100644 --- a/lib/Serialization/ASTReaderStmt.cpp +++ b/lib/Serialization/ASTReaderStmt.cpp @@ -1845,7 +1845,10 @@ void OMPClauseReader::VisitOMPScheduleClause(OMPScheduleClause *C) { C->setCommaLoc(Reader->ReadSourceLocation(Record, Idx)); } -void OMPClauseReader::VisitOMPOrderedClause(OMPOrderedClause *) {} +void OMPClauseReader::VisitOMPOrderedClause(OMPOrderedClause *C) { + C->setNumForLoops(Reader->Reader.ReadSubExpr()); + C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx)); +} void OMPClauseReader::VisitOMPNowaitClause(OMPNowaitClause *) {} diff --git a/lib/Serialization/ASTWriterStmt.cpp b/lib/Serialization/ASTWriterStmt.cpp index 3cc0835448d84857ec7bbe1997ec5e851eff2a34..74a37fd4f9bc3321f060b912ab611731a13ce972 100644 --- a/lib/Serialization/ASTWriterStmt.cpp +++ b/lib/Serialization/ASTWriterStmt.cpp @@ -1763,7 +1763,10 @@ void OMPClauseWriter::VisitOMPScheduleClause(OMPScheduleClause *C) { Writer->Writer.AddSourceLocation(C->getCommaLoc(), Record); } -void OMPClauseWriter::VisitOMPOrderedClause(OMPOrderedClause *) {} +void OMPClauseWriter::VisitOMPOrderedClause(OMPOrderedClause *C) { + Writer->Writer.AddStmt(C->getNumForLoops()); + Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record); +} void OMPClauseWriter::VisitOMPNowaitClause(OMPNowaitClause *) {} diff --git a/test/OpenMP/for_ast_print.cpp b/test/OpenMP/for_ast_print.cpp index c482ec56b9cae8d7a07006679dea8912f2c08144..d87cece1762f203672252744ed8bd897c9d5360e 100644 --- a/test/OpenMP/for_ast_print.cpp +++ b/test/OpenMP/for_ast_print.cpp @@ -20,7 +20,12 @@ T tmain(T argc) { // CHECK-NEXT: for (int i = 0; i < 2; ++i) // CHECK-NEXT: a = 2; #pragma omp parallel -#pragma omp for private(argc, b), firstprivate(c, d), lastprivate(d, f) collapse(N) schedule(static, N) ordered nowait +#pragma omp for private(argc, b), firstprivate(c, d), lastprivate(d, f) collapse(N) schedule(static, N) ordered(N) nowait + for (int i = 0; i < 10; ++i) + for (int j = 0; j < 10; ++j) + for (int j = 0; j < 10; ++j) + for (int j = 0; j < 10; ++j) + for (int j = 0; j < 10; ++j) for (int i = 0; i < 10; ++i) for (int j = 0; j < 10; ++j) for (int j = 0; j < 10; ++j) @@ -28,7 +33,12 @@ T tmain(T argc) { for (int j = 0; j < 10; ++j) foo(); // CHECK-NEXT: #pragma omp parallel - // CHECK-NEXT: #pragma omp for private(argc,b) firstprivate(c,d) lastprivate(d,f) collapse(N) schedule(static, N) ordered nowait + // CHECK-NEXT: #pragma omp for private(argc,b) firstprivate(c,d) lastprivate(d,f) collapse(N) schedule(static, N) ordered(N) nowait + // CHECK-NEXT: for (int i = 0; i < 10; ++i) + // CHECK-NEXT: for (int j = 0; j < 10; ++j) + // CHECK-NEXT: for (int j = 0; j < 10; ++j) + // CHECK-NEXT: for (int j = 0; j < 10; ++j) + // CHECK-NEXT: for (int j = 0; j < 10; ++j) // CHECK-NEXT: for (int i = 0; i < 10; ++i) // CHECK-NEXT: for (int j = 0; j < 10; ++j) // CHECK-NEXT: for (int j = 0; j < 10; ++j) diff --git a/test/OpenMP/for_ordered_clause.cpp b/test/OpenMP/for_ordered_clause.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5b08021587356a47ebfc32e536b2a1afe132142b --- /dev/null +++ b/test/OpenMP/for_ordered_clause.cpp @@ -0,0 +1,104 @@ +// RUN: %clang_cc1 -verify -fopenmp %s + +void foo() { +} + +bool foobool(int argc) { + return argc; +} + +struct S1; // expected-note {{declared here}} + +template <class T, typename S, int N, int ST> // expected-note {{declared here}} +T tmain(T argc, S **argv) { //expected-note 2 {{declared here}} +#pragma omp for ordered + for (int i = ST; i < N; i++) + argv[0][i] = argv[0][i] - argv[0][i - ST]; +#pragma omp for ordered( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} + for (int i = ST; i < N; i++) + argv[0][i] = argv[0][i] - argv[0][i - ST]; +#pragma omp for ordered() // expected-error {{expected expression}} + for (int i = ST; i < N; i++) + argv[0][i] = argv[0][i] - argv[0][i - ST]; +// expected-error@+3 {{expected ')'}} expected-note@+3 {{to match this '('}} +// expected-error@+2 2 {{expression is not an integral constant expression}} +// expected-note@+1 2 {{read of non-const variable 'argc' is not allowed in a constant expression}} +#pragma omp for ordered(argc + for (int i = ST; i < N; i++) + argv[0][i] = argv[0][i] - argv[0][i - ST]; +// expected-error@+1 2 {{argument to 'ordered' clause must be a positive integer value}} +#pragma omp for ordered(ST // expected-error {{expected ')'}} expected-note {{to match this '('}} + for (int i = ST; i < N; i++) + argv[0][i] = argv[0][i] - argv[0][i - ST]; +#pragma omp for ordered(1)) // expected-warning {{extra tokens at the end of '#pragma omp for' are ignored}} + for (int i = ST; i < N; i++) + argv[0][i] = argv[0][i] - argv[0][i - ST]; +#pragma omp for ordered((ST > 0) ? 1 + ST : 2) // expected-note 2 {{as specified in 'ordered' clause}} + for (int i = ST; i < N; i++) + argv[0][i] = argv[0][i] - argv[0][i - ST]; // expected-error 2 {{expected 2 for loops after '#pragma omp for', but found only 1}} +// expected-error@+3 2 {{directive '#pragma omp for' cannot contain more than one 'ordered' clause}} +// expected-error@+2 2 {{argument to 'ordered' clause must be a positive integer value}} +// expected-error@+1 2 {{expression is not an integral constant expression}} +#pragma omp for ordered(foobool(argc)), ordered(true), ordered(-5) + for (int i = ST; i < N; i++) + argv[0][i] = argv[0][i] - argv[0][i - ST]; +#pragma omp for ordered(S) // expected-error {{'S' does not refer to a value}} + for (int i = ST; i < N; i++) + argv[0][i] = argv[0][i] - argv[0][i - ST]; +// expected-error@+1 2 {{expression is not an integral constant expression}} +#pragma omp for ordered(argv[1] = 2) // expected-error {{expected ')'}} expected-note {{to match this '('}} + for (int i = ST; i < N; i++) + argv[0][i] = argv[0][i] - argv[0][i - ST]; +#pragma omp for ordered(1) + for (int i = ST; i < N; i++) + argv[0][i] = argv[0][i] - argv[0][i - ST]; +#pragma omp for ordered(N) // expected-error {{argument to 'ordered' clause must be a positive integer value}} + for (T i = ST; i < N; i++) + argv[0][i] = argv[0][i] - argv[0][i - ST]; +#pragma omp for ordered(2) // expected-note {{as specified in 'ordered' clause}} + foo(); // expected-error {{expected 2 for loops after '#pragma omp for'}} + return argc; +} + +int main(int argc, char **argv) { +#pragma omp for ordered + for (int i = 4; i < 12; i++) + argv[0][i] = argv[0][i] - argv[0][i - 4]; +#pragma omp for ordered( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} + for (int i = 4; i < 12; i++) + argv[0][i] = argv[0][i] - argv[0][i - 4]; +#pragma omp for ordered() // expected-error {{expected expression}} + for (int i = 4; i < 12; i++) + argv[0][i] = argv[0][i] - argv[0][i - 4]; +#pragma omp for ordered(4 // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-note {{as specified in 'ordered' clause}} + for (int i = 4; i < 12; i++) + argv[0][i] = argv[0][i] - argv[0][i - 4]; // expected-error {{expected 4 for loops after '#pragma omp for', but found only 1}} +#pragma omp for ordered(2 + 2)) // expected-warning {{extra tokens at the end of '#pragma omp for' are ignored}} expected-note {{as specified in 'ordered' clause}} + for (int i = 4; i < 12; i++) + argv[0][i] = argv[0][i] - argv[0][i - 4]; // expected-error {{expected 4 for loops after '#pragma omp for', but found only 1}} +#pragma omp for ordered(foobool(1) > 0 ? 1 : 2) // expected-error {{expression is not an integral constant expression}} + for (int i = 4; i < 12; i++) + argv[0][i] = argv[0][i] - argv[0][i - 4]; +// expected-error@+3 {{expression is not an integral constant expression}} +// expected-error@+2 2 {{directive '#pragma omp for' cannot contain more than one 'ordered' clause}} +// expected-error@+1 2 {{argument to 'ordered' clause must be a positive integer value}} +#pragma omp for ordered(foobool(argc)), ordered(true), ordered(-5) + for (int i = 4; i < 12; i++) + argv[0][i] = argv[0][i] - argv[0][i - 4]; +#pragma omp for ordered(S1) // expected-error {{'S1' does not refer to a value}} + for (int i = 4; i < 12; i++) + argv[0][i] = argv[0][i] - argv[0][i - 4]; +// expected-error@+1 {{expression is not an integral constant expression}} +#pragma omp for ordered(argv[1] = 2) // expected-error {{expected ')'}} expected-note {{to match this '('}} + for (int i = 4; i < 12; i++) + argv[0][i] = argv[0][i] - argv[0][i - 4]; +// expected-error@+3 {{statement after '#pragma omp for' must be a for loop}} +// expected-note@+1 {{in instantiation of function template specialization 'tmain<int, char, -1, -2>' requested here}} +#pragma omp for ordered(ordered(tmain < int, char, -1, -2 > (argc, argv) // expected-error 2 {{expected ')'}} expected-note 2 {{to match this '('}} + foo(); +#pragma omp for ordered(2) // expected-note {{as specified in 'ordered' clause}} + foo(); // expected-error {{expected 2 for loops after '#pragma omp for'}} + // expected-note@+1 {{in instantiation of function template specialization 'tmain<int, char, 1, 0>' requested here}} + return tmain<int, char, 1, 0>(argc, argv); +} + diff --git a/test/OpenMP/parallel_for_ast_print.cpp b/test/OpenMP/parallel_for_ast_print.cpp index f2899ee16ef540199f54be204745b4dc5028f5d6..f3025ced3b57933fa7abf13b5bcad39f03d417de 100644 --- a/test/OpenMP/parallel_for_ast_print.cpp +++ b/test/OpenMP/parallel_for_ast_print.cpp @@ -21,14 +21,24 @@ T tmain(T argc) { a = 2; // CHECK-NEXT: for (int i = 0; i < 2; ++i) // CHECK-NEXT: a = 2; -#pragma omp parallel for private(argc, b), firstprivate(c, d), lastprivate(d, f) collapse(N) schedule(static, N) ordered if (argc) num_threads(N) default(shared) shared(e) reduction(+ : h) +#pragma omp parallel for private(argc, b), firstprivate(c, d), lastprivate(d, f) collapse(N) schedule(static, N) ordered(N) if (argc) num_threads(N) default(shared) shared(e) reduction(+ : h) + for (int i = 0; i < 10; ++i) + for (int j = 0; j < 10; ++j) + for (int j = 0; j < 10; ++j) + for (int j = 0; j < 10; ++j) + for (int j = 0; j < 10; ++j) for (int i = 0; i < 10; ++i) for (int j = 0; j < 10; ++j) for (int j = 0; j < 10; ++j) for (int j = 0; j < 10; ++j) for (int j = 0; j < 10; ++j) foo(); - // CHECK-NEXT: #pragma omp parallel for private(argc,b) firstprivate(c,d) lastprivate(d,f) collapse(N) schedule(static, N) ordered if(argc) num_threads(N) default(shared) shared(e) reduction(+: h) + // CHECK-NEXT: #pragma omp parallel for private(argc,b) firstprivate(c,d) lastprivate(d,f) collapse(N) schedule(static, N) ordered(N) if(argc) num_threads(N) default(shared) shared(e) reduction(+: h) + // CHECK-NEXT: for (int i = 0; i < 10; ++i) + // CHECK-NEXT: for (int j = 0; j < 10; ++j) + // CHECK-NEXT: for (int j = 0; j < 10; ++j) + // CHECK-NEXT: for (int j = 0; j < 10; ++j) + // CHECK-NEXT: for (int j = 0; j < 10; ++j) // CHECK-NEXT: for (int i = 0; i < 10; ++i) // CHECK-NEXT: for (int j = 0; j < 10; ++j) // CHECK-NEXT: for (int j = 0; j < 10; ++j) diff --git a/test/OpenMP/parallel_for_ordered_messages.cpp b/test/OpenMP/parallel_for_ordered_messages.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4a8d3788966e597ecb9573cb67e4282324deb729 --- /dev/null +++ b/test/OpenMP/parallel_for_ordered_messages.cpp @@ -0,0 +1,104 @@ +// RUN: %clang_cc1 -verify -fopenmp %s + +void foo() { +} + +bool foobool(int argc) { + return argc; +} + +struct S1; // expected-note {{declared here}} + +template <class T, typename S, int N, int ST> // expected-note {{declared here}} +T tmain(T argc, S **argv) { //expected-note 2 {{declared here}} +#pragma omp parallel for ordered + for (int i = ST; i < N; i++) + argv[0][i] = argv[0][i] - argv[0][i - ST]; +#pragma omp parallel for ordered( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} + for (int i = ST; i < N; i++) + argv[0][i] = argv[0][i] - argv[0][i - ST]; +#pragma omp parallel for ordered() // expected-error {{expected expression}} + for (int i = ST; i < N; i++) + argv[0][i] = argv[0][i] - argv[0][i - ST]; +// expected-error@+3 {{expected ')'}} expected-note@+3 {{to match this '('}} +// expected-error@+2 2 {{expression is not an integral constant expression}} +// expected-note@+1 2 {{read of non-const variable 'argc' is not allowed in a constant expression}} +#pragma omp parallel for ordered(argc + for (int i = ST; i < N; i++) + argv[0][i] = argv[0][i] - argv[0][i - ST]; +// expected-error@+1 2 {{argument to 'ordered' clause must be a positive integer value}} +#pragma omp parallel for ordered(ST // expected-error {{expected ')'}} expected-note {{to match this '('}} + for (int i = ST; i < N; i++) + argv[0][i] = argv[0][i] - argv[0][i - ST]; +#pragma omp parallel for ordered(1)) // expected-warning {{extra tokens at the end of '#pragma omp parallel for' are ignored}} + for (int i = ST; i < N; i++) + argv[0][i] = argv[0][i] - argv[0][i - ST]; +#pragma omp parallel for ordered((ST > 0) ? 1 + ST : 2) // expected-note 2 {{as specified in 'ordered' clause}} + for (int i = ST; i < N; i++) + argv[0][i] = argv[0][i] - argv[0][i - ST]; // expected-error 2 {{expected 2 for loops after '#pragma omp parallel for', but found only 1}} +// expected-error@+3 2 {{directive '#pragma omp parallel for' cannot contain more than one 'ordered' clause}} +// expected-error@+2 2 {{argument to 'ordered' clause must be a positive integer value}} +// expected-error@+1 2 {{expression is not an integral constant expression}} +#pragma omp parallel for ordered(foobool(argc)), ordered(true), ordered(-5) + for (int i = ST; i < N; i++) + argv[0][i] = argv[0][i] - argv[0][i - ST]; +#pragma omp parallel for ordered(S) // expected-error {{'S' does not refer to a value}} + for (int i = ST; i < N; i++) + argv[0][i] = argv[0][i] - argv[0][i - ST]; +// expected-error@+1 2 {{expression is not an integral constant expression}} +#pragma omp parallel for ordered(argv[1] = 2) // expected-error {{expected ')'}} expected-note {{to match this '('}} + for (int i = ST; i < N; i++) + argv[0][i] = argv[0][i] - argv[0][i - ST]; +#pragma omp parallel for ordered(1) + for (int i = ST; i < N; i++) + argv[0][i] = argv[0][i] - argv[0][i - ST]; +#pragma omp parallel for ordered(N) // expected-error {{argument to 'ordered' clause must be a positive integer value}} + for (T i = ST; i < N; i++) + argv[0][i] = argv[0][i] - argv[0][i - ST]; +#pragma omp parallel for ordered(2) // expected-note {{as specified in 'ordered' clause}} + foo(); // expected-error {{expected 2 for loops after '#pragma omp parallel for'}} + return argc; +} + +int main(int argc, char **argv) { +#pragma omp parallel for ordered + for (int i = 4; i < 12; i++) + argv[0][i] = argv[0][i] - argv[0][i - 4]; +#pragma omp parallel for ordered( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} + for (int i = 4; i < 12; i++) + argv[0][i] = argv[0][i] - argv[0][i - 4]; +#pragma omp parallel for ordered() // expected-error {{expected expression}} + for (int i = 4; i < 12; i++) + argv[0][i] = argv[0][i] - argv[0][i - 4]; +#pragma omp parallel for ordered(4 // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-note {{as specified in 'ordered' clause}} + for (int i = 4; i < 12; i++) + argv[0][i] = argv[0][i] - argv[0][i - 4]; // expected-error {{expected 4 for loops after '#pragma omp parallel for', but found only 1}} +#pragma omp parallel for ordered(2 + 2)) // expected-warning {{extra tokens at the end of '#pragma omp parallel for' are ignored}} expected-note {{as specified in 'ordered' clause}} + for (int i = 4; i < 12; i++) + argv[0][i] = argv[0][i] - argv[0][i - 4]; // expected-error {{expected 4 for loops after '#pragma omp parallel for', but found only 1}} +#pragma omp parallel for ordered(foobool(1) > 0 ? 1 : 2) // expected-error {{expression is not an integral constant expression}} + for (int i = 4; i < 12; i++) + argv[0][i] = argv[0][i] - argv[0][i - 4]; +// expected-error@+3 {{expression is not an integral constant expression}} +// expected-error@+2 2 {{directive '#pragma omp parallel for' cannot contain more than one 'ordered' clause}} +// expected-error@+1 2 {{argument to 'ordered' clause must be a positive integer value}} +#pragma omp parallel for ordered(foobool(argc)), ordered(true), ordered(-5) + for (int i = 4; i < 12; i++) + argv[0][i] = argv[0][i] - argv[0][i - 4]; +#pragma omp parallel for ordered(S1) // expected-error {{'S1' does not refer to a value}} + for (int i = 4; i < 12; i++) + argv[0][i] = argv[0][i] - argv[0][i - 4]; +// expected-error@+1 {{expression is not an integral constant expression}} +#pragma omp parallel for ordered(argv[1] = 2) // expected-error {{expected ')'}} expected-note {{to match this '('}} + for (int i = 4; i < 12; i++) + argv[0][i] = argv[0][i] - argv[0][i - 4]; +// expected-error@+3 {{statement after '#pragma omp parallel for' must be a for loop}} +// expected-note@+1 {{in instantiation of function template specialization 'tmain<int, char, -1, -2>' requested here}} +#pragma omp parallel for ordered(ordered(tmain < int, char, -1, -2 > (argc, argv) // expected-error 2 {{expected ')'}} expected-note 2 {{to match this '('}} + foo(); +#pragma omp parallel for ordered(2) // expected-note {{as specified in 'ordered' clause}} + foo(); // expected-error {{expected 2 for loops after '#pragma omp parallel for'}} + // expected-note@+1 {{in instantiation of function template specialization 'tmain<int, char, 1, 0>' requested here}} + return tmain<int, char, 1, 0>(argc, argv); +} + diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp index f6710a096e7177aff817789841ac79c8fd0d6558..ed9a1ec6f0140feb38584e1e3ad1d940ec2fbc3c 100644 --- a/tools/libclang/CIndex.cpp +++ b/tools/libclang/CIndex.cpp @@ -2033,7 +2033,9 @@ void OMPClauseEnqueue::VisitOMPScheduleClause(const OMPScheduleClause *C) { Visitor->AddStmt(C->getHelperChunkSize()); } -void OMPClauseEnqueue::VisitOMPOrderedClause(const OMPOrderedClause *) {} +void OMPClauseEnqueue::VisitOMPOrderedClause(const OMPOrderedClause *C) { + Visitor->AddStmt(C->getNumForLoops()); +} void OMPClauseEnqueue::VisitOMPNowaitClause(const OMPNowaitClause *) {}