diff --git a/clang/docs/LibASTMatchersReference.html b/clang/docs/LibASTMatchersReference.html
--- a/clang/docs/LibASTMatchersReference.html
+++ b/clang/docs/LibASTMatchersReference.html
@@ -7298,6 +7298,16 @@
+
Matcher<CaseStmt> | hasSubstmt | Matcher<Stmt> InnerMatcher |
+Matches the substatement associated with a case statement.
+
+Given
+ switch (1) { case 1: break; case 2: return; break; default: return; break; }
+caseStmt(hasSubstmt(returnStmt()))
+ matches "case 2: return;"
+ |
+
+
Matcher<CastExpr> | hasSourceExpression | Matcher<Expr> InnerMatcher |
Matches if the cast's source expression
or opaque value's source expression matches the given matcher.
@@ -7653,6 +7663,16 @@
|
+Matcher<DefaultStmt> | hasSubstmt | Matcher<Stmt> InnerMatcher |
+Matches the substatement associated with a default statement.
+
+Given
+ switch (1) { case 1: break; case 2: return; break; default: return; break; }
+defaultStmt(hasSubstmt(returnStmt()))
+ matches "default: return;"
+ |
+
+
Matcher<DoStmt> | hasBody | Matcher<Stmt> InnerMatcher |
|
diff --git a/clang/include/clang/ASTMatchers/ASTMatchers.h b/clang/include/clang/ASTMatchers/ASTMatchers.h
--- a/clang/include/clang/ASTMatchers/ASTMatchers.h
+++ b/clang/include/clang/ASTMatchers/ASTMatchers.h
@@ -2429,6 +2429,7 @@
/// Matches co_await expressions where the type of the promise is dependent
extern const internal::VariadicDynCastAllOfMatcher
dependentCoawaitExpr;
+
/// Matches co_yield expressions.
///
/// Given
@@ -7716,6 +7717,24 @@
return InnerMatcher.matches(*Node.getLHS(), Finder, Builder);
}
+/// Matches the substatement associated with a case or default statement.
+///
+/// Given
+/// \code
+/// switch (1) { case 1: break; case 2: return; break; default: return; break; }
+/// \endcode
+///
+/// caseStmt(hasSubstmt(returnStmt()))
+/// matches "case 2: return;"
+/// defaultStmt(hasSubstmt(returnStmt()))
+/// matches "default: return;"
+AST_POLYMORPHIC_MATCHER_P(hasSubstmt,
+ AST_POLYMORPHIC_SUPPORTED_TYPES(CaseStmt,
+ DefaultStmt),
+ internal::Matcher, InnerMatcher) {
+ return InnerMatcher.matches(*Node.getSubStmt(), Finder, Builder);
+}
+
/// Matches declaration that has a given attribute.
///
/// Given
diff --git a/clang/lib/ASTMatchers/Dynamic/Registry.cpp b/clang/lib/ASTMatchers/Dynamic/Registry.cpp
--- a/clang/lib/ASTMatchers/Dynamic/Registry.cpp
+++ b/clang/lib/ASTMatchers/Dynamic/Registry.cpp
@@ -66,7 +66,7 @@
#define REGISTER_MATCHER(name) \
registerMatcher(#name, internal::makeMatcherAutoMarshall( \
- ::clang::ast_matchers::name, #name));
+ ::clang::ast_matchers::name, #name))
#define REGISTER_MATCHER_OVERLOAD(name) \
registerMatcher(#name, \
@@ -143,7 +143,7 @@
REGISTER_MATCHER(atomicType);
REGISTER_MATCHER(attr);
REGISTER_MATCHER(autoType);
- REGISTER_MATCHER(autoreleasePoolStmt)
+ REGISTER_MATCHER(autoreleasePoolStmt);
REGISTER_MATCHER(binaryConditionalOperator);
REGISTER_MATCHER(binaryOperator);
REGISTER_MATCHER(binaryOperation);
@@ -355,6 +355,7 @@
REGISTER_MATCHER(hasSpecializedTemplate);
REGISTER_MATCHER(hasStaticStorageDuration);
REGISTER_MATCHER(hasStructuredBlock);
+ REGISTER_MATCHER(hasSubstmt);
REGISTER_MATCHER(hasSyntacticForm);
REGISTER_MATCHER(hasTargetDecl);
REGISTER_MATCHER(hasTemplateArgument);
diff --git a/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
--- a/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
+++ b/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
@@ -311,6 +311,18 @@
EXPECT_TRUE(notMatches("struct Foo {};", NamedNotRecord));
}
+TEST_P(ASTMatchersTest, HasCaseSubstmt) {
+ EXPECT_TRUE(matches(
+ "void f() { switch (1) { case 1: return; break; default: break; } }",
+ traverse(TK_AsIs, caseStmt(hasSubstmt(returnStmt())))));
+}
+
+TEST_P(ASTMatchersTest, HasDefaultSubstmt) {
+ EXPECT_TRUE(matches(
+ "void f() { switch (1) { case 1: return; break; default: break; } }",
+ traverse(TK_AsIs, defaultStmt(hasSubstmt(breakStmt())))));
+}
+
TEST_P(ASTMatchersTest, HasCastKind) {
EXPECT_TRUE(
matches("char *p = 0;",