1c6e05029SPiotr Padlewski // unittests/ASTMatchers/ASTMatchersInternalTest.cpp - AST matcher unit tests //
2c6e05029SPiotr Padlewski //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6c6e05029SPiotr Padlewski //
7c6e05029SPiotr Padlewski //===----------------------------------------------------------------------===//
8c6e05029SPiotr Padlewski
9c6e05029SPiotr Padlewski #include "ASTMatchersTest.h"
10c6e05029SPiotr Padlewski #include "clang/AST/PrettyPrinter.h"
11c6e05029SPiotr Padlewski #include "clang/ASTMatchers/ASTMatchFinder.h"
12c6e05029SPiotr Padlewski #include "clang/ASTMatchers/ASTMatchers.h"
13c6e05029SPiotr Padlewski #include "clang/Tooling/Tooling.h"
14*d768bf99SArchibald Elliott #include "llvm/TargetParser/Host.h"
1562c7f035SArchibald Elliott #include "llvm/TargetParser/Triple.h"
1604a96aa3SYitzhak Mandelbaum #include "llvm/Testing/Support/SupportHelpers.h"
17c6e05029SPiotr Padlewski #include "gtest/gtest.h"
18c6e05029SPiotr Padlewski
19c6e05029SPiotr Padlewski namespace clang {
20c6e05029SPiotr Padlewski namespace ast_matchers {
2104a96aa3SYitzhak Mandelbaum using internal::DynTypedMatcher;
22c6e05029SPiotr Padlewski
23c6e05029SPiotr Padlewski #if GTEST_HAS_DEATH_TEST
TEST(HasNameDeathTest,DiesOnEmptyName)24c6e05029SPiotr Padlewski TEST(HasNameDeathTest, DiesOnEmptyName) {
25c6e05029SPiotr Padlewski ASSERT_DEBUG_DEATH({
26c6e05029SPiotr Padlewski DeclarationMatcher HasEmptyName = recordDecl(hasName(""));
27c6e05029SPiotr Padlewski EXPECT_TRUE(notMatches("class X {};", HasEmptyName));
28c6e05029SPiotr Padlewski }, "");
29c6e05029SPiotr Padlewski }
30c6e05029SPiotr Padlewski
TEST(HasNameDeathTest,DiesOnEmptyPattern)31c6e05029SPiotr Padlewski TEST(HasNameDeathTest, DiesOnEmptyPattern) {
32c6e05029SPiotr Padlewski ASSERT_DEBUG_DEATH({
33c6e05029SPiotr Padlewski DeclarationMatcher HasEmptyName = recordDecl(matchesName(""));
34c6e05029SPiotr Padlewski EXPECT_TRUE(notMatches("class X {};", HasEmptyName));
35c6e05029SPiotr Padlewski }, "");
36c6e05029SPiotr Padlewski }
37b97f2608SNathan James
38251b5b86SNathan James // FIXME Re-enable these tests without breaking standalone builds.
39251b5b86SNathan James #if 0
40b97f2608SNathan James // FIXME: Figure out why back traces aren't being generated on clang builds on
41b97f2608SNathan James // windows.
42b97f2608SNathan James #if ENABLE_BACKTRACES && (!defined(_MSC_VER) || !defined(__clang__))
43b4ad3c38SNathan James
44b4ad3c38SNathan James AST_MATCHER(Decl, causeCrash) {
45b4ad3c38SNathan James abort();
46b4ad3c38SNathan James return true;
47b4ad3c38SNathan James }
48b4ad3c38SNathan James
49b4ad3c38SNathan James TEST(MatcherCrashDeathTest, CrashOnMatcherDump) {
50b4ad3c38SNathan James llvm::EnablePrettyStackTrace();
51b4ad3c38SNathan James auto Matcher = testing::HasSubstr(
52b4ad3c38SNathan James "ASTMatcher: Matching '<unknown>' against:\n\tFunctionDecl foo : "
53b4ad3c38SNathan James "<input.cc:1:1, col:10>");
54b4ad3c38SNathan James ASSERT_DEATH(matches("void foo();", functionDecl(causeCrash())), Matcher);
55b4ad3c38SNathan James }
56b4ad3c38SNathan James
57b97f2608SNathan James template <typename MatcherT>
58b97f2608SNathan James static void crashTestNodeDump(MatcherT Matcher,
59b97f2608SNathan James ArrayRef<StringRef> MatchedNodes,
60b4ad3c38SNathan James StringRef Against, StringRef Code) {
61b97f2608SNathan James llvm::EnablePrettyStackTrace();
62b97f2608SNathan James MatchFinder Finder;
63b97f2608SNathan James
64b97f2608SNathan James struct CrashCallback : public MatchFinder::MatchCallback {
65b97f2608SNathan James void run(const MatchFinder::MatchResult &Result) override { abort(); }
66b0de3630SFangrui Song std::optional<TraversalKind> getCheckTraversalKind() const override {
67b97f2608SNathan James return TK_IgnoreUnlessSpelledInSource;
68b97f2608SNathan James }
69b97f2608SNathan James StringRef getID() const override { return "CrashTester"; }
70b97f2608SNathan James } Callback;
71b97f2608SNathan James Finder.addMatcher(std::move(Matcher), &Callback);
72b97f2608SNathan James if (MatchedNodes.empty()) {
73b97f2608SNathan James ASSERT_DEATH(tooling::runToolOnCode(
74b97f2608SNathan James newFrontendActionFactory(&Finder)->create(), Code),
75b97f2608SNathan James testing::HasSubstr(
76b4ad3c38SNathan James ("ASTMatcher: Processing 'CrashTester' against:\n\t" +
77b4ad3c38SNathan James Against + "\nNo bound nodes")
78b4ad3c38SNathan James .str()));
79b97f2608SNathan James } else {
80b97f2608SNathan James std::vector<testing::PolymorphicMatcher<
81b97f2608SNathan James testing::internal::HasSubstrMatcher<std::string>>>
82b97f2608SNathan James Matchers;
83b97f2608SNathan James Matchers.reserve(MatchedNodes.size());
84b97f2608SNathan James for (auto Node : MatchedNodes) {
85b97f2608SNathan James Matchers.push_back(testing::HasSubstr(Node.str()));
86b97f2608SNathan James }
87b97f2608SNathan James auto CrashMatcher = testing::AllOf(
88b97f2608SNathan James testing::HasSubstr(
89b4ad3c38SNathan James ("ASTMatcher: Processing 'CrashTester' against:\n\t" + Against +
90b4ad3c38SNathan James "\n--- Bound Nodes Begin ---")
91b4ad3c38SNathan James .str()),
92b97f2608SNathan James testing::HasSubstr("--- Bound Nodes End ---"),
93b97f2608SNathan James testing::AllOfArray(Matchers));
94b97f2608SNathan James
95b97f2608SNathan James ASSERT_DEATH(tooling::runToolOnCode(
96b97f2608SNathan James newFrontendActionFactory(&Finder)->create(), Code),
97b97f2608SNathan James CrashMatcher);
98b97f2608SNathan James }
99b97f2608SNathan James }
100b97f2608SNathan James TEST(MatcherCrashDeathTest, CrashOnCallbackDump) {
101b4ad3c38SNathan James crashTestNodeDump(forStmt(), {}, "ForStmt : <input.cc:1:14, col:21>",
102b4ad3c38SNathan James "void foo() { for(;;); }");
103b97f2608SNathan James crashTestNodeDump(
104b97f2608SNathan James forStmt(hasLoopInit(declStmt(hasSingleDecl(
105b97f2608SNathan James varDecl(hasType(qualType().bind("QT")),
106b97f2608SNathan James hasType(type().bind("T")),
107b97f2608SNathan James hasInitializer(
108b97f2608SNathan James integerLiteral().bind("IL")))
109b97f2608SNathan James .bind("VD")))
110b97f2608SNathan James .bind("DS")))
111b97f2608SNathan James .bind("FS"),
112b97f2608SNathan James {"FS - { ForStmt : <input.cc:3:5, line:4:5> }",
113b97f2608SNathan James "DS - { DeclStmt : <input.cc:3:10, col:19> }",
114b97f2608SNathan James "IL - { IntegerLiteral : <input.cc:3:18> }", "QT - { QualType : int }",
115b97f2608SNathan James "T - { BuiltinType : int }",
116b97f2608SNathan James "VD - { VarDecl I : <input.cc:3:10, col:18> }"},
117b4ad3c38SNathan James "ForStmt : <input.cc:3:5, line:4:5>",
118b97f2608SNathan James R"cpp(
119b97f2608SNathan James void foo() {
120b97f2608SNathan James for (int I = 0; I < 5; ++I) {
121b97f2608SNathan James }
122b97f2608SNathan James }
123b97f2608SNathan James )cpp");
124b97f2608SNathan James crashTestNodeDump(
125b97f2608SNathan James cxxRecordDecl(hasMethod(cxxMethodDecl(hasName("operator+")).bind("Op+")))
126b97f2608SNathan James .bind("Unnamed"),
127b97f2608SNathan James {"Unnamed - { CXXRecordDecl (anonymous) : <input.cc:1:1, col:36> }",
128b97f2608SNathan James "Op+ - { CXXMethodDecl (anonymous struct)::operator+ : <input.cc:1:10, "
129b97f2608SNathan James "col:29> }"},
130b4ad3c38SNathan James "CXXRecordDecl (anonymous) : <input.cc:1:1, col:36>",
131b97f2608SNathan James "struct { int operator+(int) const; } Unnamed;");
132b97f2608SNathan James crashTestNodeDump(
133b97f2608SNathan James cxxRecordDecl(hasMethod(cxxConstructorDecl(isDefaulted()).bind("Ctor")),
134b97f2608SNathan James hasMethod(cxxDestructorDecl(isDefaulted()).bind("Dtor"))),
135b97f2608SNathan James {"Ctor - { CXXConstructorDecl Foo::Foo : <input.cc:1:14, col:28> }",
136b97f2608SNathan James "Dtor - { CXXDestructorDecl Foo::~Foo : <input.cc:1:31, col:46> }"},
137b4ad3c38SNathan James "CXXRecordDecl Foo : <input.cc:1:1, col:49>",
138b97f2608SNathan James "struct Foo { Foo() = default; ~Foo() = default; };");
139b97f2608SNathan James }
140b97f2608SNathan James #endif // ENABLE_BACKTRACES
141c6e05029SPiotr Padlewski #endif
142251b5b86SNathan James #endif
143c6e05029SPiotr Padlewski
TEST(ConstructVariadic,MismatchedTypes_Regression)144c6e05029SPiotr Padlewski TEST(ConstructVariadic, MismatchedTypes_Regression) {
145c6e05029SPiotr Padlewski EXPECT_TRUE(
146cd625114SReid Kleckner matches("const int a = 0;", internal::DynTypedMatcher::constructVariadic(
147c6e05029SPiotr Padlewski internal::DynTypedMatcher::VO_AnyOf,
148cd625114SReid Kleckner ASTNodeKind::getFromNodeKind<QualType>(),
149c6e05029SPiotr Padlewski {isConstQualified(), arrayType()})
150c6e05029SPiotr Padlewski .convertTo<QualType>()));
151c6e05029SPiotr Padlewski }
152c6e05029SPiotr Padlewski
153c6e05029SPiotr Padlewski // For testing AST_MATCHER_P().
AST_MATCHER_P(Decl,just,internal::Matcher<Decl>,AMatcher)154c6e05029SPiotr Padlewski AST_MATCHER_P(Decl, just, internal::Matcher<Decl>, AMatcher) {
155c6e05029SPiotr Padlewski // Make sure all special variables are used: node, match_finder,
156c6e05029SPiotr Padlewski // bound_nodes_builder, and the parameter named 'AMatcher'.
157c6e05029SPiotr Padlewski return AMatcher.matches(Node, Finder, Builder);
158c6e05029SPiotr Padlewski }
159c6e05029SPiotr Padlewski
TEST(AstMatcherPMacro,Works)160c6e05029SPiotr Padlewski TEST(AstMatcherPMacro, Works) {
161c6e05029SPiotr Padlewski DeclarationMatcher HasClassB = just(has(recordDecl(hasName("B")).bind("b")));
162c6e05029SPiotr Padlewski
163c6e05029SPiotr Padlewski EXPECT_TRUE(matchAndVerifyResultTrue("class A { class B {}; };",
1642b3d49b6SJonas Devlieghere HasClassB, std::make_unique<VerifyIdIsBoundTo<Decl>>("b")));
165c6e05029SPiotr Padlewski
166c6e05029SPiotr Padlewski EXPECT_TRUE(matchAndVerifyResultFalse("class A { class B {}; };",
1672b3d49b6SJonas Devlieghere HasClassB, std::make_unique<VerifyIdIsBoundTo<Decl>>("a")));
168c6e05029SPiotr Padlewski
169c6e05029SPiotr Padlewski EXPECT_TRUE(matchAndVerifyResultFalse("class A { class C {}; };",
1702b3d49b6SJonas Devlieghere HasClassB, std::make_unique<VerifyIdIsBoundTo<Decl>>("b")));
171c6e05029SPiotr Padlewski }
172c6e05029SPiotr Padlewski
AST_POLYMORPHIC_MATCHER_P(polymorphicHas,AST_POLYMORPHIC_SUPPORTED_TYPES (Decl,Stmt),internal::Matcher<Decl>,AMatcher)173c6e05029SPiotr Padlewski AST_POLYMORPHIC_MATCHER_P(polymorphicHas,
174c6e05029SPiotr Padlewski AST_POLYMORPHIC_SUPPORTED_TYPES(Decl, Stmt),
175c6e05029SPiotr Padlewski internal::Matcher<Decl>, AMatcher) {
176c6e05029SPiotr Padlewski return Finder->matchesChildOf(
177c6e05029SPiotr Padlewski Node, AMatcher, Builder,
178c6e05029SPiotr Padlewski ASTMatchFinder::BK_First);
179c6e05029SPiotr Padlewski }
180c6e05029SPiotr Padlewski
TEST(AstPolymorphicMatcherPMacro,Works)181c6e05029SPiotr Padlewski TEST(AstPolymorphicMatcherPMacro, Works) {
182c6e05029SPiotr Padlewski DeclarationMatcher HasClassB =
183c6e05029SPiotr Padlewski polymorphicHas(recordDecl(hasName("B")).bind("b"));
184c6e05029SPiotr Padlewski
185c6e05029SPiotr Padlewski EXPECT_TRUE(matchAndVerifyResultTrue("class A { class B {}; };",
1862b3d49b6SJonas Devlieghere HasClassB, std::make_unique<VerifyIdIsBoundTo<Decl>>("b")));
187c6e05029SPiotr Padlewski
188c6e05029SPiotr Padlewski EXPECT_TRUE(matchAndVerifyResultFalse("class A { class B {}; };",
1892b3d49b6SJonas Devlieghere HasClassB, std::make_unique<VerifyIdIsBoundTo<Decl>>("a")));
190c6e05029SPiotr Padlewski
191c6e05029SPiotr Padlewski EXPECT_TRUE(matchAndVerifyResultFalse("class A { class C {}; };",
1922b3d49b6SJonas Devlieghere HasClassB, std::make_unique<VerifyIdIsBoundTo<Decl>>("b")));
193c6e05029SPiotr Padlewski
194c6e05029SPiotr Padlewski StatementMatcher StatementHasClassB =
195c6e05029SPiotr Padlewski polymorphicHas(recordDecl(hasName("B")));
196c6e05029SPiotr Padlewski
197c6e05029SPiotr Padlewski EXPECT_TRUE(matches("void x() { class B {}; }", StatementHasClassB));
198c6e05029SPiotr Padlewski }
199c6e05029SPiotr Padlewski
TEST(MatchFinder,CheckProfiling)200c6e05029SPiotr Padlewski TEST(MatchFinder, CheckProfiling) {
201c6e05029SPiotr Padlewski MatchFinder::MatchFinderOptions Options;
202c6e05029SPiotr Padlewski llvm::StringMap<llvm::TimeRecord> Records;
203c6e05029SPiotr Padlewski Options.CheckProfiling.emplace(Records);
204c6e05029SPiotr Padlewski MatchFinder Finder(std::move(Options));
205c6e05029SPiotr Padlewski
206c6e05029SPiotr Padlewski struct NamedCallback : public MatchFinder::MatchCallback {
207c6e05029SPiotr Padlewski void run(const MatchFinder::MatchResult &Result) override {}
208c6e05029SPiotr Padlewski StringRef getID() const override { return "MyID"; }
209c6e05029SPiotr Padlewski } Callback;
210c6e05029SPiotr Padlewski Finder.addMatcher(decl(), &Callback);
211c6e05029SPiotr Padlewski std::unique_ptr<FrontendActionFactory> Factory(
212c6e05029SPiotr Padlewski newFrontendActionFactory(&Finder));
213c6e05029SPiotr Padlewski ASSERT_TRUE(tooling::runToolOnCode(Factory->create(), "int x;"));
214c6e05029SPiotr Padlewski
215c6e05029SPiotr Padlewski EXPECT_EQ(1u, Records.size());
216c6e05029SPiotr Padlewski EXPECT_EQ("MyID", Records.begin()->getKey());
217c6e05029SPiotr Padlewski }
218c6e05029SPiotr Padlewski
219c6e05029SPiotr Padlewski class VerifyStartOfTranslationUnit : public MatchFinder::MatchCallback {
220c6e05029SPiotr Padlewski public:
VerifyStartOfTranslationUnit()221c6e05029SPiotr Padlewski VerifyStartOfTranslationUnit() : Called(false) {}
run(const MatchFinder::MatchResult & Result)222c6e05029SPiotr Padlewski void run(const MatchFinder::MatchResult &Result) override {
223c6e05029SPiotr Padlewski EXPECT_TRUE(Called);
224c6e05029SPiotr Padlewski }
onStartOfTranslationUnit()225c6e05029SPiotr Padlewski void onStartOfTranslationUnit() override { Called = true; }
226c6e05029SPiotr Padlewski bool Called;
227c6e05029SPiotr Padlewski };
228c6e05029SPiotr Padlewski
TEST(MatchFinder,InterceptsStartOfTranslationUnit)229c6e05029SPiotr Padlewski TEST(MatchFinder, InterceptsStartOfTranslationUnit) {
230c6e05029SPiotr Padlewski MatchFinder Finder;
231c6e05029SPiotr Padlewski VerifyStartOfTranslationUnit VerifyCallback;
232c6e05029SPiotr Padlewski Finder.addMatcher(decl(), &VerifyCallback);
233c6e05029SPiotr Padlewski std::unique_ptr<FrontendActionFactory> Factory(
234c6e05029SPiotr Padlewski newFrontendActionFactory(&Finder));
235c6e05029SPiotr Padlewski ASSERT_TRUE(tooling::runToolOnCode(Factory->create(), "int x;"));
236c6e05029SPiotr Padlewski EXPECT_TRUE(VerifyCallback.Called);
237c6e05029SPiotr Padlewski
238c6e05029SPiotr Padlewski VerifyCallback.Called = false;
239c6e05029SPiotr Padlewski std::unique_ptr<ASTUnit> AST(tooling::buildASTFromCode("int x;"));
240c6e05029SPiotr Padlewski ASSERT_TRUE(AST.get());
241c6e05029SPiotr Padlewski Finder.matchAST(AST->getASTContext());
242c6e05029SPiotr Padlewski EXPECT_TRUE(VerifyCallback.Called);
243c6e05029SPiotr Padlewski }
244c6e05029SPiotr Padlewski
245c6e05029SPiotr Padlewski class VerifyEndOfTranslationUnit : public MatchFinder::MatchCallback {
246c6e05029SPiotr Padlewski public:
VerifyEndOfTranslationUnit()247c6e05029SPiotr Padlewski VerifyEndOfTranslationUnit() : Called(false) {}
run(const MatchFinder::MatchResult & Result)248c6e05029SPiotr Padlewski void run(const MatchFinder::MatchResult &Result) override {
249c6e05029SPiotr Padlewski EXPECT_FALSE(Called);
250c6e05029SPiotr Padlewski }
onEndOfTranslationUnit()251c6e05029SPiotr Padlewski void onEndOfTranslationUnit() override { Called = true; }
252c6e05029SPiotr Padlewski bool Called;
253c6e05029SPiotr Padlewski };
254c6e05029SPiotr Padlewski
TEST(MatchFinder,InterceptsEndOfTranslationUnit)255c6e05029SPiotr Padlewski TEST(MatchFinder, InterceptsEndOfTranslationUnit) {
256c6e05029SPiotr Padlewski MatchFinder Finder;
257c6e05029SPiotr Padlewski VerifyEndOfTranslationUnit VerifyCallback;
258c6e05029SPiotr Padlewski Finder.addMatcher(decl(), &VerifyCallback);
259c6e05029SPiotr Padlewski std::unique_ptr<FrontendActionFactory> Factory(
260c6e05029SPiotr Padlewski newFrontendActionFactory(&Finder));
261c6e05029SPiotr Padlewski ASSERT_TRUE(tooling::runToolOnCode(Factory->create(), "int x;"));
262c6e05029SPiotr Padlewski EXPECT_TRUE(VerifyCallback.Called);
263c6e05029SPiotr Padlewski
264c6e05029SPiotr Padlewski VerifyCallback.Called = false;
265c6e05029SPiotr Padlewski std::unique_ptr<ASTUnit> AST(tooling::buildASTFromCode("int x;"));
266c6e05029SPiotr Padlewski ASSERT_TRUE(AST.get());
267c6e05029SPiotr Padlewski Finder.matchAST(AST->getASTContext());
268c6e05029SPiotr Padlewski EXPECT_TRUE(VerifyCallback.Called);
269c6e05029SPiotr Padlewski }
270c6e05029SPiotr Padlewski
TEST(Matcher,matchOverEntireASTContext)271c6e05029SPiotr Padlewski TEST(Matcher, matchOverEntireASTContext) {
272c6e05029SPiotr Padlewski std::unique_ptr<ASTUnit> AST =
273c6e05029SPiotr Padlewski clang::tooling::buildASTFromCode("struct { int *foo; };");
274c6e05029SPiotr Padlewski ASSERT_TRUE(AST.get());
275c6e05029SPiotr Padlewski auto PT = selectFirst<PointerType>(
276c6e05029SPiotr Padlewski "x", match(pointerType().bind("x"), AST->getASTContext()));
277c6e05029SPiotr Padlewski EXPECT_NE(nullptr, PT);
278c6e05029SPiotr Padlewski }
279c6e05029SPiotr Padlewski
TEST(DynTypedMatcherTest,TraversalKindForwardsToImpl)28004a96aa3SYitzhak Mandelbaum TEST(DynTypedMatcherTest, TraversalKindForwardsToImpl) {
28104a96aa3SYitzhak Mandelbaum auto M = DynTypedMatcher(decl());
282b8df4093SKazu Hirata EXPECT_FALSE(M.getTraversalKind());
28304a96aa3SYitzhak Mandelbaum
28404a96aa3SYitzhak Mandelbaum M = DynTypedMatcher(traverse(TK_AsIs, decl()));
28504a96aa3SYitzhak Mandelbaum EXPECT_THAT(M.getTraversalKind(), llvm::ValueIs(TK_AsIs));
28604a96aa3SYitzhak Mandelbaum }
28704a96aa3SYitzhak Mandelbaum
TEST(DynTypedMatcherTest,ConstructWithTraversalKindSetsTK)28804a96aa3SYitzhak Mandelbaum TEST(DynTypedMatcherTest, ConstructWithTraversalKindSetsTK) {
28904a96aa3SYitzhak Mandelbaum auto M = DynTypedMatcher(decl()).withTraversalKind(TK_AsIs);
29004a96aa3SYitzhak Mandelbaum EXPECT_THAT(M.getTraversalKind(), llvm::ValueIs(TK_AsIs));
29104a96aa3SYitzhak Mandelbaum }
29204a96aa3SYitzhak Mandelbaum
TEST(DynTypedMatcherTest,ConstructWithTraversalKindOverridesNestedTK)29304a96aa3SYitzhak Mandelbaum TEST(DynTypedMatcherTest, ConstructWithTraversalKindOverridesNestedTK) {
29404a96aa3SYitzhak Mandelbaum auto M = DynTypedMatcher(decl()).withTraversalKind(TK_AsIs).withTraversalKind(
29504a96aa3SYitzhak Mandelbaum TK_IgnoreUnlessSpelledInSource);
29604a96aa3SYitzhak Mandelbaum EXPECT_THAT(M.getTraversalKind(),
29704a96aa3SYitzhak Mandelbaum llvm::ValueIs(TK_IgnoreUnlessSpelledInSource));
29804a96aa3SYitzhak Mandelbaum }
29904a96aa3SYitzhak Mandelbaum
TEST(IsInlineMatcher,IsInline)300c6e05029SPiotr Padlewski TEST(IsInlineMatcher, IsInline) {
301c6e05029SPiotr Padlewski EXPECT_TRUE(matches("void g(); inline void f();",
302c6e05029SPiotr Padlewski functionDecl(isInline(), hasName("f"))));
303c6e05029SPiotr Padlewski EXPECT_TRUE(matches("namespace n { inline namespace m {} }",
304c6e05029SPiotr Padlewski namespaceDecl(isInline(), hasName("m"))));
305c34d8981SNathan James EXPECT_TRUE(matches("inline int Foo = 5;",
306c34d8981SNathan James varDecl(isInline(), hasName("Foo")), {Lang_CXX17}));
307c6e05029SPiotr Padlewski }
308c6e05029SPiotr Padlewski
309c6e05029SPiotr Padlewski // FIXME: Figure out how to specify paths so the following tests pass on
310c6e05029SPiotr Padlewski // Windows.
3111865df49SNico Weber #ifndef _WIN32
312c6e05029SPiotr Padlewski
TEST(Matcher,IsExpansionInMainFileMatcher)313c6e05029SPiotr Padlewski TEST(Matcher, IsExpansionInMainFileMatcher) {
314c6e05029SPiotr Padlewski EXPECT_TRUE(matches("class X {};",
315c6e05029SPiotr Padlewski recordDecl(hasName("X"), isExpansionInMainFile())));
316c6e05029SPiotr Padlewski EXPECT_TRUE(notMatches("", recordDecl(isExpansionInMainFile())));
317c6e05029SPiotr Padlewski FileContentMappings M;
318c6e05029SPiotr Padlewski M.push_back(std::make_pair("/other", "class X {};"));
319c6e05029SPiotr Padlewski EXPECT_TRUE(matchesConditionally("#include <other>\n",
320c6e05029SPiotr Padlewski recordDecl(isExpansionInMainFile()), false,
321b5fc1debSDmitri Gribenko {"-isystem/"}, M));
322c6e05029SPiotr Padlewski }
323c6e05029SPiotr Padlewski
TEST(Matcher,IsExpansionInSystemHeader)324c6e05029SPiotr Padlewski TEST(Matcher, IsExpansionInSystemHeader) {
325c6e05029SPiotr Padlewski FileContentMappings M;
326c6e05029SPiotr Padlewski M.push_back(std::make_pair("/other", "class X {};"));
327c6e05029SPiotr Padlewski EXPECT_TRUE(matchesConditionally("#include \"other\"\n",
328c6e05029SPiotr Padlewski recordDecl(isExpansionInSystemHeader()),
329b5fc1debSDmitri Gribenko true, {"-isystem/"}, M));
330b5fc1debSDmitri Gribenko EXPECT_TRUE(matchesConditionally("#include \"other\"\n",
331b5fc1debSDmitri Gribenko recordDecl(isExpansionInSystemHeader()),
332b5fc1debSDmitri Gribenko false, {"-I/"}, M));
333c6e05029SPiotr Padlewski EXPECT_TRUE(notMatches("class X {};",
334c6e05029SPiotr Padlewski recordDecl(isExpansionInSystemHeader())));
335c6e05029SPiotr Padlewski EXPECT_TRUE(notMatches("", recordDecl(isExpansionInSystemHeader())));
336c6e05029SPiotr Padlewski }
337c6e05029SPiotr Padlewski
TEST(Matcher,IsExpansionInFileMatching)338c6e05029SPiotr Padlewski TEST(Matcher, IsExpansionInFileMatching) {
339c6e05029SPiotr Padlewski FileContentMappings M;
340c6e05029SPiotr Padlewski M.push_back(std::make_pair("/foo", "class A {};"));
341c6e05029SPiotr Padlewski M.push_back(std::make_pair("/bar", "class B {};"));
342c6e05029SPiotr Padlewski EXPECT_TRUE(matchesConditionally(
343c6e05029SPiotr Padlewski "#include <foo>\n"
344c6e05029SPiotr Padlewski "#include <bar>\n"
345c6e05029SPiotr Padlewski "class X {};",
346c6e05029SPiotr Padlewski recordDecl(isExpansionInFileMatching("b.*"), hasName("B")), true,
347b5fc1debSDmitri Gribenko {"-isystem/"}, M));
348c6e05029SPiotr Padlewski EXPECT_TRUE(matchesConditionally(
349c6e05029SPiotr Padlewski "#include <foo>\n"
350c6e05029SPiotr Padlewski "#include <bar>\n"
351c6e05029SPiotr Padlewski "class X {};",
352c6e05029SPiotr Padlewski recordDecl(isExpansionInFileMatching("f.*"), hasName("X")), false,
353b5fc1debSDmitri Gribenko {"-isystem/"}, M));
354c6e05029SPiotr Padlewski }
355c6e05029SPiotr Padlewski
3561865df49SNico Weber #endif // _WIN32
357c6e05029SPiotr Padlewski
358c6e05029SPiotr Padlewski } // end namespace ast_matchers
359c6e05029SPiotr Padlewski } // end namespace clang
360