зеркало из https://github.com/microsoft/clang-1.git
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
This commit is contained in:
Родитель
3dd82f7f01
Коммит
31f7c08a0d
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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>
|
||||
|
|
Загрузка…
Ссылка в новой задаче