Dividied ASTMatcherTests into 4 files
fix for long compilation [20061] http://reviews.llvm.org/D20210 llvm-svn: 269802
This commit is contained in:
parent
5439b64af0
commit
c6e0502997
7 changed files with 5703 additions and 5650 deletions
240
clang/unittests/ASTMatchers/ASTMatchersInternalTest.cpp
Normal file
240
clang/unittests/ASTMatchers/ASTMatchersInternalTest.cpp
Normal file
|
@ -0,0 +1,240 @@
|
|||
// unittests/ASTMatchers/ASTMatchersInternalTest.cpp - AST matcher unit tests //
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "ASTMatchersTest.h"
|
||||
#include "clang/AST/PrettyPrinter.h"
|
||||
#include "clang/ASTMatchers/ASTMatchFinder.h"
|
||||
#include "clang/ASTMatchers/ASTMatchers.h"
|
||||
#include "clang/Tooling/Tooling.h"
|
||||
#include "llvm/ADT/Triple.h"
|
||||
#include "llvm/Support/Host.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
namespace clang {
|
||||
namespace ast_matchers {
|
||||
|
||||
#if GTEST_HAS_DEATH_TEST
|
||||
TEST(HasNameDeathTest, DiesOnEmptyName) {
|
||||
ASSERT_DEBUG_DEATH({
|
||||
DeclarationMatcher HasEmptyName = recordDecl(hasName(""));
|
||||
EXPECT_TRUE(notMatches("class X {};", HasEmptyName));
|
||||
}, "");
|
||||
}
|
||||
|
||||
TEST(HasNameDeathTest, DiesOnEmptyPattern) {
|
||||
ASSERT_DEBUG_DEATH({
|
||||
DeclarationMatcher HasEmptyName = recordDecl(matchesName(""));
|
||||
EXPECT_TRUE(notMatches("class X {};", HasEmptyName));
|
||||
}, "");
|
||||
}
|
||||
|
||||
TEST(IsDerivedFromDeathTest, DiesOnEmptyBaseName) {
|
||||
ASSERT_DEBUG_DEATH({
|
||||
DeclarationMatcher IsDerivedFromEmpty = cxxRecordDecl(isDerivedFrom(""));
|
||||
EXPECT_TRUE(notMatches("class X {};", IsDerivedFromEmpty));
|
||||
}, "");
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST(ConstructVariadic, MismatchedTypes_Regression) {
|
||||
EXPECT_TRUE(
|
||||
matches("const int a = 0;",
|
||||
internal::DynTypedMatcher::constructVariadic(
|
||||
internal::DynTypedMatcher::VO_AnyOf,
|
||||
ast_type_traits::ASTNodeKind::getFromNodeKind<QualType>(),
|
||||
{isConstQualified(), arrayType()})
|
||||
.convertTo<QualType>()));
|
||||
}
|
||||
|
||||
// For testing AST_MATCHER_P().
|
||||
AST_MATCHER_P(Decl, just, internal::Matcher<Decl>, AMatcher) {
|
||||
// Make sure all special variables are used: node, match_finder,
|
||||
// bound_nodes_builder, and the parameter named 'AMatcher'.
|
||||
return AMatcher.matches(Node, Finder, Builder);
|
||||
}
|
||||
|
||||
TEST(AstMatcherPMacro, Works) {
|
||||
DeclarationMatcher HasClassB = just(has(recordDecl(hasName("B")).bind("b")));
|
||||
|
||||
EXPECT_TRUE(matchAndVerifyResultTrue("class A { class B {}; };",
|
||||
HasClassB, llvm::make_unique<VerifyIdIsBoundTo<Decl>>("b")));
|
||||
|
||||
EXPECT_TRUE(matchAndVerifyResultFalse("class A { class B {}; };",
|
||||
HasClassB, llvm::make_unique<VerifyIdIsBoundTo<Decl>>("a")));
|
||||
|
||||
EXPECT_TRUE(matchAndVerifyResultFalse("class A { class C {}; };",
|
||||
HasClassB, llvm::make_unique<VerifyIdIsBoundTo<Decl>>("b")));
|
||||
}
|
||||
|
||||
AST_POLYMORPHIC_MATCHER_P(polymorphicHas,
|
||||
AST_POLYMORPHIC_SUPPORTED_TYPES(Decl, Stmt),
|
||||
internal::Matcher<Decl>, AMatcher) {
|
||||
return Finder->matchesChildOf(
|
||||
Node, AMatcher, Builder,
|
||||
ASTMatchFinder::TK_IgnoreImplicitCastsAndParentheses,
|
||||
ASTMatchFinder::BK_First);
|
||||
}
|
||||
|
||||
TEST(AstPolymorphicMatcherPMacro, Works) {
|
||||
DeclarationMatcher HasClassB =
|
||||
polymorphicHas(recordDecl(hasName("B")).bind("b"));
|
||||
|
||||
EXPECT_TRUE(matchAndVerifyResultTrue("class A { class B {}; };",
|
||||
HasClassB, llvm::make_unique<VerifyIdIsBoundTo<Decl>>("b")));
|
||||
|
||||
EXPECT_TRUE(matchAndVerifyResultFalse("class A { class B {}; };",
|
||||
HasClassB, llvm::make_unique<VerifyIdIsBoundTo<Decl>>("a")));
|
||||
|
||||
EXPECT_TRUE(matchAndVerifyResultFalse("class A { class C {}; };",
|
||||
HasClassB, llvm::make_unique<VerifyIdIsBoundTo<Decl>>("b")));
|
||||
|
||||
StatementMatcher StatementHasClassB =
|
||||
polymorphicHas(recordDecl(hasName("B")));
|
||||
|
||||
EXPECT_TRUE(matches("void x() { class B {}; }", StatementHasClassB));
|
||||
}
|
||||
|
||||
TEST(MatchFinder, CheckProfiling) {
|
||||
MatchFinder::MatchFinderOptions Options;
|
||||
llvm::StringMap<llvm::TimeRecord> Records;
|
||||
Options.CheckProfiling.emplace(Records);
|
||||
MatchFinder Finder(std::move(Options));
|
||||
|
||||
struct NamedCallback : public MatchFinder::MatchCallback {
|
||||
void run(const MatchFinder::MatchResult &Result) override {}
|
||||
StringRef getID() const override { return "MyID"; }
|
||||
} Callback;
|
||||
Finder.addMatcher(decl(), &Callback);
|
||||
std::unique_ptr<FrontendActionFactory> Factory(
|
||||
newFrontendActionFactory(&Finder));
|
||||
ASSERT_TRUE(tooling::runToolOnCode(Factory->create(), "int x;"));
|
||||
|
||||
EXPECT_EQ(1u, Records.size());
|
||||
EXPECT_EQ("MyID", Records.begin()->getKey());
|
||||
}
|
||||
|
||||
class VerifyStartOfTranslationUnit : public MatchFinder::MatchCallback {
|
||||
public:
|
||||
VerifyStartOfTranslationUnit() : Called(false) {}
|
||||
void run(const MatchFinder::MatchResult &Result) override {
|
||||
EXPECT_TRUE(Called);
|
||||
}
|
||||
void onStartOfTranslationUnit() override { Called = true; }
|
||||
bool Called;
|
||||
};
|
||||
|
||||
TEST(MatchFinder, InterceptsStartOfTranslationUnit) {
|
||||
MatchFinder Finder;
|
||||
VerifyStartOfTranslationUnit VerifyCallback;
|
||||
Finder.addMatcher(decl(), &VerifyCallback);
|
||||
std::unique_ptr<FrontendActionFactory> Factory(
|
||||
newFrontendActionFactory(&Finder));
|
||||
ASSERT_TRUE(tooling::runToolOnCode(Factory->create(), "int x;"));
|
||||
EXPECT_TRUE(VerifyCallback.Called);
|
||||
|
||||
VerifyCallback.Called = false;
|
||||
std::unique_ptr<ASTUnit> AST(tooling::buildASTFromCode("int x;"));
|
||||
ASSERT_TRUE(AST.get());
|
||||
Finder.matchAST(AST->getASTContext());
|
||||
EXPECT_TRUE(VerifyCallback.Called);
|
||||
}
|
||||
|
||||
class VerifyEndOfTranslationUnit : public MatchFinder::MatchCallback {
|
||||
public:
|
||||
VerifyEndOfTranslationUnit() : Called(false) {}
|
||||
void run(const MatchFinder::MatchResult &Result) override {
|
||||
EXPECT_FALSE(Called);
|
||||
}
|
||||
void onEndOfTranslationUnit() override { Called = true; }
|
||||
bool Called;
|
||||
};
|
||||
|
||||
TEST(MatchFinder, InterceptsEndOfTranslationUnit) {
|
||||
MatchFinder Finder;
|
||||
VerifyEndOfTranslationUnit VerifyCallback;
|
||||
Finder.addMatcher(decl(), &VerifyCallback);
|
||||
std::unique_ptr<FrontendActionFactory> Factory(
|
||||
newFrontendActionFactory(&Finder));
|
||||
ASSERT_TRUE(tooling::runToolOnCode(Factory->create(), "int x;"));
|
||||
EXPECT_TRUE(VerifyCallback.Called);
|
||||
|
||||
VerifyCallback.Called = false;
|
||||
std::unique_ptr<ASTUnit> AST(tooling::buildASTFromCode("int x;"));
|
||||
ASSERT_TRUE(AST.get());
|
||||
Finder.matchAST(AST->getASTContext());
|
||||
EXPECT_TRUE(VerifyCallback.Called);
|
||||
}
|
||||
|
||||
TEST(Matcher, matchOverEntireASTContext) {
|
||||
std::unique_ptr<ASTUnit> AST =
|
||||
clang::tooling::buildASTFromCode("struct { int *foo; };");
|
||||
ASSERT_TRUE(AST.get());
|
||||
auto PT = selectFirst<PointerType>(
|
||||
"x", match(pointerType().bind("x"), AST->getASTContext()));
|
||||
EXPECT_NE(nullptr, PT);
|
||||
}
|
||||
|
||||
TEST(IsInlineMatcher, IsInline) {
|
||||
EXPECT_TRUE(matches("void g(); inline void f();",
|
||||
functionDecl(isInline(), hasName("f"))));
|
||||
EXPECT_TRUE(matches("namespace n { inline namespace m {} }",
|
||||
namespaceDecl(isInline(), hasName("m"))));
|
||||
}
|
||||
|
||||
// FIXME: Figure out how to specify paths so the following tests pass on
|
||||
// Windows.
|
||||
#ifndef LLVM_ON_WIN32
|
||||
|
||||
TEST(Matcher, IsExpansionInMainFileMatcher) {
|
||||
EXPECT_TRUE(matches("class X {};",
|
||||
recordDecl(hasName("X"), isExpansionInMainFile())));
|
||||
EXPECT_TRUE(notMatches("", recordDecl(isExpansionInMainFile())));
|
||||
FileContentMappings M;
|
||||
M.push_back(std::make_pair("/other", "class X {};"));
|
||||
EXPECT_TRUE(matchesConditionally("#include <other>\n",
|
||||
recordDecl(isExpansionInMainFile()), false,
|
||||
"-isystem/", M));
|
||||
}
|
||||
|
||||
TEST(Matcher, IsExpansionInSystemHeader) {
|
||||
FileContentMappings M;
|
||||
M.push_back(std::make_pair("/other", "class X {};"));
|
||||
EXPECT_TRUE(matchesConditionally(
|
||||
"#include \"other\"\n", recordDecl(isExpansionInSystemHeader()), true,
|
||||
"-isystem/", M));
|
||||
EXPECT_TRUE(matchesConditionally("#include \"other\"\n",
|
||||
recordDecl(isExpansionInSystemHeader()),
|
||||
false, "-I/", M));
|
||||
EXPECT_TRUE(notMatches("class X {};",
|
||||
recordDecl(isExpansionInSystemHeader())));
|
||||
EXPECT_TRUE(notMatches("", recordDecl(isExpansionInSystemHeader())));
|
||||
}
|
||||
|
||||
TEST(Matcher, IsExpansionInFileMatching) {
|
||||
FileContentMappings M;
|
||||
M.push_back(std::make_pair("/foo", "class A {};"));
|
||||
M.push_back(std::make_pair("/bar", "class B {};"));
|
||||
EXPECT_TRUE(matchesConditionally(
|
||||
"#include <foo>\n"
|
||||
"#include <bar>\n"
|
||||
"class X {};",
|
||||
recordDecl(isExpansionInFileMatching("b.*"), hasName("B")), true,
|
||||
"-isystem/", M));
|
||||
EXPECT_TRUE(matchesConditionally(
|
||||
"#include <foo>\n"
|
||||
"#include <bar>\n"
|
||||
"class X {};",
|
||||
recordDecl(isExpansionInFileMatching("f.*"), hasName("X")), false,
|
||||
"-isystem/", M));
|
||||
}
|
||||
|
||||
#endif // LLVM_ON_WIN32
|
||||
|
||||
} // end namespace ast_matchers
|
||||
} // end namespace clang
|
1888
clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
Normal file
1888
clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
Normal file
File diff suppressed because it is too large
Load diff
1514
clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
Normal file
1514
clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
Normal file
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -278,7 +278,79 @@ matchAndVerifyResultFalse(const std::string &Code, const T &AMatcher,
|
|||
Code, AMatcher, std::move(FindResultVerifier), false);
|
||||
}
|
||||
|
||||
} // end namespace ast_matchers
|
||||
} // end namespace clang
|
||||
// Implements a run method that returns whether BoundNodes contains a
|
||||
// Decl bound to Id that can be dynamically cast to T.
|
||||
// Optionally checks that the check succeeded a specific number of times.
|
||||
template <typename T>
|
||||
class VerifyIdIsBoundTo : public BoundNodesCallback {
|
||||
public:
|
||||
// Create an object that checks that a node of type \c T was bound to \c Id.
|
||||
// Does not check for a certain number of matches.
|
||||
explicit VerifyIdIsBoundTo(llvm::StringRef Id)
|
||||
: Id(Id), ExpectedCount(-1), Count(0) {}
|
||||
|
||||
// Create an object that checks that a node of type \c T was bound to \c Id.
|
||||
// Checks that there were exactly \c ExpectedCount matches.
|
||||
VerifyIdIsBoundTo(llvm::StringRef Id, int ExpectedCount)
|
||||
: Id(Id), ExpectedCount(ExpectedCount), Count(0) {}
|
||||
|
||||
// Create an object that checks that a node of type \c T was bound to \c Id.
|
||||
// Checks that there was exactly one match with the name \c ExpectedName.
|
||||
// Note that \c T must be a NamedDecl for this to work.
|
||||
VerifyIdIsBoundTo(llvm::StringRef Id, llvm::StringRef ExpectedName,
|
||||
int ExpectedCount = 1)
|
||||
: Id(Id), ExpectedCount(ExpectedCount), Count(0),
|
||||
ExpectedName(ExpectedName) {}
|
||||
|
||||
void onEndOfTranslationUnit() override {
|
||||
if (ExpectedCount != -1)
|
||||
EXPECT_EQ(ExpectedCount, Count);
|
||||
if (!ExpectedName.empty())
|
||||
EXPECT_EQ(ExpectedName, Name);
|
||||
Count = 0;
|
||||
Name.clear();
|
||||
}
|
||||
|
||||
~VerifyIdIsBoundTo() override {
|
||||
EXPECT_EQ(0, Count);
|
||||
EXPECT_EQ("", Name);
|
||||
}
|
||||
|
||||
bool run(const BoundNodes *Nodes) override {
|
||||
const BoundNodes::IDToNodeMap &M = Nodes->getMap();
|
||||
if (Nodes->getNodeAs<T>(Id)) {
|
||||
++Count;
|
||||
if (const NamedDecl *Named = Nodes->getNodeAs<NamedDecl>(Id)) {
|
||||
Name = Named->getNameAsString();
|
||||
} else if (const NestedNameSpecifier *NNS =
|
||||
Nodes->getNodeAs<NestedNameSpecifier>(Id)) {
|
||||
llvm::raw_string_ostream OS(Name);
|
||||
NNS->print(OS, PrintingPolicy(LangOptions()));
|
||||
}
|
||||
BoundNodes::IDToNodeMap::const_iterator I = M.find(Id);
|
||||
EXPECT_NE(M.end(), I);
|
||||
if (I != M.end())
|
||||
EXPECT_EQ(Nodes->getNodeAs<T>(Id), I->second.get<T>());
|
||||
return true;
|
||||
}
|
||||
EXPECT_TRUE(M.count(Id) == 0 ||
|
||||
M.find(Id)->second.template get<T>() == nullptr);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool run(const BoundNodes *Nodes, ASTContext *Context) override {
|
||||
return run(Nodes);
|
||||
}
|
||||
|
||||
private:
|
||||
const std::string Id;
|
||||
const int ExpectedCount;
|
||||
int Count;
|
||||
const std::string ExpectedName;
|
||||
std::string Name;
|
||||
};
|
||||
|
||||
} // namespace ast_matchers
|
||||
} // namespace clang
|
||||
|
||||
#endif // LLVM_CLANG_UNITTESTS_AST_MATCHERS_AST_MATCHERS_TEST_H
|
||||
|
|
1979
clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
Normal file
1979
clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
Normal file
File diff suppressed because it is too large
Load diff
|
@ -5,11 +5,17 @@ set(LLVM_LINK_COMPONENTS
|
|||
# By default MSVC has a 2^16 limit on the number of sections in an object file,
|
||||
# and this needs more than that.
|
||||
if (MSVC)
|
||||
set_source_files_properties(ASTMatchersTest.cpp PROPERTIES COMPILE_FLAGS /bigobj)
|
||||
set_source_files_properties(InternalASTMatchersTest.cpp PROPERTIES COMPILE_FLAGS /bigobj)
|
||||
set_source_files_properties(NodeMatchersTest.cpp PROPERTIES COMPILE_FLAGS /bigobj)
|
||||
set_source_files_properties(NarrowingMatchersTest.cpp PROPERTIES COMPILE_FLAGS /bigobj)
|
||||
set_source_files_properties(ASTTraversalMatchersTest.cpp PROPERTIES COMPILE_FLAGS /bigobj)
|
||||
endif()
|
||||
|
||||
add_clang_unittest(ASTMatchersTests
|
||||
ASTMatchersTest.cpp)
|
||||
ASTMatchersInternalTest.cpp
|
||||
ASTMatchersNodeTest.cpp
|
||||
ASTMatchersNarrowingTest.cpp
|
||||
ASTMatchersTraversalTest.cpp)
|
||||
|
||||
target_link_libraries(ASTMatchersTests
|
||||
clangAST
|
||||
|
|
Loading…
Reference in a new issue