Index: docs/LibASTMatchersReference.html =================================================================== --- docs/LibASTMatchersReference.html +++ docs/LibASTMatchersReference.html @@ -3400,8 +3400,8 @@
Matches a 'for', 'while', or 'do while' statement that has -a given body. + Matches a 'for', 'while', 'do while' statement or a function +declaration that has a given body. Given for (;;) {} @@ -3825,8 +3825,8 @@- Matcher<DoStmt> hasBody Matcher<Stmt> InnerMatcher Matches a 'for', 'while', or 'do while' statement that has -a given body. + Matches a 'for', 'while', 'do while' statement or a function +declaration that has a given body. Given for (;;) {} @@ -4006,8 +4006,8 @@- Matcher<ForStmt> hasBody Matcher<Stmt> InnerMatcher Matches a 'for', 'while', or 'do while' statement that has -a given body. ++ Matches a 'for', 'while', 'do while' statement or a function +declaration that has a given body. Given for (;;) {} @@ -4061,6 +4061,19 @@+ Matcher<FunctionDecl> hasBody Matcher<Stmt> InnerMatcher + + Matches a 'for', 'while', 'do while' statement or a function +declaration that has a given body. + +Given + for (;;) {} +hasBody(compoundStmt()) + matches 'for (;;) {}' +with compoundStmt() + matching '{}' +Matcher<FunctionDecl> hasParameter unsigned N, Matcher<ParmVarDecl> InnerMatcher Matches the n'th parameter of a function declaration. @@ -4838,8 +4851,8 @@- Matcher<WhileStmt> hasBody Matcher<Stmt> InnerMatcher Matches a 'for', 'while', or 'do while' statement that has -a given body. + Matches a 'for', 'while', 'do while' statement or a function +declaration that has a given body. Given for (;;) {} Index: include/clang/ASTMatchers/ASTMatchers.h =================================================================== --- include/clang/ASTMatchers/ASTMatchers.h +++ include/clang/ASTMatchers/ASTMatchers.h @@ -3114,8 +3114,8 @@ return false; } -/// \brief Matches a 'for', 'while', or 'do while' statement that has -/// a given body. +/// \brief Matches a 'for', 'while', 'do while' statement or a function +/// declaration that has a given body. /// /// Given /// \code @@ -3128,9 +3128,10 @@ AST_POLYMORPHIC_MATCHER_P(hasBody, AST_POLYMORPHIC_SUPPORTED_TYPES(DoStmt, ForStmt, WhileStmt, - CXXForRangeStmt), + CXXForRangeStmt, + FunctionDecl), internal::Matcher, InnerMatcher) { - const Stmt *const Statement = Node.getBody(); + const Stmt *const Statement = internal::GetBodyMatcher ::get(Node); return (Statement != nullptr && InnerMatcher.matches(*Statement, Finder, Builder)); } Index: include/clang/ASTMatchers/ASTMatchersInternal.h =================================================================== --- include/clang/ASTMatchers/ASTMatchersInternal.h +++ include/clang/ASTMatchers/ASTMatchersInternal.h @@ -1584,6 +1584,14 @@ ast_type_traits::DynTypedNode Node; }; + +template +struct GetBodyMatcher { +static const Stmt *get(const Ty &Node) { + return Node.getBody(); +} +}; + } // end namespace internal } // end namespace ast_matchers } // end namespace clang Index: lib/ASTMatchers/ASTMatchersInternal.cpp =================================================================== --- lib/ASTMatchers/ASTMatchersInternal.cpp +++ lib/ASTMatchers/ASTMatchersInternal.cpp @@ -339,6 +339,11 @@ return matchesNodeFull(Node); } +template <> +const Stmt *GetBodyMatcher ::get(const FunctionDecl &Node) { + return Node.isThisDeclarationADefinition() ? Node.getBody() : NULL; +} + } // end namespace internal } // end namespace ast_matchers } // end namespace clang Index: unittests/ASTMatchers/ASTMatchersTest.cpp =================================================================== --- unittests/ASTMatchers/ASTMatchersTest.cpp +++ unittests/ASTMatchers/ASTMatchersTest.cpp @@ -2858,7 +2858,7 @@ compoundStmt())); } -TEST(HasBody, FindsBodyOfForWhileDoLoops) { +TEST(HasBody, FindsBodyOfForWhileDoLoopsAndFunctions) { EXPECT_TRUE(matches("void f() { for(;;) {} }", forStmt(hasBody(compoundStmt())))); EXPECT_TRUE(notMatches("void f() { for(;;); }", @@ -2869,6 +2869,10 @@ doStmt(hasBody(compoundStmt())))); EXPECT_TRUE(matches("void f() { int p[2]; for (auto x : p) {} }", cxxForRangeStmt(hasBody(compoundStmt())))); + EXPECT_TRUE(matches("void f() {}", functionDecl(hasBody(compoundStmt())))); + EXPECT_TRUE(notMatches("void f();", functionDecl(hasBody(compoundStmt())))); + EXPECT_TRUE(matches("void f(); void f() {}", + functionDecl(hasBody(compoundStmt())))); } TEST(HasAnySubstatement, MatchesForTopLevelCompoundStatement) { Index: unittests/ASTMatchers/Dynamic/ParserTest.cpp =================================================================== --- unittests/ASTMatchers/Dynamic/ParserTest.cpp +++ unittests/ASTMatchers/Dynamic/ParserTest.cpp @@ -263,7 +263,7 @@ "1:1: Matcher does not support binding.", ParseWithError("isArrow().bind(\"foo\")")); EXPECT_EQ("Input value has unresolved overloaded type: " - "Matcher ", + "Matcher ", ParseMatcherWithError("hasBody(stmt())")); }