[flang-commits] [flang] 1a43fd2 - [OpenMP51] Initial support for masked directive and filter clause
via flang-commits
flang-commits at lists.llvm.org
Fri Apr 9 12:01:07 PDT 2021
Author: cchen
Date: 2021-04-09T14:00:36-05:00
New Revision: 1a43fd27691c6ae5c3d725ca7c6f4fd19357f4b8
URL: https://github.com/llvm/llvm-project/commit/1a43fd27691c6ae5c3d725ca7c6f4fd19357f4b8
DIFF: https://github.com/llvm/llvm-project/commit/1a43fd27691c6ae5c3d725ca7c6f4fd19357f4b8.diff
LOG: [OpenMP51] Initial support for masked directive and filter clause
Adds basic parsing/sema/serialization support for the #pragma omp masked
directive.
Reviewed By: ABataev
Differential Revision: https://reviews.llvm.org/D99995
Added:
clang/test/OpenMP/masked_ast_print.cpp
clang/test/OpenMP/masked_messages.cpp
Modified:
clang/include/clang-c/Index.h
clang/include/clang/AST/OpenMPClause.h
clang/include/clang/AST/RecursiveASTVisitor.h
clang/include/clang/AST/StmtOpenMP.h
clang/include/clang/Basic/StmtNodes.td
clang/include/clang/Sema/Sema.h
clang/include/clang/Serialization/ASTBitCodes.h
clang/lib/AST/OpenMPClause.cpp
clang/lib/AST/StmtOpenMP.cpp
clang/lib/AST/StmtPrinter.cpp
clang/lib/AST/StmtProfile.cpp
clang/lib/CodeGen/CGStmt.cpp
clang/lib/CodeGen/CGStmtOpenMP.cpp
clang/lib/Parse/ParseOpenMP.cpp
clang/lib/Sema/SemaExceptionSpec.cpp
clang/lib/Sema/SemaOpenMP.cpp
clang/lib/Sema/TreeTransform.h
clang/lib/Serialization/ASTReader.cpp
clang/lib/Serialization/ASTReaderStmt.cpp
clang/lib/Serialization/ASTWriter.cpp
clang/lib/Serialization/ASTWriterStmt.cpp
clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
clang/tools/libclang/CIndex.cpp
clang/tools/libclang/CXCursor.cpp
flang/lib/Semantics/check-omp-structure.cpp
llvm/include/llvm/Frontend/OpenMP/OMP.td
Removed:
################################################################################
diff --git a/clang/include/clang-c/Index.h b/clang/include/clang-c/Index.h
index 696e271a72313..87592156dd6b8 100644
--- a/clang/include/clang-c/Index.h
+++ b/clang/include/clang-c/Index.h
@@ -2584,7 +2584,11 @@ enum CXCursorKind {
*/
CXCursor_OMPDispatchDirective = 291,
- CXCursor_LastStmt = CXCursor_OMPDispatchDirective,
+ /** OpenMP masked directive.
+ */
+ CXCursor_OMPMaskedDirective = 292,
+
+ CXCursor_LastStmt = CXCursor_OMPMaskedDirective,
/**
* Cursor that represents the translation unit itself.
diff --git a/clang/include/clang/AST/OpenMPClause.h b/clang/include/clang/AST/OpenMPClause.h
index 11eb453a02060..e484a89bc84a8 100644
--- a/clang/include/clang/AST/OpenMPClause.h
+++ b/clang/include/clang/AST/OpenMPClause.h
@@ -8225,6 +8225,77 @@ class OMPAffinityClause final
}
};
+/// This represents 'filter' clause in the '#pragma omp ...' directive.
+///
+/// \code
+/// #pragma omp masked filter(tid)
+/// \endcode
+/// In this example directive '#pragma omp masked' has 'filter' clause with
+/// thread id.
+class OMPFilterClause final : public OMPClause, public OMPClauseWithPreInit {
+ friend class OMPClauseReader;
+
+ /// Location of '('.
+ SourceLocation LParenLoc;
+
+ /// Express of the 'filter' clause.
+ Stmt *ThreadID = nullptr;
+
+ /// Sets the thread identifier.
+ void setThreadID(Expr *TID) { ThreadID = TID; }
+
+ /// Sets the location of '('.
+ void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
+
+public:
+ /// Build 'filter' clause with thread-id \a ThreadID.
+ ///
+ /// \param ThreadID Thread identifier.
+ /// \param HelperE Helper expression associated with this clause.
+ /// \param CaptureRegion Innermost OpenMP region where expressions in this
+ /// clause must be captured.
+ /// \param StartLoc Starting location of the clause.
+ /// \param LParenLoc Location of '('.
+ /// \param EndLoc Ending location of the clause.
+ OMPFilterClause(Expr *ThreadID, Stmt *HelperE,
+ OpenMPDirectiveKind CaptureRegion, SourceLocation StartLoc,
+ SourceLocation LParenLoc, SourceLocation EndLoc)
+ : OMPClause(llvm::omp::OMPC_filter, StartLoc, EndLoc),
+ OMPClauseWithPreInit(this), LParenLoc(LParenLoc), ThreadID(ThreadID) {
+ setPreInitStmt(HelperE, CaptureRegion);
+ }
+
+ /// Build an empty clause.
+ OMPFilterClause()
+ : OMPClause(llvm::omp::OMPC_filter, SourceLocation(), SourceLocation()),
+ OMPClauseWithPreInit(this) {}
+ /// Returns the location of '('.
+ SourceLocation getLParenLoc() const { return LParenLoc; }
+
+ /// Return thread identifier.
+ Expr *getThreadID() { return cast<Expr>(ThreadID); }
+
+ /// Return thread identifier.
+ Expr *getThreadID() const { return cast<Expr>(ThreadID); }
+
+ child_range children() { return child_range(&ThreadID, &ThreadID + 1); }
+
+ const_child_range children() const {
+ return const_child_range(&ThreadID, &ThreadID + 1);
+ }
+
+ child_range used_children() {
+ return child_range(child_iterator(), child_iterator());
+ }
+ const_child_range used_children() const {
+ return const_child_range(const_child_iterator(), const_child_iterator());
+ }
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == llvm::omp::OMPC_filter;
+ }
+};
+
/// This class implements a simple visitor for OMPClause
/// subclasses.
template<class ImplClass, template <typename> class Ptr, typename RetTy>
diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h
index 8ca7c509776b4..9499564e46e0e 100644
--- a/clang/include/clang/AST/RecursiveASTVisitor.h
+++ b/clang/include/clang/AST/RecursiveASTVisitor.h
@@ -2974,6 +2974,9 @@ DEF_TRAVERSE_STMT(OMPInteropDirective,
DEF_TRAVERSE_STMT(OMPDispatchDirective,
{ TRY_TO(TraverseOMPExecutableDirective(S)); })
+DEF_TRAVERSE_STMT(OMPMaskedDirective,
+ { TRY_TO(TraverseOMPExecutableDirective(S)); })
+
// OpenMP clauses.
template <typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseOMPClause(OMPClause *C) {
@@ -3609,6 +3612,13 @@ bool RecursiveASTVisitor<Derived>::VisitOMPAffinityClause(
return true;
}
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPFilterClause(OMPFilterClause *C) {
+ TRY_TO(VisitOMPClauseWithPreInit(C));
+ TRY_TO(TraverseStmt(C->getThreadID()));
+ return true;
+}
+
// FIXME: look at the following tricky-seeming exprs to see if we
// need to recurse on anything. These are ones that have methods
// returning decls or qualtypes or nestednamespecifier -- though I'm
diff --git a/clang/include/clang/AST/StmtOpenMP.h b/clang/include/clang/AST/StmtOpenMP.h
index a59b36c302a3d..4d14848830fa7 100644
--- a/clang/include/clang/AST/StmtOpenMP.h
+++ b/clang/include/clang/AST/StmtOpenMP.h
@@ -5205,6 +5205,56 @@ class OMPDispatchDirective final : public OMPExecutableDirective {
}
};
+/// This represents '#pragma omp masked' directive.
+/// \code
+/// #pragma omp masked filter(tid)
+/// \endcode
+/// This example shows a directive '#pragma omp masked' with a filter clause
+/// with variable 'tid'.
+///
+class OMPMaskedDirective final : public OMPExecutableDirective {
+ friend class ASTStmtReader;
+ friend class OMPExecutableDirective;
+
+ /// Build directive with the given start and end location.
+ ///
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending location of the directive.
+ ///
+ OMPMaskedDirective(SourceLocation StartLoc, SourceLocation EndLoc)
+ : OMPExecutableDirective(OMPMaskedDirectiveClass, llvm::omp::OMPD_masked,
+ StartLoc, EndLoc) {}
+
+ /// Build an empty directive.
+ ///
+ explicit OMPMaskedDirective()
+ : OMPExecutableDirective(OMPMaskedDirectiveClass, llvm::omp::OMPD_masked,
+ SourceLocation(), SourceLocation()) {}
+
+public:
+ /// Creates directive.
+ ///
+ /// \param C AST context.
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending Location of the directive.
+ /// \param AssociatedStmt Statement, associated with the directive.
+ ///
+ static OMPMaskedDirective *
+ Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
+ ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt);
+
+ /// Creates an empty directive.
+ ///
+ /// \param C AST context.
+ ///
+ static OMPMaskedDirective *CreateEmpty(const ASTContext &C,
+ unsigned NumClauses, EmptyShell);
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == OMPMaskedDirectiveClass;
+ }
+};
+
} // end namespace clang
#endif
diff --git a/clang/include/clang/Basic/StmtNodes.td b/clang/include/clang/Basic/StmtNodes.td
index d2e8fa69a5840..ecaf7b027e778 100644
--- a/clang/include/clang/Basic/StmtNodes.td
+++ b/clang/include/clang/Basic/StmtNodes.td
@@ -277,3 +277,4 @@ def OMPTargetTeamsDistributeParallelForSimdDirective : StmtNode<OMPLoopDirective
def OMPTargetTeamsDistributeSimdDirective : StmtNode<OMPLoopDirective>;
def OMPInteropDirective : StmtNode<OMPExecutableDirective>;
def OMPDispatchDirective : StmtNode<OMPExecutableDirective>;
+def OMPMaskedDirective : StmtNode<OMPExecutableDirective>;
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index b8029b6707477..ebf63764be1aa 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -10803,6 +10803,11 @@ class Sema final {
StmtResult ActOnOpenMPDispatchDirective(ArrayRef<OMPClause *> Clauses,
Stmt *AStmt, SourceLocation StartLoc,
SourceLocation EndLoc);
+ /// Called on well-formed '\#pragma omp masked' after parsing of the
+ // /associated statement.
+ StmtResult ActOnOpenMPMaskedDirective(ArrayRef<OMPClause *> Clauses,
+ Stmt *AStmt, SourceLocation StartLoc,
+ SourceLocation EndLoc);
/// Checks correctness of linear modifiers.
bool CheckOpenMPLinearModifier(OpenMPLinearClauseKind LinKind,
@@ -11021,6 +11026,10 @@ class Sema final {
SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc);
+ /// Called on well-formed 'filter' clause.
+ OMPClause *ActOnOpenMPFilterClause(Expr *ThreadID, SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc);
/// Called on well-formed 'threads' clause.
OMPClause *ActOnOpenMPThreadsClause(SourceLocation StartLoc,
SourceLocation EndLoc);
diff --git a/clang/include/clang/Serialization/ASTBitCodes.h b/clang/include/clang/Serialization/ASTBitCodes.h
index 17690b901eacf..5e5a73e730924 100644
--- a/clang/include/clang/Serialization/ASTBitCodes.h
+++ b/clang/include/clang/Serialization/ASTBitCodes.h
@@ -1942,6 +1942,7 @@ enum StmtCode {
STMT_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD_DIRECTIVE,
STMT_OMP_INTEROP_DIRECTIVE,
STMT_OMP_DISPATCH_DIRECTIVE,
+ STMT_OMP_MASKED_DIRECTIVE,
EXPR_OMP_ARRAY_SECTION,
EXPR_OMP_ARRAY_SHAPING,
EXPR_OMP_ITERATOR,
diff --git a/clang/lib/AST/OpenMPClause.cpp b/clang/lib/AST/OpenMPClause.cpp
index 0e648dd3a1608..2f542a16a8e75 100644
--- a/clang/lib/AST/OpenMPClause.cpp
+++ b/clang/lib/AST/OpenMPClause.cpp
@@ -100,6 +100,8 @@ const OMPClauseWithPreInit *OMPClauseWithPreInit::get(const OMPClause *C) {
return static_cast<const OMPNovariantsClause *>(C);
case OMPC_nocontext:
return static_cast<const OMPNocontextClause *>(C);
+ case OMPC_filter:
+ return static_cast<const OMPFilterClause *>(C);
case OMPC_default:
case OMPC_proc_bind:
case OMPC_safelen:
@@ -2245,6 +2247,12 @@ void OMPClausePrinter::VisitOMPAffinityClause(OMPAffinityClause *Node) {
OS << ")";
}
+void OMPClausePrinter::VisitOMPFilterClause(OMPFilterClause *Node) {
+ OS << "filter(";
+ Node->getThreadID()->printPretty(OS, nullptr, Policy, 0);
+ OS << ")";
+}
+
void OMPTraitInfo::getAsVariantMatchInfo(ASTContext &ASTCtx,
VariantMatchInfo &VMI) const {
for (const OMPTraitSet &Set : Sets) {
diff --git a/clang/lib/AST/StmtOpenMP.cpp b/clang/lib/AST/StmtOpenMP.cpp
index 7dc43ea924508..a9905949d7afa 100644
--- a/clang/lib/AST/StmtOpenMP.cpp
+++ b/clang/lib/AST/StmtOpenMP.cpp
@@ -1977,3 +1977,20 @@ OMPDispatchDirective *OMPDispatchDirective::CreateEmpty(const ASTContext &C,
/*HasAssociatedStmt=*/true,
/*NumChildren=*/0);
}
+
+OMPMaskedDirective *OMPMaskedDirective::Create(const ASTContext &C,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc,
+ ArrayRef<OMPClause *> Clauses,
+ Stmt *AssociatedStmt) {
+ return createDirective<OMPMaskedDirective>(C, Clauses, AssociatedStmt,
+ /*NumChildren=*/0, StartLoc,
+ EndLoc);
+}
+
+OMPMaskedDirective *OMPMaskedDirective::CreateEmpty(const ASTContext &C,
+ unsigned NumClauses,
+ EmptyShell) {
+ return createEmptyDirective<OMPMaskedDirective>(C, NumClauses,
+ /*HasAssociatedStmt=*/true);
+}
diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp
index 5993268971f8b..9a7e40fd88e05 100644
--- a/clang/lib/AST/StmtPrinter.cpp
+++ b/clang/lib/AST/StmtPrinter.cpp
@@ -972,6 +972,11 @@ void StmtPrinter::VisitOMPDispatchDirective(OMPDispatchDirective *Node) {
PrintOMPExecutableDirective(Node);
}
+void StmtPrinter::VisitOMPMaskedDirective(OMPMaskedDirective *Node) {
+ Indent() << "#pragma omp masked";
+ PrintOMPExecutableDirective(Node);
+}
+
//===----------------------------------------------------------------------===//
// Expr printing methods.
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp
index 3d62349b6624c..fc1f8a5327244 100644
--- a/clang/lib/AST/StmtProfile.cpp
+++ b/clang/lib/AST/StmtProfile.cpp
@@ -569,6 +569,12 @@ void OMPClauseProfiler::VisitOMPDestroyClause(const OMPDestroyClause *C) {
Profiler->VisitStmt(C->getInteropVar());
}
+void OMPClauseProfiler::VisitOMPFilterClause(const OMPFilterClause *C) {
+ VistOMPClauseWithPreInit(C);
+ if (C->getThreadID())
+ Profiler->VisitStmt(C->getThreadID());
+}
+
template<typename T>
void OMPClauseProfiler::VisitOMPClauseList(T *Node) {
for (auto *E : Node->varlists()) {
@@ -1160,6 +1166,10 @@ void StmtProfiler::VisitOMPDispatchDirective(const OMPDispatchDirective *S) {
VisitOMPExecutableDirective(S);
}
+void StmtProfiler::VisitOMPMaskedDirective(const OMPMaskedDirective *S) {
+ VisitOMPExecutableDirective(S);
+}
+
void StmtProfiler::VisitExpr(const Expr *S) {
VisitStmt(S);
}
diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp
index b4ddfa586d1aa..daecb44abbd89 100644
--- a/clang/lib/CodeGen/CGStmt.cpp
+++ b/clang/lib/CodeGen/CGStmt.cpp
@@ -381,6 +381,9 @@ void CodeGenFunction::EmitStmt(const Stmt *S, ArrayRef<const Attr *> Attrs) {
case Stmt::OMPDispatchDirectiveClass:
llvm_unreachable("Dispatch directive not supported yet.");
break;
+ case Stmt::OMPMaskedDirectiveClass:
+ llvm_unreachable("Masked directive not supported yet.");
+ break;
}
}
diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp
index ac77c2d67e12e..4b93fddab5235 100644
--- a/clang/lib/CodeGen/CGStmtOpenMP.cpp
+++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp
@@ -5614,6 +5614,7 @@ static void emitOMPAtomicExpr(CodeGenFunction &CGF, OpenMPClauseKind Kind,
case OMPC_use:
case OMPC_novariants:
case OMPC_nocontext:
+ case OMPC_filter:
llvm_unreachable("Clause is not allowed in 'omp atomic'.");
}
}
diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp
index 8928b1191f2f9..05731fea25ddb 100644
--- a/clang/lib/Parse/ParseOpenMP.cpp
+++ b/clang/lib/Parse/ParseOpenMP.cpp
@@ -2208,6 +2208,7 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
case OMPD_target_teams_distribute_parallel_for_simd:
case OMPD_target_teams_distribute_simd:
case OMPD_dispatch:
+ case OMPD_masked:
Diag(Tok, diag::err_omp_unexpected_directive)
<< 1 << getOpenMPDirectiveName(DKind);
break;
@@ -2257,7 +2258,7 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
/// simd' | 'teams distribute parallel for simd' | 'teams distribute
/// parallel for' | 'target teams' | 'target teams distribute' | 'target
/// teams distribute parallel for' | 'target teams distribute parallel
-/// for simd' | 'target teams distribute simd' {clause}
+/// for simd' | 'target teams distribute simd' | 'masked' {clause}
/// annot_pragma_openmp_end
///
StmtResult
@@ -2432,7 +2433,8 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(ParsedStmtContext StmtCtx) {
case OMPD_target_teams_distribute_parallel_for:
case OMPD_target_teams_distribute_parallel_for_simd:
case OMPD_target_teams_distribute_simd:
- case OMPD_dispatch: {
+ case OMPD_dispatch:
+ case OMPD_masked: {
// Special processing for flush and depobj clauses.
Token ImplicitTok;
bool ImplicitClauseAllowed = false;
@@ -2778,6 +2780,7 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
case OMPC_detach:
case OMPC_novariants:
case OMPC_nocontext:
+ case OMPC_filter:
// OpenMP [2.5, Restrictions]
// At most one num_threads clause can appear on the directive.
// OpenMP [2.8.1, simd construct, Restrictions]
diff --git a/clang/lib/Sema/SemaExceptionSpec.cpp b/clang/lib/Sema/SemaExceptionSpec.cpp
index 12f47cb0630d0..54f9fb3db9e39 100644
--- a/clang/lib/Sema/SemaExceptionSpec.cpp
+++ b/clang/lib/Sema/SemaExceptionSpec.cpp
@@ -1488,6 +1488,7 @@ CanThrowResult Sema::canThrow(const Stmt *S) {
case Stmt::OMPTeamsDistributeSimdDirectiveClass:
case Stmt::OMPInteropDirectiveClass:
case Stmt::OMPDispatchDirectiveClass:
+ case Stmt::OMPMaskedDirectiveClass:
case Stmt::ReturnStmtClass:
case Stmt::SEHExceptStmtClass:
case Stmt::SEHFinallyStmtClass:
diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp
index 2d2f02c7ed904..ecab867964b91 100644
--- a/clang/lib/Sema/SemaOpenMP.cpp
+++ b/clang/lib/Sema/SemaOpenMP.cpp
@@ -3425,6 +3425,7 @@ class DSAAttrChecker final : public StmtVisitor<DSAAttrChecker, void> {
S->getDirectiveKind() == OMPD_critical ||
S->getDirectiveKind() == OMPD_section ||
S->getDirectiveKind() == OMPD_master ||
+ S->getDirectiveKind() == OMPD_masked ||
isOpenMPLoopTransformationDirective(S->getDirectiveKind())) {
Visit(S->getAssociatedStmt());
return;
@@ -3968,6 +3969,7 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) {
case OMPD_critical:
case OMPD_section:
case OMPD_master:
+ case OMPD_masked:
case OMPD_tile:
break;
case OMPD_simd:
@@ -4450,7 +4452,8 @@ StmtResult Sema::ActOnOpenMPRegionEnd(StmtResult S,
if (DSAStack->getCurrentDirective() == OMPD_atomic ||
DSAStack->getCurrentDirective() == OMPD_critical ||
DSAStack->getCurrentDirective() == OMPD_section ||
- DSAStack->getCurrentDirective() == OMPD_master)
+ DSAStack->getCurrentDirective() == OMPD_master ||
+ DSAStack->getCurrentDirective() == OMPD_masked)
return S;
bool ErrorFound = false;
@@ -4719,10 +4722,10 @@ static bool checkNestingOfRegions(Sema &SemaRef, const DSAStackTy *Stack,
(ParentRegion == OMPD_section || ParentRegion == OMPD_sections ||
ParentRegion == OMPD_parallel_sections)));
OrphanSeen = ParentRegion == OMPD_unknown;
- } else if (CurrentRegion == OMPD_master) {
- // OpenMP [2.16, Nesting of Regions]
- // A master region may not be closely nested inside a worksharing,
- // atomic, or explicit task region.
+ } else if (CurrentRegion == OMPD_master || CurrentRegion == OMPD_masked) {
+ // OpenMP 5.1 [2.22, Nesting of Regions]
+ // A masked region may not be closely nested inside a worksharing, loop,
+ // atomic, task, or taskloop region.
NestingProhibited = isOpenMPWorksharingDirective(ParentRegion) ||
isOpenMPTaskingDirective(ParentRegion);
} else if (CurrentRegion == OMPD_critical && CurrentName.getName()) {
@@ -4752,27 +4755,28 @@ static bool checkNestingOfRegions(Sema &SemaRef, const DSAStackTy *Stack,
return true;
}
} else if (CurrentRegion == OMPD_barrier) {
- // OpenMP [2.16, Nesting of Regions]
- // A barrier region may not be closely nested inside a worksharing,
- // explicit task, critical, ordered, atomic, or master region.
- NestingProhibited = isOpenMPWorksharingDirective(ParentRegion) ||
- isOpenMPTaskingDirective(ParentRegion) ||
- ParentRegion == OMPD_master ||
- ParentRegion == OMPD_parallel_master ||
- ParentRegion == OMPD_critical ||
- ParentRegion == OMPD_ordered;
+ // OpenMP 5.1 [2.22, Nesting of Regions]
+ // A barrier region may not be closely nested inside a worksharing, loop,
+ // task, taskloop, critical, ordered, atomic, or masked region.
+ NestingProhibited =
+ isOpenMPWorksharingDirective(ParentRegion) ||
+ isOpenMPTaskingDirective(ParentRegion) ||
+ ParentRegion == OMPD_master || ParentRegion == OMPD_masked ||
+ ParentRegion == OMPD_parallel_master ||
+ ParentRegion == OMPD_critical || ParentRegion == OMPD_ordered;
} else if (isOpenMPWorksharingDirective(CurrentRegion) &&
!isOpenMPParallelDirective(CurrentRegion) &&
!isOpenMPTeamsDirective(CurrentRegion)) {
- // OpenMP [2.16, Nesting of Regions]
- // A worksharing region may not be closely nested inside a worksharing,
- // explicit task, critical, ordered, atomic, or master region.
- NestingProhibited = isOpenMPWorksharingDirective(ParentRegion) ||
- isOpenMPTaskingDirective(ParentRegion) ||
- ParentRegion == OMPD_master ||
- ParentRegion == OMPD_parallel_master ||
- ParentRegion == OMPD_critical ||
- ParentRegion == OMPD_ordered;
+ // OpenMP 5.1 [2.22, Nesting of Regions]
+ // A loop region that binds to a parallel region or a worksharing region
+ // may not be closely nested inside a worksharing, loop, task, taskloop,
+ // critical, ordered, atomic, or masked region.
+ NestingProhibited =
+ isOpenMPWorksharingDirective(ParentRegion) ||
+ isOpenMPTaskingDirective(ParentRegion) ||
+ ParentRegion == OMPD_master || ParentRegion == OMPD_masked ||
+ ParentRegion == OMPD_parallel_master ||
+ ParentRegion == OMPD_critical || ParentRegion == OMPD_ordered;
Recommend = ShouldBeInParallelRegion;
} else if (CurrentRegion == OMPD_ordered) {
// OpenMP [2.16, Nesting of Regions]
@@ -5699,7 +5703,7 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(
ClausesWithImplicit.append(Clauses.begin(), Clauses.end());
if (AStmt && !CurContext->isDependentContext() && Kind != OMPD_atomic &&
Kind != OMPD_critical && Kind != OMPD_section && Kind != OMPD_master &&
- !isOpenMPLoopTransformationDirective(Kind)) {
+ Kind != OMPD_masked && !isOpenMPLoopTransformationDirective(Kind)) {
assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
// Check default data sharing attributes for referenced variables.
@@ -5854,6 +5858,10 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(
"No clauses are allowed for 'omp master' directive");
Res = ActOnOpenMPMasterDirective(AStmt, StartLoc, EndLoc);
break;
+ case OMPD_masked:
+ Res = ActOnOpenMPMaskedDirective(ClausesWithImplicit, AStmt, StartLoc,
+ EndLoc);
+ break;
case OMPD_critical:
Res = ActOnOpenMPCriticalDirective(DirName, ClausesWithImplicit, AStmt,
StartLoc, EndLoc);
@@ -9865,6 +9873,18 @@ StmtResult Sema::ActOnOpenMPMasterDirective(Stmt *AStmt,
return OMPMasterDirective::Create(Context, StartLoc, EndLoc, AStmt);
}
+StmtResult Sema::ActOnOpenMPMaskedDirective(ArrayRef<OMPClause *> Clauses,
+ Stmt *AStmt,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc) {
+ if (!AStmt)
+ return StmtError();
+
+ setFunctionHasBranchProtectedScope();
+
+ return OMPMaskedDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt);
+}
+
StmtResult Sema::ActOnOpenMPCriticalDirective(
const DeclarationNameInfo &DirName, ArrayRef<OMPClause *> Clauses,
Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc) {
@@ -12793,6 +12813,9 @@ OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr,
case OMPC_nocontext:
Res = ActOnOpenMPNocontextClause(Expr, StartLoc, LParenLoc, EndLoc);
break;
+ case OMPC_filter:
+ Res = ActOnOpenMPFilterClause(Expr, StartLoc, LParenLoc, EndLoc);
+ break;
case OMPC_device:
case OMPC_if:
case OMPC_default:
@@ -13000,6 +13023,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(
case OMPD_section:
case OMPD_single:
case OMPD_master:
+ case OMPD_masked:
case OMPD_critical:
case OMPD_taskgroup:
case OMPD_distribute:
@@ -13078,6 +13102,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(
case OMPD_section:
case OMPD_single:
case OMPD_master:
+ case OMPD_masked:
case OMPD_critical:
case OMPD_taskgroup:
case OMPD_distribute:
@@ -13158,6 +13183,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(
case OMPD_section:
case OMPD_single:
case OMPD_master:
+ case OMPD_masked:
case OMPD_critical:
case OMPD_taskgroup:
case OMPD_distribute:
@@ -13236,6 +13262,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(
case OMPD_section:
case OMPD_single:
case OMPD_master:
+ case OMPD_masked:
case OMPD_critical:
case OMPD_taskgroup:
case OMPD_distribute:
@@ -13313,6 +13340,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(
case OMPD_section:
case OMPD_single:
case OMPD_master:
+ case OMPD_masked:
case OMPD_critical:
case OMPD_taskgroup:
case OMPD_distribute:
@@ -13393,6 +13421,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(
case OMPD_section:
case OMPD_single:
case OMPD_master:
+ case OMPD_masked:
case OMPD_critical:
case OMPD_taskgroup:
case OMPD_ordered:
@@ -13472,6 +13501,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(
case OMPD_section:
case OMPD_single:
case OMPD_master:
+ case OMPD_masked:
case OMPD_critical:
case OMPD_taskgroup:
case OMPD_distribute:
@@ -13552,6 +13582,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(
case OMPD_section:
case OMPD_single:
case OMPD_master:
+ case OMPD_masked:
case OMPD_critical:
case OMPD_taskgroup:
case OMPD_distribute:
@@ -13575,6 +13606,9 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(
llvm_unreachable("Unexpected OpenMP directive");
}
break;
+ case OMPC_filter:
+ // Do not capture filter-clause expressions.
+ break;
case OMPC_firstprivate:
case OMPC_lastprivate:
case OMPC_reduction:
@@ -14945,6 +14979,27 @@ OMPClause *Sema::ActOnOpenMPNocontextClause(Expr *Condition,
StartLoc, LParenLoc, EndLoc);
}
+OMPClause *Sema::ActOnOpenMPFilterClause(Expr *ThreadID,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ Expr *ValExpr = ThreadID;
+ Stmt *HelperValStmt = nullptr;
+
+ OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
+ OpenMPDirectiveKind CaptureRegion =
+ getOpenMPCaptureRegionForClause(DKind, OMPC_filter, LangOpts.OpenMP);
+ if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
+ ValExpr = MakeFullExpr(ValExpr).get();
+ llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
+ ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
+ HelperValStmt = buildPreInits(Context, Captures);
+ }
+
+ return new (Context) OMPFilterClause(ValExpr, HelperValStmt, CaptureRegion,
+ StartLoc, LParenLoc, EndLoc);
+}
+
OMPClause *Sema::ActOnOpenMPVarListClause(
OpenMPClauseKind Kind, ArrayRef<Expr *> VarList, Expr *DepModOrTailExpr,
const OMPVarListLocTy &Locs, SourceLocation ColonLoc,
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index cbc91561d6ed2..ee661f0fc1ab5 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -2231,6 +2231,17 @@ class TreeTransform {
EndLoc);
}
+ /// Build a new OpenMP 'filter' clause.
+ ///
+ /// By default, performs semantic analysis to build the new OpenMP clause.
+ /// Subclasses may override this routine to provide
diff erent behavior.
+ OMPClause *RebuildOMPFilterClause(Expr *ThreadID, SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ return getSema().ActOnOpenMPFilterClause(ThreadID, StartLoc, LParenLoc,
+ EndLoc);
+ }
+
/// Rebuild the operand to an Objective-C \@synchronized statement.
///
/// By default, performs semantic analysis to build the new statement.
@@ -9103,6 +9114,17 @@ TreeTransform<Derived>::TransformOMPDispatchDirective(OMPDispatchDirective *D) {
return Res;
}
+template <typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformOMPMaskedDirective(OMPMaskedDirective *D) {
+ DeclarationNameInfo DirName;
+ getDerived().getSema().StartOpenMPDSABlock(OMPD_masked, DirName, nullptr,
+ D->getBeginLoc());
+ StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
+ getDerived().getSema().EndOpenMPDSABlock(Res.get());
+ return Res;
+}
+
//===----------------------------------------------------------------------===//
// OpenMP clause transformation
//===----------------------------------------------------------------------===//
@@ -9420,6 +9442,16 @@ TreeTransform<Derived>::TransformOMPNocontextClause(OMPNocontextClause *C) {
Cond.get(), C->getBeginLoc(), C->getLParenLoc(), C->getEndLoc());
}
+template <typename Derived>
+OMPClause *
+TreeTransform<Derived>::TransformOMPFilterClause(OMPFilterClause *C) {
+ ExprResult ThreadID = getDerived().TransformExpr(C->getThreadID());
+ if (ThreadID.isInvalid())
+ return nullptr;
+ return getDerived().RebuildOMPFilterClause(ThreadID.get(), C->getBeginLoc(),
+ C->getLParenLoc(), C->getEndLoc());
+}
+
template <typename Derived>
OMPClause *TreeTransform<Derived>::TransformOMPUnifiedAddressClause(
OMPUnifiedAddressClause *C) {
diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index a6f1aef42e914..72bb125397dbd 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -11993,6 +11993,9 @@ OMPClause *OMPClauseReader::readClause() {
case llvm::omp::OMPC_affinity:
C = OMPAffinityClause::CreateEmpty(Context, Record.readInt());
break;
+ case llvm::omp::OMPC_filter:
+ C = new (Context) OMPFilterClause();
+ break;
#define OMP_CLAUSE_NO_CLASS(Enum, Str) \
case llvm::omp::Enum: \
break;
@@ -12964,6 +12967,12 @@ void OMPClauseReader::VisitOMPOrderClause(OMPOrderClause *C) {
C->setKindKwLoc(Record.readSourceLocation());
}
+void OMPClauseReader::VisitOMPFilterClause(OMPFilterClause *C) {
+ VisitOMPClauseWithPreInit(C);
+ C->setThreadID(Record.readSubExpr());
+ C->setLParenLoc(Record.readSourceLocation());
+}
+
OMPTraitInfo *ASTRecordReader::readOMPTraitInfo() {
OMPTraitInfo &TI = getContext().getNewOMPTraitInfo();
TI.Sets.resize(readUInt32());
diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp
index 6e552e9a2441f..30fb627c2a616 100644
--- a/clang/lib/Serialization/ASTReaderStmt.cpp
+++ b/clang/lib/Serialization/ASTReaderStmt.cpp
@@ -2599,6 +2599,11 @@ void ASTStmtReader::VisitOMPDispatchDirective(OMPDispatchDirective *D) {
D->setTargetCallLoc(Record.readSourceLocation());
}
+void ASTStmtReader::VisitOMPMaskedDirective(OMPMaskedDirective *D) {
+ VisitStmt(D);
+ VisitOMPExecutableDirective(D);
+}
+
//===----------------------------------------------------------------------===//
// ASTReader Implementation
//===----------------------------------------------------------------------===//
@@ -3524,6 +3529,11 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
Context, Record[ASTStmtReader::NumStmtFields], Empty);
break;
+ case STMT_OMP_MASKED_DIRECTIVE:
+ S = OMPMaskedDirective::CreateEmpty(
+ Context, Record[ASTStmtReader::NumStmtFields], Empty);
+ break;
+
case EXPR_CXX_OPERATOR_CALL:
S = CXXOperatorCallExpr::CreateEmpty(
Context, /*NumArgs=*/Record[ASTStmtReader::NumExprFields],
diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp
index ad0349f707742..daa0b54d1b320 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -6249,6 +6249,12 @@ void OMPClauseWriter::VisitOMPNocontextClause(OMPNocontextClause *C) {
Record.AddSourceLocation(C->getLParenLoc());
}
+void OMPClauseWriter::VisitOMPFilterClause(OMPFilterClause *C) {
+ VisitOMPClauseWithPreInit(C);
+ Record.AddStmt(C->getThreadID());
+ Record.AddSourceLocation(C->getLParenLoc());
+}
+
void OMPClauseWriter::VisitOMPPrivateClause(OMPPrivateClause *C) {
Record.push_back(C->varlist_size());
Record.AddSourceLocation(C->getLParenLoc());
diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp
index 97ecd5a773ea1..063a81bbcf3f7 100644
--- a/clang/lib/Serialization/ASTWriterStmt.cpp
+++ b/clang/lib/Serialization/ASTWriterStmt.cpp
@@ -2554,6 +2554,12 @@ void ASTStmtWriter::VisitOMPDispatchDirective(OMPDispatchDirective *D) {
Code = serialization::STMT_OMP_DISPATCH_DIRECTIVE;
}
+void ASTStmtWriter::VisitOMPMaskedDirective(OMPMaskedDirective *D) {
+ VisitStmt(D);
+ VisitOMPExecutableDirective(D);
+ Code = serialization::STMT_OMP_MASKED_DIRECTIVE;
+}
+
//===----------------------------------------------------------------------===//
// ASTWriter Implementation
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
index 1498efd135d2c..ccfc84bd7a58a 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -1296,6 +1296,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
case Stmt::OMPTileDirectiveClass:
case Stmt::OMPInteropDirectiveClass:
case Stmt::OMPDispatchDirectiveClass:
+ case Stmt::OMPMaskedDirectiveClass:
case Stmt::CapturedStmtClass: {
const ExplodedNode *node = Bldr.generateSink(S, Pred, Pred->getState());
Engine.addAbortedBlock(node, currBldrCtx->getBlock());
diff --git a/clang/test/OpenMP/masked_ast_print.cpp b/clang/test/OpenMP/masked_ast_print.cpp
new file mode 100644
index 0000000000000..45727395a2be4
--- /dev/null
+++ b/clang/test/OpenMP/masked_ast_print.cpp
@@ -0,0 +1,54 @@
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=51 -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=51 -x c++ -std=c++11 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=51 -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=51 -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=51 -x c++ -std=c++11 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=51 -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+// expected-no-diagnostics
+
+#ifndef HEADER
+#define HEADER
+
+void foo() {}
+
+int main (int argc, char **argv) {
+ int b = argc, c, d, e, f, g;
+ static int a;
+// CHECK: static int a;
+#pragma omp parallel
+{
+#pragma omp masked
+{
+ a=2;
+}
+
+#pragma omp masked filter(1)
+{
+ a=3;
+}
+
+#pragma omp masked filter(a)
+{
+ a=4;
+}
+}
+// CHECK-NEXT: #pragma omp parallel
+// CHECK-NEXT: {
+// CHECK-NEXT: #pragma omp masked{{$}}
+// CHECK-NEXT: {
+// CHECK-NEXT: a = 2;
+// CHECK-NEXT: }
+// CHECK-NEXT: #pragma omp masked filter(1){{$}}
+// CHECK-NEXT: {
+// CHECK-NEXT: a = 3;
+// CHECK-NEXT: }
+// CHECK-NEXT: #pragma omp masked filter(a){{$}}
+// CHECK-NEXT: {
+// CHECK-NEXT: a = 4;
+// CHECK-NEXT: }
+// CHECK-NEXT: }
+ return (0);
+}
+
+#endif
diff --git a/clang/test/OpenMP/masked_messages.cpp b/clang/test/OpenMP/masked_messages.cpp
new file mode 100644
index 0000000000000..31ed9af846e6b
--- /dev/null
+++ b/clang/test/OpenMP/masked_messages.cpp
@@ -0,0 +1,86 @@
+// RUN: %clang_cc1 -verify -fopenmp %s -Wuninitialized
+
+// RUN: %clang_cc1 -verify -fopenmp-simd %s -Wuninitialized
+
+void xxx(int argc) {
+ int x; // expected-note {{initialize the variable 'x' to silence this warning}}
+#pragma omp masked
+ argc = x; // expected-warning {{variable 'x' is uninitialized when used here}}
+}
+
+void yyy(int argc) {
+ int x; // expected-note {{initialize the variable 'x' to silence this warning}}
+#pragma omp masked filter(1)
+ argc = x; // expected-warning {{variable 'x' is uninitialized when used here}}
+}
+
+int foo();
+
+int main() {
+ #pragma omp masked
+ ;
+ #pragma omp masked filter(1) filter(2) // expected-error {{directive '#pragma omp masked' cannot contain more than one 'filter' clause}}
+ ;
+ int x,y,z;
+ #pragma omp masked filter(x) filter(y) filter(z) // expected-error 2 {{directive '#pragma omp masked' cannot contain more than one 'filter' clause}}
+ ;
+ #pragma omp masked nowait // expected-error {{unexpected OpenMP clause 'nowait' in directive '#pragma omp masked'}}
+ #pragma omp masked unknown // expected-warning {{extra tokens at the end of '#pragma omp masked' are ignored}}
+ foo();
+ {
+ #pragma omp masked
+ } // expected-error {{expected statement}}
+ {
+ #pragma omp masked filter(2)
+ } // expected-error {{expected statement}}
+ #pragma omp for
+ for (int i = 0; i < 10; ++i) {
+ foo();
+ #pragma omp masked filter(1) // expected-error {{region cannot be closely nested inside 'for' region}}
+ foo();
+ }
+ #pragma omp sections
+ {
+ foo();
+ #pragma omp masked // expected-error {{region cannot be closely nested inside 'sections' region}}
+ foo();
+ }
+ #pragma omp single
+ for (int i = 0; i < 10; ++i) {
+ foo();
+ #pragma omp masked allocate(i) // expected-error {{region cannot be closely nested inside 'single' region}} expected-error {{unexpected OpenMP clause 'allocate' in directive '#pragma omp masked'}}
+ foo();
+ }
+ #pragma omp masked
+ for (int i = 0; i < 10; ++i) {
+ foo();
+ #pragma omp masked
+ foo();
+ }
+ #pragma omp for ordered
+ for (int i = 0; i < 10; ++i)
+ #pragma omp masked // expected-error {{region cannot be closely nested inside 'for' region}}
+ {
+ foo();
+ }
+
+ return 0;
+}
+
+int foo() {
+ L1: // expected-note {{jump exits scope of OpenMP structured block}}
+ foo();
+ #pragma omp masked filter(0)
+ {
+ foo();
+ goto L1; // expected-error {{cannot jump from this goto statement to its label}}
+ }
+ goto L2; // expected-error {{cannot jump from this goto statement to its label}}
+ #pragma omp masked filter(-2)
+ { // expected-note {{jump bypasses OpenMP structured block}}
+ L2:
+ foo();
+ }
+
+ return 0;
+}
diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp
index 7f48bda035a14..a6a9cfc39827e 100644
--- a/clang/tools/libclang/CIndex.cpp
+++ b/clang/tools/libclang/CIndex.cpp
@@ -2299,6 +2299,11 @@ void OMPClauseEnqueue::VisitOMPNocontextClause(const OMPNocontextClause *C) {
Visitor->AddStmt(C->getCondition());
}
+void OMPClauseEnqueue::VisitOMPFilterClause(const OMPFilterClause *C) {
+ VisitOMPClauseWithPreInit(C);
+ Visitor->AddStmt(C->getThreadID());
+}
+
void OMPClauseEnqueue::VisitOMPUnifiedAddressClause(
const OMPUnifiedAddressClause *) {}
@@ -5678,6 +5683,8 @@ CXString clang_getCursorKindSpelling(enum CXCursorKind Kind) {
return cxstring::createRef("OMPInteropDirective");
case CXCursor_OMPDispatchDirective:
return cxstring::createRef("OMPDispatchDirective");
+ case CXCursor_OMPMaskedDirective:
+ return cxstring::createRef("OMPMaskedDirective");
case CXCursor_OverloadCandidate:
return cxstring::createRef("OverloadCandidate");
case CXCursor_TypeAliasTemplateDecl:
diff --git a/clang/tools/libclang/CXCursor.cpp b/clang/tools/libclang/CXCursor.cpp
index d715d761f6911..b4822d3b1e934 100644
--- a/clang/tools/libclang/CXCursor.cpp
+++ b/clang/tools/libclang/CXCursor.cpp
@@ -813,6 +813,9 @@ CXCursor cxcursor::MakeCXCursor(const Stmt *S, const Decl *Parent,
case Stmt::OMPDispatchDirectiveClass:
K = CXCursor_OMPDispatchDirective;
break;
+ case Stmt::OMPMaskedDirectiveClass:
+ K = CXCursor_OMPMaskedDirective;
+ break;
case Stmt::BuiltinBitCastExprClass:
K = CXCursor_BuiltinBitCastExpr;
}
diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index ec872d20691b2..dcb70015d5d82 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -772,6 +772,7 @@ CHECK_SIMPLE_CLAUSE(Init, OMPC_init)
CHECK_SIMPLE_CLAUSE(Use, OMPC_use)
CHECK_SIMPLE_CLAUSE(Novariants, OMPC_novariants)
CHECK_SIMPLE_CLAUSE(Nocontext, OMPC_nocontext)
+CHECK_SIMPLE_CLAUSE(Filter, OMPC_filter)
CHECK_REQ_SCALAR_INT_CLAUSE(Allocator, OMPC_allocator)
CHECK_REQ_SCALAR_INT_CLAUSE(Grainsize, OMPC_grainsize)
diff --git a/llvm/include/llvm/Frontend/OpenMP/OMP.td b/llvm/include/llvm/Frontend/OpenMP/OMP.td
index 9d656c0f5201a..817dcba1b9e66 100644
--- a/llvm/include/llvm/Frontend/OpenMP/OMP.td
+++ b/llvm/include/llvm/Frontend/OpenMP/OMP.td
@@ -331,6 +331,10 @@ def OMPC_Link : Clause<"link"> {
}
def OMPC_Inbranch : Clause<"inbranch"> {}
def OMPC_Notinbranch : Clause<"notinbranch"> {}
+def OMPC_Filter : Clause<"filter"> {
+ let clangClass = "OMPFilterClause";
+ let flangClass = "ScalarIntExpr";
+}
//===----------------------------------------------------------------------===//
// Definition of OpenMP directives
@@ -1675,6 +1679,11 @@ def OMP_dispatch : Directive<"dispatch"> {
VersionedClause<OMPC_Nocontext>
];
}
+def OMP_masked : Directive<"masked"> {
+ let allowedOnceClauses = [
+ VersionedClause<OMPC_Filter>
+ ];
+}
def OMP_Unknown : Directive<"unknown"> {
let isDefault = true;
}
More information about the flang-commits
mailing list