#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/TargetParser/Host.h"
#include "llvm/TargetParser/Triple.h"
#include "llvm/Testing/Support/SupportHelpers.h"
#include "gtest/gtest.h"
namespace clang {
namespace ast_matchers {
DynTypedMatcher;
#if GTEST_HAS_DEATH_TEST
TEST(HasNameDeathTest, DiesOnEmptyName) { … }
TEST(HasNameDeathTest, DiesOnEmptyPattern) { … }
#if 0
#if ENABLE_BACKTRACES && (!defined(_MSC_VER) || !defined(__clang__))
AST_MATCHER(Decl, causeCrash) {
abort();
return true;
}
TEST(MatcherCrashDeathTest, CrashOnMatcherDump) {
llvm::EnablePrettyStackTrace();
auto Matcher = testing::HasSubstr(
"ASTMatcher: Matching '<unknown>' against:\n\tFunctionDecl foo : "
"<input.cc:1:1, col:10>");
ASSERT_DEATH(matches("void foo();", functionDecl(causeCrash())), Matcher);
}
template <typename MatcherT>
static void crashTestNodeDump(MatcherT Matcher,
ArrayRef<StringRef> MatchedNodes,
StringRef Against, StringRef Code) {
llvm::EnablePrettyStackTrace();
MatchFinder Finder;
struct CrashCallback : public MatchFinder::MatchCallback {
void run(const MatchFinder::MatchResult &Result) override { abort(); }
std::optional<TraversalKind> getCheckTraversalKind() const override {
return TK_IgnoreUnlessSpelledInSource;
}
StringRef getID() const override { return "CrashTester"; }
} Callback;
Finder.addMatcher(std::move(Matcher), &Callback);
if (MatchedNodes.empty()) {
ASSERT_DEATH(tooling::runToolOnCode(
newFrontendActionFactory(&Finder)->create(), Code),
testing::HasSubstr(
("ASTMatcher: Processing 'CrashTester' against:\n\t" +
Against + "\nNo bound nodes")
.str()));
} else {
std::vector<testing::PolymorphicMatcher<
testing::internal::HasSubstrMatcher<std::string>>>
Matchers;
Matchers.reserve(MatchedNodes.size());
for (auto Node : MatchedNodes) {
Matchers.push_back(testing::HasSubstr(Node.str()));
}
auto CrashMatcher = testing::AllOf(
testing::HasSubstr(
("ASTMatcher: Processing 'CrashTester' against:\n\t" + Against +
"\n--- Bound Nodes Begin ---")
.str()),
testing::HasSubstr("--- Bound Nodes End ---"),
testing::AllOfArray(Matchers));
ASSERT_DEATH(tooling::runToolOnCode(
newFrontendActionFactory(&Finder)->create(), Code),
CrashMatcher);
}
}
TEST(MatcherCrashDeathTest, CrashOnCallbackDump) {
crashTestNodeDump(forStmt(), {}, "ForStmt : <input.cc:1:14, col:21>",
"void foo() { for(;;); }");
crashTestNodeDump(
forStmt(hasLoopInit(declStmt(hasSingleDecl(
varDecl(hasType(qualType().bind("QT")),
hasType(type().bind("T")),
hasInitializer(
integerLiteral().bind("IL")))
.bind("VD")))
.bind("DS")))
.bind("FS"),
{"FS - { ForStmt : <input.cc:3:5, line:4:5> }",
"DS - { DeclStmt : <input.cc:3:10, col:19> }",
"IL - { IntegerLiteral : <input.cc:3:18> }", "QT - { QualType : int }",
"T - { BuiltinType : int }",
"VD - { VarDecl I : <input.cc:3:10, col:18> }"},
"ForStmt : <input.cc:3:5, line:4:5>",
R"cpp(
void foo() {
for (int I = 0; I < 5; ++I) {
}
}
)cpp");
crashTestNodeDump(
cxxRecordDecl(hasMethod(cxxMethodDecl(hasName("operator+")).bind("Op+")))
.bind("Unnamed"),
{"Unnamed - { CXXRecordDecl (anonymous) : <input.cc:1:1, col:36> }",
"Op+ - { CXXMethodDecl (anonymous struct)::operator+ : <input.cc:1:10, "
"col:29> }"},
"CXXRecordDecl (anonymous) : <input.cc:1:1, col:36>",
"struct { int operator+(int) const; } Unnamed;");
crashTestNodeDump(
cxxRecordDecl(hasMethod(cxxConstructorDecl(isDefaulted()).bind("Ctor")),
hasMethod(cxxDestructorDecl(isDefaulted()).bind("Dtor"))),
{"Ctor - { CXXConstructorDecl Foo::Foo : <input.cc:1:14, col:28> }",
"Dtor - { CXXDestructorDecl Foo::~Foo : <input.cc:1:31, col:46> }"},
"CXXRecordDecl Foo : <input.cc:1:1, col:49>",
"struct Foo { Foo() = default; ~Foo() = default; };");
}
#endif
#endif
#endif
TEST(ConstructVariadic, MismatchedTypes_Regression) { … }
AST_MATCHER_P(Decl, just, internal::Matcher<Decl>, AMatcher) { … }
TEST(AstMatcherPMacro, Works) { … }
AST_POLYMORPHIC_MATCHER_P(polymorphicHas,
AST_POLYMORPHIC_SUPPORTED_TYPES(Decl, Stmt),
internal::Matcher<Decl>, AMatcher) { … }
TEST(AstPolymorphicMatcherPMacro, Works) { … }
TEST(MatchFinder, CheckProfiling) { … }
class VerifyStartOfTranslationUnit : public MatchFinder::MatchCallback { … };
TEST(MatchFinder, InterceptsStartOfTranslationUnit) { … }
class VerifyEndOfTranslationUnit : public MatchFinder::MatchCallback { … };
TEST(MatchFinder, InterceptsEndOfTranslationUnit) { … }
TEST(Matcher, matchOverEntireASTContext) { … }
TEST(DynTypedMatcherTest, TraversalKindForwardsToImpl) { … }
TEST(DynTypedMatcherTest, ConstructWithTraversalKindSetsTK) { … }
TEST(DynTypedMatcherTest, ConstructWithTraversalKindOverridesNestedTK) { … }
TEST(IsInlineMatcher, IsInline) { … }
#ifndef _WIN32
TEST(Matcher, IsExpansionInMainFileMatcher) { … }
TEST(Matcher, IsExpansionInSystemHeader) { … }
TEST(Matcher, IsExpansionInFileMatching) { … }
#endif
}
}