[cfe-commits] r160115 - in /cfe/trunk: include/clang/ASTMatchers/ASTMatchers.h unittests/ASTMatchers/ASTMatchersTest.cpp

Daniel Jasper djasper at google.com
Thu Jul 12 01:50:38 PDT 2012


Author: djasper
Date: Thu Jul 12 03:50:38 2012
New Revision: 160115

URL: http://llvm.org/viewvc/llvm-project?rev=160115&view=rev
Log:
This commit combines three patches to the ASTMatchers.

One adds matchers for the various parts of a for loop (initializer, condition,
increment), as well as extending the hasBody matcher to work for while and
do-while loops. The second patch adds an isInteger matcher for types.
The third patch fixes a bug in allOf, where a few of the name chages
(AllOf --> allOf) had been missed.

All matchers come with unit tests.

Patches by Sam Panzer!

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=160115&r1=160114&r2=160115&view=diff
==============================================================================
--- cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h (original)
+++ cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h Thu Jul 12 03:50:38 2012
@@ -471,6 +471,31 @@
 const internal::VariadicDynCastAllOfMatcher<
   Stmt, ForStmt> forStmt;
 
+/// \brief Matches the increment statement of a for loop.
+///
+/// Example:
+///     forStmt(hasIncrement(unaryOperator(hasOperatorName("++"))))
+/// matches '++x' in
+///     for (x; x < N; ++x) { }
+AST_MATCHER_P(ForStmt, hasIncrement, internal::Matcher<Stmt>,
+              InnerMatcher) {
+  const Stmt *const Increment = Node.getInc();
+  return (Increment != NULL &&
+          InnerMatcher.matches(*Increment, Finder, Builder));
+}
+
+/// \brief Matches the initialization statement of a for loop.
+///
+/// Example:
+///     forStmt(hasLoopInit(declarationStatement()))
+/// matches 'int x = 0' in
+///     for (int x = 0; x < N; ++x) { }
+AST_MATCHER_P(ForStmt, hasLoopInit, internal::Matcher<Stmt>,
+              InnerMatcher) {
+  const Stmt *const Init = Node.getInit();
+  return (Init != NULL && InnerMatcher.matches(*Init, Finder, Builder));
+}
+
 /// \brief Matches while statements.
 ///
 /// Given
@@ -702,7 +727,7 @@
 internal::PolymorphicMatcherWithParam2<internal::AllOfMatcher, C1,
     internal::PolymorphicMatcherWithParam2<internal::AllOfMatcher, C2, C3> >
 allOf(const C1& P1, const C2& P2, const C3& P3) {
-  return AllOf(P1, AllOf(P2, P3));
+  return allOf(P1, allOf(P2, P3));
 }
 /// @}
 
@@ -1334,8 +1359,8 @@
   return Matcher.matches(Node.getResultType(), Finder, Builder);
 }
 
-/// \brief Matches the condition expression of an if statement or conditional
-/// operator.
+/// \brief Matches the condition expression of an if statement, for loop,
+/// or conditional operator.
 ///
 /// Example matches true (matcher = hasCondition(boolLiteral(equals(true))))
 ///   if (true) {}
@@ -1343,8 +1368,11 @@
                           InnerMatcher) {
   TOOLING_COMPILE_ASSERT(
     (llvm::is_base_of<IfStmt, NodeType>::value) ||
+    (llvm::is_base_of<ForStmt, NodeType>::value) ||
+    (llvm::is_base_of<WhileStmt, NodeType>::value) ||
+    (llvm::is_base_of<DoStmt, NodeType>::value) ||
     (llvm::is_base_of<ConditionalOperator, NodeType>::value),
-    has_condition_requires_if_statement_or_conditional_operator);
+    has_condition_requires_if_statement_conditional_operator_or_loop);
   const Expr *const Condition = Node.getCond();
   return (Condition != NULL &&
           InnerMatcher.matches(*Condition, Finder, Builder));
@@ -1393,7 +1421,8 @@
   return false;
 }
 
-/// \brief Matches a 'for' statement that has a given body.
+/// \brief Matches a 'for', 'while', or 'do while' statement that has
+/// a given body.
 ///
 /// Given
 ///   for (;;) {}
@@ -1401,8 +1430,13 @@
 ///   matches 'for (;;) {}'
 /// with compoundStatement()
 ///   matching '{}'
-AST_MATCHER_P(ForStmt, hasBody, internal::Matcher<Stmt>,
-              InnerMatcher) {
+AST_POLYMORPHIC_MATCHER_P(hasBody, internal::Matcher<Stmt>,
+                          InnerMatcher) {
+  TOOLING_COMPILE_ASSERT(
+      (llvm::is_base_of<DoStmt, NodeType>::value) ||
+      (llvm::is_base_of<ForStmt, NodeType>::value) ||
+      (llvm::is_base_of<WhileStmt, NodeType>::value),
+      has_body_requires_for_while_or_do_statement);
   const Stmt *const Statement = Node.getBody();
   return (Statement != NULL &&
           InnerMatcher.matches(*Statement, Finder, Builder));
@@ -1614,6 +1648,18 @@
   return makeMatcher(new internal::IsArrowMatcher());
 }
 
+/// \brief Matches QualType nodes that are of integer type.
+///
+/// Given
+///   void a(int);
+///   void b(long);
+///   void c(double);
+/// function(hasAnyParameter(hasType(isInteger())))
+/// matches "a(int)", "b(long)", but not "c(double)".
+AST_MATCHER(QualType, isInteger) {
+    return Node->isIntegerType();
+}
+
 /// \brief Matches QualType nodes that are const-qualified, i.e., that
 /// include "top-level" const.
 ///

Modified: cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.cpp?rev=160115&r1=160114&r2=160115&view=diff
==============================================================================
--- cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.cpp (original)
+++ cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.cpp Thu Jul 12 03:50:38 2012
@@ -276,6 +276,18 @@
                                        isDerivedFrom("Base2")))))));
 }
 
+TEST(AllOf, AllOverloadsWork) {
+  const char Program[] =
+      "struct T { }; int f(int, T*); void g(int x) { T t; f(x, &t); }";
+  EXPECT_TRUE(matches(Program,
+      call(allOf(callee(function(hasName("f"))),
+                 hasArgument(0, declarationReference(to(variable())))))));
+  EXPECT_TRUE(matches(Program,
+      call(allOf(callee(function(hasName("f"))),
+                 hasArgument(0, declarationReference(to(variable()))),
+                 hasArgument(1, hasType(pointsTo(record(hasName("T")))))))));
+}
+
 TEST(DeclarationMatcher, MatchAnyOf) {
   DeclarationMatcher YOrZDerivedFromX =
       record(anyOf(hasName("Y"), allOf(isDerivedFrom("X"), hasName("Z"))));
@@ -898,6 +910,20 @@
               memberExpression()));
 }
 
+TEST(IsInteger, MatchesIntegers) {
+  EXPECT_TRUE(matches("int i = 0;", variable(hasType(isInteger()))));
+  EXPECT_TRUE(matches("long long i = 0; void f(long long) { }; void g() {f(i);}",
+                      call(hasArgument(0, declarationReference(
+                          to(variable(hasType(isInteger()))))))));
+}
+
+TEST(IsInteger, ReportsNoFalsePositives) {
+  EXPECT_TRUE(notMatches("int *i;", variable(hasType(isInteger()))));
+  EXPECT_TRUE(notMatches("struct T {}; T t; void f(T *) { }; void g() {f(&t);}",
+                      call(hasArgument(0, declarationReference(
+                          to(variable(hasType(isInteger()))))))));
+}
+
 TEST(IsArrow, MatchesMemberVariablesViaArrow) {
   EXPECT_TRUE(matches("class Y { void x() { this->y; } int y; };",
               memberExpression(isArrow())));
@@ -1747,6 +1773,20 @@
   EXPECT_TRUE(matches("void f() { if(true) for(;;); }", forStmt()));
 }
 
+TEST(For, ForLoopInternals) {
+  EXPECT_TRUE(matches("void f(){ int i; for (; i < 3 ; ); }",
+                      forStmt(hasCondition(anything()))));
+  EXPECT_TRUE(matches("void f() { for (int i = 0; ;); }",
+                      forStmt(hasLoopInit(anything()))));
+}
+
+TEST(For, NegativeForLoopInternals) {
+  EXPECT_TRUE(notMatches("void f(){ for (int i = 0; ; ++i); }",
+                         forStmt(hasCondition(expression()))));
+  EXPECT_TRUE(notMatches("void f() {int i; for (; i < 4; ++i) {} }",
+                         forStmt(hasLoopInit(anything()))));
+}
+
 TEST(For, ReportsNoFalsePositives) {
   EXPECT_TRUE(notMatches("void f() { ; }", forStmt()));
   EXPECT_TRUE(notMatches("void f() { if(true); }", forStmt()));
@@ -1767,13 +1807,15 @@
               compoundStatement()));
 }
 
-TEST(HasBody, FindsBodyOfForLoop) {
-  StatementMatcher HasCompoundStatementBody =
-      forStmt(hasBody(compoundStatement()));
+TEST(HasBody, FindsBodyOfForWhileDoLoops) {
   EXPECT_TRUE(matches("void f() { for(;;) {} }",
-              HasCompoundStatementBody));
+              forStmt(hasBody(compoundStatement()))));
   EXPECT_TRUE(notMatches("void f() { for(;;); }",
-              HasCompoundStatementBody));
+              forStmt(hasBody(compoundStatement()))));
+  EXPECT_TRUE(matches("void f() { while(true) {} }",
+              whileStmt(hasBody(compoundStatement()))));
+  EXPECT_TRUE(matches("void f() { do {} while(true); }",
+              doStmt(hasBody(compoundStatement()))));
 }
 
 TEST(HasAnySubstatement, MatchesForTopLevelCompoundStatement) {





More information about the cfe-commits mailing list