1 //===-- ParsedASTTests.cpp ------------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // These tests cover clangd's logic to build a TU, which generally uses the APIs
10 // in ParsedAST and Preamble, via the TestTU helper.
12 //===----------------------------------------------------------------------===//
14 #include "../../clang-tidy/ClangTidyCheck.h"
18 #include "Diagnostics.h"
20 #include "ParsedAST.h"
22 #include "SourceCode.h"
25 #include "TidyProvider.h"
26 #include "support/Context.h"
27 #include "clang/AST/DeclTemplate.h"
28 #include "clang/Basic/SourceLocation.h"
29 #include "clang/Basic/SourceManager.h"
30 #include "clang/Basic/TokenKinds.h"
31 #include "clang/Tooling/Syntax/Tokens.h"
32 #include "llvm/ADT/StringRef.h"
33 #include "llvm/Testing/Annotations/Annotations.h"
34 #include "llvm/Testing/Support/Error.h"
35 #include "gmock/gmock-matchers.h"
36 #include "gmock/gmock.h"
37 #include "gtest/gtest.h"
44 using ::testing::AllOf
;
45 using ::testing::Contains
;
46 using ::testing::ElementsAre
;
47 using ::testing::ElementsAreArray
;
48 using ::testing::IsEmpty
;
49 using ::testing::UnorderedElementsAreArray
;
51 MATCHER_P(declNamed
, Name
, "") {
52 if (NamedDecl
*ND
= dyn_cast
<NamedDecl
>(arg
))
53 if (ND
->getName() == Name
)
55 if (auto *Stream
= result_listener
->stream()) {
56 llvm::raw_os_ostream
OS(*Stream
);
62 MATCHER_P(declKind
, Kind
, "") {
63 if (NamedDecl
*ND
= dyn_cast
<NamedDecl
>(arg
))
64 if (ND
->getDeclKindName() == llvm::StringRef(Kind
))
66 if (auto *Stream
= result_listener
->stream()) {
67 llvm::raw_os_ostream
OS(*Stream
);
73 // Matches if the Decl has template args equal to ArgName. If the decl is a
74 // NamedDecl and ArgName is an empty string it also matches.
75 MATCHER_P(withTemplateArgs
, ArgName
, "") {
76 if (const FunctionDecl
*FD
= dyn_cast
<FunctionDecl
>(arg
)) {
77 if (const auto *Args
= FD
->getTemplateSpecializationArgs()) {
78 std::string SpecializationArgs
;
79 // Without the PrintingPolicy "bool" will be printed as "_Bool".
81 PrintingPolicy
Policy(LO
);
82 Policy
.adjustForCPlusPlus();
83 for (const auto &Arg
: Args
->asArray()) {
84 if (SpecializationArgs
.size() > 0)
85 SpecializationArgs
+= ",";
86 SpecializationArgs
+= Arg
.getAsType().getAsString(Policy
);
88 if (Args
->size() == 0)
89 return ArgName
== SpecializationArgs
;
90 return ArgName
== "<" + SpecializationArgs
+ ">";
93 if (const NamedDecl
*ND
= dyn_cast
<NamedDecl
>(arg
))
94 return printTemplateSpecializationArgs(*ND
) == ArgName
;
98 MATCHER_P(pragmaTrivia
, P
, "") { return arg
.Trivia
== P
; }
101 Inclusion Actual
= testing::get
<0>(arg
);
102 Inclusion Expected
= testing::get
<1>(arg
);
103 return std::tie(Actual
.HashLine
, Actual
.Written
) ==
104 std::tie(Expected
.HashLine
, Expected
.Written
);
107 TEST(ParsedASTTest
, TopLevelDecls
) {
115 template <typename> bool X = true;
117 auto AST
= TU
.build();
118 EXPECT_THAT(AST
.getLocalTopLevelDecls(),
119 testing::UnorderedElementsAreArray(
120 {AllOf(declNamed("main"), declKind("Function")),
121 AllOf(declNamed("X"), declKind("VarTemplate"))}));
124 TEST(ParsedASTTest
, DoesNotGetIncludedTopDecls
) {
126 TU
.HeaderCode
= R
"cpp(
127 #define LL void foo(){}
140 auto AST
= TU
.build();
141 EXPECT_THAT(AST
.getLocalTopLevelDecls(), ElementsAre(declNamed("main")));
144 TEST(ParsedASTTest
, DoesNotGetImplicitTemplateTopDecls
) {
154 auto AST
= TU
.build();
155 EXPECT_THAT(AST
.getLocalTopLevelDecls(),
156 ElementsAre(declNamed("f"), declNamed("s")));
160 GetsExplicitInstantiationAndSpecializationTemplateTopDecls
) {
163 template <typename T>
167 template void f(double);
179 double d = foo<double>;
187 auto AST
= TU
.build();
189 AST
.getLocalTopLevelDecls(),
190 ElementsAreArray({AllOf(declNamed("f"), withTemplateArgs("")),
191 AllOf(declNamed("f"), withTemplateArgs("<bool>")),
192 AllOf(declNamed("f"), withTemplateArgs("<double>")),
193 AllOf(declNamed("V"), withTemplateArgs("")),
194 AllOf(declNamed("V"), withTemplateArgs("<T *>")),
195 AllOf(declNamed("V"), withTemplateArgs("<bool>")),
196 AllOf(declNamed("foo"), withTemplateArgs("")),
197 AllOf(declNamed("i"), withTemplateArgs("")),
198 AllOf(declNamed("d"), withTemplateArgs("")),
199 AllOf(declNamed("foo"), withTemplateArgs("<T *>")),
200 AllOf(declNamed("foo"), withTemplateArgs("<bool>"))}));
203 TEST(ParsedASTTest
, IgnoresDelayedTemplateParsing
) {
204 auto TU
= TestTU::withCode(R
"cpp(
205 template <typename T> void xxx() {
209 TU
.ExtraArgs
.push_back("-fdelayed-template-parsing");
210 auto AST
= TU
.build();
211 EXPECT_EQ(Decl::Var
, findUnqualifiedDecl(AST
, "yyy").getKind());
214 TEST(ParsedASTTest
, TokensAfterPreamble
) {
216 TU
.AdditionalFiles
["foo.h"] = R
"(
223 // error-ok: invalid syntax, just examining token stream
227 auto AST
= TU
.build();
228 const syntax::TokenBuffer
&T
= AST
.getTokens();
229 const auto &SM
= AST
.getSourceManager();
231 ASSERT_GT(T
.expandedTokens().size(), 2u);
232 // Check first token after the preamble.
233 EXPECT_EQ(T
.expandedTokens().front().text(SM
), "first_token");
234 // Last token is always 'eof'.
235 EXPECT_EQ(T
.expandedTokens().back().kind(), tok::eof
);
236 // Check the token before 'eof'.
237 EXPECT_EQ(T
.expandedTokens().drop_back().back().text(SM
), "last_token");
239 // The spelled tokens for the main file should have everything.
240 auto Spelled
= T
.spelledTokens(SM
.getMainFileID());
241 ASSERT_FALSE(Spelled
.empty());
242 EXPECT_EQ(Spelled
.front().kind(), tok::hash
);
243 EXPECT_EQ(Spelled
.back().text(SM
), "last_token");
246 TEST(ParsedASTTest
, NoCrashOnTokensWithTidyCheck
) {
248 // this check runs the preprocessor, we need to make sure it does not break
249 // our recording logic.
250 TU
.ClangTidyProvider
= addTidyChecks("modernize-use-trailing-return-type");
251 TU
.Code
= "inline int foo() {}";
253 auto AST
= TU
.build();
254 const syntax::TokenBuffer
&T
= AST
.getTokens();
255 const auto &SM
= AST
.getSourceManager();
257 ASSERT_GT(T
.expandedTokens().size(), 7u);
258 // Check first token after the preamble.
259 EXPECT_EQ(T
.expandedTokens().front().text(SM
), "inline");
260 // Last token is always 'eof'.
261 EXPECT_EQ(T
.expandedTokens().back().kind(), tok::eof
);
262 // Check the token before 'eof'.
263 EXPECT_EQ(T
.expandedTokens().drop_back().back().text(SM
), "}");
266 TEST(ParsedASTTest
, CanBuildInvocationWithUnknownArgs
) {
268 FS
.Files
= {{testPath("foo.cpp"), "void test() {}"}};
269 // Unknown flags should not prevent a build of compiler invocation.
272 Inputs
.CompileCommand
.CommandLine
= {"clang", "-fsome-unknown-flag",
273 testPath("foo.cpp")};
274 IgnoreDiagnostics IgnoreDiags
;
275 EXPECT_NE(buildCompilerInvocation(Inputs
, IgnoreDiags
), nullptr);
277 // Unknown forwarded to -cc1 should not a failure either.
278 Inputs
.CompileCommand
.CommandLine
= {
279 "clang", "-Xclang", "-fsome-unknown-flag", testPath("foo.cpp")};
280 EXPECT_NE(buildCompilerInvocation(Inputs
, IgnoreDiags
), nullptr);
283 TEST(ParsedASTTest
, CollectsMainFileMacroExpansions
) {
284 llvm::Annotations
TestCase(R
"cpp(
285 #define ^MACRO_ARGS(X, Y) X Y
288 // Macro arguments included.
289 ^MACRO_ARGS(^MACRO_ARGS(^MACRO_EXP(int), E), ^ID(= 2));
291 // Macro names inside other macros not included.
292 #define ^MACRO_ARGS2(X, Y) X Y
297 // Macros from token concatenations not included.
298 #define ^CONCAT(X) X##A()
299 #define ^PREPEND(X) MACRO##X()
300 #define ^MACROA() 123
301 int G = ^CONCAT(MACRO);
304 // Macros included not from preamble not included.
307 int printf(const char*, ...);
309 #define ^assert(COND) if (!(COND)) { printf("%s
", #COND); exit(0); }
312 // Includes macro expansions in arguments that are expressions
319 #define ^MULTIPLE_DEFINITION 1
320 #undef ^MULTIPLE_DEFINITION
322 #define ^MULTIPLE_DEFINITION 2
323 #undef ^MULTIPLE_DEFINITION
325 auto TU
= TestTU::withCode(TestCase
.code());
326 TU
.HeaderCode
= R
"cpp(
328 #define MACRO_EXP(X) ID(X)
331 TU
.AdditionalFiles
["foo.inc"] = R
"cpp(
336 ParsedAST AST
= TU
.build();
337 std::vector
<size_t> MacroExpansionPositions
;
338 for (const auto &SIDToRefs
: AST
.getMacros().MacroRefs
) {
339 for (const auto &R
: SIDToRefs
.second
)
340 MacroExpansionPositions
.push_back(R
.StartOffset
);
342 for (const auto &R
: AST
.getMacros().UnknownMacros
)
343 MacroExpansionPositions
.push_back(R
.StartOffset
);
345 MacroExpansionPositions
,
346 testing::UnorderedElementsAreArray(TestCase
.points()));
349 MATCHER_P(withFileName
, Inc
, "") { return arg
.FileName
== Inc
; }
351 TEST(ParsedASTTest
, PatchesAdditionalIncludes
) {
352 llvm::StringLiteral ModifiedContents
= R
"cpp(
361 // Build expected ast with symbols coming from headers.
363 TU
.Filename
= "foo.cpp";
364 TU
.AdditionalFiles
["foo.h"] = "void foo();";
365 TU
.AdditionalFiles
["sub/baz.h"] = "void baz();";
366 TU
.AdditionalFiles
["sub/aux.h"] = "void aux();";
367 TU
.ExtraArgs
= {"-I" + testPath("sub")};
368 TU
.Code
= ModifiedContents
.str();
369 auto ExpectedAST
= TU
.build();
371 // Build preamble with no includes.
375 auto Inputs
= TU
.inputs(FS
);
376 auto CI
= buildCompilerInvocation(Inputs
, Diags
);
378 buildPreamble(testPath("foo.cpp"), *CI
, Inputs
, true, nullptr);
379 ASSERT_TRUE(EmptyPreamble
);
380 EXPECT_THAT(EmptyPreamble
->Includes
.MainFileIncludes
, IsEmpty());
382 // Now build an AST using empty preamble and ensure patched includes worked.
383 TU
.Code
= ModifiedContents
.str();
384 Inputs
= TU
.inputs(FS
);
385 auto PatchedAST
= ParsedAST::build(testPath("foo.cpp"), Inputs
, std::move(CI
),
387 ASSERT_TRUE(PatchedAST
);
389 // Ensure source location information is correct, including resolved paths.
390 EXPECT_THAT(PatchedAST
->getIncludeStructure().MainFileIncludes
,
392 eqInc(), ExpectedAST
.getIncludeStructure().MainFileIncludes
));
393 // Ensure file proximity signals are correct.
394 auto &SM
= PatchedAST
->getSourceManager();
395 auto &FM
= SM
.getFileManager();
396 // Copy so that we can use operator[] to get the children.
397 IncludeStructure Includes
= PatchedAST
->getIncludeStructure();
398 auto MainFE
= FM
.getFile(testPath("foo.cpp"));
400 auto MainID
= Includes
.getID(*MainFE
);
401 auto AuxFE
= FM
.getFile(testPath("sub/aux.h"));
403 auto AuxID
= Includes
.getID(*AuxFE
);
404 EXPECT_THAT(Includes
.IncludeChildren
[*MainID
], Contains(*AuxID
));
407 TEST(ParsedASTTest
, PatchesDeletedIncludes
) {
409 TU
.Filename
= "foo.cpp";
411 auto ExpectedAST
= TU
.build();
413 // Build preamble with no includes.
414 TU
.Code
= R
"cpp(#include <foo.h>)cpp";
417 auto Inputs
= TU
.inputs(FS
);
418 auto CI
= buildCompilerInvocation(Inputs
, Diags
);
419 auto BaselinePreamble
=
420 buildPreamble(testPath("foo.cpp"), *CI
, Inputs
, true, nullptr);
421 ASSERT_TRUE(BaselinePreamble
);
422 EXPECT_THAT(BaselinePreamble
->Includes
.MainFileIncludes
,
423 ElementsAre(testing::Field(&Inclusion::Written
, "<foo.h>")));
425 // Now build an AST using additional includes and check that locations are
428 Inputs
= TU
.inputs(FS
);
429 auto PatchedAST
= ParsedAST::build(testPath("foo.cpp"), Inputs
, std::move(CI
),
430 {}, BaselinePreamble
);
431 ASSERT_TRUE(PatchedAST
);
433 // Ensure source location information is correct.
434 EXPECT_THAT(PatchedAST
->getIncludeStructure().MainFileIncludes
,
436 eqInc(), ExpectedAST
.getIncludeStructure().MainFileIncludes
));
437 // Ensure file proximity signals are correct.
438 auto &SM
= ExpectedAST
.getSourceManager();
439 auto &FM
= SM
.getFileManager();
440 // Copy so that we can getOrCreateID().
441 IncludeStructure Includes
= ExpectedAST
.getIncludeStructure();
442 auto MainFE
= FM
.getFileRef(testPath("foo.cpp"));
443 ASSERT_THAT_EXPECTED(MainFE
, llvm::Succeeded());
444 auto MainID
= Includes
.getOrCreateID(*MainFE
);
445 auto &PatchedFM
= PatchedAST
->getSourceManager().getFileManager();
446 IncludeStructure PatchedIncludes
= PatchedAST
->getIncludeStructure();
447 auto PatchedMainFE
= PatchedFM
.getFileRef(testPath("foo.cpp"));
448 ASSERT_THAT_EXPECTED(PatchedMainFE
, llvm::Succeeded());
449 auto PatchedMainID
= PatchedIncludes
.getOrCreateID(*PatchedMainFE
);
450 EXPECT_EQ(Includes
.includeDepth(MainID
)[MainID
],
451 PatchedIncludes
.includeDepth(PatchedMainID
)[PatchedMainID
]);
454 // Returns Code guarded by #ifndef guards
455 std::string
guard(llvm::StringRef Code
) {
456 static int GuardID
= 0;
457 std::string GuardName
= ("GUARD_" + llvm::Twine(++GuardID
)).str();
458 return llvm::formatv("#ifndef {0}\n#define {0}\n{1}\n#endif\n", GuardName
,
462 std::string
once(llvm::StringRef Code
) {
463 return llvm::formatv("#pragma once\n{0}\n", Code
);
466 bool mainIsGuarded(const ParsedAST
&AST
) {
467 const auto &SM
= AST
.getSourceManager();
468 const FileEntry
*MainFE
= SM
.getFileEntryForID(SM
.getMainFileID());
469 return AST
.getPreprocessor()
470 .getHeaderSearchInfo()
471 .isFileMultipleIncludeGuarded(MainFE
);
474 MATCHER_P(diag
, Desc
, "") {
475 return llvm::StringRef(arg
.Message
).contains(Desc
);
478 // Check our understanding of whether the main file is header guarded or not.
479 TEST(ParsedASTTest
, HeaderGuards
) {
481 TU
.ImplicitHeaderGuard
= false;
484 EXPECT_FALSE(mainIsGuarded(TU
.build()));
486 TU
.Code
= guard(";");
487 EXPECT_TRUE(mainIsGuarded(TU
.build()));
490 EXPECT_TRUE(mainIsGuarded(TU
.build()));
496 EXPECT_FALSE(mainIsGuarded(TU
.build())); // FIXME: true
505 EXPECT_FALSE(mainIsGuarded(TU
.build()));
508 // Check our handling of files that include themselves.
509 // Ideally we allow this if the file has header guards.
511 // Note: the semicolons (empty statements) are significant!
512 // - they force the preamble to end and the body to begin. Directives can have
513 // different effects in the preamble vs main file (which we try to hide).
514 // - if the preamble would otherwise cover the whole file, a trailing semicolon
515 // forces their sizes to be different. This is significant because the file
516 // size is part of the lookup key for HeaderFileInfo, and we don't want to
517 // rely on the preamble's HFI being looked up when parsing the main file.
518 TEST(ParsedASTTest
, HeaderGuardsSelfInclude
) {
519 // Disable include cleaner diagnostics to prevent them from interfering with
520 // other diagnostics.
522 Cfg
.Diagnostics
.MissingIncludes
= Config::IncludesPolicy::None
;
523 Cfg
.Diagnostics
.UnusedIncludes
= Config::IncludesPolicy::None
;
524 WithContextValue
Ctx(Config::Key
, std::move(Cfg
));
527 TU
.ImplicitHeaderGuard
= false;
528 TU
.Filename
= "self.h";
531 #include "self
.h
" // error-ok
534 auto AST
= TU
.build();
535 EXPECT_THAT(AST
.getDiagnostics(),
536 ElementsAre(diag("recursively when building a preamble")));
537 EXPECT_FALSE(mainIsGuarded(AST
));
541 #include "self
.h
" // error-ok
544 EXPECT_THAT(AST
.getDiagnostics(), ElementsAre(diag("nested too deeply")));
545 EXPECT_FALSE(mainIsGuarded(AST
));
553 EXPECT_THAT(AST
.getDiagnostics(), IsEmpty());
554 EXPECT_TRUE(mainIsGuarded(AST
));
562 EXPECT_THAT(AST
.getDiagnostics(), IsEmpty());
563 EXPECT_TRUE(mainIsGuarded(AST
));
571 EXPECT_THAT(AST
.getDiagnostics(), IsEmpty());
572 EXPECT_TRUE(mainIsGuarded(AST
));
577 #include "self
.h
" // error-ok: FIXME, this would be nice to support
582 EXPECT_THAT(AST
.getDiagnostics(),
583 ElementsAre(diag("recursively when building a preamble")));
584 EXPECT_TRUE(mainIsGuarded(AST
));
594 EXPECT_THAT(AST
.getDiagnostics(), IsEmpty());
595 EXPECT_TRUE(mainIsGuarded(AST
));
597 // Guarded too late...
599 #include "self
.h
" // error-ok
606 EXPECT_THAT(AST
.getDiagnostics(),
607 ElementsAre(diag("recursively when building a preamble")));
608 EXPECT_FALSE(mainIsGuarded(AST
));
611 #include "self
.h
" // error-ok
618 EXPECT_THAT(AST
.getDiagnostics(),
619 ElementsAre(diag("recursively when building a preamble")));
620 EXPECT_FALSE(mainIsGuarded(AST
));
630 EXPECT_THAT(AST
.getDiagnostics(), IsEmpty());
631 EXPECT_FALSE(mainIsGuarded(AST
));
634 #include "self
.h
" // error-ok
639 EXPECT_THAT(AST
.getDiagnostics(),
640 ElementsAre(diag("recursively when building a preamble")));
641 EXPECT_TRUE(mainIsGuarded(AST
));
644 #include "self
.h
" // error-ok
649 EXPECT_THAT(AST
.getDiagnostics(),
650 ElementsAre(diag("recursively when building a preamble")));
651 EXPECT_TRUE(mainIsGuarded(AST
));
654 // Tests how we handle common idioms for splitting a header-only library
655 // into interface and implementation files (e.g. *.h vs *.inl).
656 // These files mutually include each other, and need careful handling of include
657 // guards (which interact with preambles).
658 TEST(ParsedASTTest
, HeaderGuardsImplIface
) {
659 std::string Interface
= R
"cpp(
660 // error-ok: we assert on diagnostics explicitly
661 template <class T> struct Traits {
666 std::string Implementation
= R
"cpp(
667 // error-ok: we assert on diagnostics explicitly
669 template <class T> unsigned Traits<T>::size() {
675 TU
.ImplicitHeaderGuard
= false; // We're testing include guard handling!
676 TU
.ExtraArgs
.push_back("-xc++-header");
678 // Editing the interface file, which is include guarded (easy case).
679 // We mostly get this right via PP if we don't recognize the include guard.
680 TU
.Filename
= "iface.h";
681 TU
.Code
= guard(Interface
);
682 TU
.AdditionalFiles
= {{"impl.h", Implementation
}};
683 auto AST
= TU
.build();
684 EXPECT_THAT(AST
.getDiagnostics(), IsEmpty());
685 EXPECT_TRUE(mainIsGuarded(AST
));
686 // Slightly harder: the `#pragma once` is part of the preamble, and we
687 // need to transfer it to the main file's HeaderFileInfo.
688 TU
.Code
= once(Interface
);
690 EXPECT_THAT(AST
.getDiagnostics(), IsEmpty());
691 EXPECT_TRUE(mainIsGuarded(AST
));
693 // Editing the implementation file, which is not include guarded.
694 TU
.Filename
= "impl.h";
695 TU
.Code
= Implementation
;
696 TU
.AdditionalFiles
= {{"iface.h", guard(Interface
)}};
698 // The diagnostic is unfortunate in this case, but correct per our model.
699 // Ultimately the include is skipped and the code is parsed correctly though.
700 EXPECT_THAT(AST
.getDiagnostics(),
701 ElementsAre(diag("in included file: main file cannot be included "
702 "recursively when building a preamble")));
703 EXPECT_FALSE(mainIsGuarded(AST
));
704 // Interface is pragma once guarded, same thing.
705 TU
.AdditionalFiles
= {{"iface.h", once(Interface
)}};
707 EXPECT_THAT(AST
.getDiagnostics(),
708 ElementsAre(diag("in included file: main file cannot be included "
709 "recursively when building a preamble")));
710 EXPECT_FALSE(mainIsGuarded(AST
));
713 TEST(ParsedASTTest
, DiscoversPragmaMarks
) {
715 TU
.AdditionalFiles
["Header.h"] = R
"(
716 #pragma mark - Something API
718 #pragma mark Something else
722 #pragma mark In Preamble
723 #pragma mark - Something Impl
724 int something() { return 1; }
727 auto AST
= TU
.build();
729 EXPECT_THAT(AST
.getMarks(), ElementsAre(pragmaTrivia(" In Preamble"),
730 pragmaTrivia(" - Something Impl"),
731 pragmaTrivia(" End")));
735 } // namespace clangd