xref: /llvm-project/clang/unittests/ASTMatchers/ASTMatchersInternalTest.cpp (revision d768bf994f508d7eaf9541a568be3d71096febf5)
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