Author: pcc Date: Fri May 10 06:52:02 2013 New Revision: 181588 URL: http://llvm.org/viewvc/llvm-project?rev=181588&view=rev Log: Add caseStmt(), defaultStmt(), eachCase() and hasCaseConstant() matchers.
Differential Revision: http://llvm-reviews.chandlerc.com/D744 Modified: cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.cpp Modified: cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h?rev=181588&r1=181587&r2=181588&view=diff ============================================================================== --- cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h (original) +++ cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h Fri May 10 06:52:02 2013 @@ -894,6 +894,26 @@ const internal::VariadicDynCastAllOfMatc /// matches 'case 42: break;' and 'default: break;'. const internal::VariadicDynCastAllOfMatcher<Stmt, SwitchCase> switchCase; +/// \brief Matches case statements inside switch statements. +/// +/// Given +/// \code +/// switch(a) { case 42: break; default: break; } +/// \endcode +/// caseStmt() +/// matches 'case 42: break;'. +const internal::VariadicDynCastAllOfMatcher<Stmt, CaseStmt> caseStmt; + +/// \brief Matches default statements inside switch statements. +/// +/// Given +/// \code +/// switch(a) { case 42: break; default: break; } +/// \endcode +/// defaultStmt() +/// matches 'default: break;'. +const internal::VariadicDynCastAllOfMatcher<Stmt, DefaultStmt> defaultStmt; + /// \brief Matches compound statements. /// /// Example matches '{}' and '{{}}'in 'for (;;) {{}}' @@ -3348,6 +3368,54 @@ AST_MATCHER_P_OVERLOAD(Stmt, equalsNode, /// @} +/// \brief Matches each case or default statement belonging to the given switch +/// statement. This matcher may produce multiple matches. +/// +/// Given +/// \code +/// switch (1) { case 1: case 2: default: switch (2) { case 3: case 4: ; } } +/// \endcode +/// switchStmt(forEachSwitchCase(caseStmt().bind("c"))).bind("s") +/// matches four times, with "c" binding each of "case 1:", "case 2:", +/// "case 3:" and "case 4:", and "s" respectively binding "switch (1)", +/// "switch (1)", "switch (2)" and "switch (2)". +AST_MATCHER_P(SwitchStmt, forEachSwitchCase, internal::Matcher<SwitchCase>, + InnerMatcher) { + // FIXME: getSwitchCaseList() does not necessarily guarantee a stable + // iteration order. We should use the more general iterating matchers once + // they are capable of expressing this matcher (for example, it should ignore + // case statements belonging to nested switch statements). + bool Matched = false; + for (const SwitchCase *SC = Node.getSwitchCaseList(); SC; + SC = SC->getNextSwitchCase()) { + BoundNodesTreeBuilder CaseBuilder; + bool CaseMatched = InnerMatcher.matches(*SC, Finder, &CaseBuilder); + if (CaseMatched) { + Matched = true; + Builder->addMatch(CaseBuilder.build()); + } + } + + return Matched; +} + +/// \brief If the given case statement does not use the GNU case range +/// extension, matches the constant given in the statement. +/// +/// Given +/// \code +/// switch (1) { case 1: case 1+1: case 3 ... 4: ; } +/// \endcode +/// caseStmt(hasCaseConstant(integerLiteral())) +/// matches "case 1:" +AST_MATCHER_P(CaseStmt, hasCaseConstant, internal::Matcher<Expr>, + InnerMatcher) { + if (Node.getRHS()) + return false; + + return InnerMatcher.matches(*Node.getLHS(), Finder, Builder); +} + } // end namespace ast_matchers } // end namespace clang Modified: cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.cpp?rev=181588&r1=181587&r2=181588&view=diff ============================================================================== --- cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.cpp (original) +++ cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.cpp Fri May 10 06:52:02 2013 @@ -2924,6 +2924,31 @@ TEST(SwitchCase, MatchesSwitch) { EXPECT_TRUE(notMatches("void x() {}", switchStmt())); } +TEST(SwitchCase, MatchesEachCase) { + EXPECT_TRUE(notMatches("void x() { switch(42); }", + switchStmt(forEachSwitchCase(caseStmt())))); + EXPECT_TRUE(matches("void x() { switch(42) case 42:; }", + switchStmt(forEachSwitchCase(caseStmt())))); + EXPECT_TRUE(matches("void x() { switch(42) { case 42:; } }", + switchStmt(forEachSwitchCase(caseStmt())))); + EXPECT_TRUE(notMatches( + "void x() { if (1) switch(42) { case 42: switch (42) { default:; } } }", + ifStmt(has(switchStmt(forEachSwitchCase(defaultStmt())))))); + EXPECT_TRUE(matches("void x() { switch(42) { case 1+1: case 4:; } }", + switchStmt(forEachSwitchCase( + caseStmt(hasCaseConstant(integerLiteral())))))); + EXPECT_TRUE(notMatches("void x() { switch(42) { case 1+1: case 2+2:; } }", + switchStmt(forEachSwitchCase( + caseStmt(hasCaseConstant(integerLiteral())))))); + EXPECT_TRUE(notMatches("void x() { switch(42) { case 1 ... 2:; } }", + switchStmt(forEachSwitchCase( + caseStmt(hasCaseConstant(integerLiteral())))))); + EXPECT_TRUE(matchAndVerifyResultTrue( + "void x() { switch (42) { case 1: case 2: case 3: default:; } }", + switchStmt(forEachSwitchCase(caseStmt().bind("x"))), + new VerifyIdIsBoundTo<CaseStmt>("x", 3))); +} + TEST(ExceptionHandling, SimpleCases) { EXPECT_TRUE(matches("void foo() try { } catch(int X) { }", catchStmt())); EXPECT_TRUE(matches("void foo() try { } catch(int X) { }", tryStmt())); _______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
