[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