aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Jasper <djasper@google.com>2012-10-01 13:40:41 +0000
committerDaniel Jasper <djasper@google.com>2012-10-01 13:40:41 +0000
commit31f7c08a0d2b140bf31a08894d1948649de53c15 (patch)
tree2af101527ec81be26e28acaa67dd4d02e5dff38c
parent3dd82f7f01a9ba995bea3027a934df85850cab58 (diff)
Add matchers for selected C++11 features.
Patch by Gábor Horváth. Review: http://llvm-reviews.chandlerc.com/D46 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@164943 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/ASTMatchers/ASTMatchers.h30
-rw-r--r--unittests/ASTMatchers/ASTMatchersTest.cpp41
-rw-r--r--unittests/ASTMatchers/ASTMatchersTest.h9
3 files changed, 71 insertions, 9 deletions
diff --git a/include/clang/ASTMatchers/ASTMatchers.h b/include/clang/ASTMatchers/ASTMatchers.h
index 6507433e33..770ec779b1 100644
--- a/include/clang/ASTMatchers/ASTMatchers.h
+++ b/include/clang/ASTMatchers/ASTMatchers.h
@@ -489,6 +489,14 @@ const internal::VariadicDynCastAllOfMatcher<Stmt, MemberExpr> memberExpr;
/// \endcode
const internal::VariadicDynCastAllOfMatcher<Stmt, CallExpr> callExpr;
+/// \brief Matches lambda expressions.
+///
+/// Example matches [&](){return 5;}
+/// \code
+/// [&](){return 5;}
+/// \endcode
+const internal::VariadicDynCastAllOfMatcher<Stmt, LambdaExpr> lambdaExpr;
+
/// \brief Matches member call expressions.
///
/// Example matches x.y()
@@ -664,9 +672,19 @@ const internal::VariadicDynCastAllOfMatcher<Stmt, IfStmt> ifStmt;
/// Example matches 'for (;;) {}'
/// \code
/// for (;;) {}
+/// int i[] = {1, 2, 3}; for (auto a : i);
/// \endcode
const internal::VariadicDynCastAllOfMatcher<Stmt, ForStmt> 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<Stmt, CXXForRangeStmt> forRangeStmt;
+
/// \brief Matches the increment statement of a for loop.
///
/// Example:
@@ -884,6 +902,18 @@ const internal::VariadicDynCastAllOfMatcher<
Stmt,
IntegerLiteral> integerLiteral;
+/// \brief Matches user defined literal operator call.
+///
+/// Example match: "foo"_suffix
+const internal::VariadicDynCastAllOfMatcher<
+ Stmt,
+ UserDefinedLiteral> userDefinedLiteral;
+
+/// \brief Matches nullptr literal.
+const internal::VariadicDynCastAllOfMatcher<
+ Stmt,
+ CXXNullPtrLiteralExpr> nullPtrLiteralExpr;
+
/// \brief Matches binary operator expressions.
///
/// Example matches a || b
diff --git a/unittests/ASTMatchers/ASTMatchersTest.cpp b/unittests/ASTMatchers/ASTMatchersTest.cpp
index b49d082501..6698e4ecbc 100644
--- a/unittests/ASTMatchers/ASTMatchersTest.cpp
+++ b/unittests/ASTMatchers/ASTMatchersTest.cpp
@@ -805,6 +805,27 @@ TEST(Matcher, Call) {
MethodOnYPointer));
}
+TEST(Matcher, Lambda) {
+ EXPECT_TRUE(matches("auto f = [&] (int i) { return i; };",
+ lambdaExpr()));
+}
+
+TEST(Matcher, ForRange) {
+ EXPECT_TRUE(matches("#include <initializer_list>\n"
+ "void f() { for (auto &a : {1, 2, 3}); }",
+ forRangeStmt()));
+ EXPECT_TRUE(notMatches("void f() { for (int i; i<5; ++i); }",
+ forRangeStmt()));
+}
+
+TEST(Matcher, UserDefinedLiteral) {
+ EXPECT_TRUE(matches("constexpr char operator \"\" _inc (const char i) {"
+ " return i + 1;"
+ "}"
+ "char c = 'a'_inc;",
+ userDefinedLiteral()));
+}
+
TEST(Matcher, FlowControl) {
EXPECT_TRUE(matches("void f() { while(true) { break; } }", breakStmt()));
EXPECT_TRUE(matches("void f() { while(true) { continue; } }",
@@ -1556,6 +1577,10 @@ TEST(Matcher, IntegerLiterals) {
EXPECT_TRUE(notMatches("int i = 10.0;", HasIntLiteral));
}
+TEST(Matcher, NullPtrLiteral) {
+ EXPECT_TRUE(matches("int* i = nullptr;", nullPtrLiteralExpr()));
+}
+
TEST(Matcher, AsmStatement) {
EXPECT_TRUE(matches("void foo() { __asm(\"mov al, 2\"); }", asmStmt()));
}
@@ -1981,6 +2006,9 @@ TEST(AstPolymorphicMatcherPMacro, Works) {
TEST(For, FindsForLoops) {
EXPECT_TRUE(matches("void f() { for(;;); }", forStmt()));
EXPECT_TRUE(matches("void f() { if(true) for(;;); }", forStmt()));
+ EXPECT_TRUE(notMatches("#include <initializer_list>\n"
+ "void f() { for (auto &a : {1, 2, 3}); }",
+ forStmt()));
}
TEST(For, ForLoopInternals) {
@@ -2105,17 +2133,20 @@ TEST(Member, MatchesInMemberFunctionCall) {
}
TEST(Member, MatchesMemberAllocationFunction) {
- EXPECT_TRUE(matches("namespace std { typedef typeof(sizeof(int)) size_t; }"
- "class X { void *operator new(std::size_t); };",
- methodDecl(ofClass(hasName("X")))));
+ // Fails in C++11 mode
+ EXPECT_TRUE(matchesConditionally(
+ "namespace std { typedef typeof(sizeof(int)) size_t; }"
+ "class X { void *operator new(std::size_t); };",
+ methodDecl(ofClass(hasName("X"))), true, "-std=gnu++98"));
EXPECT_TRUE(matches("class X { void operator delete(void*); };",
methodDecl(ofClass(hasName("X")))));
- EXPECT_TRUE(matches(
+ // Fails in C++11 mode
+ EXPECT_TRUE(matchesConditionally(
"namespace std { typedef typeof(sizeof(int)) size_t; }"
"class X { void operator delete[](void*, std::size_t); };",
- methodDecl(ofClass(hasName("X")))));
+ methodDecl(ofClass(hasName("X"))), true, "-std=gnu++98"));
}
TEST(HasObjectExpression, DoesNotMatchMember) {
diff --git a/unittests/ASTMatchers/ASTMatchersTest.h b/unittests/ASTMatchers/ASTMatchersTest.h
index 6d872e8ea9..01a7c51016 100644
--- a/unittests/ASTMatchers/ASTMatchersTest.h
+++ b/unittests/ASTMatchers/ASTMatchersTest.h
@@ -51,13 +51,14 @@ private:
template <typename T>
testing::AssertionResult matchesConditionally(const std::string &Code,
const T &AMatcher,
- bool ExpectMatch) {
+ bool ExpectMatch,
+ llvm::StringRef CompileArg) {
bool Found = false;
MatchFinder Finder;
Finder.addMatcher(AMatcher, new VerifyMatch(0, &Found));
OwningPtr<FrontendActionFactory> Factory(newFrontendActionFactory(&Finder));
// Some tests use typeof, which is a gnu extension.
- std::vector<std::string> Args(1, "-std=gnu++98");
+ std::vector<std::string> Args(1, CompileArg);
if (!runToolOnCodeWithArgs(Factory->create(), Code, Args)) {
return testing::AssertionFailure() << "Parsing error in \"" << Code << "\"";
}
@@ -73,13 +74,13 @@ testing::AssertionResult matchesConditionally(const std::string &Code,
template <typename T>
testing::AssertionResult matches(const std::string &Code, const T &AMatcher) {
- return matchesConditionally(Code, AMatcher, true);
+ return matchesConditionally(Code, AMatcher, true, "-std=c++11");
}
template <typename T>
testing::AssertionResult notMatches(const std::string &Code,
const T &AMatcher) {
- return matchesConditionally(Code, AMatcher, false);
+ return matchesConditionally(Code, AMatcher, false, "-std=c++11");
}
template <typename T>