clang-tools  14.0.0git
ParsedASTTests.cpp
Go to the documentation of this file.
1 //===-- ParsedASTTests.cpp ------------------------------------------------===//
2 //
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
6 //
7 //===----------------------------------------------------------------------===//
8 //
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.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "../../clang-tidy/ClangTidyCheck.h"
15 #include "../../clang-tidy/ClangTidyModule.h"
16 #include "../../clang-tidy/ClangTidyModuleRegistry.h"
17 #include "AST.h"
18 #include "Annotations.h"
19 #include "Compiler.h"
20 #include "Diagnostics.h"
21 #include "Headers.h"
22 #include "ParsedAST.h"
23 #include "Preamble.h"
24 #include "SourceCode.h"
25 #include "TestFS.h"
26 #include "TestTU.h"
27 #include "TidyProvider.h"
28 #include "clang/AST/DeclTemplate.h"
29 #include "clang/Basic/SourceLocation.h"
30 #include "clang/Basic/SourceManager.h"
31 #include "clang/Basic/TokenKinds.h"
32 #include "clang/Lex/PPCallbacks.h"
33 #include "clang/Lex/Token.h"
34 #include "clang/Tooling/Syntax/Tokens.h"
35 #include "llvm/ADT/STLExtras.h"
36 #include "llvm/ADT/StringRef.h"
37 #include "llvm/Support/ScopedPrinter.h"
38 #include "gmock/gmock-matchers.h"
39 #include "gmock/gmock.h"
40 #include "gtest/gtest.h"
41 
42 namespace clang {
43 namespace clangd {
44 namespace {
45 
46 using ::testing::AllOf;
47 using ::testing::Contains;
48 using ::testing::ElementsAre;
49 using ::testing::ElementsAreArray;
50 using ::testing::IsEmpty;
51 using ::testing::UnorderedElementsAreArray;
52 
53 MATCHER_P(DeclNamed, Name, "") {
54  if (NamedDecl *ND = dyn_cast<NamedDecl>(arg))
55  if (ND->getName() == Name)
56  return true;
57  if (auto *Stream = result_listener->stream()) {
58  llvm::raw_os_ostream OS(*Stream);
59  arg->dump(OS);
60  }
61  return false;
62 }
63 
64 MATCHER_P(DeclKind, Kind, "") {
65  if (NamedDecl *ND = dyn_cast<NamedDecl>(arg))
66  if (ND->getDeclKindName() == llvm::StringRef(Kind))
67  return true;
68  if (auto *Stream = result_listener->stream()) {
69  llvm::raw_os_ostream OS(*Stream);
70  arg->dump(OS);
71  }
72  return false;
73 }
74 
75 // Matches if the Decl has template args equal to ArgName. If the decl is a
76 // NamedDecl and ArgName is an empty string it also matches.
77 MATCHER_P(WithTemplateArgs, ArgName, "") {
78  if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(arg)) {
79  if (const auto *Args = FD->getTemplateSpecializationArgs()) {
80  std::string SpecializationArgs;
81  // Without the PrintingPolicy "bool" will be printed as "_Bool".
82  LangOptions LO;
83  PrintingPolicy Policy(LO);
84  Policy.adjustForCPlusPlus();
85  for (const auto &Arg : Args->asArray()) {
86  if (SpecializationArgs.size() > 0)
87  SpecializationArgs += ",";
88  SpecializationArgs += Arg.getAsType().getAsString(Policy);
89  }
90  if (Args->size() == 0)
91  return ArgName == SpecializationArgs;
92  return ArgName == "<" + SpecializationArgs + ">";
93  }
94  }
95  if (const NamedDecl *ND = dyn_cast<NamedDecl>(arg))
96  return printTemplateSpecializationArgs(*ND) == ArgName;
97  return false;
98 }
99 
100 MATCHER_P(RangeIs, R, "") {
101  return arg.beginOffset() == R.Begin && arg.endOffset() == R.End;
102 }
103 
104 MATCHER_P(PragmaTrivia, P, "") { return arg.Trivia == P; }
105 
106 MATCHER(EqInc, "") {
107  Inclusion Actual = testing::get<0>(arg);
108  Inclusion Expected = testing::get<1>(arg);
109  return std::tie(Actual.HashLine, Actual.Written) ==
110  std::tie(Expected.HashLine, Expected.Written);
111 }
112 
113 TEST(ParsedASTTest, TopLevelDecls) {
114  TestTU TU;
115  TU.HeaderCode = R"(
116  int header1();
117  int header2;
118  )";
119  TU.Code = R"cpp(
120  int main();
121  template <typename> bool X = true;
122  )cpp";
123  auto AST = TU.build();
124  EXPECT_THAT(AST.getLocalTopLevelDecls(),
125  testing::UnorderedElementsAreArray(
126  {AllOf(DeclNamed("main"), DeclKind("Function")),
127  AllOf(DeclNamed("X"), DeclKind("VarTemplate"))}));
128 }
129 
130 TEST(ParsedASTTest, DoesNotGetIncludedTopDecls) {
131  TestTU TU;
132  TU.HeaderCode = R"cpp(
133  #define LL void foo(){}
134  template<class T>
135  struct H {
136  H() {}
137  LL
138  };
139  )cpp";
140  TU.Code = R"cpp(
141  int main() {
142  H<int> h;
143  h.foo();
144  }
145  )cpp";
146  auto AST = TU.build();
147  EXPECT_THAT(AST.getLocalTopLevelDecls(), ElementsAre(DeclNamed("main")));
148 }
149 
150 TEST(ParsedASTTest, DoesNotGetImplicitTemplateTopDecls) {
151  TestTU TU;
152  TU.Code = R"cpp(
153  template<typename T>
154  void f(T) {}
155  void s() {
156  f(10UL);
157  }
158  )cpp";
159 
160  auto AST = TU.build();
161  EXPECT_THAT(AST.getLocalTopLevelDecls(),
162  ElementsAre(DeclNamed("f"), DeclNamed("s")));
163 }
164 
165 TEST(ParsedASTTest,
166  GetsExplicitInstantiationAndSpecializationTemplateTopDecls) {
167  TestTU TU;
168  TU.Code = R"cpp(
169  template <typename T>
170  void f(T) {}
171  template<>
172  void f(bool);
173  template void f(double);
174 
175  template <class T>
176  struct V {};
177  template<class T>
178  struct V<T*> {};
179  template <>
180  struct V<bool> {};
181 
182  template<class T>
183  T foo = T(10);
184  int i = foo<int>;
185  double d = foo<double>;
186 
187  template <class T>
188  int foo<T*> = 0;
189  template <>
190  int foo<bool> = 0;
191  )cpp";
192 
193  auto AST = TU.build();
194  EXPECT_THAT(
195  AST.getLocalTopLevelDecls(),
196  ElementsAreArray({AllOf(DeclNamed("f"), WithTemplateArgs("")),
197  AllOf(DeclNamed("f"), WithTemplateArgs("<bool>")),
198  AllOf(DeclNamed("f"), WithTemplateArgs("<double>")),
199  AllOf(DeclNamed("V"), WithTemplateArgs("")),
200  AllOf(DeclNamed("V"), WithTemplateArgs("<T *>")),
201  AllOf(DeclNamed("V"), WithTemplateArgs("<bool>")),
202  AllOf(DeclNamed("foo"), WithTemplateArgs("")),
203  AllOf(DeclNamed("i"), WithTemplateArgs("")),
204  AllOf(DeclNamed("d"), WithTemplateArgs("")),
205  AllOf(DeclNamed("foo"), WithTemplateArgs("<T *>")),
206  AllOf(DeclNamed("foo"), WithTemplateArgs("<bool>"))}));
207 }
208 
209 TEST(ParsedASTTest, IgnoresDelayedTemplateParsing) {
210  auto TU = TestTU::withCode(R"cpp(
211  template <typename T> void xxx() {
212  int yyy = 0;
213  }
214  )cpp");
215  TU.ExtraArgs.push_back("-fdelayed-template-parsing");
216  auto AST = TU.build();
217  EXPECT_EQ(Decl::Var, findUnqualifiedDecl(AST, "yyy").getKind());
218 }
219 
220 TEST(ParsedASTTest, TokensAfterPreamble) {
221  TestTU TU;
222  TU.AdditionalFiles["foo.h"] = R"(
223  int foo();
224  )";
225  TU.Code = R"cpp(
226  #include "foo.h"
227  first_token;
228  void test() {
229  // error-ok: invalid syntax, just examining token stream
230  }
231  last_token
232 )cpp";
233  auto AST = TU.build();
234  const syntax::TokenBuffer &T = AST.getTokens();
235  const auto &SM = AST.getSourceManager();
236 
237  ASSERT_GT(T.expandedTokens().size(), 2u);
238  // Check first token after the preamble.
239  EXPECT_EQ(T.expandedTokens().front().text(SM), "first_token");
240  // Last token is always 'eof'.
241  EXPECT_EQ(T.expandedTokens().back().kind(), tok::eof);
242  // Check the token before 'eof'.
243  EXPECT_EQ(T.expandedTokens().drop_back().back().text(SM), "last_token");
244 
245  // The spelled tokens for the main file should have everything.
246  auto Spelled = T.spelledTokens(SM.getMainFileID());
247  ASSERT_FALSE(Spelled.empty());
248  EXPECT_EQ(Spelled.front().kind(), tok::hash);
249  EXPECT_EQ(Spelled.back().text(SM), "last_token");
250 }
251 
252 TEST(ParsedASTTest, NoCrashOnTokensWithTidyCheck) {
253  TestTU TU;
254  // this check runs the preprocessor, we need to make sure it does not break
255  // our recording logic.
256  TU.ClangTidyProvider = addTidyChecks("modernize-use-trailing-return-type");
257  TU.Code = "inline int foo() {}";
258 
259  auto AST = TU.build();
260  const syntax::TokenBuffer &T = AST.getTokens();
261  const auto &SM = AST.getSourceManager();
262 
263  ASSERT_GT(T.expandedTokens().size(), 7u);
264  // Check first token after the preamble.
265  EXPECT_EQ(T.expandedTokens().front().text(SM), "inline");
266  // Last token is always 'eof'.
267  EXPECT_EQ(T.expandedTokens().back().kind(), tok::eof);
268  // Check the token before 'eof'.
269  EXPECT_EQ(T.expandedTokens().drop_back().back().text(SM), "}");
270 }
271 
272 TEST(ParsedASTTest, CanBuildInvocationWithUnknownArgs) {
273  MockFS FS;
274  FS.Files = {{testPath("foo.cpp"), "void test() {}"}};
275  // Unknown flags should not prevent a build of compiler invocation.
276  ParseInputs Inputs;
277  Inputs.TFS = &FS;
278  Inputs.CompileCommand.CommandLine = {"clang", "-fsome-unknown-flag",
279  testPath("foo.cpp")};
280  IgnoreDiagnostics IgnoreDiags;
281  EXPECT_NE(buildCompilerInvocation(Inputs, IgnoreDiags), nullptr);
282 
283  // Unknown forwarded to -cc1 should not a failure either.
284  Inputs.CompileCommand.CommandLine = {
285  "clang", "-Xclang", "-fsome-unknown-flag", testPath("foo.cpp")};
286  EXPECT_NE(buildCompilerInvocation(Inputs, IgnoreDiags), nullptr);
287 }
288 
289 TEST(ParsedASTTest, CollectsMainFileMacroExpansions) {
290  Annotations TestCase(R"cpp(
291  #define ^MACRO_ARGS(X, Y) X Y
292  // - preamble ends
293  ^ID(int A);
294  // Macro arguments included.
295  ^MACRO_ARGS(^MACRO_ARGS(^MACRO_EXP(int), E), ^ID(= 2));
296 
297  // Macro names inside other macros not included.
298  #define ^MACRO_ARGS2(X, Y) X Y
299  #define ^FOO BAR
300  #define ^BAR 1
301  int F = ^FOO;
302 
303  // Macros from token concatenations not included.
304  #define ^CONCAT(X) X##A()
305  #define ^PREPEND(X) MACRO##X()
306  #define ^MACROA() 123
307  int G = ^CONCAT(MACRO);
308  int H = ^PREPEND(A);
309 
310  // Macros included not from preamble not included.
311  #include "foo.inc"
312 
313  int printf(const char*, ...);
314  void exit(int);
315  #define ^assert(COND) if (!(COND)) { printf("%s", #COND); exit(0); }
316 
317  void test() {
318  // Includes macro expansions in arguments that are expressions
319  ^assert(0 <= ^BAR);
320  }
321 
322  #ifdef ^UNDEFINED
323  #endif
324 
325  #define ^MULTIPLE_DEFINITION 1
326  #undef ^MULTIPLE_DEFINITION
327 
328  #define ^MULTIPLE_DEFINITION 2
329  #undef ^MULTIPLE_DEFINITION
330  )cpp");
331  auto TU = TestTU::withCode(TestCase.code());
332  TU.HeaderCode = R"cpp(
333  #define ID(X) X
334  #define MACRO_EXP(X) ID(X)
335  MACRO_EXP(int B);
336  )cpp";
337  TU.AdditionalFiles["foo.inc"] = R"cpp(
338  int C = ID(1);
339  #define DEF 1
340  int D = DEF;
341  )cpp";
342  ParsedAST AST = TU.build();
343  std::vector<Position> MacroExpansionPositions;
344  for (const auto &SIDToRefs : AST.getMacros().MacroRefs) {
345  for (const auto &R : SIDToRefs.second)
346  MacroExpansionPositions.push_back(R.Rng.start);
347  }
348  for (const auto &R : AST.getMacros().UnknownMacros)
349  MacroExpansionPositions.push_back(R.Rng.start);
350  EXPECT_THAT(MacroExpansionPositions,
351  testing::UnorderedElementsAreArray(TestCase.points()));
352 }
353 
354 MATCHER_P(WithFileName, Inc, "") { return arg.FileName == Inc; }
355 
356 TEST(ParsedASTTest, ReplayPreambleForTidyCheckers) {
357  struct Inclusion {
358  Inclusion(const SourceManager &SM, SourceLocation HashLoc,
359  const Token &IncludeTok, llvm::StringRef FileName, bool IsAngled,
360  CharSourceRange FilenameRange)
361  : HashOffset(SM.getDecomposedLoc(HashLoc).second), IncTok(IncludeTok),
362  IncDirective(IncludeTok.getIdentifierInfo()->getName()),
363  FileNameOffset(SM.getDecomposedLoc(FilenameRange.getBegin()).second),
365  size_t HashOffset;
366  syntax::Token IncTok;
367  llvm::StringRef IncDirective;
368  size_t FileNameOffset;
369  llvm::StringRef FileName;
370  bool IsAngled;
371  };
372  static std::vector<Inclusion> Includes;
373  static std::vector<syntax::Token> SkippedFiles;
374  struct ReplayPreamblePPCallback : public PPCallbacks {
375  const SourceManager &SM;
376  explicit ReplayPreamblePPCallback(const SourceManager &SM) : SM(SM) {}
377 
378  void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok,
379  StringRef FileName, bool IsAngled,
380  CharSourceRange FilenameRange, const FileEntry *,
381  StringRef, StringRef, const clang::Module *,
382  SrcMgr::CharacteristicKind) override {
383  Includes.emplace_back(SM, HashLoc, IncludeTok, FileName, IsAngled,
384  FilenameRange);
385  }
386 
387  void FileSkipped(const FileEntryRef &, const Token &FilenameTok,
388  SrcMgr::CharacteristicKind) override {
389  SkippedFiles.emplace_back(FilenameTok);
390  }
391  };
392  struct ReplayPreambleCheck : public tidy::ClangTidyCheck {
393  ReplayPreambleCheck(StringRef Name, tidy::ClangTidyContext *Context)
394  : ClangTidyCheck(Name, Context) {}
395  void registerPPCallbacks(const SourceManager &SM, Preprocessor *PP,
396  Preprocessor *ModuleExpanderPP) override {
397  PP->addPPCallbacks(::std::make_unique<ReplayPreamblePPCallback>(SM));
398  }
399  };
400  struct ReplayPreambleModule : public tidy::ClangTidyModule {
401  void
402  addCheckFactories(tidy::ClangTidyCheckFactories &CheckFactories) override {
403  CheckFactories.registerCheck<ReplayPreambleCheck>(
404  "replay-preamble-check");
405  }
406  };
407 
408  static tidy::ClangTidyModuleRegistry::Add<ReplayPreambleModule> X(
409  "replay-preamble-module", "");
410  TestTU TU;
411  // This check records inclusion directives replayed by clangd.
412  TU.ClangTidyProvider = addTidyChecks("replay-preamble-check");
413  llvm::Annotations Test(R"cpp(
414  $hash^#$include[[import]] $filebegin^"$filerange[[bar.h]]"
415  $hash^#$include[[include_next]] $filebegin^"$filerange[[baz.h]]"
416  $hash^#$include[[include]] $filebegin^<$filerange[[a.h]]>)cpp");
417  llvm::StringRef Code = Test.code();
418  TU.Code = Code.str();
419  TU.AdditionalFiles["bar.h"] = "";
420  TU.AdditionalFiles["baz.h"] = "";
421  TU.AdditionalFiles["a.h"] = "";
422  // Since we are also testing #import directives, and they don't make much
423  // sense in c++ (also they actually break on windows), just set language to
424  // obj-c.
425  TU.ExtraArgs = {"-isystem.", "-xobjective-c"};
426 
427  const auto &AST = TU.build();
428  const auto &SM = AST.getSourceManager();
429 
430  auto HashLocs = Test.points("hash");
431  ASSERT_EQ(HashLocs.size(), Includes.size());
432  auto IncludeRanges = Test.ranges("include");
433  ASSERT_EQ(IncludeRanges.size(), Includes.size());
434  auto FileBeginLocs = Test.points("filebegin");
435  ASSERT_EQ(FileBeginLocs.size(), Includes.size());
436  auto FileRanges = Test.ranges("filerange");
437  ASSERT_EQ(FileRanges.size(), Includes.size());
438 
439  ASSERT_EQ(SkippedFiles.size(), Includes.size());
440  for (size_t I = 0; I < Includes.size(); ++I) {
441  const auto &Inc = Includes[I];
442 
443  EXPECT_EQ(Inc.HashOffset, HashLocs[I]);
444 
445  auto IncRange = IncludeRanges[I];
446  EXPECT_THAT(Inc.IncTok.range(SM), RangeIs(IncRange));
447  EXPECT_EQ(Inc.IncTok.kind(), tok::identifier);
448  EXPECT_EQ(Inc.IncDirective,
449  Code.substr(IncRange.Begin, IncRange.End - IncRange.Begin));
450 
451  EXPECT_EQ(Inc.FileNameOffset, FileBeginLocs[I]);
452  EXPECT_EQ(Inc.IsAngled, Code[FileBeginLocs[I]] == '<');
453 
454  auto FileRange = FileRanges[I];
455  EXPECT_EQ(Inc.FileName,
456  Code.substr(FileRange.Begin, FileRange.End - FileRange.Begin));
457 
458  EXPECT_EQ(SM.getDecomposedLoc(SkippedFiles[I].location()).second,
459  Inc.FileNameOffset);
460  // This also contains quotes/angles so increment the range by one from both
461  // sides.
462  EXPECT_EQ(
463  SkippedFiles[I].text(SM),
464  Code.substr(FileRange.Begin - 1, FileRange.End - FileRange.Begin + 2));
465  EXPECT_EQ(SkippedFiles[I].kind(), tok::header_name);
466  }
467 }
468 
469 TEST(ParsedASTTest, PatchesAdditionalIncludes) {
470  llvm::StringLiteral ModifiedContents = R"cpp(
471  #include "baz.h"
472  #include "foo.h"
473  #include "sub/aux.h"
474  void bar() {
475  foo();
476  baz();
477  aux();
478  })cpp";
479  // Build expected ast with symbols coming from headers.
480  TestTU TU;
481  TU.Filename = "foo.cpp";
482  TU.AdditionalFiles["foo.h"] = "void foo();";
483  TU.AdditionalFiles["sub/baz.h"] = "void baz();";
484  TU.AdditionalFiles["sub/aux.h"] = "void aux();";
485  TU.ExtraArgs = {"-I" + testPath("sub")};
486  TU.Code = ModifiedContents.str();
487  auto ExpectedAST = TU.build();
488 
489  // Build preamble with no includes.
490  TU.Code = "";
491  StoreDiags Diags;
492  MockFS FS;
493  auto Inputs = TU.inputs(FS);
495  auto EmptyPreamble =
496  buildPreamble(testPath("foo.cpp"), *CI, Inputs, true, nullptr);
497  ASSERT_TRUE(EmptyPreamble);
498  EXPECT_THAT(EmptyPreamble->Includes.MainFileIncludes, IsEmpty());
499 
500  // Now build an AST using empty preamble and ensure patched includes worked.
501  TU.Code = ModifiedContents.str();
502  Inputs = TU.inputs(FS);
503  auto PatchedAST = ParsedAST::build(testPath("foo.cpp"), Inputs, std::move(CI),
504  {}, EmptyPreamble);
505  ASSERT_TRUE(PatchedAST);
506  ASSERT_FALSE(PatchedAST->getDiagnostics());
507 
508  // Ensure source location information is correct, including resolved paths.
509  EXPECT_THAT(PatchedAST->getIncludeStructure().MainFileIncludes,
510  testing::Pointwise(
511  EqInc(), ExpectedAST.getIncludeStructure().MainFileIncludes));
512  // Ensure file proximity signals are correct.
513  auto &SM = PatchedAST->getSourceManager();
514  auto &FM = SM.getFileManager();
515  // Copy so that we can use operator[] to get the children.
516  IncludeStructure Includes = PatchedAST->getIncludeStructure();
517  auto MainFE = FM.getFile(testPath("foo.cpp"));
518  ASSERT_TRUE(MainFE);
519  auto MainID = Includes.getID(*MainFE);
520  auto AuxFE = FM.getFile(testPath("sub/aux.h"));
521  ASSERT_TRUE(AuxFE);
522  auto AuxID = Includes.getID(*AuxFE);
523  EXPECT_THAT(Includes.IncludeChildren[*MainID], Contains(*AuxID));
524 }
525 
526 TEST(ParsedASTTest, PatchesDeletedIncludes) {
527  TestTU TU;
528  TU.Filename = "foo.cpp";
529  TU.Code = "";
530  auto ExpectedAST = TU.build();
531 
532  // Build preamble with no includes.
533  TU.Code = R"cpp(#include <foo.h>)cpp";
534  StoreDiags Diags;
535  MockFS FS;
536  auto Inputs = TU.inputs(FS);
538  auto BaselinePreamble =
539  buildPreamble(testPath("foo.cpp"), *CI, Inputs, true, nullptr);
540  ASSERT_TRUE(BaselinePreamble);
541  EXPECT_THAT(BaselinePreamble->Includes.MainFileIncludes,
542  ElementsAre(testing::Field(&Inclusion::Written, "<foo.h>")));
543 
544  // Now build an AST using additional includes and check that locations are
545  // correctly parsed.
546  TU.Code = "";
547  Inputs = TU.inputs(FS);
548  auto PatchedAST = ParsedAST::build(testPath("foo.cpp"), Inputs, std::move(CI),
549  {}, BaselinePreamble);
550  ASSERT_TRUE(PatchedAST);
551 
552  // Ensure source location information is correct.
553  EXPECT_THAT(PatchedAST->getIncludeStructure().MainFileIncludes,
554  testing::Pointwise(
555  EqInc(), ExpectedAST.getIncludeStructure().MainFileIncludes));
556  // Ensure file proximity signals are correct.
557  auto &SM = ExpectedAST.getSourceManager();
558  auto &FM = SM.getFileManager();
559  // Copy so that we can getOrCreateID().
560  IncludeStructure Includes = ExpectedAST.getIncludeStructure();
561  auto MainFE = FM.getFile(testPath("foo.cpp"));
562  ASSERT_TRUE(MainFE);
563  auto MainID = Includes.getOrCreateID(*MainFE);
564  auto &PatchedFM = PatchedAST->getSourceManager().getFileManager();
565  IncludeStructure PatchedIncludes = PatchedAST->getIncludeStructure();
566  auto PatchedMainFE = PatchedFM.getFile(testPath("foo.cpp"));
567  ASSERT_TRUE(PatchedMainFE);
568  auto PatchedMainID = PatchedIncludes.getOrCreateID(*PatchedMainFE);
569  EXPECT_EQ(Includes.includeDepth(MainID)[MainID],
570  PatchedIncludes.includeDepth(PatchedMainID)[PatchedMainID]);
571 }
572 
573 // Returns Code guarded by #ifndef guards
574 std::string guard(llvm::StringRef Code) {
575  static int GuardID = 0;
576  std::string GuardName = ("GUARD_" + llvm::Twine(++GuardID)).str();
577  return llvm::formatv("#ifndef {0}\n#define {0}\n{1}\n#endif\n", GuardName,
578  Code);
579 }
580 
581 std::string once(llvm::StringRef Code) {
582  return llvm::formatv("#pragma once\n{0}\n", Code);
583 }
584 
585 bool mainIsGuarded(const ParsedAST &AST) {
586  const auto &SM = AST.getSourceManager();
587  const FileEntry *MainFE = SM.getFileEntryForID(SM.getMainFileID());
588  return AST.getPreprocessor()
589  .getHeaderSearchInfo()
590  .isFileMultipleIncludeGuarded(MainFE);
591 }
592 
593 MATCHER_P(Diag, Desc, "") {
594  return llvm::StringRef(arg.Message).contains(Desc);
595 }
596 
597 // Check our understanding of whether the main file is header guarded or not.
598 TEST(ParsedASTTest, HeaderGuards) {
599  TestTU TU;
600  TU.ImplicitHeaderGuard = false;
601 
602  TU.Code = ";";
603  EXPECT_FALSE(mainIsGuarded(TU.build()));
604 
605  TU.Code = guard(";");
606  EXPECT_TRUE(mainIsGuarded(TU.build()));
607 
608  TU.Code = once(";");
609  EXPECT_TRUE(mainIsGuarded(TU.build()));
610 
611  TU.Code = R"cpp(
612  ;
613  #pragma once
614  )cpp";
615  EXPECT_FALSE(mainIsGuarded(TU.build())); // FIXME: true
616 
617  TU.Code = R"cpp(
618  ;
619  #ifndef GUARD
620  #define GUARD
621  ;
622  #endif
623  )cpp";
624  EXPECT_FALSE(mainIsGuarded(TU.build()));
625 }
626 
627 // Check our handling of files that include themselves.
628 // Ideally we allow this if the file has header guards.
629 //
630 // Note: the semicolons (empty statements) are significant!
631 // - they force the preamble to end and the body to begin. Directives can have
632 // different effects in the preamble vs main file (which we try to hide).
633 // - if the preamble would otherwise cover the whole file, a trailing semicolon
634 // forces their sizes to be different. This is significant because the file
635 // size is part of the lookup key for HeaderFileInfo, and we don't want to
636 // rely on the preamble's HFI being looked up when parsing the main file.
637 TEST(ParsedASTTest, HeaderGuardsSelfInclude) {
638  TestTU TU;
639  TU.ImplicitHeaderGuard = false;
640  TU.Filename = "self.h";
641 
642  TU.Code = R"cpp(
643  #include "self.h" // error-ok
644  ;
645  )cpp";
646  auto AST = TU.build();
647  EXPECT_THAT(*AST.getDiagnostics(),
648  ElementsAre(Diag("recursively when building a preamble")));
649  EXPECT_FALSE(mainIsGuarded(AST));
650 
651  TU.Code = R"cpp(
652  ;
653  #include "self.h" // error-ok
654  )cpp";
655  AST = TU.build();
656  EXPECT_THAT(*AST.getDiagnostics(), ElementsAre(Diag("nested too deeply")));
657  EXPECT_FALSE(mainIsGuarded(AST));
658 
659  TU.Code = R"cpp(
660  #pragma once
661  #include "self.h"
662  ;
663  )cpp";
664  AST = TU.build();
665  EXPECT_THAT(*AST.getDiagnostics(), IsEmpty());
666  EXPECT_TRUE(mainIsGuarded(AST));
667 
668  TU.Code = R"cpp(
669  #pragma once
670  ;
671  #include "self.h"
672  )cpp";
673  AST = TU.build();
674  EXPECT_THAT(*AST.getDiagnostics(), IsEmpty());
675  EXPECT_TRUE(mainIsGuarded(AST));
676 
677  TU.Code = R"cpp(
678  ;
679  #pragma once
680  #include "self.h"
681  )cpp";
682  AST = TU.build();
683  EXPECT_THAT(*AST.getDiagnostics(), IsEmpty());
684  EXPECT_TRUE(mainIsGuarded(AST));
685 
686  TU.Code = R"cpp(
687  #ifndef GUARD
688  #define GUARD
689  #include "self.h" // error-ok: FIXME, this would be nice to support
690  #endif
691  ;
692  )cpp";
693  AST = TU.build();
694  EXPECT_THAT(*AST.getDiagnostics(),
695  ElementsAre(Diag("recursively when building a preamble")));
696  EXPECT_TRUE(mainIsGuarded(AST));
697 
698  TU.Code = R"cpp(
699  #ifndef GUARD
700  #define GUARD
701  ;
702  #include "self.h"
703  #endif
704  )cpp";
705  AST = TU.build();
706  EXPECT_THAT(*AST.getDiagnostics(), IsEmpty());
707  EXPECT_TRUE(mainIsGuarded(AST));
708 
709  // Guarded too late...
710  TU.Code = R"cpp(
711  #include "self.h" // error-ok
712  #ifndef GUARD
713  #define GUARD
714  ;
715  #endif
716  )cpp";
717  AST = TU.build();
718  EXPECT_THAT(*AST.getDiagnostics(),
719  ElementsAre(Diag("recursively when building a preamble")));
720  EXPECT_FALSE(mainIsGuarded(AST));
721 
722  TU.Code = R"cpp(
723  #include "self.h" // error-ok
724  ;
725  #ifndef GUARD
726  #define GUARD
727  #endif
728  )cpp";
729  AST = TU.build();
730  EXPECT_THAT(*AST.getDiagnostics(),
731  ElementsAre(Diag("recursively when building a preamble")));
732  EXPECT_FALSE(mainIsGuarded(AST));
733 
734  TU.Code = R"cpp(
735  ;
736  #ifndef GUARD
737  #define GUARD
738  #include "self.h"
739  #endif
740  )cpp";
741  AST = TU.build();
742  EXPECT_THAT(*AST.getDiagnostics(), IsEmpty());
743  EXPECT_FALSE(mainIsGuarded(AST));
744 
745  TU.Code = R"cpp(
746  #include "self.h" // error-ok
747  #pragma once
748  ;
749  )cpp";
750  AST = TU.build();
751  EXPECT_THAT(*AST.getDiagnostics(),
752  ElementsAre(Diag("recursively when building a preamble")));
753  EXPECT_TRUE(mainIsGuarded(AST));
754 
755  TU.Code = R"cpp(
756  #include "self.h" // error-ok
757  ;
758  #pragma once
759  )cpp";
760  AST = TU.build();
761  EXPECT_THAT(*AST.getDiagnostics(),
762  ElementsAre(Diag("recursively when building a preamble")));
763  EXPECT_TRUE(mainIsGuarded(AST));
764 }
765 
766 // Tests how we handle common idioms for splitting a header-only library
767 // into interface and implementation files (e.g. *.h vs *.inl).
768 // These files mutually include each other, and need careful handling of include
769 // guards (which interact with preambles).
770 TEST(ParsedASTTest, HeaderGuardsImplIface) {
771  std::string Interface = R"cpp(
772  // error-ok: we assert on diagnostics explicitly
773  template <class T> struct Traits {
774  unsigned size();
775  };
776  #include "impl.h"
777  )cpp";
778  std::string Implementation = R"cpp(
779  // error-ok: we assert on diagnostics explicitly
780  #include "iface.h"
781  template <class T> unsigned Traits<T>::size() {
782  return sizeof(T);
783  }
784  )cpp";
785 
786  TestTU TU;
787  TU.ImplicitHeaderGuard = false; // We're testing include guard handling!
788  TU.ExtraArgs.push_back("-xc++-header");
789 
790  // Editing the interface file, which is include guarded (easy case).
791  // We mostly get this right via PP if we don't recognize the include guard.
792  TU.Filename = "iface.h";
793  TU.Code = guard(Interface);
794  TU.AdditionalFiles = {{"impl.h", Implementation}};
795  auto AST = TU.build();
796  EXPECT_THAT(*AST.getDiagnostics(), IsEmpty());
797  EXPECT_TRUE(mainIsGuarded(AST));
798  // Slightly harder: the `#pragma once` is part of the preamble, and we
799  // need to transfer it to the main file's HeaderFileInfo.
800  TU.Code = once(Interface);
801  AST = TU.build();
802  EXPECT_THAT(*AST.getDiagnostics(), IsEmpty());
803  EXPECT_TRUE(mainIsGuarded(AST));
804 
805  // Editing the implementation file, which is not include guarded.
806  TU.Filename = "impl.h";
807  TU.Code = Implementation;
808  TU.AdditionalFiles = {{"iface.h", guard(Interface)}};
809  AST = TU.build();
810  // The diagnostic is unfortunate in this case, but correct per our model.
811  // Ultimately the include is skipped and the code is parsed correctly though.
812  EXPECT_THAT(*AST.getDiagnostics(),
813  ElementsAre(Diag("in included file: main file cannot be included "
814  "recursively when building a preamble")));
815  EXPECT_FALSE(mainIsGuarded(AST));
816  // Interface is pragma once guarded, same thing.
817  TU.AdditionalFiles = {{"iface.h", once(Interface)}};
818  AST = TU.build();
819  EXPECT_THAT(*AST.getDiagnostics(),
820  ElementsAre(Diag("in included file: main file cannot be included "
821  "recursively when building a preamble")));
822  EXPECT_FALSE(mainIsGuarded(AST));
823 }
824 
825 TEST(ParsedASTTest, DiscoversPragmaMarks) {
826  TestTU TU;
827  TU.AdditionalFiles["Header.h"] = R"(
828  #pragma mark - Something API
829  int something();
830  #pragma mark Something else
831  )";
832  TU.Code = R"cpp(
833  #include "Header.h"
834  #pragma mark In Preamble
835  #pragma mark - Something Impl
836  int something() { return 1; }
837  #pragma mark End
838  )cpp";
839  auto AST = TU.build();
840 
841  EXPECT_THAT(AST.getMarks(), ElementsAre(PragmaTrivia(" In Preamble"),
842  PragmaTrivia(" - Something Impl"),
843  PragmaTrivia(" End")));
844 }
845 
846 } // namespace
847 } // namespace clangd
848 } // namespace clang
clang::clangd::TEST
TEST(BackgroundQueueTest, Priority)
Definition: BackgroundIndexTests.cpp:751
Headers.h
clang::tidy::bugprone::getName
static SmallString< 64 > getName(const NamedDecl *ND)
Returns the diagnostic-friendly name of the node, or empty string.
Definition: EasilySwappableParametersCheck.cpp:1907
clang::clangd::testPath
std::string testPath(PathRef File, llvm::sys::path::Style Style)
Definition: TestFS.cpp:82
Expected
std::vector< const char * > Expected
Definition: PrintASTTests.cpp:27
clang::clangd::IncludeStructure::getID
llvm::Optional< HeaderID > getID(const FileEntry *Entry) const
Definition: Headers.cpp:161
CI
std::unique_ptr< CompilerInvocation > CI
Definition: TUScheduler.cpp:450
TestTU.h
Kind
BindArgumentKind Kind
Definition: AvoidBindCheck.cpp:59
clang::clangd::X
static URISchemeRegistry::Add< TestScheme > X(TestScheme::Scheme, "Test schema")
Preamble.h
clang::clangd::MainFileMacros::MacroRefs
llvm::DenseMap< SymbolID, std::vector< MacroOccurrence > > MacroRefs
Definition: CollectMacros.h:33
clang::clangd::ParseInputs::CompileCommand
tooling::CompileCommand CompileCommand
Definition: Compiler.h:48
clang::clangd::findUnqualifiedDecl
const NamedDecl & findUnqualifiedDecl(ParsedAST &AST, llvm::StringRef Name)
Definition: TestTU.cpp:256
clang::clangd::ParsedAST::build
static llvm::Optional< ParsedAST > build(llvm::StringRef Filename, const ParseInputs &Inputs, std::unique_ptr< clang::CompilerInvocation > CI, llvm::ArrayRef< Diag > CompilerInvocationDiags, std::shared_ptr< const PreambleData > Preamble)
Attempts to run Clang and store the parsed AST.
Definition: ParsedAST.cpp:248
Inputs
ParseInputs Inputs
Definition: TUScheduler.cpp:451
Code
std::string Code
Definition: FindTargetTests.cpp:67
clang::clangd::ParseInputs::TFS
const ThreadsafeFS * TFS
Definition: Compiler.h:49
clang::clangd::CompletionItemKind::Interface
@ Interface
Implementation
std::function< std::unique_ptr< Command >)> Implementation
Definition: Dexp.cpp:362
TidyProvider.h
clang::clangd::buildPreamble
std::shared_ptr< const PreambleData > buildPreamble(PathRef FileName, CompilerInvocation CI, const ParseInputs &Inputs, bool StoreInMemory, PreambleParsedCallback PreambleCallback)
Build a preamble for the new inputs unless an old one can be reused.
Definition: Preamble.cpp:323
clang::clangd::Inclusion::Written
std::string Written
Definition: Headers.h:59
Args
llvm::json::Object Args
Definition: Trace.cpp:139
TestFS.h
Name
static constexpr llvm::StringLiteral Name
Definition: UppercaseLiteralSuffixCheck.cpp:28
clang::clangd::printTemplateSpecializationArgs
std::string printTemplateSpecializationArgs(const NamedDecl &ND)
Prints template arguments of a decl as written in the source code, including enclosing '<' and '>',...
Definition: AST.cpp:254
Diagnostics.h
FileName
StringRef FileName
Definition: KernelNameRestrictionCheck.cpp:46
clang::clangd::TestTU::withCode
static TestTU withCode(llvm::StringRef Code)
Definition: TestTU.h:37
Annotations.h
clang::clangd::ParsedAST::getPreprocessor
Preprocessor & getPreprocessor()
Definition: ParsedAST.cpp:545
clang::tidy::bugprone::PP
static Preprocessor * PP
Definition: BadSignalToKillThreadCheck.cpp:29
clang::clangd::ParsedAST::getDiagnostics
const llvm::Optional< std::vector< Diag > > & getDiagnostics() const
Definition: ParsedAST.h:91
clang::clangd::buildCompilerInvocation
std::unique_ptr< CompilerInvocation > buildCompilerInvocation(const ParseInputs &Inputs, clang::DiagnosticConsumer &D, std::vector< std::string > *CC1Args)
Builds compiler invocation that could be used to build AST or preamble.
Definition: Compiler.cpp:84
SourceCode.h
clang::clangd::IncludeStructure::includeDepth
llvm::DenseMap< HeaderID, unsigned > includeDepth(HeaderID Root=MainFileID) const
Definition: Headers.cpp:193
IsAngled
bool IsAngled
true if this was an include with angle brackets
Definition: IncludeOrderCheck.cpp:40
Compiler.h
clang::clangd::RefKind::Spelled
@ Spelled
clang::clangd::ParsedAST::getMarks
const std::vector< PragmaMark > & getMarks() const
Gets all pragma marks in the main file.
Definition: ParsedAST.cpp:560
clang::clangd::MATCHER_P
MATCHER_P(Named, N, "")
Definition: BackgroundIndexTests.cpp:31
PPCallbacks
clang
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Definition: ApplyReplacements.h:27
OS
llvm::raw_string_ostream OS
Definition: TraceTests.cpp:163
clang::clangd::ParsedAST::getTokens
const syntax::TokenBuffer & getTokens() const
Tokens recorded while parsing the main file.
Definition: ParsedAST.h:108
Diags
CapturedDiags Diags
Definition: ConfigCompileTests.cpp:38
clang::clangd::ParsedAST::getLocalTopLevelDecls
ArrayRef< Decl * > getLocalTopLevelDecls()
This function returns top-level decls present in the main file of the AST.
Definition: ParsedAST.cpp:555
clang::clangd::IncludeStructure::getOrCreateID
HeaderID getOrCreateID(const FileEntry *Entry)
Definition: Headers.cpp:173
clang::clangd::Inclusion::HashOffset
unsigned HashOffset
Definition: Headers.h:61
SM
const SourceManager & SM
Definition: IncludeCleaner.cpp:108
clang::clangd::MainFileMacros::UnknownMacros
std::vector< MacroOccurrence > UnknownMacros
Definition: CollectMacros.h:37
clang::clangd::ParsedAST::getSourceManager
SourceManager & getSourceManager()
Definition: ParsedAST.h:75
clang::clangd::addTidyChecks
TidyProvider addTidyChecks(llvm::StringRef Checks, llvm::StringRef WarningsAsErrors)
Provider the enables a specific set of checks and warnings as errors.
Definition: TidyProvider.cpp:187
IgnoreDiags
IgnoringDiagConsumer IgnoreDiags
Definition: HeadersTests.cpp:139
clang::clangd::IncludeStructure::IncludeChildren
llvm::DenseMap< HeaderID, SmallVector< HeaderID > > IncludeChildren
Definition: Headers.h:152
clang::clangd::MATCHER
MATCHER(Declared, "")
Definition: BackgroundIndexTests.cpp:33
AST.h
ParsedAST.h
clang::clangd::ParsedAST::getMacros
const MainFileMacros & getMacros() const
Gets all macro references (definition, expansions) present in the main file, including those in the p...
Definition: ParsedAST.cpp:559