• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===--- Preamble.cpp - Reusing expensive parts of the AST ----------------===//
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 #include "Preamble.h"
10 #include "Compiler.h"
11 #include "Headers.h"
12 #include "SourceCode.h"
13 #include "support/Logger.h"
14 #include "support/ThreadsafeFS.h"
15 #include "support/Trace.h"
16 #include "clang/AST/DeclTemplate.h"
17 #include "clang/Basic/Diagnostic.h"
18 #include "clang/Basic/LangOptions.h"
19 #include "clang/Basic/SourceLocation.h"
20 #include "clang/Basic/SourceManager.h"
21 #include "clang/Basic/TokenKinds.h"
22 #include "clang/Frontend/CompilerInvocation.h"
23 #include "clang/Frontend/FrontendActions.h"
24 #include "clang/Lex/Lexer.h"
25 #include "clang/Lex/PPCallbacks.h"
26 #include "clang/Lex/Preprocessor.h"
27 #include "clang/Lex/PreprocessorOptions.h"
28 #include "clang/Tooling/CompilationDatabase.h"
29 #include "llvm/ADT/ArrayRef.h"
30 #include "llvm/ADT/DenseMap.h"
31 #include "llvm/ADT/DenseSet.h"
32 #include "llvm/ADT/IntrusiveRefCntPtr.h"
33 #include "llvm/ADT/None.h"
34 #include "llvm/ADT/Optional.h"
35 #include "llvm/ADT/STLExtras.h"
36 #include "llvm/ADT/SmallString.h"
37 #include "llvm/ADT/StringExtras.h"
38 #include "llvm/ADT/StringRef.h"
39 #include "llvm/ADT/StringSet.h"
40 #include "llvm/Support/Error.h"
41 #include "llvm/Support/ErrorHandling.h"
42 #include "llvm/Support/FormatVariadic.h"
43 #include "llvm/Support/MemoryBuffer.h"
44 #include "llvm/Support/Path.h"
45 #include "llvm/Support/VirtualFileSystem.h"
46 #include "llvm/Support/raw_ostream.h"
47 #include <iterator>
48 #include <memory>
49 #include <string>
50 #include <system_error>
51 #include <utility>
52 #include <vector>
53 
54 namespace clang {
55 namespace clangd {
56 namespace {
57 constexpr llvm::StringLiteral PreamblePatchHeaderName = "__preamble_patch__.h";
58 
compileCommandsAreEqual(const tooling::CompileCommand & LHS,const tooling::CompileCommand & RHS)59 bool compileCommandsAreEqual(const tooling::CompileCommand &LHS,
60                              const tooling::CompileCommand &RHS) {
61   // We don't check for Output, it should not matter to clangd.
62   return LHS.Directory == RHS.Directory && LHS.Filename == RHS.Filename &&
63          llvm::makeArrayRef(LHS.CommandLine).equals(RHS.CommandLine);
64 }
65 
66 class CppFilePreambleCallbacks : public PreambleCallbacks {
67 public:
CppFilePreambleCallbacks(PathRef File,PreambleParsedCallback ParsedCallback)68   CppFilePreambleCallbacks(PathRef File, PreambleParsedCallback ParsedCallback)
69       : File(File), ParsedCallback(ParsedCallback) {}
70 
takeIncludes()71   IncludeStructure takeIncludes() { return std::move(Includes); }
72 
takeMacros()73   MainFileMacros takeMacros() { return std::move(Macros); }
74 
takeCanonicalIncludes()75   CanonicalIncludes takeCanonicalIncludes() { return std::move(CanonIncludes); }
76 
AfterExecute(CompilerInstance & CI)77   void AfterExecute(CompilerInstance &CI) override {
78     if (!ParsedCallback)
79       return;
80     trace::Span Tracer("Running PreambleCallback");
81     ParsedCallback(CI.getASTContext(), CI.getPreprocessorPtr(), CanonIncludes);
82   }
83 
BeforeExecute(CompilerInstance & CI)84   void BeforeExecute(CompilerInstance &CI) override {
85     CanonIncludes.addSystemHeadersMapping(CI.getLangOpts());
86     LangOpts = &CI.getLangOpts();
87     SourceMgr = &CI.getSourceManager();
88   }
89 
createPPCallbacks()90   std::unique_ptr<PPCallbacks> createPPCallbacks() override {
91     assert(SourceMgr && LangOpts &&
92            "SourceMgr and LangOpts must be set at this point");
93 
94     return std::make_unique<PPChainedCallbacks>(
95         collectIncludeStructureCallback(*SourceMgr, &Includes),
96         std::make_unique<CollectMainFileMacros>(*SourceMgr, Macros));
97   }
98 
getCommentHandler()99   CommentHandler *getCommentHandler() override {
100     IWYUHandler = collectIWYUHeaderMaps(&CanonIncludes);
101     return IWYUHandler.get();
102   }
103 
shouldSkipFunctionBody(Decl * D)104   bool shouldSkipFunctionBody(Decl *D) override {
105     // Generally we skip function bodies in preambles for speed.
106     // We can make exceptions for functions that are cheap to parse and
107     // instantiate, widely used, and valuable (e.g. commonly produce errors).
108     if (const auto *FT = llvm::dyn_cast<clang::FunctionTemplateDecl>(D)) {
109       if (const auto *II = FT->getDeclName().getAsIdentifierInfo())
110         // std::make_unique is trivial, and we diagnose bad constructor calls.
111         if (II->isStr("make_unique") && FT->isInStdNamespace())
112           return false;
113     }
114     return true;
115   }
116 
117 private:
118   PathRef File;
119   PreambleParsedCallback ParsedCallback;
120   IncludeStructure Includes;
121   CanonicalIncludes CanonIncludes;
122   MainFileMacros Macros;
123   std::unique_ptr<CommentHandler> IWYUHandler = nullptr;
124   const clang::LangOptions *LangOpts = nullptr;
125   const SourceManager *SourceMgr = nullptr;
126 };
127 
128 // Represents directives other than includes, where basic textual information is
129 // enough.
130 struct TextualPPDirective {
131   unsigned DirectiveLine;
132   // Full text that's representing the directive, including the `#`.
133   std::string Text;
134 
operator ==clang::clangd::__anon863f4f5a0111::TextualPPDirective135   bool operator==(const TextualPPDirective &RHS) const {
136     return std::tie(DirectiveLine, Text) ==
137            std::tie(RHS.DirectiveLine, RHS.Text);
138   }
139 };
140 
141 // Formats a PP directive consisting of Prefix (e.g. "#define ") and Body ("X
142 // 10"). The formatting is copied so that the tokens in Body have PresumedLocs
143 // with correct columns and lines.
spellDirective(llvm::StringRef Prefix,CharSourceRange DirectiveRange,const LangOptions & LangOpts,const SourceManager & SM,unsigned & DirectiveLine)144 std::string spellDirective(llvm::StringRef Prefix,
145                            CharSourceRange DirectiveRange,
146                            const LangOptions &LangOpts, const SourceManager &SM,
147                            unsigned &DirectiveLine) {
148   std::string SpelledDirective;
149   llvm::raw_string_ostream OS(SpelledDirective);
150   OS << Prefix;
151 
152   // Make sure DirectiveRange is a char range and doesn't contain macro ids.
153   DirectiveRange = SM.getExpansionRange(DirectiveRange);
154   if (DirectiveRange.isTokenRange()) {
155     DirectiveRange.setEnd(
156         Lexer::getLocForEndOfToken(DirectiveRange.getEnd(), 0, SM, LangOpts));
157   }
158 
159   auto DecompLoc = SM.getDecomposedLoc(DirectiveRange.getBegin());
160   DirectiveLine = SM.getLineNumber(DecompLoc.first, DecompLoc.second);
161   auto TargetColumn = SM.getColumnNumber(DecompLoc.first, DecompLoc.second) - 1;
162 
163   // Pad with spaces before DirectiveRange to make sure it will be on right
164   // column when patched.
165   if (Prefix.size() <= TargetColumn) {
166     // There is enough space for Prefix and space before directive, use it.
167     // We try to squeeze the Prefix into the same line whenever we can, as
168     // putting onto a separate line won't work at the beginning of the file.
169     OS << std::string(TargetColumn - Prefix.size(), ' ');
170   } else {
171     // Prefix was longer than the space we had. We produce e.g.:
172     // #line N-1
173     // #define \
174     //    X 10
175     OS << "\\\n" << std::string(TargetColumn, ' ');
176     // Decrement because we put an additional line break before
177     // DirectiveRange.begin().
178     --DirectiveLine;
179   }
180   OS << toSourceCode(SM, DirectiveRange.getAsRange());
181   return OS.str();
182 }
183 
184 // Collects #define directives inside the main file.
185 struct DirectiveCollector : public PPCallbacks {
DirectiveCollectorclang::clangd::__anon863f4f5a0111::DirectiveCollector186   DirectiveCollector(const Preprocessor &PP,
187                      std::vector<TextualPPDirective> &TextualDirectives)
188       : LangOpts(PP.getLangOpts()), SM(PP.getSourceManager()),
189         TextualDirectives(TextualDirectives) {}
190 
FileChangedclang::clangd::__anon863f4f5a0111::DirectiveCollector191   void FileChanged(SourceLocation Loc, FileChangeReason Reason,
192                    SrcMgr::CharacteristicKind FileType,
193                    FileID PrevFID) override {
194     InMainFile = SM.isWrittenInMainFile(Loc);
195   }
196 
MacroDefinedclang::clangd::__anon863f4f5a0111::DirectiveCollector197   void MacroDefined(const Token &MacroNameTok,
198                     const MacroDirective *MD) override {
199     if (!InMainFile)
200       return;
201     TextualDirectives.emplace_back();
202     TextualPPDirective &TD = TextualDirectives.back();
203 
204     const auto *MI = MD->getMacroInfo();
205     TD.Text =
206         spellDirective("#define ",
207                        CharSourceRange::getTokenRange(
208                            MI->getDefinitionLoc(), MI->getDefinitionEndLoc()),
209                        LangOpts, SM, TD.DirectiveLine);
210   }
211 
212 private:
213   bool InMainFile = true;
214   const LangOptions &LangOpts;
215   const SourceManager &SM;
216   std::vector<TextualPPDirective> &TextualDirectives;
217 };
218 
219 struct ScannedPreamble {
220   std::vector<Inclusion> Includes;
221   std::vector<TextualPPDirective> TextualDirectives;
222   PreambleBounds Bounds = {0, false};
223 };
224 
225 /// Scans the preprocessor directives in the preamble section of the file by
226 /// running preprocessor over \p Contents. Returned includes do not contain
227 /// resolved paths. \p Cmd is used to build the compiler invocation, which might
228 /// stat/read files.
229 llvm::Expected<ScannedPreamble>
scanPreamble(llvm::StringRef Contents,const tooling::CompileCommand & Cmd)230 scanPreamble(llvm::StringRef Contents, const tooling::CompileCommand &Cmd) {
231   class EmptyFS : public ThreadsafeFS {
232   private:
233     llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> viewImpl() const override {
234       return new llvm::vfs::InMemoryFileSystem;
235     }
236   };
237   EmptyFS FS;
238   // Build and run Preprocessor over the preamble.
239   ParseInputs PI;
240   PI.Contents = Contents.str();
241   PI.TFS = &FS;
242   PI.CompileCommand = Cmd;
243   IgnoringDiagConsumer IgnoreDiags;
244   auto CI = buildCompilerInvocation(PI, IgnoreDiags);
245   if (!CI)
246     return error("failed to create compiler invocation");
247   CI->getDiagnosticOpts().IgnoreWarnings = true;
248   auto ContentsBuffer = llvm::MemoryBuffer::getMemBuffer(Contents);
249   // This means we're scanning (though not preprocessing) the preamble section
250   // twice. However, it's important to precisely follow the preamble bounds used
251   // elsewhere.
252   auto Bounds = ComputePreambleBounds(*CI->getLangOpts(), *ContentsBuffer, 0);
253   auto PreambleContents =
254       llvm::MemoryBuffer::getMemBufferCopy(Contents.substr(0, Bounds.Size));
255   auto Clang = prepareCompilerInstance(
256       std::move(CI), nullptr, std::move(PreambleContents),
257       // Provide an empty FS to prevent preprocessor from performing IO. This
258       // also implies missing resolved paths for includes.
259       FS.view(llvm::None), IgnoreDiags);
260   if (Clang->getFrontendOpts().Inputs.empty())
261     return error("compiler instance had no inputs");
262   // We are only interested in main file includes.
263   Clang->getPreprocessorOpts().SingleFileParseMode = true;
264   PreprocessOnlyAction Action;
265   if (!Action.BeginSourceFile(*Clang, Clang->getFrontendOpts().Inputs[0]))
266     return error("failed BeginSourceFile");
267   const auto &SM = Clang->getSourceManager();
268   Preprocessor &PP = Clang->getPreprocessor();
269   IncludeStructure Includes;
270   PP.addPPCallbacks(collectIncludeStructureCallback(SM, &Includes));
271   ScannedPreamble SP;
272   SP.Bounds = Bounds;
273   PP.addPPCallbacks(
274       std::make_unique<DirectiveCollector>(PP, SP.TextualDirectives));
275   if (llvm::Error Err = Action.Execute())
276     return std::move(Err);
277   Action.EndSourceFile();
278   SP.Includes = std::move(Includes.MainFileIncludes);
279   return SP;
280 }
281 
spellingForIncDirective(tok::PPKeywordKind IncludeDirective)282 const char *spellingForIncDirective(tok::PPKeywordKind IncludeDirective) {
283   switch (IncludeDirective) {
284   case tok::pp_include:
285     return "include";
286   case tok::pp_import:
287     return "import";
288   case tok::pp_include_next:
289     return "include_next";
290   default:
291     break;
292   }
293   llvm_unreachable("not an include directive");
294 }
295 
296 // Checks whether \p FileName is a valid spelling of main file.
isMainFile(llvm::StringRef FileName,const SourceManager & SM)297 bool isMainFile(llvm::StringRef FileName, const SourceManager &SM) {
298   auto FE = SM.getFileManager().getFile(FileName);
299   return FE && *FE == SM.getFileEntryForID(SM.getMainFileID());
300 }
301 
302 } // namespace
303 
PreambleData(const ParseInputs & Inputs,PrecompiledPreamble Preamble,std::vector<Diag> Diags,IncludeStructure Includes,MainFileMacros Macros,std::unique_ptr<PreambleFileStatusCache> StatCache,CanonicalIncludes CanonIncludes)304 PreambleData::PreambleData(const ParseInputs &Inputs,
305                            PrecompiledPreamble Preamble,
306                            std::vector<Diag> Diags, IncludeStructure Includes,
307                            MainFileMacros Macros,
308                            std::unique_ptr<PreambleFileStatusCache> StatCache,
309                            CanonicalIncludes CanonIncludes)
310     : Version(Inputs.Version), CompileCommand(Inputs.CompileCommand),
311       Preamble(std::move(Preamble)), Diags(std::move(Diags)),
312       Includes(std::move(Includes)), Macros(std::move(Macros)),
313       StatCache(std::move(StatCache)), CanonIncludes(std::move(CanonIncludes)) {
314 }
315 
316 std::shared_ptr<const PreambleData>
buildPreamble(PathRef FileName,CompilerInvocation CI,const ParseInputs & Inputs,bool StoreInMemory,PreambleParsedCallback PreambleCallback)317 buildPreamble(PathRef FileName, CompilerInvocation CI,
318               const ParseInputs &Inputs, bool StoreInMemory,
319               PreambleParsedCallback PreambleCallback) {
320   // Note that we don't need to copy the input contents, preamble can live
321   // without those.
322   auto ContentsBuffer =
323       llvm::MemoryBuffer::getMemBuffer(Inputs.Contents, FileName);
324   auto Bounds = ComputePreambleBounds(*CI.getLangOpts(), *ContentsBuffer, 0);
325 
326   trace::Span Tracer("BuildPreamble");
327   SPAN_ATTACH(Tracer, "File", FileName);
328   StoreDiags PreambleDiagnostics;
329   llvm::IntrusiveRefCntPtr<DiagnosticsEngine> PreambleDiagsEngine =
330       CompilerInstance::createDiagnostics(&CI.getDiagnosticOpts(),
331                                           &PreambleDiagnostics, false);
332 
333   // Skip function bodies when building the preamble to speed up building
334   // the preamble and make it smaller.
335   assert(!CI.getFrontendOpts().SkipFunctionBodies);
336   CI.getFrontendOpts().SkipFunctionBodies = true;
337   // We don't want to write comment locations into PCH. They are racy and slow
338   // to read back. We rely on dynamic index for the comments instead.
339   CI.getPreprocessorOpts().WriteCommentListToPCH = false;
340 
341   CppFilePreambleCallbacks SerializedDeclsCollector(FileName, PreambleCallback);
342   auto VFS = Inputs.TFS->view(Inputs.CompileCommand.Directory);
343   llvm::SmallString<32> AbsFileName(FileName);
344   VFS->makeAbsolute(AbsFileName);
345   auto StatCache = std::make_unique<PreambleFileStatusCache>(AbsFileName);
346   auto BuiltPreamble = PrecompiledPreamble::Build(
347       CI, ContentsBuffer.get(), Bounds, *PreambleDiagsEngine,
348       StatCache->getProducingFS(VFS),
349       std::make_shared<PCHContainerOperations>(), StoreInMemory,
350       SerializedDeclsCollector);
351 
352   // When building the AST for the main file, we do want the function
353   // bodies.
354   CI.getFrontendOpts().SkipFunctionBodies = false;
355 
356   if (BuiltPreamble) {
357     vlog("Built preamble of size {0} for file {1} version {2}",
358          BuiltPreamble->getSize(), FileName, Inputs.Version);
359     std::vector<Diag> Diags = PreambleDiagnostics.take();
360     return std::make_shared<PreambleData>(
361         Inputs, std::move(*BuiltPreamble), std::move(Diags),
362         SerializedDeclsCollector.takeIncludes(),
363         SerializedDeclsCollector.takeMacros(), std::move(StatCache),
364         SerializedDeclsCollector.takeCanonicalIncludes());
365   } else {
366     elog("Could not build a preamble for file {0} version {1}", FileName,
367          Inputs.Version);
368     return nullptr;
369   }
370 }
371 
isPreambleCompatible(const PreambleData & Preamble,const ParseInputs & Inputs,PathRef FileName,const CompilerInvocation & CI)372 bool isPreambleCompatible(const PreambleData &Preamble,
373                           const ParseInputs &Inputs, PathRef FileName,
374                           const CompilerInvocation &CI) {
375   auto ContentsBuffer =
376       llvm::MemoryBuffer::getMemBuffer(Inputs.Contents, FileName);
377   auto Bounds = ComputePreambleBounds(*CI.getLangOpts(), *ContentsBuffer, 0);
378   auto VFS = Inputs.TFS->view(Inputs.CompileCommand.Directory);
379   return compileCommandsAreEqual(Inputs.CompileCommand,
380                                  Preamble.CompileCommand) &&
381          Preamble.Preamble.CanReuse(CI, ContentsBuffer.get(), Bounds,
382                                     VFS.get());
383 }
384 
escapeBackslashAndQuotes(llvm::StringRef Text,llvm::raw_ostream & OS)385 void escapeBackslashAndQuotes(llvm::StringRef Text, llvm::raw_ostream &OS) {
386   for (char C : Text) {
387     switch (C) {
388     case '\\':
389     case '"':
390       OS << '\\';
391       break;
392     default:
393       break;
394     }
395     OS << C;
396   }
397 }
398 
create(llvm::StringRef FileName,const ParseInputs & Modified,const PreambleData & Baseline)399 PreamblePatch PreamblePatch::create(llvm::StringRef FileName,
400                                     const ParseInputs &Modified,
401                                     const PreambleData &Baseline) {
402   trace::Span Tracer("CreatePreamblePatch");
403   SPAN_ATTACH(Tracer, "File", FileName);
404   assert(llvm::sys::path::is_absolute(FileName) && "relative FileName!");
405   // First scan preprocessor directives in Baseline and Modified. These will be
406   // used to figure out newly added directives in Modified. Scanning can fail,
407   // the code just bails out and creates an empty patch in such cases, as:
408   // - If scanning for Baseline fails, no knowledge of existing includes hence
409   //   patch will contain all the includes in Modified. Leading to rebuild of
410   //   whole preamble, which is terribly slow.
411   // - If scanning for Modified fails, cannot figure out newly added ones so
412   //   there's nothing to do but generate an empty patch.
413   auto BaselineScan = scanPreamble(
414       // Contents needs to be null-terminated.
415       Baseline.Preamble.getContents().str(), Modified.CompileCommand);
416   if (!BaselineScan) {
417     elog("Failed to scan baseline of {0}: {1}", FileName,
418          BaselineScan.takeError());
419     return PreamblePatch::unmodified(Baseline);
420   }
421   auto ModifiedScan = scanPreamble(Modified.Contents, Modified.CompileCommand);
422   if (!ModifiedScan) {
423     elog("Failed to scan modified contents of {0}: {1}", FileName,
424          ModifiedScan.takeError());
425     return PreamblePatch::unmodified(Baseline);
426   }
427 
428   bool IncludesChanged = BaselineScan->Includes != ModifiedScan->Includes;
429   bool DirectivesChanged =
430       BaselineScan->TextualDirectives != ModifiedScan->TextualDirectives;
431   if (!IncludesChanged && !DirectivesChanged)
432     return PreamblePatch::unmodified(Baseline);
433 
434   PreamblePatch PP;
435   // This shouldn't coincide with any real file name.
436   llvm::SmallString<128> PatchName;
437   llvm::sys::path::append(PatchName, llvm::sys::path::parent_path(FileName),
438                           PreamblePatchHeaderName);
439   PP.PatchFileName = PatchName.str().str();
440   PP.ModifiedBounds = ModifiedScan->Bounds;
441 
442   llvm::raw_string_ostream Patch(PP.PatchContents);
443   // Set default filename for subsequent #line directives
444   Patch << "#line 0 \"";
445   // FileName part of a line directive is subject to backslash escaping, which
446   // might lead to problems on windows especially.
447   escapeBackslashAndQuotes(FileName, Patch);
448   Patch << "\"\n";
449 
450   if (IncludesChanged) {
451     // We are only interested in newly added includes, record the ones in
452     // Baseline for exclusion.
453     llvm::DenseMap<std::pair<tok::PPKeywordKind, llvm::StringRef>,
454                    /*Resolved=*/llvm::StringRef>
455         ExistingIncludes;
456     for (const auto &Inc : Baseline.Includes.MainFileIncludes)
457       ExistingIncludes[{Inc.Directive, Inc.Written}] = Inc.Resolved;
458     // There might be includes coming from disabled regions, record these for
459     // exclusion too. note that we don't have resolved paths for those.
460     for (const auto &Inc : BaselineScan->Includes)
461       ExistingIncludes.try_emplace({Inc.Directive, Inc.Written});
462     // Calculate extra includes that needs to be inserted.
463     for (auto &Inc : ModifiedScan->Includes) {
464       auto It = ExistingIncludes.find({Inc.Directive, Inc.Written});
465       // Include already present in the baseline preamble. Set resolved path and
466       // put into preamble includes.
467       if (It != ExistingIncludes.end()) {
468         Inc.Resolved = It->second.str();
469         PP.PreambleIncludes.push_back(Inc);
470         continue;
471       }
472       // Include is new in the modified preamble. Inject it into the patch and
473       // use #line to set the presumed location to where it is spelled.
474       auto LineCol = offsetToClangLineColumn(Modified.Contents, Inc.HashOffset);
475       Patch << llvm::formatv("#line {0}\n", LineCol.first);
476       Patch << llvm::formatv(
477           "#{0} {1}\n", spellingForIncDirective(Inc.Directive), Inc.Written);
478     }
479   }
480 
481   if (DirectivesChanged) {
482     // We need to patch all the directives, since they are order dependent. e.g:
483     // #define BAR(X) NEW(X) // Newly introduced in Modified
484     // #define BAR(X) OLD(X) // Exists in the Baseline
485     //
486     // If we've patched only the first directive, the macro definition would've
487     // been wrong for the rest of the file, since patch is applied after the
488     // baseline preamble.
489     //
490     // Note that we deliberately ignore conditional directives and undefs to
491     // reduce complexity. The former might cause problems because scanning is
492     // imprecise and might pick directives from disabled regions.
493     for (const auto &TD : ModifiedScan->TextualDirectives) {
494       Patch << "#line " << TD.DirectiveLine << '\n';
495       Patch << TD.Text << '\n';
496     }
497   }
498   dlog("Created preamble patch: {0}", Patch.str());
499   Patch.flush();
500   return PP;
501 }
502 
apply(CompilerInvocation & CI) const503 void PreamblePatch::apply(CompilerInvocation &CI) const {
504   // No need to map an empty file.
505   if (PatchContents.empty())
506     return;
507   auto &PPOpts = CI.getPreprocessorOpts();
508   auto PatchBuffer =
509       // we copy here to ensure contents are still valid if CI outlives the
510       // PreamblePatch.
511       llvm::MemoryBuffer::getMemBufferCopy(PatchContents, PatchFileName);
512   // CI will take care of the lifetime of the buffer.
513   PPOpts.addRemappedFile(PatchFileName, PatchBuffer.release());
514   // The patch will be parsed after loading the preamble ast and before parsing
515   // the main file.
516   PPOpts.Includes.push_back(PatchFileName);
517 }
518 
preambleIncludes() const519 std::vector<Inclusion> PreamblePatch::preambleIncludes() const {
520   return PreambleIncludes;
521 }
522 
unmodified(const PreambleData & Preamble)523 PreamblePatch PreamblePatch::unmodified(const PreambleData &Preamble) {
524   PreamblePatch PP;
525   PP.PreambleIncludes = Preamble.Includes.MainFileIncludes;
526   PP.ModifiedBounds = Preamble.Preamble.getBounds();
527   return PP;
528 }
529 
translatePreamblePatchLocation(SourceLocation Loc,const SourceManager & SM)530 SourceLocation translatePreamblePatchLocation(SourceLocation Loc,
531                                               const SourceManager &SM) {
532   auto DefFile = SM.getFileID(Loc);
533   if (auto *FE = SM.getFileEntryForID(DefFile)) {
534     auto IncludeLoc = SM.getIncludeLoc(DefFile);
535     // Preamble patch is included inside the builtin file.
536     if (IncludeLoc.isValid() && SM.isWrittenInBuiltinFile(IncludeLoc) &&
537         FE->getName().endswith(PreamblePatchHeaderName)) {
538       auto Presumed = SM.getPresumedLoc(Loc);
539       // Check that line directive is pointing at main file.
540       if (Presumed.isValid() && Presumed.getFileID().isInvalid() &&
541           isMainFile(Presumed.getFilename(), SM)) {
542         Loc = SM.translateLineCol(SM.getMainFileID(), Presumed.getLine(),
543                                   Presumed.getColumn());
544       }
545     }
546   }
547   return Loc;
548 }
549 } // namespace clangd
550 } // namespace clang
551