diff options
| author | Daniel Jasper <djasper@google.com> | 2012-10-01 13:40:41 +0000 |
|---|---|---|
| committer | Daniel Jasper <djasper@google.com> | 2012-10-01 13:40:41 +0000 |
| commit | 5901e47e8f1bc708ccf796d33b852768c859b79b (patch) | |
| tree | 26581e27205c74a5b8cb3ba26cb706598f884f38 | |
| parent | 9866b97f94f481fcf0b8e85566f63cef04227fbe (diff) | |
| download | bcm5719-llvm-5901e47e8f1bc708ccf796d33b852768c859b79b.tar.gz bcm5719-llvm-5901e47e8f1bc708ccf796d33b852768c859b79b.zip | |
Add matchers for selected C++11 features.
Patch by Gábor Horváth.
Review: http://llvm-reviews.chandlerc.com/D46
llvm-svn: 164943
| -rw-r--r-- | clang/include/clang/ASTMatchers/ASTMatchers.h | 30 | ||||
| -rw-r--r-- | clang/unittests/ASTMatchers/ASTMatchersTest.cpp | 41 | ||||
| -rw-r--r-- | clang/unittests/ASTMatchers/ASTMatchersTest.h | 9 |
3 files changed, 71 insertions, 9 deletions
diff --git a/clang/include/clang/ASTMatchers/ASTMatchers.h b/clang/include/clang/ASTMatchers/ASTMatchers.h index 6507433e332..770ec779b15 100644 --- a/clang/include/clang/ASTMatchers/ASTMatchers.h +++ b/clang/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/clang/unittests/ASTMatchers/ASTMatchersTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersTest.cpp index b49d082501b..6698e4ecbc6 100644 --- a/clang/unittests/ASTMatchers/ASTMatchersTest.cpp +++ b/clang/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/clang/unittests/ASTMatchers/ASTMatchersTest.h b/clang/unittests/ASTMatchers/ASTMatchersTest.h index 6d872e8ea99..01a7c510162 100644 --- a/clang/unittests/ASTMatchers/ASTMatchersTest.h +++ b/clang/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> |

