From 5901e47e8f1bc708ccf796d33b852768c859b79b Mon Sep 17 00:00:00 2001 From: Daniel Jasper Date: Mon, 1 Oct 2012 13:40:41 +0000 Subject: [PATCH] Add matchers for selected C++11 features. MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Patch by Gábor Horváth. Review: http://llvm-reviews.chandlerc.com/D46 llvm-svn: 164943 --- clang/include/clang/ASTMatchers/ASTMatchers.h | 30 ++++++++++++++++++ clang/unittests/ASTMatchers/ASTMatchersTest.cpp | 41 ++++++++++++++++++++++--- 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 6507433..770ec77 100644 --- a/clang/include/clang/ASTMatchers/ASTMatchers.h +++ b/clang/include/clang/ASTMatchers/ASTMatchers.h @@ -489,6 +489,14 @@ const internal::VariadicDynCastAllOfMatcher memberExpr; /// \endcode const internal::VariadicDynCastAllOfMatcher callExpr; +/// \brief Matches lambda expressions. +/// +/// Example matches [&](){return 5;} +/// \code +/// [&](){return 5;} +/// \endcode +const internal::VariadicDynCastAllOfMatcher lambdaExpr; + /// \brief Matches member call expressions. /// /// Example matches x.y() @@ -664,9 +672,19 @@ const internal::VariadicDynCastAllOfMatcher ifStmt; /// Example matches 'for (;;) {}' /// \code /// for (;;) {} +/// int i[] = {1, 2, 3}; for (auto a : i); /// \endcode const internal::VariadicDynCastAllOfMatcher 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 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 b49d082..6698e4e 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 \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 \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 6d872e8..01a7c51 100644 --- a/clang/unittests/ASTMatchers/ASTMatchersTest.h +++ b/clang/unittests/ASTMatchers/ASTMatchersTest.h @@ -51,13 +51,14 @@ private: template 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 Factory(newFrontendActionFactory(&Finder)); // Some tests use typeof, which is a gnu extension. - std::vector Args(1, "-std=gnu++98"); + std::vector 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 testing::AssertionResult matches(const std::string &Code, const T &AMatcher) { - return matchesConditionally(Code, AMatcher, true); + return matchesConditionally(Code, AMatcher, true, "-std=c++11"); } template testing::AssertionResult notMatches(const std::string &Code, const T &AMatcher) { - return matchesConditionally(Code, AMatcher, false); + return matchesConditionally(Code, AMatcher, false, "-std=c++11"); } template -- 2.7.4