Dividied ASTMatcherTests into 4 files

fix for long compilation [20061]
http://reviews.llvm.org/D20210

llvm-svn: 269802
This commit is contained in:
Piotr Padlewski 2016-05-17 19:22:57 +00:00
parent 5439b64af0
commit c6e0502997
7 changed files with 5703 additions and 5650 deletions

View 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

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -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

File diff suppressed because it is too large Load diff

View file

@ -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