Index: include/clang/ASTMatchers/ASTMatchers.h =================================================================== --- include/clang/ASTMatchers/ASTMatchers.h +++ include/clang/ASTMatchers/ASTMatchers.h @@ -842,15 +842,6 @@ /// \endcode const internal::VariadicDynCastAllOfMatcher forStmt; -/// \brief Matches range-based for statements. -/// -/// forRangeStmt() matches 'for (auto a : i)' -/// \code -/// int i[] = {1, 2, 3}; for (auto a : i); -/// for(int j = 0; j < 5; ++j); -/// \endcode -const internal::VariadicDynCastAllOfMatcher forRangeStmt; - /// \brief Matches the increment statement of a for loop. /// /// Example: @@ -880,6 +871,29 @@ return (Init != NULL && InnerMatcher.matches(*Init, Finder, Builder)); } +/// \brief Matches range-based for statements. +/// +/// forRangeStmt() matches 'for (auto a : i)' +/// \code +/// int i[] = {1, 2, 3}; for (auto a : i); +/// for(int j = 0; j < 5; ++j); +/// \endcode +const internal::VariadicDynCastAllOfMatcher forRangeStmt; + +/// \brief Matches the initialization statement of a for loop. +/// +/// Example: +/// forStmt(hasLoopVarStmt()) +/// matches 'int x' in +/// \code +/// for (int x : a) { } +/// \endcode +AST_MATCHER_P(CXXForRangeStmt, hasLoopVariable, internal::Matcher, + InnerMatcher) { + const VarDecl *const Var = Node.getLoopVariable(); + return (Var != NULL && InnerMatcher.matches(*Var, Finder, Builder)); +} + /// \brief Matches while statements. /// /// Given Index: unittests/ASTMatchers/ASTMatchersTest.cpp =================================================================== --- unittests/ASTMatchers/ASTMatchersTest.cpp +++ unittests/ASTMatchers/ASTMatchersTest.cpp @@ -2339,6 +2339,11 @@ forStmt(hasLoopInit(anything())))); } +TEST(For, ForRangeLoopInternals) { + EXPECT_TRUE(matches("void f(){ int a[] {1, 2}; for (int i : a); }", + forRangeStmt(hasLoopVariable(anything())))); +} + TEST(For, NegativeForLoopInternals) { EXPECT_TRUE(notMatches("void f(){ for (int i = 0; ; ++i); }", forStmt(hasCondition(expr()))));