From: Alexey Bataev Date: Fri, 18 Jul 2014 07:47:19 +0000 (+0000) Subject: [OPENMP] Initial parsing and sema analysis of 'taskyield' directive. X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=68446b72530b7b8badf295a350de43265dbec06a;p=platform%2Fupstream%2Fllvm.git [OPENMP] Initial parsing and sema analysis of 'taskyield' directive. llvm-svn: 213355 --- diff --git a/clang/include/clang-c/Index.h b/clang/include/clang-c/Index.h index c514fb0..a467f7d 100644 --- a/clang/include/clang-c/Index.h +++ b/clang/include/clang-c/Index.h @@ -2171,9 +2171,13 @@ enum CXCursorKind { */ CXCursor_OMPMasterDirective = 241, + /** \brief OpenMP taskyield directive. + */ + CXCursor_OMPTaskyieldDirective = 242, + /** \brief Windows Structured Exception Handling's leave statement. */ - CXCursor_SEHLeaveStmt = 242, + CXCursor_SEHLeaveStmt = 243, CXCursor_LastStmt = CXCursor_SEHLeaveStmt, diff --git a/clang/include/clang/AST/DataRecursiveASTVisitor.h b/clang/include/clang/AST/DataRecursiveASTVisitor.h index f9de4fb..09c83ed 100644 --- a/clang/include/clang/AST/DataRecursiveASTVisitor.h +++ b/clang/include/clang/AST/DataRecursiveASTVisitor.h @@ -2309,6 +2309,9 @@ DEF_TRAVERSE_STMT(OMPParallelSectionsDirective, DEF_TRAVERSE_STMT(OMPTaskDirective, { TRY_TO(TraverseOMPExecutableDirective(S)); }) +DEF_TRAVERSE_STMT(OMPTaskyieldDirective, + { 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 f427dd8..a10962e 100644 --- a/clang/include/clang/AST/RecursiveASTVisitor.h +++ b/clang/include/clang/AST/RecursiveASTVisitor.h @@ -2331,6 +2331,9 @@ DEF_TRAVERSE_STMT(OMPParallelSectionsDirective, DEF_TRAVERSE_STMT(OMPTaskDirective, { TRY_TO(TraverseOMPExecutableDirective(S)); }) +DEF_TRAVERSE_STMT(OMPTaskyieldDirective, + { 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 1c09785..acecf43 100644 --- a/clang/include/clang/AST/StmtOpenMP.h +++ b/clang/include/clang/AST/StmtOpenMP.h @@ -83,7 +83,10 @@ protected: /// /// /param S Associated statement. /// - void setAssociatedStmt(Stmt *S) { *child_begin() = S; } + void setAssociatedStmt(Stmt *S) { + assert(hasAssociatedStmt() && "no associated statement."); + *child_begin() = S; + } public: /// \brief Iterates over a filtered subrange of clauses applied to a @@ -150,8 +153,14 @@ public: /// OMPClause *getClause(unsigned i) const { return clauses()[i]; } + /// \brief Returns true if directive has associated statement. + bool hasAssociatedStmt() const { return NumChildren > 0; } + /// \brief Returns statement associated with the directive. - Stmt *getAssociatedStmt() const { return const_cast(*child_begin()); } + Stmt *getAssociatedStmt() const { + assert(hasAssociatedStmt() && "no associated statement."); + return const_cast(*child_begin()); + } OpenMPDirectiveKind getDirectiveKind() const { return Kind; } @@ -161,6 +170,8 @@ public: } child_range children() { + if (!hasAssociatedStmt()) + return child_range(); Stmt **ChildStorage = reinterpret_cast(getClauses().end()); return child_range(ChildStorage, ChildStorage + NumChildren); } @@ -763,6 +774,50 @@ public: } }; +/// \brief This represents '#pragma omp taskyield' directive. +/// +/// \code +/// #pragma omp taskyield +/// \endcode +/// +class OMPTaskyieldDirective : 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. + /// + OMPTaskyieldDirective(SourceLocation StartLoc, SourceLocation EndLoc) + : OMPExecutableDirective(this, OMPTaskyieldDirectiveClass, OMPD_taskyield, + StartLoc, EndLoc, 0, 0) {} + + /// \brief Build an empty directive. + /// + explicit OMPTaskyieldDirective() + : OMPExecutableDirective(this, OMPTaskyieldDirectiveClass, OMPD_taskyield, + SourceLocation(), SourceLocation(), 0, 0) {} + +public: + /// \brief Creates directive. + /// + /// \param C AST context. + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending Location of the directive. + /// + static OMPTaskyieldDirective * + Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc); + + /// \brief Creates an empty directive. + /// + /// \param C AST context. + /// + static OMPTaskyieldDirective *CreateEmpty(const ASTContext &C, EmptyShell); + + static bool classof(const Stmt *T) { + return T->getStmtClass() == OMPTaskyieldDirectiveClass; + } +}; + } // end namespace clang #endif diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td index 24011d3..1956afc8 100644 --- a/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -908,6 +908,8 @@ def err_omp_unexpected_clause : Error< "unexpected OpenMP clause '%0' in directive '#pragma omp %1'">; def err_omp_more_one_clause : Error< "directive '#pragma omp %0' cannot contain more than one '%1' clause">; +def err_omp_immediate_directive : Error< + "'#pragma omp %0' cannot be an immediate substatement">; // Pragma loop support. def err_pragma_loop_invalid_option : Error< diff --git a/clang/include/clang/Basic/OpenMPKinds.def b/clang/include/clang/Basic/OpenMPKinds.def index 91b026e..8e93f73 100644 --- a/clang/include/clang/Basic/OpenMPKinds.def +++ b/clang/include/clang/Basic/OpenMPKinds.def @@ -65,6 +65,7 @@ OPENMP_DIRECTIVE(sections) OPENMP_DIRECTIVE(section) OPENMP_DIRECTIVE(single) OPENMP_DIRECTIVE(master) +OPENMP_DIRECTIVE(taskyield) 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 9d56783..ab3a0ab 100644 --- a/clang/include/clang/Basic/StmtNodes.td +++ b/clang/include/clang/Basic/StmtNodes.td @@ -188,3 +188,4 @@ def OMPMasterDirective : DStmt; def OMPParallelForDirective : DStmt; def OMPParallelSectionsDirective : DStmt; def OMPTaskDirective : DStmt; +def OMPTaskyieldDirective : DStmt; diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index 5378762..fa7281b 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -2339,7 +2339,12 @@ private: SmallVectorImpl &VarList, bool AllowScopeSpecifier); /// \brief Parses declarative or executable directive. - StmtResult ParseOpenMPDeclarativeOrExecutableDirective(); + /// + /// \param StandAloneAllowed true if allowed stand-alone directives, + /// false - otherwise + /// + StmtResult + ParseOpenMPDeclarativeOrExecutableDirective(bool StandAloneAllowed); /// \brief Parses clause of kind \a CKind for directive of a kind \a Kind. /// /// \param DKind Kind of current directive. diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 4a6fe35..7e3b383 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -7368,6 +7368,10 @@ public: StmtResult ActOnOpenMPTaskDirective(ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc); + /// \brief Called on well-formed '\#pragma omp taskyield' after parsing of the + /// associated statement. + StmtResult ActOnOpenMPTaskyieldDirective(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 d1d32ac..6d5b4cc 100644 --- a/clang/include/clang/Serialization/ASTBitCodes.h +++ b/clang/include/clang/Serialization/ASTBitCodes.h @@ -1350,6 +1350,7 @@ namespace clang { STMT_OMP_PARALLEL_FOR_DIRECTIVE, STMT_OMP_PARALLEL_SECTIONS_DIRECTIVE, STMT_OMP_TASK_DIRECTIVE, + STMT_OMP_TASKYIELD_DIRECTIVE, // ARC EXPR_OBJC_BRIDGED_CAST, // ObjCBridgedCastExpr diff --git a/clang/lib/AST/Stmt.cpp b/clang/lib/AST/Stmt.cpp index 9185e48..53c48cc 100644 --- a/clang/lib/AST/Stmt.cpp +++ b/clang/lib/AST/Stmt.cpp @@ -1574,3 +1574,18 @@ OMPTaskDirective *OMPTaskDirective::CreateEmpty(const ASTContext &C, return new (Mem) OMPTaskDirective(NumClauses); } +OMPTaskyieldDirective *OMPTaskyieldDirective::Create(const ASTContext &C, + SourceLocation StartLoc, + SourceLocation EndLoc) { + void *Mem = C.Allocate(sizeof(OMPTaskyieldDirective)); + OMPTaskyieldDirective *Dir = + new (Mem) OMPTaskyieldDirective(StartLoc, EndLoc); + return Dir; +} + +OMPTaskyieldDirective *OMPTaskyieldDirective::CreateEmpty(const ASTContext &C, + EmptyShell) { + void *Mem = C.Allocate(sizeof(OMPTaskyieldDirective)); + return new (Mem) OMPTaskyieldDirective(); +} + diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp index da9a413..dfecc34 100644 --- a/clang/lib/AST/StmtPrinter.cpp +++ b/clang/lib/AST/StmtPrinter.cpp @@ -791,7 +791,7 @@ void StmtPrinter::PrintOMPExecutableDirective(OMPExecutableDirective *S) { OS << ' '; } OS << "\n"; - if (S->getAssociatedStmt()) { + if (S->hasAssociatedStmt() && S->getAssociatedStmt()) { assert(isa(S->getAssociatedStmt()) && "Expected captured statement!"); Stmt *CS = cast(S->getAssociatedStmt())->getCapturedStmt(); @@ -850,6 +850,11 @@ void StmtPrinter::VisitOMPTaskDirective(OMPTaskDirective *Node) { PrintOMPExecutableDirective(Node); } +void StmtPrinter::VisitOMPTaskyieldDirective(OMPTaskyieldDirective *Node) { + Indent() << "#pragma omp taskyield"; + PrintOMPExecutableDirective(Node); +} + //===----------------------------------------------------------------------===// // Expr printing methods. //===----------------------------------------------------------------------===// diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp index c4289df..a4943bf 100644 --- a/clang/lib/AST/StmtProfile.cpp +++ b/clang/lib/AST/StmtProfile.cpp @@ -407,6 +407,10 @@ void StmtProfiler::VisitOMPTaskDirective(const OMPTaskDirective *S) { VisitOMPExecutableDirective(S); } +void StmtProfiler::VisitOMPTaskyieldDirective(const OMPTaskyieldDirective *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 7e00b7a..543bdb3 100644 --- a/clang/lib/Basic/OpenMPKinds.cpp +++ b/clang/lib/Basic/OpenMPKinds.cpp @@ -257,6 +257,7 @@ bool clang::isAllowedClauseForDirective(OpenMPDirectiveKind DKind, case OMPD_threadprivate: case OMPD_section: case OMPD_master: + case OMPD_taskyield: break; } return false; diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp index 788fd06..3a8e71c 100644 --- a/clang/lib/CodeGen/CGStmt.cpp +++ b/clang/lib/CodeGen/CGStmt.cpp @@ -206,6 +206,9 @@ void CodeGenFunction::EmitStmt(const Stmt *S) { case Stmt::OMPTaskDirectiveClass: EmitOMPTaskDirective(cast(*S)); break; + case Stmt::OMPTaskyieldDirectiveClass: + EmitOMPTaskyieldDirective(cast(*S)); + break; } } diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp index f086146..fbf5274 100644 --- a/clang/lib/CodeGen/CGStmtOpenMP.cpp +++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp @@ -108,3 +108,7 @@ void CodeGenFunction::EmitOMPTaskDirective(const OMPTaskDirective &) { llvm_unreachable("CodeGen for 'omp task' is not supported yet."); } +void CodeGenFunction::EmitOMPTaskyieldDirective(const OMPTaskyieldDirective &) { + llvm_unreachable("CodeGen for 'omp taskyield' is not supported yet."); +} + diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index f7a9168..3dc30d3 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -1931,6 +1931,7 @@ public: void EmitOMPParallelForDirective(const OMPParallelForDirective &S); void EmitOMPParallelSectionsDirective(const OMPParallelSectionsDirective &S); void EmitOMPTaskDirective(const OMPTaskDirective &S); + void EmitOMPTaskyieldDirective(const OMPTaskyieldDirective &S); //===--------------------------------------------------------------------===// // LValue Expression Emission diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp index cfe1602..06fe1ad 100644 --- a/clang/lib/Parse/ParseOpenMP.cpp +++ b/clang/lib/Parse/ParseOpenMP.cpp @@ -83,6 +83,7 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirective() { case OMPD_parallel: case OMPD_simd: case OMPD_task: + case OMPD_taskyield: case OMPD_for: case OMPD_sections: case OMPD_section: @@ -107,9 +108,11 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirective() { /// executable-directive: /// annot_pragma_openmp 'parallel' | 'simd' | 'for' | 'sections' | /// 'section' | 'single' | 'master' | 'parallel for' | -/// 'parallel sections' | 'task' {clause} annot_pragma_openmp_end +/// 'parallel sections' | 'task' | 'taskyield' {clause} +/// annot_pragma_openmp_end /// -StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective() { +StmtResult +Parser::ParseOpenMPDeclarativeOrExecutableDirective(bool StandAloneAllowed) { assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!"); ParenBraceBracketBalancer BalancerRAIIObj(*this); SmallVector Identifiers; @@ -123,6 +126,7 @@ StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective() { // Name of critical directive. DeclarationNameInfo DirName; StmtResult Directive = StmtError(); + bool HasAssociatedStatement = true; switch (DKind) { case OMPD_threadprivate: @@ -141,6 +145,12 @@ StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective() { } SkipUntil(tok::annot_pragma_openmp_end); break; + case OMPD_taskyield: + if (!StandAloneAllowed) { + Diag(Tok, diag::err_omp_immediate_directive) + << getOpenMPDirectiveName(DKind); + } + HasAssociatedStatement = false; case OMPD_parallel: case OMPD_simd: case OMPD_for: @@ -183,7 +193,7 @@ StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective() { StmtResult AssociatedStmt; bool CreateDirective = true; - { + if (HasAssociatedStatement) { // The body is a block scope like in Lambdas and Blocks. Sema::CompoundScopeRAII CompoundScope(Actions); Actions.ActOnOpenMPRegionStart(DKind, getCurScope()); diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp index d29da83..01abf5f 100644 --- a/clang/lib/Parse/ParseStmt.cpp +++ b/clang/lib/Parse/ParseStmt.cpp @@ -345,7 +345,7 @@ Retry: case tok::annot_pragma_openmp: ProhibitAttributes(Attrs); - return ParseOpenMPDeclarativeOrExecutableDirective(); + return ParseOpenMPDeclarativeOrExecutableDirective(!OnlyStatement); case tok::annot_pragma_ms_pointers_to_members: ProhibitAttributes(Attrs); diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index 9f63dbb..67f9eb9 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -1036,6 +1036,14 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) { Params); break; } + case OMPD_taskyield: { + 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: @@ -1060,6 +1068,7 @@ bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | parallel | parallel for | * | // | parallel |parallel sections| * | // | parallel | task | * | + // | parallel | taskyield | * | // +------------------+-----------------+------------------------------------+ // | for | parallel | * | // | for | for | + | @@ -1071,6 +1080,7 @@ bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | for | parallel for | * | // | for |parallel sections| * | // | for | task | * | + // | for | taskyield | * | // +------------------+-----------------+------------------------------------+ // | master | parallel | * | // | master | for | + | @@ -1082,6 +1092,7 @@ bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | master | parallel for | * | // | master |parallel sections| * | // | master | task | * | + // | master | taskyield | * | // +------------------+-----------------+------------------------------------+ // | simd | parallel | | // | simd | for | | @@ -1093,6 +1104,7 @@ bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | simd | parallel for | | // | simd |parallel sections| | // | simd | task | | + // | simd | taskyield | | // +------------------+-----------------+------------------------------------+ // | sections | parallel | * | // | sections | for | + | @@ -1104,6 +1116,7 @@ bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | sections | parallel for | * | // | sections |parallel sections| * | // | sections | task | * | + // | sections | taskyield | * | // +------------------+-----------------+------------------------------------+ // | section | parallel | * | // | section | for | + | @@ -1115,6 +1128,7 @@ bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | section | parallel for | * | // | section |parallel sections| * | // | section | task | * | + // | section | taskyield | * | // +------------------+-----------------+------------------------------------+ // | single | parallel | * | // | single | for | + | @@ -1126,6 +1140,7 @@ bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | single | parallel for | * | // | single |parallel sections| * | // | single | task | * | + // | single | taskyield | * | // +------------------+-----------------+------------------------------------+ // | parallel for | parallel | * | // | parallel for | for | + | @@ -1137,6 +1152,7 @@ bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | parallel for | parallel for | * | // | parallel for |parallel sections| * | // | parallel for | task | * | + // | parallel for | taskyield | * | // +------------------+-----------------+------------------------------------+ // | parallel sections| parallel | * | // | parallel sections| for | + | @@ -1148,6 +1164,7 @@ bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | parallel sections| parallel for | * | // | parallel sections|parallel sections| * | // | parallel sections| task | * | + // | parallel sections| taskyield | * | // +------------------+-----------------+------------------------------------+ // | task | parallel | * | // | task | for | + | @@ -1159,6 +1176,7 @@ bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | task | parallel for | * | // | task |parallel sections| * | // | task | task | * | + // | task | taskyield | * | // +------------------+-----------------+------------------------------------+ if (Stack->getCurScope()) { auto ParentRegion = Stack->getParentDirective(); @@ -1219,32 +1237,35 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(OpenMPDirectiveKind Kind, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc) { - assert(AStmt && isa(AStmt) && "Captured statement expected"); - StmtResult Res = StmtError(); if (CheckNestingOfRegions(*this, DSAStack, Kind, StartLoc)) return StmtError(); - // Check default data sharing attributes for referenced variables. - DSAAttrChecker DSAChecker(DSAStack, *this, cast(AStmt)); - DSAChecker.Visit(cast(AStmt)->getCapturedStmt()); - if (DSAChecker.isErrorFound()) - return StmtError(); - // Generate list of implicitly defined firstprivate variables. - auto &VarsWithInheritedDSA = DSAChecker.getVarsWithInheritedDSA(); llvm::SmallVector ClausesWithImplicit; - ClausesWithImplicit.append(Clauses.begin(), Clauses.end()); - + llvm::DenseMap VarsWithInheritedDSA; bool ErrorFound = false; - if (!DSAChecker.getImplicitFirstprivate().empty()) { - if (OMPClause *Implicit = ActOnOpenMPFirstprivateClause( - DSAChecker.getImplicitFirstprivate(), SourceLocation(), - SourceLocation(), SourceLocation())) { - ClausesWithImplicit.push_back(Implicit); - ErrorFound = cast(Implicit)->varlist_size() != - DSAChecker.getImplicitFirstprivate().size(); - } else - ErrorFound = true; + if (AStmt) { + assert(isa(AStmt) && "Captured statement expected"); + + // Check default data sharing attributes for referenced variables. + DSAAttrChecker DSAChecker(DSAStack, *this, cast(AStmt)); + DSAChecker.Visit(cast(AStmt)->getCapturedStmt()); + if (DSAChecker.isErrorFound()) + return StmtError(); + // Generate list of implicitly defined firstprivate variables. + VarsWithInheritedDSA = DSAChecker.getVarsWithInheritedDSA(); + ClausesWithImplicit.append(Clauses.begin(), Clauses.end()); + + if (!DSAChecker.getImplicitFirstprivate().empty()) { + if (OMPClause *Implicit = ActOnOpenMPFirstprivateClause( + DSAChecker.getImplicitFirstprivate(), SourceLocation(), + SourceLocation(), SourceLocation())) { + ClausesWithImplicit.push_back(Implicit); + ErrorFound = cast(Implicit)->varlist_size() != + DSAChecker.getImplicitFirstprivate().size(); + } else + ErrorFound = true; + } } switch (Kind) { @@ -1290,6 +1311,13 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(OpenMPDirectiveKind Kind, Res = ActOnOpenMPTaskDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc); break; + case OMPD_taskyield: + assert(ClausesWithImplicit.empty() && + "No clauses are allowed for 'omp taskyield' directive"); + assert(AStmt == nullptr && + "No associated statement allowed for 'omp taskyield' directive"); + Res = ActOnOpenMPTaskyieldDirective(StartLoc, EndLoc); + break; case OMPD_threadprivate: llvm_unreachable("OpenMP Directive is not allowed"); case OMPD_unknown: @@ -2033,6 +2061,11 @@ StmtResult Sema::ActOnOpenMPTaskDirective(ArrayRef Clauses, return OMPTaskDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt); } +StmtResult Sema::ActOnOpenMPTaskyieldDirective(SourceLocation StartLoc, + SourceLocation EndLoc) { + return OMPTaskyieldDirective::Create(Context, StartLoc, EndLoc); +} + OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr, SourceLocation StartLoc, SourceLocation LParenLoc, diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 0f1d24c..741abb9 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -6428,12 +6428,17 @@ StmtResult TreeTransform::TransformOMPExecutableDirective( TClauses.push_back(nullptr); } } - if (!D->getAssociatedStmt()) { - return StmtError(); + StmtResult AssociatedStmt; + if (D->hasAssociatedStmt()) { + if (!D->getAssociatedStmt()) { + return StmtError(); + } + AssociatedStmt = getDerived().TransformStmt(D->getAssociatedStmt()); + if (AssociatedStmt.isInvalid()) { + return StmtError(); + } } - StmtResult AssociatedStmt = - getDerived().TransformStmt(D->getAssociatedStmt()); - if (AssociatedStmt.isInvalid() || TClauses.size() != Clauses.size()) { + if (TClauses.size() != Clauses.size()) { return StmtError(); } @@ -6552,6 +6557,17 @@ TreeTransform::TransformOMPTaskDirective(OMPTaskDirective *D) { return Res; } +template +StmtResult TreeTransform::TransformOMPTaskyieldDirective( + OMPTaskyieldDirective *D) { + DeclarationNameInfo DirName; + getDerived().getSema().StartOpenMPDSABlock(OMPD_taskyield, 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 c89c939..c9ecebb 100644 --- a/clang/lib/Serialization/ASTReaderStmt.cpp +++ b/clang/lib/Serialization/ASTReaderStmt.cpp @@ -1919,7 +1919,8 @@ void ASTStmtReader::VisitOMPExecutableDirective(OMPExecutableDirective *E) { for (unsigned i = 0; i < E->getNumClauses(); ++i) Clauses.push_back(ClauseReader.readClause()); E->setClauses(Clauses); - E->setAssociatedStmt(Reader.ReadSubStmt()); + if (E->hasAssociatedStmt()) + E->setAssociatedStmt(Reader.ReadSubStmt()); } void ASTStmtReader::VisitOMPParallelDirective(OMPParallelDirective *D) { @@ -1989,6 +1990,11 @@ void ASTStmtReader::VisitOMPTaskDirective(OMPTaskDirective *D) { VisitOMPExecutableDirective(D); } +void ASTStmtReader::VisitOMPTaskyieldDirective(OMPTaskyieldDirective *D) { + VisitStmt(D); + VisitOMPExecutableDirective(D); +} + //===----------------------------------------------------------------------===// // ASTReader Implementation //===----------------------------------------------------------------------===// @@ -2523,6 +2529,10 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { Context, Record[ASTStmtReader::NumStmtFields], Empty); break; + case STMT_OMP_TASKYIELD_DIRECTIVE: + S = OMPTaskyieldDirective::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 38bcdbe..4ea0fd7 100644 --- a/clang/lib/Serialization/ASTWriterStmt.cpp +++ b/clang/lib/Serialization/ASTWriterStmt.cpp @@ -1815,7 +1815,8 @@ void ASTStmtWriter::VisitOMPExecutableDirective(OMPExecutableDirective *E) { for (unsigned i = 0; i < E->getNumClauses(); ++i) { ClauseWriter.writeClause(E->getClause(i)); } - Writer.AddStmt(E->getAssociatedStmt()); + if (E->hasAssociatedStmt()) + Writer.AddStmt(E->getAssociatedStmt()); } void ASTStmtWriter::VisitOMPParallelDirective(OMPParallelDirective *D) { @@ -1890,6 +1891,12 @@ void ASTStmtWriter::VisitOMPTaskDirective(OMPTaskDirective *D) { Code = serialization::STMT_OMP_TASK_DIRECTIVE; } +void ASTStmtWriter::VisitOMPTaskyieldDirective(OMPTaskyieldDirective *D) { + VisitStmt(D); + VisitOMPExecutableDirective(D); + Code = serialization::STMT_OMP_TASKYIELD_DIRECTIVE; +} + //===----------------------------------------------------------------------===// // ASTWriter Implementation //===----------------------------------------------------------------------===// diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp index 58b3357..b91f8e6 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -741,6 +741,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred, case Stmt::OMPParallelForDirectiveClass: case Stmt::OMPParallelSectionsDirectiveClass: case Stmt::OMPTaskDirectiveClass: + case Stmt::OMPTaskyieldDirectiveClass: 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 d61ac3f..84f3936 100644 --- a/clang/test/OpenMP/nesting_of_regions.cpp +++ b/clang/test/OpenMP/nesting_of_regions.cpp @@ -46,6 +46,11 @@ void foo() { { bar(); } +#pragma omp parallel + { +#pragma omp taskyield + bar(); + } // SIMD DIRECTIVE #pragma omp simd @@ -114,6 +119,11 @@ void foo() { bar(); } } +#pragma omp simd + for (int i = 0; i < 10; ++i) { +#pragma omp taskyield // expected-error {{OpenMP constructs may not be nested inside a simd region}} + bar(); + } // FOR DIRECTIVE #pragma omp for @@ -201,6 +211,11 @@ void foo() { bar(); } } +#pragma omp for + for (int i = 0; i < 10; ++i) { +#pragma omp taskyield + bar(); + } // SECTIONS DIRECTIVE #pragma omp sections @@ -291,6 +306,10 @@ void foo() { bar(); } } +#pragma omp sections + { +#pragma omp taskyield + } // SECTION DIRECTIVE #pragma omp section // expected-error {{orphaned 'omp section' directives are prohibited, it must be closely nested to a sections region}} @@ -403,6 +422,14 @@ void foo() { } } } +#pragma omp sections + { +#pragma omp section + { +#pragma omp taskyield + bar(); + } + } // SINGLE DIRECTIVE #pragma omp single @@ -481,6 +508,11 @@ void foo() { bar(); } } +#pragma omp single + { +#pragma omp taskyield + bar(); + } // MASTER DIRECTIVE #pragma omp master @@ -559,6 +591,11 @@ void foo() { bar(); } } +#pragma omp master + { +#pragma omp taskyield + bar(); + } // PARALLEL FOR DIRECTIVE #pragma omp parallel for @@ -646,6 +683,11 @@ void foo() { bar(); } } +#pragma omp parallel for + for (int i = 0; i < 10; ++i) { +#pragma omp taskyield + bar(); + } // PARALLEL SECTIONS DIRECTIVE #pragma omp parallel sections @@ -733,6 +775,10 @@ void foo() { bar(); } } +#pragma omp parallel sections + { +#pragma omp taskyield + } // TASK DIRECTIVE #pragma omp task @@ -773,7 +819,11 @@ void foo() { { bar(); } - +#pragma omp task + { +#pragma omp taskyield + bar(); + } } void foo() { @@ -821,6 +871,11 @@ void foo() { { bar(); } +#pragma omp parallel + { +#pragma omp taskyield + bar(); + } // SIMD DIRECTIVE #pragma omp simd @@ -882,6 +937,11 @@ void foo() { bar(); } } +#pragma omp simd + for (int i = 0; i < 10; ++i) { +#pragma omp taskyield // expected-error {{OpenMP constructs may not be nested inside a simd region}} + bar(); + } // FOR DIRECTIVE #pragma omp for @@ -960,6 +1020,11 @@ void foo() { bar(); } } +#pragma omp for + for (int i = 0; i < 10; ++i) { +#pragma omp taskyield + bar(); + } // SECTIONS DIRECTIVE #pragma omp sections @@ -1038,6 +1103,11 @@ void foo() { bar(); } } +#pragma omp sections + { +#pragma omp task + bar(); + } // SECTION DIRECTIVE #pragma omp section // expected-error {{orphaned 'omp section' directives are prohibited, it must be closely nested to a sections region}} @@ -1150,6 +1220,14 @@ void foo() { } } } +#pragma omp sections + { +#pragma omp section + { +#pragma omp taskyield + bar(); + } + } // SINGLE DIRECTIVE #pragma omp single @@ -1223,6 +1301,11 @@ void foo() { bar(); } } +#pragma omp single + { +#pragma omp taskyield + bar(); + } // MASTER DIRECTIVE #pragma omp master @@ -1301,6 +1384,11 @@ void foo() { bar(); } } +#pragma omp master + { +#pragma omp taskyield + bar(); + } // PARALLEL FOR DIRECTIVE #pragma omp parallel for @@ -1387,6 +1475,11 @@ void foo() { bar(); } } +#pragma omp parallel for + for (int i = 0; i < 10; ++i) { +#pragma omp taskyield + bar(); + } // PARALLEL SECTIONS DIRECTIVE #pragma omp parallel sections @@ -1472,6 +1565,10 @@ void foo() { bar(); } } +#pragma omp parallel sections + { +#pragma omp taskyield + } // TASK DIRECTIVE #pragma omp task @@ -1512,6 +1609,11 @@ void foo() { { bar(); } +#pragma omp task + { +#pragma omp taskyield + bar(); + } return foo(); } diff --git a/clang/test/OpenMP/taskyield_ast_print.cpp b/clang/test/OpenMP/taskyield_ast_print.cpp new file mode 100644 index 0000000..4c3ca47 --- /dev/null +++ b/clang/test/OpenMP/taskyield_ast_print.cpp @@ -0,0 +1,32 @@ +// 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) { + static T a; +#pragma omp taskyield + return a + argc; +} +// CHECK: static int a; +// CHECK-NEXT: #pragma omp taskyield +// CHECK: static char a; +// CHECK-NEXT: #pragma omp taskyield +// CHECK: static T a; +// CHECK-NEXT: #pragma omp taskyield + +int main(int argc, char **argv) { + static int a; +// CHECK: static int a; +#pragma omp taskyield + // CHECK-NEXT: #pragma omp taskyield + return tmain(argc) + tmain(argv[0][0]) + a; +} + +#endif diff --git a/clang/test/OpenMP/taskyield_messages.cpp b/clang/test/OpenMP/taskyield_messages.cpp new file mode 100644 index 0000000..7c35559 --- /dev/null +++ b/clang/test/OpenMP/taskyield_messages.cpp @@ -0,0 +1,110 @@ +// RUN: %clang_cc1 -verify -fopenmp=libiomp5 -ferror-limit 100 %s + +template +T tmain(T argc) { +#pragma omp taskyield + ; +#pragma omp taskyield untied // expected-error {{unexpected OpenMP clause 'untied' in directive '#pragma omp taskyield'}} +#pragma omp taskyield unknown // expected-warning {{extra tokens at the end of '#pragma omp taskyield' are ignored}} + if (argc) +#pragma omp taskyield // expected-error {{'#pragma omp taskyield' cannot be an immediate substatement}} + if (argc) { +#pragma omp taskyield + } + while (argc) +#pragma omp taskyield // expected-error {{'#pragma omp taskyield' cannot be an immediate substatement}} + while (argc) { +#pragma omp taskyield + } + do +#pragma omp taskyield // expected-error {{'#pragma omp taskyield' cannot be an immediate substatement}} + while (argc) + ; + do { +#pragma omp taskyield + } while (argc); + switch (argc) +#pragma omp taskyield // expected-error {{'#pragma omp taskyield' cannot be an immediate substatement}} + switch (argc) + case 1: +#pragma omp taskyield // expected-error {{'#pragma omp taskyield' cannot be an immediate substatement}} + switch (argc) + case 1: { +#pragma omp taskyield + } + switch (argc) { +#pragma omp taskyield + case 1: +#pragma omp taskyield // expected-error {{'#pragma omp taskyield' cannot be an immediate substatement}} + break; + default: { +#pragma omp taskyield + } break; + } + for (;;) +#pragma omp taskyield // expected-error {{'#pragma omp taskyield' cannot be an immediate substatement}} + for (;;) { +#pragma omp taskyield + } +label: +#pragma omp taskyield // expected-error {{'#pragma omp taskyield' cannot be an immediate substatement}} +label1 : { +#pragma omp taskyield +} + + return T(); +} + +int main(int argc, char **argv) { +#pragma omp taskyield + ; +#pragma omp taskyield untied // expected-error {{unexpected OpenMP clause 'untied' in directive '#pragma omp taskyield'}} +#pragma omp taskyield unknown // expected-warning {{extra tokens at the end of '#pragma omp taskyield' are ignored}} + if (argc) +#pragma omp taskyield // expected-error {{'#pragma omp taskyield' cannot be an immediate substatement}} + if (argc) { +#pragma omp taskyield + } + while (argc) +#pragma omp taskyield // expected-error {{'#pragma omp taskyield' cannot be an immediate substatement}} + while (argc) { +#pragma omp taskyield + } + do +#pragma omp taskyield // expected-error {{'#pragma omp taskyield' cannot be an immediate substatement}} + while (argc) + ; + do { +#pragma omp taskyield + } while (argc); + switch (argc) +#pragma omp taskyield // expected-error {{'#pragma omp taskyield' cannot be an immediate substatement}} + switch (argc) + case 1: +#pragma omp taskyield // expected-error {{'#pragma omp taskyield' cannot be an immediate substatement}} + switch (argc) + case 1: { +#pragma omp taskyield + } + switch (argc) { +#pragma omp taskyield + case 1: +#pragma omp taskyield // expected-error {{'#pragma omp taskyield' cannot be an immediate substatement}} + break; + default: { +#pragma omp taskyield + } break; + } + for (;;) +#pragma omp taskyield // expected-error {{'#pragma omp taskyield' cannot be an immediate substatement}} + for (;;) { +#pragma omp taskyield + } +label: +#pragma omp taskyield // expected-error {{'#pragma omp taskyield' cannot be an immediate substatement}} +label1 : { +#pragma omp taskyield +} + + return tmain(argc); +} diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp index 54b6db2..b22d925 100644 --- a/clang/tools/libclang/CIndex.cpp +++ b/clang/tools/libclang/CIndex.cpp @@ -1864,6 +1864,7 @@ public: void VisitOMPParallelForDirective(const OMPParallelForDirective *D); void VisitOMPParallelSectionsDirective(const OMPParallelSectionsDirective *D); void VisitOMPTaskDirective(const OMPTaskDirective *D); + void VisitOMPTaskyieldDirective(const OMPTaskyieldDirective *D); private: void AddDeclarationNameInfo(const Stmt *S); @@ -2341,6 +2342,11 @@ void EnqueueVisitor::VisitOMPTaskDirective(const OMPTaskDirective *D) { VisitOMPExecutableDirective(D); } +void +EnqueueVisitor::VisitOMPTaskyieldDirective(const OMPTaskyieldDirective *D) { + VisitOMPExecutableDirective(D); +} + void CursorVisitor::EnqueueWorkList(VisitorWorkList &WL, const Stmt *S) { EnqueueVisitor(WL, MakeCXCursor(S, StmtParent, TU,RegionOfInterest)).Visit(S); } @@ -4033,6 +4039,8 @@ CXString clang_getCursorKindSpelling(enum CXCursorKind Kind) { return cxstring::createRef("OMPParallelSectionsDirective"); case CXCursor_OMPTaskDirective: return cxstring::createRef("OMPTaskDirective"); + case CXCursor_OMPTaskyieldDirective: + return cxstring::createRef("OMPTaskyieldDirective"); } llvm_unreachable("Unhandled CXCursorKind"); diff --git a/clang/tools/libclang/CXCursor.cpp b/clang/tools/libclang/CXCursor.cpp index e50a156a..f96e17f 100644 --- a/clang/tools/libclang/CXCursor.cpp +++ b/clang/tools/libclang/CXCursor.cpp @@ -547,6 +547,9 @@ CXCursor cxcursor::MakeCXCursor(const Stmt *S, const Decl *Parent, case Stmt::OMPTaskDirectiveClass: K = CXCursor_OMPTaskDirective; break; + case Stmt::OMPTaskyieldDirectiveClass: + K = CXCursor_OMPTaskyieldDirective; + break; } CXCursor C = { K, 0, { Parent, S, TU } };