Index: docs/LibASTMatchersReference.html =================================================================== --- docs/LibASTMatchersReference.html +++ docs/LibASTMatchersReference.html @@ -3460,6 +3460,20 @@ +Matcher<OMPExecutableDirective>isStandaloneDirective +
Given OpenMP directive, matches if it is an OpenMP standalone directive,
+i.e. an executable directive with no structured block.
+
+Example:
+
+Given ``ompExecutableDirective(isStandaloneDirective()))``:
+
+  #pragma omp parallel   // <- no match, not standalone
+  {}
+  #pragma omp taskyield  // <- match, is standalone
+
+ + Matcher<ObjCMessageExpr>argumentCountIsunsigned N
Checks that a call expression or a constructor call expression has
 a specific number of arguments (including absent default arguments).
@@ -3830,6 +3844,19 @@
 
+Matcher<Stmt>isOMPStructuredBlock +
Will match the Stmt AST node that is marked as being the structured block
+of an OpenMP executable directive.
+
+Example:
+
+Given ``stmt(isOMPStructuredBlock()))``:
+
+   #pragma omp parallel
+   ;                     // <- will match `;`
+
+ + Matcher<StringLiteral>hasSizeunsigned N
Matches nodes that have the specified size.
 
@@ -6197,6 +6224,24 @@
 
+Matcher<OMPExecutableDirective>hasStructuredBlockMatcher<Stmt> InnerMatcher +
Given OpenMP executable directive, matches if the InnerMatcher matches the
+structured block of this OpenMP executable directive.
+
+Prerequisite: the executable directive must not be standalone directive.
+
+Example:
+
+Given ``ompExecutableDirective(hasStructuredBlock(nullStmt()))``:
+
+   #pragma omp parallel
+   ;                     // <- will match `;`
+
+   #pragma omp parallel
+   {}                    // <- no match
+
+ + Matcher<OMPExecutableDirective>isAllowedToContainClauseMatcher<OMPClause> ClauseMatcher
Matches if the OpenMP directive is allowed to contain the specified OpenMP
 clause kind.
Index: include/clang/ASTMatchers/ASTMatchers.h
===================================================================
--- include/clang/ASTMatchers/ASTMatchers.h
+++ include/clang/ASTMatchers/ASTMatchers.h
@@ -6386,6 +6386,58 @@
 extern const internal::VariadicDynCastAllOfMatcher
     ompExecutableDirective;
 
+/// Given OpenMP directive, matches if it is an OpenMP standalone directive,
+/// i.e. an executable directive with no structured block.
+///
+/// Example:
+///
+/// Given ``ompExecutableDirective(isStandaloneDirective()))``:
+///
+/// \code
+///   #pragma omp parallel   // <- no match, not standalone
+///   {}
+///   #pragma omp taskyield  // <- match, is standalone
+/// \endcode
+AST_MATCHER(OMPExecutableDirective, isStandaloneDirective) {
+  return Node.isStandaloneDirective();
+}
+
+/// Will match the Stmt AST node that is marked as being the structured block
+/// of an OpenMP executable directive.
+///
+/// Example:
+///
+/// Given ``stmt(isOMPStructuredBlock()))``:
+///
+/// \code
+///    #pragma omp parallel
+///    ;                     // <- will match `;`
+/// \endcode
+AST_MATCHER(Stmt, isOMPStructuredBlock) { return Node.isOMPStructuredBlock(); }
+
+/// Given OpenMP executable directive, matches if the InnerMatcher matches the
+/// structured block of this OpenMP executable directive.
+///
+/// Prerequisite: the executable directive must not be standalone directive.
+///
+/// Example:
+///
+/// Given ``ompExecutableDirective(hasStructuredBlock(nullStmt()))``:
+///
+/// \code
+///    #pragma omp parallel
+///    ;                     // <- will match `;`
+/// \endcode
+///
+/// \code
+///    #pragma omp parallel
+///    {}                    // <- no match
+/// \endcode
+AST_MATCHER_P(OMPExecutableDirective, hasStructuredBlock,
+              internal::Matcher, InnerMatcher) {
+  return InnerMatcher.matches(*Node.getStructuredBlock(), Finder, Builder);
+}
+
 /// Given OpenMP directive, matches the first clause (out of all specified),
 /// that matches InnerMatcher.
 ///
Index: lib/ASTMatchers/Dynamic/Registry.cpp
===================================================================
--- lib/ASTMatchers/Dynamic/Registry.cpp
+++ lib/ASTMatchers/Dynamic/Registry.cpp
@@ -510,6 +510,9 @@
   REGISTER_MATCHER(ompDefaultClause);
   REGISTER_MATCHER(isNoneKind);
   REGISTER_MATCHER(isAllowedToContainClause);
+  REGISTER_MATCHER(isStandaloneDirective);
+  REGISTER_MATCHER(isOMPStructuredBlock);
+  REGISTER_MATCHER(hasStructuredBlock);
 }
 
 RegistryMaps::~RegistryMaps() = default;
Index: unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
===================================================================
--- unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
+++ unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
@@ -2274,6 +2274,57 @@
     notMatches("int main2() {}", functionDecl(isMain())));
 }
 
+TEST(OMPExecutableDirective, isStandaloneDirective) {
+  auto Matcher = ompExecutableDirective(isStandaloneDirective());
+
+  const std::string Source0 = R"(void x() {
+#pragma omp parallel
+;
+})";
+  EXPECT_TRUE(notMatchesWithOpenMP(Source0, Matcher));
+
+  const std::string Source1 = R"(void x() {
+#pragma omp taskyield
+})";
+  EXPECT_TRUE(matchesWithOpenMP(Source1, Matcher));
+}
+
+TEST(Stmt, isOMPStructuredBlock) {
+  const std::string Source0 = R"(void x() {
+#pragma omp parallel
+;
+})";
+  EXPECT_TRUE(
+      matchesWithOpenMP(Source0, stmt(nullStmt(), isOMPStructuredBlock())));
+
+  const std::string Source1 = R"(void x() {
+#pragma omp parallel
+{;}
+})";
+  EXPECT_TRUE(
+      notMatchesWithOpenMP(Source1, stmt(nullStmt(), isOMPStructuredBlock())));
+  EXPECT_TRUE(
+      matchesWithOpenMP(Source1, stmt(compoundStmt(), isOMPStructuredBlock())));
+}
+
+TEST(OMPExecutableDirective, hasStructuredBlock) {
+  const std::string Source0 = R"(void x() {
+#pragma omp parallel
+;
+})";
+  EXPECT_TRUE(matchesWithOpenMP(
+      Source0, ompExecutableDirective(hasStructuredBlock(nullStmt()))));
+
+  const std::string Source1 = R"(void x() {
+#pragma omp parallel
+{;}
+})";
+  EXPECT_TRUE(notMatchesWithOpenMP(
+      Source1, ompExecutableDirective(hasStructuredBlock(nullStmt()))));
+  EXPECT_TRUE(matchesWithOpenMP(
+      Source1, ompExecutableDirective(hasStructuredBlock(compoundStmt()))));
+}
+
 TEST(OMPExecutableDirective, hasClause) {
   auto Matcher = ompExecutableDirective(hasClause(anything()));