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