summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
authorAlexey Bataev <a.bataev@hotmail.com>2015-07-02 11:25:17 +0000
committerAlexey Bataev <a.bataev@hotmail.com>2015-07-02 11:25:17 +0000
commit80909878adc79d9f1277373af175041718f05953 (patch)
treec673079a9bf2cc7e6d7635625bdb1691e162686b /clang
parent3937bc650cad69cbd607ca3ea64ea6623808fc19 (diff)
downloadbcm5719-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')
-rw-r--r--clang/include/clang-c/Index.h6
-rw-r--r--clang/include/clang/AST/DataRecursiveASTVisitor.h3
-rw-r--r--clang/include/clang/AST/RecursiveASTVisitor.h3
-rw-r--r--clang/include/clang/AST/StmtOpenMP.h57
-rw-r--r--clang/include/clang/Basic/OpenMPKinds.def1
-rw-r--r--clang/include/clang/Basic/StmtNodes.td1
-rw-r--r--clang/include/clang/Sema/Sema.h4
-rw-r--r--clang/include/clang/Serialization/ASTBitCodes.h1
-rw-r--r--clang/lib/AST/Stmt.cpp20
-rw-r--r--clang/lib/AST/StmtPrinter.cpp6
-rw-r--r--clang/lib/AST/StmtProfile.cpp4
-rw-r--r--clang/lib/Basic/OpenMPKinds.cpp1
-rw-r--r--clang/lib/CodeGen/CGStmt.cpp3
-rw-r--r--clang/lib/CodeGen/CGStmtOpenMP.cpp4
-rw-r--r--clang/lib/CodeGen/CodeGenFunction.h1
-rw-r--r--clang/lib/Parse/ParseOpenMP.cpp4
-rw-r--r--clang/lib/Sema/SemaOpenMP.cpp57
-rw-r--r--clang/lib/Sema/TreeTransform.h13
-rw-r--r--clang/lib/Serialization/ASTReaderStmt.cpp10
-rw-r--r--clang/lib/Serialization/ASTWriterStmt.cpp7
-rw-r--r--clang/lib/StaticAnalyzer/Core/ExprEngine.cpp1
-rw-r--r--clang/test/OpenMP/cancel_ast_print.cpp47
-rw-r--r--clang/test/OpenMP/cancel_messages.cpp83
-rw-r--r--clang/tools/libclang/CIndex.cpp7
-rw-r--r--clang/tools/libclang/CXCursor.cpp3
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 } };
OpenPOWER on IntegriCloud