Hi klimek, djasper,

http://llvm-reviews.chandlerc.com/D744

Files:
  include/clang/ASTMatchers/ASTMatchers.h
  unittests/ASTMatchers/ASTMatchersTest.cpp

Index: include/clang/ASTMatchers/ASTMatchers.h
===================================================================
--- include/clang/ASTMatchers/ASTMatchers.h
+++ include/clang/ASTMatchers/ASTMatchers.h
@@ -894,6 +894,26 @@
 ///   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 (;;) {{}}'
@@ -3331,6 +3351,36 @@
 
 /// @}
 
+/// \brief Matches each case or default statement belonging to the given switch
+/// statement.
+AST_MATCHER_P(SwitchStmt, eachCase, internal::Matcher<SwitchCase>,
+              InnerMatcher) {
+  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 switch case is a case statement which does not use
+/// the GNU case range extension, matches the constant given in the case
+/// statement.
+AST_MATCHER_P(SwitchCase, hasCaseConstant, internal::Matcher<Expr>,
+              InnerMatcher) {
+  const CaseStmt *CS = dyn_cast<CaseStmt>(&Node);
+  if (!CS || CS->getRHS()) // We don't handle the GNU case range extension.
+    return false;
+
+  return InnerMatcher.matches(*CS->getLHS(), Finder, Builder);
+}
+
 } // end namespace ast_matchers
 } // end namespace clang
 
Index: unittests/ASTMatchers/ASTMatchersTest.cpp
===================================================================
--- unittests/ASTMatchers/ASTMatchersTest.cpp
+++ unittests/ASTMatchers/ASTMatchersTest.cpp
@@ -2917,6 +2917,23 @@
   EXPECT_TRUE(notMatches("void x() {}", switchStmt()));
 }
 
+TEST(SwitchCase, MatchesEachCase) {
+  EXPECT_TRUE(
+      notMatches("void x() { switch(42); }", 
switchStmt(eachCase(caseStmt()))));
+  EXPECT_TRUE(matches("void x() { switch(42) case 42:; }",
+                      switchStmt(eachCase(caseStmt()))));
+  EXPECT_TRUE(matches("void x() { switch(42) { case 42:; } }",
+                      switchStmt(eachCase(caseStmt()))));
+  EXPECT_TRUE(notMatches(
+      "void x() { if (1) switch(42) { case 42: switch (42) { default:; } } }",
+      ifStmt(switchStmt(eachCase(defaultStmt())))));
+  EXPECT_TRUE(matches("void x() { switch(42) { case 1+1: case 4:; } }",
+                      
switchStmt(eachCase(hasCaseConstant(integerLiteral())))));
+  EXPECT_TRUE(
+      notMatches("void x() { switch(42) { case 1+1: case 2+2:; } }",
+                 switchStmt(eachCase(hasCaseConstant(integerLiteral())))));
+}
+
 TEST(ExceptionHandling, SimpleCases) {
   EXPECT_TRUE(matches("void foo() try { } catch(int X) { }", catchStmt()));
   EXPECT_TRUE(matches("void foo() try { } catch(int X) { }", tryStmt()));
Index: include/clang/ASTMatchers/ASTMatchers.h
===================================================================
--- include/clang/ASTMatchers/ASTMatchers.h
+++ include/clang/ASTMatchers/ASTMatchers.h
@@ -894,6 +894,26 @@
 ///   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 (;;) {{}}'
@@ -3331,6 +3351,36 @@
 
 /// @}
 
+/// \brief Matches each case or default statement belonging to the given switch
+/// statement.
+AST_MATCHER_P(SwitchStmt, eachCase, internal::Matcher<SwitchCase>,
+              InnerMatcher) {
+  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 switch case is a case statement which does not use
+/// the GNU case range extension, matches the constant given in the case
+/// statement.
+AST_MATCHER_P(SwitchCase, hasCaseConstant, internal::Matcher<Expr>,
+              InnerMatcher) {
+  const CaseStmt *CS = dyn_cast<CaseStmt>(&Node);
+  if (!CS || CS->getRHS()) // We don't handle the GNU case range extension.
+    return false;
+
+  return InnerMatcher.matches(*CS->getLHS(), Finder, Builder);
+}
+
 } // end namespace ast_matchers
 } // end namespace clang
 
Index: unittests/ASTMatchers/ASTMatchersTest.cpp
===================================================================
--- unittests/ASTMatchers/ASTMatchersTest.cpp
+++ unittests/ASTMatchers/ASTMatchersTest.cpp
@@ -2917,6 +2917,23 @@
   EXPECT_TRUE(notMatches("void x() {}", switchStmt()));
 }
 
+TEST(SwitchCase, MatchesEachCase) {
+  EXPECT_TRUE(
+      notMatches("void x() { switch(42); }", switchStmt(eachCase(caseStmt()))));
+  EXPECT_TRUE(matches("void x() { switch(42) case 42:; }",
+                      switchStmt(eachCase(caseStmt()))));
+  EXPECT_TRUE(matches("void x() { switch(42) { case 42:; } }",
+                      switchStmt(eachCase(caseStmt()))));
+  EXPECT_TRUE(notMatches(
+      "void x() { if (1) switch(42) { case 42: switch (42) { default:; } } }",
+      ifStmt(switchStmt(eachCase(defaultStmt())))));
+  EXPECT_TRUE(matches("void x() { switch(42) { case 1+1: case 4:; } }",
+                      switchStmt(eachCase(hasCaseConstant(integerLiteral())))));
+  EXPECT_TRUE(
+      notMatches("void x() { switch(42) { case 1+1: case 2+2:; } }",
+                 switchStmt(eachCase(hasCaseConstant(integerLiteral())))));
+}
+
 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

Reply via email to