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