From: Alexey Bataev Date: Tue, 22 Jul 2014 06:45:04 +0000 (+0000) Subject: [OPENMP] Initial parsing and sema analysis for 'ordered' directive. X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=9fb6e647e71678341e7a344051df439a1020aaf4;p=platform%2Fupstream%2Fllvm.git [OPENMP] Initial parsing and sema analysis for 'ordered' directive. llvm-svn: 213616 --- diff --git a/clang/include/clang-c/Index.h b/clang/include/clang-c/Index.h index f69f567c2..2808a37 100644 --- a/clang/include/clang-c/Index.h +++ b/clang/include/clang-c/Index.h @@ -2190,10 +2190,14 @@ enum CXCursorKind { /** \brief OpenMP flush directive. */ CXCursor_OMPFlushDirective = 246, + + /** \brief OpenMP ordered directive. + */ + CXCursor_OMPOrderedDirective = 247, /** \brief Windows Structured Exception Handling's leave statement. */ - CXCursor_SEHLeaveStmt = 247, + CXCursor_SEHLeaveStmt = 248, CXCursor_LastStmt = CXCursor_SEHLeaveStmt, diff --git a/clang/include/clang/AST/DataRecursiveASTVisitor.h b/clang/include/clang/AST/DataRecursiveASTVisitor.h index 9ef0087..89ddfe4 100644 --- a/clang/include/clang/AST/DataRecursiveASTVisitor.h +++ b/clang/include/clang/AST/DataRecursiveASTVisitor.h @@ -2326,6 +2326,9 @@ DEF_TRAVERSE_STMT(OMPTaskwaitDirective, DEF_TRAVERSE_STMT(OMPFlushDirective, { TRY_TO(TraverseOMPExecutableDirective(S)); }) +DEF_TRAVERSE_STMT(OMPOrderedDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + // OpenMP clauses. template bool RecursiveASTVisitor::TraverseOMPClause(OMPClause *C) { diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h index ff46ffb..c50a68a 100644 --- a/clang/include/clang/AST/RecursiveASTVisitor.h +++ b/clang/include/clang/AST/RecursiveASTVisitor.h @@ -2348,6 +2348,9 @@ DEF_TRAVERSE_STMT(OMPTaskwaitDirective, DEF_TRAVERSE_STMT(OMPFlushDirective, { TRY_TO(TraverseOMPExecutableDirective(S)); }) +DEF_TRAVERSE_STMT(OMPOrderedDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + // OpenMP clauses. template bool RecursiveASTVisitor::TraverseOMPClause(OMPClause *C) { diff --git a/clang/include/clang/AST/StmtOpenMP.h b/clang/include/clang/AST/StmtOpenMP.h index db02afe..17bd0ee 100644 --- a/clang/include/clang/AST/StmtOpenMP.h +++ b/clang/include/clang/AST/StmtOpenMP.h @@ -1028,6 +1028,53 @@ public: } }; +/// \brief This represents '#pragma omp ordered' directive. +/// +/// \code +/// #pragma omp ordered +/// \endcode +/// +class OMPOrderedDirective : public OMPExecutableDirective { + friend class ASTStmtReader; + /// \brief Build directive with the given start and end location. + /// + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending location of the directive. + /// + OMPOrderedDirective(SourceLocation StartLoc, SourceLocation EndLoc) + : OMPExecutableDirective(this, OMPOrderedDirectiveClass, OMPD_ordered, + StartLoc, EndLoc, 0, 1) {} + + /// \brief Build an empty directive. + /// + explicit OMPOrderedDirective() + : OMPExecutableDirective(this, OMPOrderedDirectiveClass, OMPD_ordered, + SourceLocation(), SourceLocation(), 0, 1) {} + +public: + /// \brief Creates directive. + /// + /// \param C AST context. + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending Location of the directive. + /// \param AssociatedStmt Statement, associated with the directive. + /// + static OMPOrderedDirective *Create(const ASTContext &C, + SourceLocation StartLoc, + SourceLocation EndLoc, + Stmt *AssociatedStmt); + + /// \brief Creates an empty directive. + /// + /// \param C AST context. + /// + static OMPOrderedDirective *CreateEmpty(const ASTContext &C, EmptyShell); + + static bool classof(const Stmt *T) { + return T->getStmtClass() == OMPOrderedDirectiveClass; + } +}; + } // end namespace clang #endif diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 89749ed..baf83cf 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -7123,7 +7123,8 @@ def err_omp_reduction_id_not_compatible : Error< "variable of type %0 is not valid for specified reduction operation">; def err_omp_prohibited_region : Error< "region cannot be%select{| closely}0 nested inside '%1' region" - "%select{|; perhaps you forget to enclose 'omp %3' directive into a parallel region?}2">; + "%select{|; perhaps you forget to enclose 'omp %3' directive into a parallel region?|" + "; perhaps you forget to enclose 'omp %3' directive into a for or a parallel for region with 'ordered' clause?}2">; def err_omp_prohibited_region_simd : Error< "OpenMP constructs may not be nested inside a simd region">; def err_omp_prohibited_region_critical_same_name : Error< diff --git a/clang/include/clang/Basic/OpenMPKinds.def b/clang/include/clang/Basic/OpenMPKinds.def index 6cfa5ea..e89147f 100644 --- a/clang/include/clang/Basic/OpenMPKinds.def +++ b/clang/include/clang/Basic/OpenMPKinds.def @@ -70,6 +70,7 @@ OPENMP_DIRECTIVE(taskyield) OPENMP_DIRECTIVE(barrier) OPENMP_DIRECTIVE(taskwait) OPENMP_DIRECTIVE(flush) +OPENMP_DIRECTIVE(ordered) OPENMP_DIRECTIVE_EXT(parallel_for, "parallel for") OPENMP_DIRECTIVE_EXT(parallel_sections, "parallel sections") diff --git a/clang/include/clang/Basic/StmtNodes.td b/clang/include/clang/Basic/StmtNodes.td index d980648..ce6a6d6 100644 --- a/clang/include/clang/Basic/StmtNodes.td +++ b/clang/include/clang/Basic/StmtNodes.td @@ -193,3 +193,4 @@ def OMPTaskyieldDirective : DStmt; def OMPBarrierDirective : DStmt; def OMPTaskwaitDirective : DStmt; def OMPFlushDirective : DStmt; +def OMPOrderedDirective : DStmt; diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index e254afd..e110236 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -7395,6 +7395,10 @@ public: StmtResult ActOnOpenMPFlushDirective(ArrayRef Clauses, SourceLocation StartLoc, SourceLocation EndLoc); + /// \brief Called on well-formed '\#pragma omp master' after parsing of the + /// associated statement. + StmtResult ActOnOpenMPOrderedDirective(Stmt *AStmt, SourceLocation StartLoc, + SourceLocation EndLoc); OMPClause *ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr, diff --git a/clang/include/clang/Serialization/ASTBitCodes.h b/clang/include/clang/Serialization/ASTBitCodes.h index 7ae1977..440e2cd 100644 --- a/clang/include/clang/Serialization/ASTBitCodes.h +++ b/clang/include/clang/Serialization/ASTBitCodes.h @@ -1355,6 +1355,7 @@ namespace clang { STMT_OMP_BARRIER_DIRECTIVE, STMT_OMP_TASKWAIT_DIRECTIVE, STMT_OMP_FLUSH_DIRECTIVE, + STMT_OMP_ORDERED_DIRECTIVE, // ARC EXPR_OBJC_BRIDGED_CAST, // ObjCBridgedCastExpr diff --git a/clang/lib/AST/Stmt.cpp b/clang/lib/AST/Stmt.cpp index a8483dc..2eba875 100644 --- a/clang/lib/AST/Stmt.cpp +++ b/clang/lib/AST/Stmt.cpp @@ -1678,3 +1678,23 @@ OMPFlushDirective *OMPFlushDirective::CreateEmpty(const ASTContext &C, return new (Mem) OMPFlushDirective(NumClauses); } +OMPOrderedDirective *OMPOrderedDirective::Create(const ASTContext &C, + SourceLocation StartLoc, + SourceLocation EndLoc, + Stmt *AssociatedStmt) { + unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPOrderedDirective), + llvm::alignOf()); + void *Mem = C.Allocate(Size + sizeof(Stmt *)); + OMPOrderedDirective *Dir = new (Mem) OMPOrderedDirective(StartLoc, EndLoc); + Dir->setAssociatedStmt(AssociatedStmt); + return Dir; +} + +OMPOrderedDirective *OMPOrderedDirective::CreateEmpty(const ASTContext &C, + EmptyShell) { + unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPOrderedDirective), + llvm::alignOf()); + void *Mem = C.Allocate(Size + sizeof(Stmt *)); + return new (Mem) OMPOrderedDirective(); +} + diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp index 1fdad9f..e8fbdf4 100644 --- a/clang/lib/AST/StmtPrinter.cpp +++ b/clang/lib/AST/StmtPrinter.cpp @@ -886,6 +886,11 @@ void StmtPrinter::VisitOMPFlushDirective(OMPFlushDirective *Node) { PrintOMPExecutableDirective(Node); } +void StmtPrinter::VisitOMPOrderedDirective(OMPOrderedDirective *Node) { + Indent() << "#pragma omp ordered"; + PrintOMPExecutableDirective(Node); +} + //===----------------------------------------------------------------------===// // Expr printing methods. //===----------------------------------------------------------------------===// diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp index f44f25c..0e30886 100644 --- a/clang/lib/AST/StmtProfile.cpp +++ b/clang/lib/AST/StmtProfile.cpp @@ -431,6 +431,10 @@ void StmtProfiler::VisitOMPFlushDirective(const OMPFlushDirective *S) { VisitOMPExecutableDirective(S); } +void StmtProfiler::VisitOMPOrderedDirective(const OMPOrderedDirective *S) { + VisitOMPExecutableDirective(S); +} + void StmtProfiler::VisitExpr(const Expr *S) { VisitStmt(S); } diff --git a/clang/lib/Basic/OpenMPKinds.cpp b/clang/lib/Basic/OpenMPKinds.cpp index 06f010f..2f37f2f 100644 --- a/clang/lib/Basic/OpenMPKinds.cpp +++ b/clang/lib/Basic/OpenMPKinds.cpp @@ -268,6 +268,7 @@ bool clang::isAllowedClauseForDirective(OpenMPDirectiveKind DKind, case OMPD_taskyield: case OMPD_barrier: case OMPD_taskwait: + case OMPD_ordered: break; } return false; diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp index c2b64a7..d34a69e 100644 --- a/clang/lib/CodeGen/CGStmt.cpp +++ b/clang/lib/CodeGen/CGStmt.cpp @@ -221,6 +221,9 @@ void CodeGenFunction::EmitStmt(const Stmt *S) { case Stmt::OMPFlushDirectiveClass: EmitOMPFlushDirective(cast(*S)); break; + case Stmt::OMPOrderedDirectiveClass: + EmitOMPOrderedDirective(cast(*S)); + break; } } diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp index 867f415..8fdec17 100644 --- a/clang/lib/CodeGen/CGStmtOpenMP.cpp +++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp @@ -128,3 +128,7 @@ void CodeGenFunction::EmitOMPFlushDirective(const OMPFlushDirective &) { llvm_unreachable("CodeGen for 'omp flush' is not supported yet."); } +void CodeGenFunction::EmitOMPOrderedDirective(const OMPOrderedDirective &) { + llvm_unreachable("CodeGen for 'omp ordered' is not supported yet."); +} + diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 59cc30d..f2ecc4a 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -1936,6 +1936,7 @@ public: void EmitOMPBarrierDirective(const OMPBarrierDirective &S); void EmitOMPTaskwaitDirective(const OMPTaskwaitDirective &S); void EmitOMPFlushDirective(const OMPFlushDirective &S); + void EmitOMPOrderedDirective(const OMPOrderedDirective &S); //===--------------------------------------------------------------------===// // LValue Expression Emission diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp index d1544e6..9afe26c 100644 --- a/clang/lib/Parse/ParseOpenMP.cpp +++ b/clang/lib/Parse/ParseOpenMP.cpp @@ -92,6 +92,7 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirective() { case OMPD_section: case OMPD_single: case OMPD_master: + case OMPD_ordered: case OMPD_critical: case OMPD_parallel_for: case OMPD_parallel_sections: @@ -113,7 +114,8 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirective() { /// annot_pragma_openmp 'parallel' | 'simd' | 'for' | 'sections' | /// 'section' | 'single' | 'master' | 'critical' [ '(' ')' ] | /// 'parallel for' | 'parallel sections' | 'task' | 'taskyield' | -/// 'barrier' | 'taskwait' | 'flush' {clause} annot_pragma_openmp_end +/// 'barrier' | 'taskwait' | 'flush' | 'ordered' {clause} +/// annot_pragma_openmp_end /// StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective(bool StandAloneAllowed) { @@ -176,7 +178,8 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(bool StandAloneAllowed) { case OMPD_critical: case OMPD_parallel_for: case OMPD_parallel_sections: - case OMPD_task: { + case OMPD_task: + case OMPD_ordered: { ConsumeToken(); // Parse directive name of the 'critical' directive if any. if (DKind == OMPD_critical) { diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index 7f2af68..23ed631 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -91,15 +91,16 @@ private: DeclarationNameInfo DirectiveName; Scope *CurScope; SourceLocation ConstructLoc; + bool OrderedRegion; SharingMapTy(OpenMPDirectiveKind DKind, DeclarationNameInfo Name, Scope *CurScope, SourceLocation Loc) : SharingMap(), AlignedMap(), DefaultAttr(DSA_unspecified), Directive(DKind), DirectiveName(std::move(Name)), CurScope(CurScope), - ConstructLoc(Loc) {} + ConstructLoc(Loc), OrderedRegion(false) {} SharingMapTy() : SharingMap(), AlignedMap(), DefaultAttr(DSA_unspecified), Directive(OMPD_unknown), DirectiveName(), CurScope(nullptr), - ConstructLoc() {} + ConstructLoc(), OrderedRegion(false) {} }; typedef SmallVector StackTy; @@ -194,6 +195,18 @@ public: return isOpenMPThreadPrivate(DVar.CKind); } + /// \brief Marks current region as ordered (it has an 'ordered' clause). + void setOrderedRegion(bool IsOrdered = true) { + Stack.back().OrderedRegion = IsOrdered; + } + /// \brief Returns true, if parent region is ordered (has associated + /// 'ordered' clause), false - otherwise. + bool isParentOrderedRegion() const { + if (Stack.size() > 2) + return Stack[Stack.size() - 2].OrderedRegion; + return false; + } + Scope *getCurScope() const { return Stack.back().CurScope; } Scope *getCurScope() { return Stack.back().CurScope; } SourceLocation getConstructLoc() { return Stack.back().ConstructLoc; } @@ -1093,6 +1106,14 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) { Params); break; } + case OMPD_ordered: { + Sema::CapturedParamNameType Params[] = { + std::make_pair(StringRef(), QualType()) // __context with shared vars + }; + ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP, + Params); + break; + } case OMPD_threadprivate: llvm_unreachable("OpenMP Directive is not allowed"); case OMPD_unknown: @@ -1123,6 +1144,7 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | parallel | barrier | * | // | parallel | taskwait | * | // | parallel | flush | * | + // | parallel | ordered | + | // +------------------+-----------------+------------------------------------+ // | for | parallel | * | // | for | for | + | @@ -1139,6 +1161,7 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | for | barrier | + | // | for | taskwait | * | // | for | flush | * | + // | for | ordered | * (if construct is ordered) | // +------------------+-----------------+------------------------------------+ // | master | parallel | * | // | master | for | + | @@ -1155,11 +1178,12 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | master | barrier | + | // | master | taskwait | * | // | master | flush | * | + // | master | ordered | + | // +------------------+-----------------+------------------------------------+ // | critical | parallel | * | // | critical | for | + | // | critical | master | * | - // | critical | critical | * (should have dirrerent names) | + // | critical | critical | * (should have different names) | // | critical | simd | * | // | critical | sections | + | // | critical | section | + | @@ -1170,6 +1194,7 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | critical | taskyield | * | // | critical | barrier | + | // | critical | taskwait | * | + // | critical | ordered | + | // +------------------+-----------------+------------------------------------+ // | simd | parallel | | // | simd | for | | @@ -1186,6 +1211,7 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | simd | barrier | | // | simd | taskwait | | // | simd | flush | | + // | simd | ordered | | // +------------------+-----------------+------------------------------------+ // | sections | parallel | * | // | sections | for | + | @@ -1202,6 +1228,7 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | sections | barrier | + | // | sections | taskwait | * | // | sections | flush | * | + // | sections | ordered | + | // +------------------+-----------------+------------------------------------+ // | section | parallel | * | // | section | for | + | @@ -1218,6 +1245,7 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | section | barrier | + | // | section | taskwait | * | // | section | flush | * | + // | section | ordered | + | // +------------------+-----------------+------------------------------------+ // | single | parallel | * | // | single | for | + | @@ -1234,6 +1262,7 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | single | barrier | + | // | single | taskwait | * | // | single | flush | * | + // | single | ordered | + | // +------------------+-----------------+------------------------------------+ // | parallel for | parallel | * | // | parallel for | for | + | @@ -1250,6 +1279,7 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | parallel for | barrier | + | // | parallel for | taskwait | * | // | parallel for | flush | * | + // | parallel for | ordered | * (if construct is ordered) | // +------------------+-----------------+------------------------------------+ // | parallel sections| parallel | * | // | parallel sections| for | + | @@ -1266,6 +1296,7 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | parallel sections| barrier | + | // | parallel sections| taskwait | * | // | parallel sections| flush | * | + // | parallel sections| ordered | + | // +------------------+-----------------+------------------------------------+ // | task | parallel | * | // | task | for | + | @@ -1282,12 +1313,34 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | task | barrier | + | // | task | taskwait | * | // | task | flush | * | + // | task | ordered | + | + // +------------------+-----------------+------------------------------------+ + // | ordered | parallel | * | + // | ordered | for | + | + // | ordered | master | * | + // | ordered | critical | * | + // | ordered | simd | * | + // | ordered | sections | + | + // | ordered | section | + | + // | ordered | single | + | + // | ordered | parallel for | * | + // | ordered |parallel sections| * | + // | ordered | task | * | + // | ordered | taskyield | * | + // | ordered | barrier | + | + // | ordered | taskwait | * | + // | ordered | flush | * | + // | ordered | ordered | + | // +------------------+-----------------+------------------------------------+ if (Stack->getCurScope()) { auto ParentRegion = Stack->getParentDirective(); bool NestingProhibited = false; bool CloseNesting = true; - bool ShouldBeInParallelRegion = false; + enum { + NoRecommend, + ShouldBeInParallelRegion, + ShouldBeInOrderedRegion + } Recommend = NoRecommend; if (isOpenMPSimdDirective(ParentRegion)) { // OpenMP [2.16, Nesting of Regions] // OpenMP constructs may not be nested inside a simd region. @@ -1308,6 +1361,10 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, } return false; } + // Allow some constructs to be orphaned (they could be used in functions, + // called from OpenMP regions with the required preconditions). + if (ParentRegion == OMPD_unknown) + return false; if (CurrentRegion == OMPD_master) { // OpenMP [2.16, Nesting of Regions] // A master region may not be closely nested inside a worksharing, @@ -1346,12 +1403,11 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, } else if (CurrentRegion == OMPD_barrier) { // OpenMP [2.16, Nesting of Regions] // A barrier region may not be closely nested inside a worksharing, - // explicit task, critical, ordered(TODO), atomic(TODO), or master - // region. - NestingProhibited = isOpenMPWorksharingDirective(ParentRegion) || - ParentRegion == OMPD_task || - ParentRegion == OMPD_master || - ParentRegion == OMPD_critical; + // explicit task, critical, ordered, atomic(TODO), or master region. + NestingProhibited = + isOpenMPWorksharingDirective(ParentRegion) || + ParentRegion == OMPD_task || ParentRegion == OMPD_master || + ParentRegion == OMPD_critical || ParentRegion == OMPD_ordered; } else if (isOpenMPWorksharingDirective(CurrentRegion) && !isOpenMPParallelDirective(CurrentRegion) && !isOpenMPSimdDirective(CurrentRegion)) { @@ -1359,17 +1415,27 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // A worksharing region may not be closely nested inside a worksharing, // explicit task, critical, ordered, atomic, or master region. // TODO - NestingProhibited = (isOpenMPWorksharingDirective(ParentRegion) && - !isOpenMPSimdDirective(ParentRegion)) || + NestingProhibited = + (isOpenMPWorksharingDirective(ParentRegion) && + !isOpenMPSimdDirective(ParentRegion)) || + ParentRegion == OMPD_task || ParentRegion == OMPD_master || + ParentRegion == OMPD_critical || ParentRegion == OMPD_ordered; + Recommend = ShouldBeInParallelRegion; + } else if (CurrentRegion == OMPD_ordered) { + // OpenMP [2.16, Nesting of Regions] + // An ordered region may not be closely nested inside a critical, + // atomic(TODO), or explicit task region. + // An ordered region must be closely nested inside a loop region (or + // parallel loop region) with an ordered clause. + NestingProhibited = ParentRegion == OMPD_critical || ParentRegion == OMPD_task || - ParentRegion == OMPD_master || - ParentRegion == OMPD_critical; - ShouldBeInParallelRegion = true; + !Stack->isParentOrderedRegion(); + Recommend = ShouldBeInOrderedRegion; } if (NestingProhibited) { SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region) - << CloseNesting << getOpenMPDirectiveName(ParentRegion) - << ShouldBeInParallelRegion << getOpenMPDirectiveName(CurrentRegion); + << CloseNesting << getOpenMPDirectiveName(ParentRegion) << Recommend + << getOpenMPDirectiveName(CurrentRegion); return true; } } @@ -1487,6 +1553,11 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(OpenMPDirectiveKind Kind, "No associated statement allowed for 'omp flush' directive"); Res = ActOnOpenMPFlushDirective(ClausesWithImplicit, StartLoc, EndLoc); break; + case OMPD_ordered: + assert(ClausesWithImplicit.empty() && + "No clauses are allowed for 'omp ordered' directive"); + Res = ActOnOpenMPOrderedDirective(AStmt, StartLoc, EndLoc); + break; case OMPD_threadprivate: llvm_unreachable("OpenMP Directive is not allowed"); case OMPD_unknown: @@ -2264,6 +2335,16 @@ StmtResult Sema::ActOnOpenMPFlushDirective(ArrayRef Clauses, return OMPFlushDirective::Create(Context, StartLoc, EndLoc, Clauses); } +StmtResult Sema::ActOnOpenMPOrderedDirective(Stmt *AStmt, + SourceLocation StartLoc, + SourceLocation EndLoc) { + assert(AStmt && isa(AStmt) && "Captured statement expected"); + + getCurFunction()->setHasBranchProtectedScope(); + + return OMPOrderedDirective::Create(Context, StartLoc, EndLoc, AStmt); +} + OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr, SourceLocation StartLoc, SourceLocation LParenLoc, @@ -2727,6 +2808,7 @@ OMPClause *Sema::ActOnOpenMPClause(OpenMPClauseKind Kind, OMPClause *Sema::ActOnOpenMPOrderedClause(SourceLocation StartLoc, SourceLocation EndLoc) { + DSAStack->setOrderedRegion(); return new (Context) OMPOrderedClause(StartLoc, EndLoc); } diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 34d13c9..22a01bb 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -6633,6 +6633,17 @@ TreeTransform::TransformOMPFlushDirective(OMPFlushDirective *D) { return Res; } +template +StmtResult +TreeTransform::TransformOMPOrderedDirective(OMPOrderedDirective *D) { + DeclarationNameInfo DirName; + getDerived().getSema().StartOpenMPDSABlock(OMPD_ordered, DirName, nullptr, + D->getLocStart()); + StmtResult Res = getDerived().TransformOMPExecutableDirective(D); + getDerived().getSema().EndOpenMPDSABlock(Res.get()); + return Res; +} + //===----------------------------------------------------------------------===// // OpenMP clause transformation //===----------------------------------------------------------------------===// diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp index 8bf17d5..3d6a9a7 100644 --- a/clang/lib/Serialization/ASTReaderStmt.cpp +++ b/clang/lib/Serialization/ASTReaderStmt.cpp @@ -2031,6 +2031,11 @@ void ASTStmtReader::VisitOMPFlushDirective(OMPFlushDirective *D) { VisitOMPExecutableDirective(D); } +void ASTStmtReader::VisitOMPOrderedDirective(OMPOrderedDirective *D) { + VisitStmt(D); + VisitOMPExecutableDirective(D); +} + //===----------------------------------------------------------------------===// // ASTReader Implementation //===----------------------------------------------------------------------===// @@ -2586,6 +2591,10 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { Context, Record[ASTStmtReader::NumStmtFields], Empty); break; + case STMT_OMP_ORDERED_DIRECTIVE: + S = OMPOrderedDirective::CreateEmpty(Context, Empty); + break; + case EXPR_CXX_OPERATOR_CALL: S = new (Context) CXXOperatorCallExpr(Context, Empty); break; diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp index a43b352..486f89d 100644 --- a/clang/lib/Serialization/ASTWriterStmt.cpp +++ b/clang/lib/Serialization/ASTWriterStmt.cpp @@ -1930,6 +1930,12 @@ void ASTStmtWriter::VisitOMPFlushDirective(OMPFlushDirective *D) { Code = serialization::STMT_OMP_FLUSH_DIRECTIVE; } +void ASTStmtWriter::VisitOMPOrderedDirective(OMPOrderedDirective *D) { + VisitStmt(D); + VisitOMPExecutableDirective(D); + Code = serialization::STMT_OMP_ORDERED_DIRECTIVE; +} + //===----------------------------------------------------------------------===// // ASTWriter Implementation //===----------------------------------------------------------------------===// diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp index 4e4095c..eac8dd0 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -746,6 +746,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred, case Stmt::OMPBarrierDirectiveClass: case Stmt::OMPTaskwaitDirectiveClass: case Stmt::OMPFlushDirectiveClass: + case Stmt::OMPOrderedDirectiveClass: llvm_unreachable("Stmt should not be in analyzer evaluation loop"); case Stmt::ObjCSubscriptRefExprClass: diff --git a/clang/test/OpenMP/nesting_of_regions.cpp b/clang/test/OpenMP/nesting_of_regions.cpp index d8dcec5..255f2043 100644 --- a/clang/test/OpenMP/nesting_of_regions.cpp +++ b/clang/test/OpenMP/nesting_of_regions.cpp @@ -71,6 +71,11 @@ void foo() { #pragma omp flush bar(); } +#pragma omp parallel + { +#pragma omp ordered // expected-error {{region cannot be closely nested inside 'parallel' region; perhaps you forget to enclose 'omp ordered' directive into a for or a parallel for region with 'ordered' clause?}} + bar(); + } // SIMD DIRECTIVE #pragma omp simd @@ -166,6 +171,11 @@ void foo() { #pragma omp flush // expected-error {{OpenMP constructs may not be nested inside a simd region}} bar(); } +#pragma omp simd + for (int i = 0; i < 10; ++i) { +#pragma omp ordered // expected-error {{OpenMP constructs may not be nested inside a simd region}} + bar(); + } // FOR DIRECTIVE #pragma omp for @@ -279,6 +289,16 @@ void foo() { #pragma omp flush bar(); } +#pragma omp for + for (int i = 0; i < 10; ++i) { +#pragma omp ordered // expected-error {{region cannot be closely nested inside 'for' region; perhaps you forget to enclose 'omp ordered' directive into a for or a parallel for region with 'ordered' clause?}} + bar(); + } +#pragma omp for ordered + for (int i = 0; i < 10; ++i) { +#pragma omp ordered // OK + bar(); + } // SECTIONS DIRECTIVE #pragma omp sections @@ -404,6 +424,11 @@ void foo() { { #pragma omp flush } +#pragma omp sections + { +#pragma omp ordered // expected-error {{region cannot be closely nested inside 'sections' region; perhaps you forget to enclose 'omp ordered' directive into a for or a parallel for region with 'ordered' clause?}} + bar(); + } // SECTION DIRECTIVE #pragma omp section // expected-error {{orphaned 'omp section' directives are prohibited, it must be closely nested to a sections region}} @@ -550,6 +575,14 @@ void foo() { bar(); } } +#pragma omp sections + { +#pragma omp section + { +#pragma omp ordered // expected-error {{region cannot be closely nested inside 'section' region; perhaps you forget to enclose 'omp ordered' directive into a for or a parallel for region with 'ordered' clause?}} + bar(); + } + } // SINGLE DIRECTIVE #pragma omp single @@ -655,6 +688,11 @@ void foo() { #pragma omp flush bar(); } +#pragma omp single + { +#pragma omp ordered // expected-error {{region cannot be closely nested inside 'single' region; perhaps you forget to enclose 'omp ordered' directive into a for or a parallel for region with 'ordered' clause?}} + bar(); + } // MASTER DIRECTIVE #pragma omp master @@ -760,6 +798,11 @@ void foo() { #pragma omp flush bar(); } +#pragma omp master + { +#pragma omp ordered // expected-error {{region cannot be closely nested inside 'master' region; perhaps you forget to enclose 'omp ordered' directive into a for or a parallel for region with 'ordered' clause?}} + bar(); + } // CRITICAL DIRECTIVE #pragma omp critical @@ -879,6 +922,11 @@ void foo() { } } } +#pragma omp critical + { +#pragma omp ordered // expected-error {{region cannot be closely nested inside 'critical' region; perhaps you forget to enclose 'omp ordered' directive into a for or a parallel for region with 'ordered' clause?}} + bar(); + } // PARALLEL FOR DIRECTIVE #pragma omp parallel for @@ -994,6 +1042,16 @@ void foo() { #pragma omp flush bar(); } +#pragma omp parallel for + for (int i = 0; i < 10; ++i) { +#pragma omp ordered // expected-error {{region cannot be closely nested inside 'parallel for' region; perhaps you forget to enclose 'omp ordered' directive into a for or a parallel for region with 'ordered' clause?}} + bar(); + } +#pragma omp parallel for ordered + for (int i = 0; i < 10; ++i) { +#pragma omp ordered // OK + bar(); + } // PARALLEL SECTIONS DIRECTIVE #pragma omp parallel sections @@ -1105,6 +1163,11 @@ void foo() { { #pragma omp flush } +#pragma omp parallel sections + { +#pragma omp ordered // expected-error {{region cannot be closely nested inside 'parallel sections' region; perhaps you forget to enclose 'omp ordered' directive into a for or a parallel for region with 'ordered' clause?}} + bar(); + } // TASK DIRECTIVE #pragma omp task @@ -1169,6 +1232,114 @@ void foo() { #pragma omp flush bar(); } +#pragma omp task + { +#pragma omp ordered // expected-error {{region cannot be closely nested inside 'task' region; perhaps you forget to enclose 'omp ordered' directive into a for or a parallel for region with 'ordered' clause?}} + bar(); + } + +// ORDERED DIRECTIVE +#pragma omp ordered + { +#pragma omp for // expected-error {{region cannot be closely nested inside 'ordered' region; perhaps you forget to enclose 'omp for' directive into a parallel region?}} + for (int i = 0; i < 10; ++i) + ; + } +#pragma omp ordered + { +#pragma omp simd + for (int i = 0; i < 10; ++i) + ; + } +#pragma omp ordered + { +#pragma omp parallel + for (int i = 0; i < 10; ++i) + ; + } +#pragma omp ordered + { +#pragma omp single // expected-error {{region cannot be closely nested inside 'ordered' region; perhaps you forget to enclose 'omp single' directive into a parallel region?}} + { + bar(); + } + } +#pragma omp ordered + { +#pragma omp master // OK, though second 'ordered' is redundant + { + bar(); + } + } +#pragma omp ordered + { +#pragma omp critical + { + bar(); + } + } +#pragma omp ordered + { +#pragma omp sections // expected-error {{region cannot be closely nested inside 'ordered' region; perhaps you forget to enclose 'omp sections' directive into a parallel region?}} + { + bar(); + } + } +#pragma omp ordered + { +#pragma omp parallel for ordered + for (int j = 0; j < 10; ++j) { +#pragma omp ordered // OK + { + bar(); + } + } + } +#pragma omp ordered + { +#pragma omp parallel for + for (int i = 0; i < 10; ++i) + ; + } +#pragma omp ordered + { +#pragma omp parallel sections + { + bar(); + } + } +#pragma omp ordered + { +#pragma omp task + { + bar(); + } + } +#pragma omp ordered + { +#pragma omp taskyield + bar(); + } +#pragma omp ordered + { +#pragma omp barrier // expected-error {{region cannot be closely nested inside 'ordered' region}} + bar(); + } +#pragma omp ordered + { +#pragma omp taskwait + bar(); + } +#pragma omp ordered + { +#pragma omp flush + bar(); + } +#pragma omp ordered + { +#pragma omp ordered // expected-error {{region cannot be closely nested inside 'ordered' region; perhaps you forget to enclose 'omp ordered' directive into a for or a parallel for region with 'ordered' clause?}} + bar(); + } } void foo() { @@ -1239,6 +1410,11 @@ void foo() { #pragma omp flush bar(); } +#pragma omp parallel + { +#pragma omp ordered // expected-error {{region cannot be closely nested inside 'parallel' region; perhaps you forget to enclose 'omp ordered' directive into a for or a parallel for region with 'ordered' clause?}} + bar(); + } // SIMD DIRECTIVE #pragma omp simd @@ -1327,6 +1503,11 @@ void foo() { #pragma omp flush // expected-error {{OpenMP constructs may not be nested inside a simd region}} bar(); } +#pragma omp simd + for (int i = 0; i < 10; ++i) { +#pragma omp ordered // expected-error {{OpenMP constructs may not be nested inside a simd region}} + bar(); + } // FOR DIRECTIVE #pragma omp for @@ -1427,6 +1608,16 @@ void foo() { #pragma omp flush bar(); } +#pragma omp for + for (int i = 0; i < 10; ++i) { +#pragma omp ordered // expected-error {{region cannot be closely nested inside 'for' region; perhaps you forget to enclose 'omp ordered' directive into a for or a parallel for region with 'ordered' clause?}} + bar(); + } +#pragma omp for ordered + for (int i = 0; i < 10; ++i) { +#pragma omp ordered // OK + bar(); + } // SECTIONS DIRECTIVE #pragma omp sections @@ -1524,6 +1715,11 @@ void foo() { { #pragma omp flush } +#pragma omp sections + { +#pragma omp ordered // expected-error {{region cannot be closely nested inside 'sections' region; perhaps you forget to enclose 'omp ordered' directive into a for or a parallel for region with 'ordered' clause?}} + bar(); + } // SECTION DIRECTIVE #pragma omp section // expected-error {{orphaned 'omp section' directives are prohibited, it must be closely nested to a sections region}} @@ -1670,6 +1866,14 @@ void foo() { bar(); } } +#pragma omp sections + { +#pragma omp section + { +#pragma omp ordered // expected-error {{region cannot be closely nested inside 'section' region; perhaps you forget to enclose 'omp ordered' directive into a for or a parallel for region with 'ordered' clause?}} + bar(); + } + } // SINGLE DIRECTIVE #pragma omp single @@ -1765,6 +1969,11 @@ void foo() { #pragma omp flush bar(); } +#pragma omp single + { +#pragma omp ordered // expected-error {{region cannot be closely nested inside 'single' region; perhaps you forget to enclose 'omp ordered' directive into a for or a parallel for region with 'ordered' clause?}} + bar(); + } // MASTER DIRECTIVE #pragma omp master @@ -1870,6 +2079,11 @@ void foo() { #pragma omp flush bar(); } +#pragma omp master + { +#pragma omp ordered // expected-error {{region cannot be closely nested inside 'master' region; perhaps you forget to enclose 'omp ordered' directive into a for or a parallel for region with 'ordered' clause?}} + bar(); + } // CRITICAL DIRECTIVE #pragma omp critical @@ -1989,6 +2203,11 @@ void foo() { } } } +#pragma omp critical + { +#pragma omp ordered // expected-error {{region cannot be closely nested inside 'critical' region; perhaps you forget to enclose 'omp ordered' directive into a for or a parallel for region with 'ordered' clause?}} + bar(); + } // PARALLEL FOR DIRECTIVE #pragma omp parallel for @@ -2103,6 +2322,16 @@ void foo() { #pragma omp flush bar(); } +#pragma omp parallel for + for (int i = 0; i < 10; ++i) { +#pragma omp ordered // expected-error {{region cannot be closely nested inside 'parallel for' region; perhaps you forget to enclose 'omp ordered' directive into a for or a parallel for region with 'ordered' clause?}} + bar(); + } +#pragma omp parallel for ordered + for (int i = 0; i < 10; ++i) { +#pragma omp ordered // OK + bar(); + } // PARALLEL SECTIONS DIRECTIVE #pragma omp parallel sections @@ -2210,6 +2439,11 @@ void foo() { { #pragma omp flush } +#pragma omp parallel sections + { +#pragma omp ordered // expected-error {{region cannot be closely nested inside 'parallel sections' region; perhaps you forget to enclose 'omp ordered' directive into a for or a parallel for region with 'ordered' clause?}} + bar(); + } // TASK DIRECTIVE #pragma omp task @@ -2273,6 +2507,11 @@ void foo() { #pragma omp flush bar(); } +#pragma omp task + { +#pragma omp ordered // expected-error {{region cannot be closely nested inside 'task' region; perhaps you forget to enclose 'omp ordered' directive into a for or a parallel for region with 'ordered' clause?}} + bar(); + } return foo(); } diff --git a/clang/test/OpenMP/ordered_ast_print.cpp b/clang/test/OpenMP/ordered_ast_print.cpp new file mode 100644 index 0000000..a443500 --- /dev/null +++ b/clang/test/OpenMP/ordered_ast_print.cpp @@ -0,0 +1,59 @@ +// RUN: %clang_cc1 -verify -fopenmp=libiomp5 -ast-print %s | FileCheck %s +// RUN: %clang_cc1 -fopenmp=libiomp5 -x c++ -std=c++11 -emit-pch -o %t %s +// RUN: %clang_cc1 -fopenmp=libiomp5 -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s +// expected-no-diagnostics + +#ifndef HEADER +#define HEADER + +void foo() {} + +template +T tmain (T argc) { + T b = argc, c, d, e, f, g; + static T a; + #pragma omp for ordered + for (int i =0 ; i < argc; ++i) + #pragma omp ordered + { + a=2; + } + return (0); +} + +// CHECK: static int a; +// CHECK-NEXT: #pragma omp for ordered +// CHECK-NEXT: for (int i = 0; i < argc; ++i) +// CHECK-NEXT: #pragma omp ordered +// CHECK-NEXT: { +// CHECK-NEXT: a = 2; +// CHECK-NEXT: } + +// CHECK: static T a; +// CHECK-NEXT: #pragma omp for ordered +// CHECK-NEXT: for (int i = 0; i < argc; ++i) +// CHECK-NEXT: #pragma omp ordered +// CHECK-NEXT: { +// CHECK-NEXT: a = 2; +// CHECK-NEXT: } + +int main (int argc, char **argv) { + int b = argc, c, d, e, f, g; + static int a; +// CHECK: static int a; + #pragma omp for ordered + for (int i =0 ; i < argc; ++i) + #pragma omp ordered + { + a=2; + } +// CHECK-NEXT: #pragma omp for ordered +// CHECK-NEXT: for (int i = 0; i < argc; ++i) +// CHECK-NEXT: #pragma omp ordered +// CHECK-NEXT: { +// CHECK-NEXT: a = 2; +// CHECK-NEXT: } + return tmain(argc); +} + +#endif diff --git a/clang/test/OpenMP/ordered_messages.cpp b/clang/test/OpenMP/ordered_messages.cpp new file mode 100644 index 0000000..3f79df6 --- /dev/null +++ b/clang/test/OpenMP/ordered_messages.cpp @@ -0,0 +1,54 @@ +// RUN: %clang_cc1 -verify -fopenmp=libiomp5 -ferror-limit 100 -o - %s + +int foo(); + +template +T foo() { + #pragma omp for ordered + for (int i = 0; i < 10; ++i) { + L1: + foo(); + #pragma omp ordered + { + foo(); + goto L1; // expected-error {{use of undeclared label 'L1'}} + } + } + #pragma omp for ordered + for (int i = 0; i < 10; ++i) { + foo(); + goto L2; // expected-error {{use of undeclared label 'L2'}} + #pragma omp ordered + { + L2: + foo(); + } + } + + return T(); +} + +int foo() { + #pragma omp for ordered + for (int i = 0; i < 10; ++i) { + L1: + foo(); + #pragma omp ordered + { + foo(); + goto L1; // expected-error {{use of undeclared label 'L1'}} + } + } + #pragma omp for ordered + for (int i = 0; i < 10; ++i) { + foo(); + goto L2; // expected-error {{use of undeclared label 'L2'}} + #pragma omp ordered + { + L2: + foo(); + } + } + + return foo(); +} diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp index fc8703a..8e9a7bd 100644 --- a/clang/tools/libclang/CIndex.cpp +++ b/clang/tools/libclang/CIndex.cpp @@ -1871,6 +1871,7 @@ public: void VisitOMPBarrierDirective(const OMPBarrierDirective *D); void VisitOMPTaskwaitDirective(const OMPTaskwaitDirective *D); void VisitOMPFlushDirective(const OMPFlushDirective *D); + void VisitOMPOrderedDirective(const OMPOrderedDirective *D); private: void AddDeclarationNameInfo(const Stmt *S); @@ -2373,6 +2374,10 @@ void EnqueueVisitor::VisitOMPFlushDirective(const OMPFlushDirective *D) { VisitOMPExecutableDirective(D); } +void EnqueueVisitor::VisitOMPOrderedDirective(const OMPOrderedDirective *D) { + VisitOMPExecutableDirective(D); +} + void CursorVisitor::EnqueueWorkList(VisitorWorkList &WL, const Stmt *S) { EnqueueVisitor(WL, MakeCXCursor(S, StmtParent, TU,RegionOfInterest)).Visit(S); } @@ -4075,6 +4080,8 @@ CXString clang_getCursorKindSpelling(enum CXCursorKind Kind) { return cxstring::createRef("OMPTaskwaitDirective"); case CXCursor_OMPFlushDirective: return cxstring::createRef("OMPFlushDirective"); + case CXCursor_OMPOrderedDirective: + return cxstring::createRef("OMPOrderedDirective"); } llvm_unreachable("Unhandled CXCursorKind"); diff --git a/clang/tools/libclang/CXCursor.cpp b/clang/tools/libclang/CXCursor.cpp index 4321903..796c25c 100644 --- a/clang/tools/libclang/CXCursor.cpp +++ b/clang/tools/libclang/CXCursor.cpp @@ -562,6 +562,9 @@ CXCursor cxcursor::MakeCXCursor(const Stmt *S, const Decl *Parent, case Stmt::OMPFlushDirectiveClass: K = CXCursor_OMPFlushDirective; break; + case Stmt::OMPOrderedDirectiveClass: + K = CXCursor_OMPOrderedDirective; + break; } CXCursor C = { K, 0, { Parent, S, TU } };