diff options
author | Alexey Bataev <a.bataev@hotmail.com> | 2015-07-02 11:25:17 +0000 |
---|---|---|
committer | Alexey Bataev <a.bataev@hotmail.com> | 2015-07-02 11:25:17 +0000 |
commit | 80909878adc79d9f1277373af175041718f05953 (patch) | |
tree | c673079a9bf2cc7e6d7635625bdb1691e162686b /clang | |
parent | 3937bc650cad69cbd607ca3ea64ea6623808fc19 (diff) | |
download | bcm5719-llvm-80909878adc79d9f1277373af175041718f05953.tar.gz bcm5719-llvm-80909878adc79d9f1277373af175041718f05953.zip |
[OPENMP 4.0] Initial support for 'omp cancel' construct.
Implemented parsing/sema analysis + (de)serialization.
llvm-svn: 241253
Diffstat (limited to 'clang')
25 files changed, 342 insertions, 5 deletions
diff --git a/clang/include/clang-c/Index.h b/clang/include/clang-c/Index.h index 5a2e0882749..fad9cfa61b3 100644 --- a/clang/include/clang-c/Index.h +++ b/clang/include/clang-c/Index.h @@ -2233,7 +2233,11 @@ enum CXCursorKind { */ CXCursor_OMPCancellationPointDirective = 255, - CXCursor_LastStmt = CXCursor_OMPCancellationPointDirective, + /** \brief OpenMP cancel directive. + */ + CXCursor_OMPCancelDirective = 256, + + CXCursor_LastStmt = CXCursor_OMPCancelDirective, /** * \brief Cursor that represents the translation unit itself. diff --git a/clang/include/clang/AST/DataRecursiveASTVisitor.h b/clang/include/clang/AST/DataRecursiveASTVisitor.h index 7a4ebf062fe..e4c3e8fb323 100644 --- a/clang/include/clang/AST/DataRecursiveASTVisitor.h +++ b/clang/include/clang/AST/DataRecursiveASTVisitor.h @@ -2361,6 +2361,9 @@ DEF_TRAVERSE_STMT(OMPTaskgroupDirective, DEF_TRAVERSE_STMT(OMPCancellationPointDirective, { TRY_TO(TraverseOMPExecutableDirective(S)); }) +DEF_TRAVERSE_STMT(OMPCancelDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + DEF_TRAVERSE_STMT(OMPFlushDirective, { TRY_TO(TraverseOMPExecutableDirective(S)); }) diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h index 1fe5b553429..a99587b5a89 100644 --- a/clang/include/clang/AST/RecursiveASTVisitor.h +++ b/clang/include/clang/AST/RecursiveASTVisitor.h @@ -2394,6 +2394,9 @@ DEF_TRAVERSE_STMT(OMPTaskgroupDirective, DEF_TRAVERSE_STMT(OMPCancellationPointDirective, { TRY_TO(TraverseOMPExecutableDirective(S)); }) +DEF_TRAVERSE_STMT(OMPCancelDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + DEF_TRAVERSE_STMT(OMPFlushDirective, { TRY_TO(TraverseOMPExecutableDirective(S)); }) diff --git a/clang/include/clang/AST/StmtOpenMP.h b/clang/include/clang/AST/StmtOpenMP.h index 8c8985dabf1..b412daaf285 100644 --- a/clang/include/clang/AST/StmtOpenMP.h +++ b/clang/include/clang/AST/StmtOpenMP.h @@ -1914,6 +1914,63 @@ public: } }; +/// \brief This represents '#pragma omp cancel' directive. +/// +/// \code +/// #pragma omp cancel for +/// \endcode +/// +/// In this example a cancel is created for innermost 'for' region. +class OMPCancelDirective : public OMPExecutableDirective { + friend class ASTStmtReader; + OpenMPDirectiveKind CancelRegion; + /// \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. + /// + OMPCancelDirective(SourceLocation StartLoc, SourceLocation EndLoc) + : OMPExecutableDirective(this, OMPCancelDirectiveClass, OMPD_cancel, + StartLoc, EndLoc, 0, 0), + CancelRegion(OMPD_unknown) {} + + /// \brief Build an empty directive. + /// + explicit OMPCancelDirective() + : OMPExecutableDirective(this, OMPCancelDirectiveClass, OMPD_cancel, + SourceLocation(), SourceLocation(), 0, 0), + CancelRegion(OMPD_unknown) {} + + /// \brief Set cancel region for current cancellation point. + /// \param CR Cancellation region. + void setCancelRegion(OpenMPDirectiveKind CR) { CancelRegion = CR; } + +public: + /// \brief Creates directive. + /// + /// \param C AST context. + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending Location of the directive. + /// + static OMPCancelDirective *Create(const ASTContext &C, + SourceLocation StartLoc, + SourceLocation EndLoc, + OpenMPDirectiveKind CancelRegion); + + /// \brief Creates an empty directive. + /// + /// \param C AST context. + /// + static OMPCancelDirective *CreateEmpty(const ASTContext &C, EmptyShell); + + /// \brief Get cancellation region for the current cancellation point. + OpenMPDirectiveKind getCancelRegion() const { return CancelRegion; } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == OMPCancelDirectiveClass; + } +}; + } // end namespace clang #endif diff --git a/clang/include/clang/Basic/OpenMPKinds.def b/clang/include/clang/Basic/OpenMPKinds.def index 892c992b09e..67a5068cc2c 100644 --- a/clang/include/clang/Basic/OpenMPKinds.def +++ b/clang/include/clang/Basic/OpenMPKinds.def @@ -93,6 +93,7 @@ OPENMP_DIRECTIVE(ordered) OPENMP_DIRECTIVE(atomic) OPENMP_DIRECTIVE(target) OPENMP_DIRECTIVE(teams) +OPENMP_DIRECTIVE(cancel) OPENMP_DIRECTIVE_EXT(parallel_for, "parallel for") OPENMP_DIRECTIVE_EXT(parallel_for_simd, "parallel for simd") OPENMP_DIRECTIVE_EXT(parallel_sections, "parallel sections") diff --git a/clang/include/clang/Basic/StmtNodes.td b/clang/include/clang/Basic/StmtNodes.td index 79f5463d796..9d7b6fb0cbe 100644 --- a/clang/include/clang/Basic/StmtNodes.td +++ b/clang/include/clang/Basic/StmtNodes.td @@ -206,3 +206,4 @@ def OMPAtomicDirective : DStmt<OMPExecutableDirective>; def OMPTargetDirective : DStmt<OMPExecutableDirective>; def OMPTeamsDirective : DStmt<OMPExecutableDirective>; def OMPCancellationPointDirective : DStmt<OMPExecutableDirective>; +def OMPCancelDirective : DStmt<OMPExecutableDirective>; diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 07a47484cdf..72a0e0b19e3 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -7778,6 +7778,10 @@ public: ActOnOpenMPCancellationPointDirective(SourceLocation StartLoc, SourceLocation EndLoc, OpenMPDirectiveKind CancelRegion); + /// \brief Called on well-formed '\#pragma omp cancel'. + StmtResult ActOnOpenMPCancelDirective(SourceLocation StartLoc, + SourceLocation EndLoc, + OpenMPDirectiveKind CancelRegion); OMPClause *ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr, diff --git a/clang/include/clang/Serialization/ASTBitCodes.h b/clang/include/clang/Serialization/ASTBitCodes.h index 781c80ef643..ee8e3f4c671 100644 --- a/clang/include/clang/Serialization/ASTBitCodes.h +++ b/clang/include/clang/Serialization/ASTBitCodes.h @@ -1398,6 +1398,7 @@ namespace clang { STMT_OMP_TEAMS_DIRECTIVE, STMT_OMP_TASKGROUP_DIRECTIVE, STMT_OMP_CANCELLATION_POINT_DIRECTIVE, + STMT_OMP_CANCEL_DIRECTIVE, // ARC EXPR_OBJC_BRIDGED_CAST, // ObjCBridgedCastExpr diff --git a/clang/lib/AST/Stmt.cpp b/clang/lib/AST/Stmt.cpp index 911ec5e30ef..c0aab4c4db7 100644 --- a/clang/lib/AST/Stmt.cpp +++ b/clang/lib/AST/Stmt.cpp @@ -2106,6 +2106,26 @@ OMPCancellationPointDirective::CreateEmpty(const ASTContext &C, EmptyShell) { return new (Mem) OMPCancellationPointDirective(); } +OMPCancelDirective * +OMPCancelDirective::Create(const ASTContext &C, SourceLocation StartLoc, + SourceLocation EndLoc, + OpenMPDirectiveKind CancelRegion) { + unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPCancelDirective), + llvm::alignOf<Stmt *>()); + void *Mem = C.Allocate(Size); + OMPCancelDirective *Dir = new (Mem) OMPCancelDirective(StartLoc, EndLoc); + Dir->setCancelRegion(CancelRegion); + return Dir; +} + +OMPCancelDirective *OMPCancelDirective::CreateEmpty(const ASTContext &C, + EmptyShell) { + unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPCancelDirective), + llvm::alignOf<Stmt *>()); + void *Mem = C.Allocate(Size); + return new (Mem) OMPCancelDirective(); +} + OMPFlushDirective *OMPFlushDirective::Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp index 26019fd530d..79600773f56 100644 --- a/clang/lib/AST/StmtPrinter.cpp +++ b/clang/lib/AST/StmtPrinter.cpp @@ -957,6 +957,12 @@ void StmtPrinter::VisitOMPCancellationPointDirective( << getOpenMPDirectiveName(Node->getCancelRegion()); PrintOMPExecutableDirective(Node); } + +void StmtPrinter::VisitOMPCancelDirective(OMPCancelDirective *Node) { + Indent() << "#pragma omp cancel " + << getOpenMPDirectiveName(Node->getCancelRegion()); + PrintOMPExecutableDirective(Node); +} //===----------------------------------------------------------------------===// // Expr printing methods. //===----------------------------------------------------------------------===// diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp index 7d1d48be791..63f432ca4c3 100644 --- a/clang/lib/AST/StmtProfile.cpp +++ b/clang/lib/AST/StmtProfile.cpp @@ -542,6 +542,10 @@ void StmtProfiler::VisitOMPCancellationPointDirective( VisitOMPExecutableDirective(S); } +void StmtProfiler::VisitOMPCancelDirective(const OMPCancelDirective *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 0e9d0c0d5fc..b7407f60e6d 100644 --- a/clang/lib/Basic/OpenMPKinds.cpp +++ b/clang/lib/Basic/OpenMPKinds.cpp @@ -348,6 +348,7 @@ bool clang::isAllowedClauseForDirective(OpenMPDirectiveKind DKind, case OMPD_taskwait: case OMPD_taskgroup: case OMPD_cancellation_point: + case OMPD_cancel: case OMPD_ordered: break; } diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp index 81b115c34b5..a12f29534bf 100644 --- a/clang/lib/CodeGen/CGStmt.cpp +++ b/clang/lib/CodeGen/CGStmt.cpp @@ -243,6 +243,9 @@ void CodeGenFunction::EmitStmt(const Stmt *S) { case Stmt::OMPCancellationPointDirectiveClass: EmitOMPCancellationPointDirective(cast<OMPCancellationPointDirective>(*S)); break; + case Stmt::OMPCancelDirectiveClass: + EmitOMPCancelDirective(cast<OMPCancelDirective>(*S)); + break; } } diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp index 655fae11a2e..b297e2d10cb 100644 --- a/clang/lib/CodeGen/CGStmtOpenMP.cpp +++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp @@ -2112,3 +2112,7 @@ void CodeGenFunction::EmitOMPCancellationPointDirective( S.getCancelRegion()); } +void CodeGenFunction::EmitOMPCancelDirective(const OMPCancelDirective &S) { + llvm_unreachable("CodeGen for 'omp cancel' is not supported yet."); +} + diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 21b33a556a0..cc427c9c889 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -2204,6 +2204,7 @@ public: void EmitOMPTeamsDirective(const OMPTeamsDirective &S); void EmitOMPCancellationPointDirective(const OMPCancellationPointDirective &S); + void EmitOMPCancelDirective(const OMPCancelDirective &S); /// \brief Emit inner loop of the worksharing/simd construct. /// diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp index b1d8f2fd319..0113a3157c2 100644 --- a/clang/lib/Parse/ParseOpenMP.cpp +++ b/clang/lib/Parse/ParseOpenMP.cpp @@ -126,6 +126,7 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirective() { case OMPD_target: case OMPD_teams: case OMPD_cancellation_point: + case OMPD_cancel: Diag(Tok, diag::err_omp_unexpected_directive) << getOpenMPDirectiveName(DKind); break; @@ -196,6 +197,7 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(bool StandAloneAllowed) { case OMPD_barrier: case OMPD_taskwait: case OMPD_cancellation_point: + case OMPD_cancel: if (!StandAloneAllowed) { Diag(Tok, diag::err_omp_immediate_directive) << getOpenMPDirectiveName(DKind); @@ -235,7 +237,7 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(bool StandAloneAllowed) { } T.consumeClose(); } - } else if (DKind == OMPD_cancellation_point) { + } else if (DKind == OMPD_cancellation_point || DKind == OMPD_cancel) { CancelRegion = ParseOpenMPDirectiveKind(*this); if (Tok.isNot(tok::annot_pragma_openmp_end)) ConsumeToken(); diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index 8d6d01e6eb0..7286301fe6e 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -1325,6 +1325,7 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) { case OMPD_barrier: case OMPD_taskwait: case OMPD_cancellation_point: + case OMPD_cancel: case OMPD_flush: llvm_unreachable("OpenMP Directive is not allowed"); case OMPD_unknown: @@ -1395,6 +1396,7 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | parallel | teams | + | // | parallel | cancellation | | // | | point | ! | + // | parallel | cancel | ! | // +------------------+-----------------+------------------------------------+ // | for | parallel | * | // | for | for | + | @@ -1420,6 +1422,7 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | for | teams | + | // | for | cancellation | | // | | point | ! | + // | for | cancel | ! | // +------------------+-----------------+------------------------------------+ // | master | parallel | * | // | master | for | + | @@ -1445,6 +1448,7 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | master | teams | + | // | master | cancellation | | // | | point | | + // | master | cancel | | // +------------------+-----------------+------------------------------------+ // | critical | parallel | * | // | critical | for | + | @@ -1469,6 +1473,7 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | critical | teams | + | // | critical | cancellation | | // | | point | | + // | critical | cancel | | // +------------------+-----------------+------------------------------------+ // | simd | parallel | | // | simd | for | | @@ -1494,6 +1499,7 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | simd | teams | | // | simd | cancellation | | // | | point | | + // | simd | cancel | | // +------------------+-----------------+------------------------------------+ // | for simd | parallel | | // | for simd | for | | @@ -1519,6 +1525,7 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | for simd | teams | | // | for simd | cancellation | | // | | point | | + // | for simd | cancel | | // +------------------+-----------------+------------------------------------+ // | parallel for simd| parallel | | // | parallel for simd| for | | @@ -1544,6 +1551,7 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | parallel for simd| teams | | // | parallel for simd| cancellation | | // | | point | | + // | parallel for simd| cancel | | // +------------------+-----------------+------------------------------------+ // | sections | parallel | * | // | sections | for | + | @@ -1569,6 +1577,7 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | sections | teams | + | // | sections | cancellation | | // | | point | ! | + // | sections | cancel | ! | // +------------------+-----------------+------------------------------------+ // | section | parallel | * | // | section | for | + | @@ -1594,6 +1603,7 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | section | teams | + | // | section | cancellation | | // | | point | ! | + // | section | cancel | ! | // +------------------+-----------------+------------------------------------+ // | single | parallel | * | // | single | for | + | @@ -1619,6 +1629,7 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | single | teams | + | // | single | cancellation | | // | | point | | + // | single | cancel | | // +------------------+-----------------+------------------------------------+ // | parallel for | parallel | * | // | parallel for | for | + | @@ -1644,6 +1655,7 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | parallel for | teams | + | // | parallel for | cancellation | | // | | point | ! | + // | parallel for | cancel | ! | // +------------------+-----------------+------------------------------------+ // | parallel sections| parallel | * | // | parallel sections| for | + | @@ -1669,6 +1681,7 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | parallel sections| teams | + | // | parallel sections| cancellation | | // | | point | ! | + // | parallel sections| cancel | ! | // +------------------+-----------------+------------------------------------+ // | task | parallel | * | // | task | for | + | @@ -1693,7 +1706,8 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | task | target | * | // | task | teams | + | // | task | cancellation | | - // | | point | ! | + // | | point | ! | + // | task | cancel | ! | // +------------------+-----------------+------------------------------------+ // | ordered | parallel | * | // | ordered | for | + | @@ -1719,6 +1733,7 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | ordered | teams | + | // | ordered | cancellation | | // | | point | | + // | ordered | cancel | | // +------------------+-----------------+------------------------------------+ // | atomic | parallel | | // | atomic | for | | @@ -1744,6 +1759,7 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | atomic | teams | | // | atomic | cancellation | | // | | point | | + // | atomic | cancel | | // +------------------+-----------------+------------------------------------+ // | target | parallel | * | // | target | for | * | @@ -1769,6 +1785,7 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | target | teams | * | // | target | cancellation | | // | | point | | + // | target | cancel | | // +------------------+-----------------+------------------------------------+ // | teams | parallel | * | // | teams | for | + | @@ -1786,7 +1803,7 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | teams | taskyield | + | // | teams | barrier | + | // | teams | taskwait | + | - // | teams | taskgroup | + | + // | teams | taskgroup | + | // | teams | flush | + | // | teams | ordered | + | // | teams | atomic | + | @@ -1794,6 +1811,7 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | teams | teams | + | // | teams | cancellation | | // | | point | | + // | teams | cancel | | // +------------------+-----------------+------------------------------------+ if (Stack->getCurScope()) { auto ParentRegion = Stack->getParentDirective(); @@ -1835,13 +1853,19 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // called from OpenMP regions with the required preconditions). if (ParentRegion == OMPD_unknown) return false; - if (CurrentRegion == OMPD_cancellation_point) { + if (CurrentRegion == OMPD_cancellation_point || + CurrentRegion == OMPD_cancel) { // OpenMP [2.16, Nesting of Regions] // A cancellation point construct for which construct-type-clause is // taskgroup must be nested inside a task construct. A cancellation // point construct for which construct-type-clause is not taskgroup must // be closely nested inside an OpenMP construct that matches the type // specified in construct-type-clause. + // A cancel construct for which construct-type-clause is taskgroup must be + // nested inside a task construct. A cancel construct for which + // construct-type-clause is not taskgroup must be closely nested inside an + // OpenMP construct that matches the type specified in + // construct-type-clause. NestingProhibited = !((CancelRegion == OMPD_parallel && ParentRegion == OMPD_parallel) || (CancelRegion == OMPD_for && ParentRegion == OMPD_for) || @@ -2085,6 +2109,13 @@ StmtResult Sema::ActOnOpenMPExecutableDirective( "cancellation point' directive"); Res = ActOnOpenMPCancellationPointDirective(StartLoc, EndLoc, CancelRegion); break; + case OMPD_cancel: + assert(ClausesWithImplicit.empty() && + "No clauses are allowed for 'omp cancel' directive"); + assert(AStmt == nullptr && + "No associated statement allowed for 'omp cancel' directive"); + Res = ActOnOpenMPCancelDirective(StartLoc, EndLoc, CancelRegion); + break; case OMPD_threadprivate: llvm_unreachable("OpenMP Directive is not allowed"); case OMPD_unknown: @@ -4293,6 +4324,26 @@ Sema::ActOnOpenMPCancellationPointDirective(SourceLocation StartLoc, CancelRegion); } +StmtResult Sema::ActOnOpenMPCancelDirective(SourceLocation StartLoc, + SourceLocation EndLoc, + OpenMPDirectiveKind CancelRegion) { + if (CancelRegion != OMPD_parallel && CancelRegion != OMPD_for && + CancelRegion != OMPD_sections && CancelRegion != OMPD_taskgroup) { + Diag(StartLoc, diag::err_omp_wrong_cancel_region) + << getOpenMPDirectiveName(CancelRegion); + return StmtError(); + } + if (DSAStack->isParentNowaitRegion()) { + Diag(StartLoc, diag::err_omp_parent_cancel_region_nowait) << 1; + return StmtError(); + } + if (DSAStack->isParentOrderedRegion()) { + Diag(StartLoc, diag::err_omp_parent_cancel_region_ordered) << 1; + return StmtError(); + } + return OMPCancelDirective::Create(Context, StartLoc, EndLoc, CancelRegion); +} + 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 41ab5a2e9b0..80896be981d 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -6719,6 +6719,8 @@ StmtResult TreeTransform<Derived>::TransformOMPExecutableDirective( OpenMPDirectiveKind CancelRegion = OMPD_unknown; if (D->getDirectiveKind() == OMPD_cancellation_point) { CancelRegion = cast<OMPCancellationPointDirective>(D)->getCancelRegion(); + } else if (D->getDirectiveKind() == OMPD_cancel) { + CancelRegion = cast<OMPCancelDirective>(D)->getCancelRegion(); } return getDerived().RebuildOMPExecutableDirective( @@ -6978,6 +6980,17 @@ StmtResult TreeTransform<Derived>::TransformOMPCancellationPointDirective( return Res; } +template <typename Derived> +StmtResult +TreeTransform<Derived>::TransformOMPCancelDirective(OMPCancelDirective *D) { + DeclarationNameInfo DirName; + getDerived().getSema().StartOpenMPDSABlock(OMPD_cancel, 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 d7975c434f8..ca5d0be6329 100644 --- a/clang/lib/Serialization/ASTReaderStmt.cpp +++ b/clang/lib/Serialization/ASTReaderStmt.cpp @@ -2256,6 +2256,12 @@ void ASTStmtReader::VisitOMPCancellationPointDirective( D->setCancelRegion(static_cast<OpenMPDirectiveKind>(Record[Idx++])); } +void ASTStmtReader::VisitOMPCancelDirective(OMPCancelDirective *D) { + VisitStmt(D); + VisitOMPExecutableDirective(D); + D->setCancelRegion(static_cast<OpenMPDirectiveKind>(Record[Idx++])); +} + //===----------------------------------------------------------------------===// // ASTReader Implementation //===----------------------------------------------------------------------===// @@ -2863,6 +2869,10 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { S = OMPCancellationPointDirective::CreateEmpty(Context, Empty); break; + case STMT_OMP_CANCEL_DIRECTIVE: + S = OMPCancelDirective::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 846acd04d4f..cddefaca8f3 100644 --- a/clang/lib/Serialization/ASTWriterStmt.cpp +++ b/clang/lib/Serialization/ASTWriterStmt.cpp @@ -2115,6 +2115,13 @@ void ASTStmtWriter::VisitOMPCancellationPointDirective( Code = serialization::STMT_OMP_CANCELLATION_POINT_DIRECTIVE; } +void ASTStmtWriter::VisitOMPCancelDirective(OMPCancelDirective *D) { + VisitStmt(D); + VisitOMPExecutableDirective(D); + Record.push_back(D->getCancelRegion()); + Code = serialization::STMT_OMP_CANCEL_DIRECTIVE; +} + //===----------------------------------------------------------------------===// // ASTWriter Implementation //===----------------------------------------------------------------------===// diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp index e8eba7c593a..a3239f591a3 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -823,6 +823,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred, case Stmt::OMPTargetDirectiveClass: case Stmt::OMPTeamsDirectiveClass: case Stmt::OMPCancellationPointDirectiveClass: + case Stmt::OMPCancelDirectiveClass: llvm_unreachable("Stmt should not be in analyzer evaluation loop"); case Stmt::ObjCSubscriptRefExprClass: diff --git a/clang/test/OpenMP/cancel_ast_print.cpp b/clang/test/OpenMP/cancel_ast_print.cpp new file mode 100644 index 00000000000..f244c784e86 --- /dev/null +++ b/clang/test/OpenMP/cancel_ast_print.cpp @@ -0,0 +1,47 @@ +// RUN: %clang_cc1 -verify -fopenmp -ast-print %s | FileCheck %s +// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -emit-pch -o %t %s +// RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s +// expected-no-diagnostics + +#ifndef HEADER +#define HEADER + +int main (int argc, char **argv) { +// CHECK: int main(int argc, char **argv) { +#pragma omp parallel +{ +#pragma omp cancel parallel +} +// CHECK: #pragma omp parallel +// CHECK-NEXT: { +// CHECK-NEXT: #pragma omp cancel parallel +// CHECK-NEXT: } +#pragma omp sections +{ +#pragma omp cancel sections +} +// CHECK-NEXT: #pragma omp sections +// CHECK: { +// CHECK: #pragma omp cancel sections +// CHECK: } +#pragma omp for +for (int i = 0; i < argc; ++i) { +#pragma omp cancel for +} +// CHECK: #pragma omp for +// CHECK-NEXT: for (int i = 0; i < argc; ++i) { +// CHECK-NEXT: #pragma omp cancel for +// CHECK-NEXT: } +#pragma omp task +{ +#pragma omp cancel taskgroup +} +// CHECK: #pragma omp task +// CHECK: { +// CHECK: #pragma omp cancel taskgroup +// CHECK: } +// CHECK: return argc; + return argc; +} + +#endif diff --git a/clang/test/OpenMP/cancel_messages.cpp b/clang/test/OpenMP/cancel_messages.cpp new file mode 100644 index 00000000000..07088387cb4 --- /dev/null +++ b/clang/test/OpenMP/cancel_messages.cpp @@ -0,0 +1,83 @@ +// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 %s + +int main(int argc, char **argv) { +#pragma omp cancellation // expected-error {{expected an OpenMP directive}} +#pragma omp cancel // expected-error {{one of 'for', 'parallel', 'sections' or 'taskgroup' is expected}} + ; +#pragma omp cancel parallel untied // expected-error {{unexpected OpenMP clause 'untied' in directive '#pragma omp cancel'}} +#pragma omp cancel unknown // expected-error {{one of 'for', 'parallel', 'sections' or 'taskgroup' is expected}} +#pragma omp cancel sections( // expected-warning {{extra tokens at the end of '#pragma omp cancel' are ignored}} +#pragma omp cancel for, ) // expected-warning {{extra tokens at the end of '#pragma omp cancel' are ignored}} +#pragma omp cancel taskgroup() // expected-warning {{extra tokens at the end of '#pragma omp cancel' are ignored}} +#pragma omp cancel parallel, if // expected-warning {{extra tokens at the end of '#pragma omp cancel' are ignored}} + if (argc) +#pragma omp cancel for // expected-error {{'#pragma omp cancel' cannot be an immediate substatement}} + if (argc) { +#pragma omp taskgroup +#pragma omp task +#pragma omp parallel + { +#pragma omp cancel taskgroup // expected-error {{region cannot be closely nested inside 'parallel' region}} + } + } +#pragma omp parallel +#pragma omp taskgroup + { +#pragma omp cancel taskgroup // expected-error {{region cannot be closely nested inside 'taskgroup' region}} + } +#pragma omp parallel + { +#pragma omp cancel for // expected-error {{region cannot be closely nested inside 'parallel' region}} + } +#pragma omp task + { +#pragma omp cancel sections // expected-error {{region cannot be closely nested inside 'task' region}} + } +#pragma omp sections + { +#pragma omp cancel parallel // expected-error {{region cannot be closely nested inside 'sections' region}} + } + while (argc) +#pragma omp cancel for // expected-error {{'#pragma omp cancel' cannot be an immediate substatement}} + while (argc) { +#pragma omp cancel sections + } + do +#pragma omp cancel parallel // expected-error {{'#pragma omp cancel' cannot be an immediate substatement}} + while (argc) + ; + do { +#pragma omp cancel taskgroup + } while (argc); + switch (argc) +#pragma omp cancel parallel // expected-error {{'#pragma omp cancel' cannot be an immediate substatement}} + switch (argc) + case 1: +#pragma omp cancel sections // expected-error {{'#pragma omp cancel' cannot be an immediate substatement}} + switch (argc) + case 1: { +#pragma omp cancel for + } + switch (argc) { +#pragma omp cancel taskgroup + case 1: +#pragma omp cancel parallel // expected-error {{'#pragma omp cancel' cannot be an immediate substatement}} + break; + default: { +#pragma omp cancel sections + } break; + } + for (;;) +#pragma omp cancel for // expected-error {{'#pragma omp cancel' cannot be an immediate substatement}} + for (;;) { +#pragma omp cancel taskgroup + } +label: +#pragma omp cancel parallel // expected-error {{'#pragma omp cancel' cannot be an immediate substatement}} +label1 : { +#pragma omp cancel sections +} + + return 0; +} + diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp index 2bb53348527..09edc8d2e76 100644 --- a/clang/tools/libclang/CIndex.cpp +++ b/clang/tools/libclang/CIndex.cpp @@ -1882,6 +1882,7 @@ public: void VisitOMPTaskgroupDirective(const OMPTaskgroupDirective *D); void VisitOMPCancellationPointDirective(const OMPCancellationPointDirective *D); + void VisitOMPCancelDirective(const OMPCancelDirective *D); void VisitOMPFlushDirective(const OMPFlushDirective *D); void VisitOMPOrderedDirective(const OMPOrderedDirective *D); void VisitOMPAtomicDirective(const OMPAtomicDirective *D); @@ -2514,6 +2515,10 @@ void EnqueueVisitor::VisitOMPCancellationPointDirective( VisitOMPExecutableDirective(D); } +void EnqueueVisitor::VisitOMPCancelDirective(const OMPCancelDirective *D) { + VisitOMPExecutableDirective(D); +} + void CursorVisitor::EnqueueWorkList(VisitorWorkList &WL, const Stmt *S) { EnqueueVisitor(WL, MakeCXCursor(S, StmtParent, TU,RegionOfInterest)).Visit(S); } @@ -4292,6 +4297,8 @@ CXString clang_getCursorKindSpelling(enum CXCursorKind Kind) { return cxstring::createRef("OMPTeamsDirective"); case CXCursor_OMPCancellationPointDirective: return cxstring::createRef("OMPCancellationPointDirective"); + case CXCursor_OMPCancelDirective: + return cxstring::createRef("OMPCancelDirective"); case CXCursor_OverloadCandidate: return cxstring::createRef("OverloadCandidate"); } diff --git a/clang/tools/libclang/CXCursor.cpp b/clang/tools/libclang/CXCursor.cpp index 0c66e43c855..fe9ba4eac1b 100644 --- a/clang/tools/libclang/CXCursor.cpp +++ b/clang/tools/libclang/CXCursor.cpp @@ -591,6 +591,9 @@ CXCursor cxcursor::MakeCXCursor(const Stmt *S, const Decl *Parent, case Stmt::OMPCancellationPointDirectiveClass: K = CXCursor_OMPCancellationPointDirective; break; + case Stmt::OMPCancelDirectiveClass: + K = CXCursor_OMPCancelDirective; + break; } CXCursor C = { K, 0, { Parent, S, TU } }; |