41 changes: 41 additions & 0 deletions clang/unittests/ASTMatchers/ASTMatchersTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4625,5 +4625,46 @@ TEST(EqualsBoundNodeMatcher, UnlessDescendantsOfAncestorsMatch) {
.bind("data")));
}

TEST(TypeDefDeclMatcher, Match) {
EXPECT_TRUE(matches("typedef int typedefDeclTest;",
typedefDecl(hasName("typedefDeclTest"))));
}

TEST(Matcher, IsExpansionInMainFileMatcher) {
EXPECT_TRUE(matches("class X {};",
recordDecl(hasName("X"), isExpansionInMainFile())));
EXPECT_TRUE(notMatches("", recordDecl(isExpansionInMainFile())));
EXPECT_TRUE(matchesConditionally("#include <other>\n",
recordDecl(isExpansionInMainFile()), false,
"-isystem/", {{"/other", "class X {};"}}));
}

TEST(Matcher, IsExpansionInSystemHeader) {
EXPECT_TRUE(matchesConditionally(
"#include \"other\"\n", recordDecl(isExpansionInSystemHeader()), true,
"-isystem/", {{"/other", "class X {};"}}));
EXPECT_TRUE(matchesConditionally("#include \"other\"\n",
recordDecl(isExpansionInSystemHeader()),
false, "-I/", {{"/other", "class X {};"}}));
EXPECT_TRUE(notMatches("class X {};",
recordDecl(isExpansionInSystemHeader())));
EXPECT_TRUE(notMatches("", recordDecl(isExpansionInSystemHeader())));
}

TEST(Matcher, IsExpansionInFileMatching) {
EXPECT_TRUE(matchesConditionally(
"#include <foo>\n"
"#include <bar>\n"
"class X {};",
recordDecl(isExpansionInFileMatching("b.*"), hasName("B")), true,
"-isystem/", {{"/foo", "class A {};"}, {"/bar", "class B {};"}}));
EXPECT_TRUE(matchesConditionally(
"#include <foo>\n"
"#include <bar>\n"
"class X {};",
recordDecl(isExpansionInFileMatching("f.*"), hasName("X")), false,
"-isystem/", {{"/foo", "class A {};"}, {"/bar", "class B {};"}}));
}

} // end namespace ast_matchers
} // end namespace clang
12 changes: 7 additions & 5 deletions clang/unittests/ASTMatchers/ASTMatchersTest.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ using clang::tooling::buildASTFromCodeWithArgs;
using clang::tooling::newFrontendActionFactory;
using clang::tooling::runToolOnCodeWithArgs;
using clang::tooling::FrontendActionFactory;
using clang::tooling::FileContentMappings;

class BoundNodesCallback {
public:
Expand Down Expand Up @@ -58,10 +59,10 @@ class VerifyMatch : public MatchFinder::MatchCallback {
};

template <typename T>
testing::AssertionResult matchesConditionally(const std::string &Code,
const T &AMatcher,
bool ExpectMatch,
llvm::StringRef CompileArg) {
testing::AssertionResult matchesConditionally(
const std::string &Code, const T &AMatcher, bool ExpectMatch,
llvm::StringRef CompileArg,
const FileContentMappings &VirtualMappedFiles = FileContentMappings()) {
bool Found = false, DynamicFound = false;
MatchFinder Finder;
VerifyMatch VerifyFound(nullptr, &Found);
Expand All @@ -73,7 +74,8 @@ testing::AssertionResult matchesConditionally(const std::string &Code,
newFrontendActionFactory(&Finder));
// Some tests use typeof, which is a gnu extension.
std::vector<std::string> Args(1, CompileArg);
if (!runToolOnCodeWithArgs(Factory->create(), Code, Args)) {
if (!runToolOnCodeWithArgs(Factory->create(), Code, Args, "input.cc",
VirtualMappedFiles)) {
return testing::AssertionFailure() << "Parsing error in \"" << Code << "\"";
}
if (Found != DynamicFound) {
Expand Down