clang-tools 23.0.0git
Preamble.cpp
Go to the documentation of this file.
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 "AST.h"
11#include "CollectMacros.h"
12#include "Compiler.h"
13#include "Config.h"
14#include "Diagnostics.h"
15#include "FS.h"
16#include "FeatureModule.h"
17#include "Headers.h"
18#include "Protocol.h"
19#include "SourceCode.h"
20#include "clang-include-cleaner/Record.h"
21#include "support/Logger.h"
22#include "support/Path.h"
24#include "support/Trace.h"
25#include "clang/AST/DeclTemplate.h"
26#include "clang/AST/Type.h"
27#include "clang/Basic/Diagnostic.h"
28#include "clang/Basic/DiagnosticLex.h"
29#include "clang/Basic/DiagnosticOptions.h"
30#include "clang/Basic/LangOptions.h"
31#include "clang/Basic/SourceLocation.h"
32#include "clang/Basic/SourceManager.h"
33#include "clang/Basic/TargetInfo.h"
34#include "clang/Basic/TokenKinds.h"
35#include "clang/Frontend/CompilerInstance.h"
36#include "clang/Frontend/CompilerInvocation.h"
37#include "clang/Frontend/FrontendActions.h"
38#include "clang/Frontend/PrecompiledPreamble.h"
39#include "clang/Lex/HeaderSearch.h"
40#include "clang/Lex/Lexer.h"
41#include "clang/Lex/PPCallbacks.h"
42#include "clang/Lex/Preprocessor.h"
43#include "clang/Lex/PreprocessorOptions.h"
44#include "clang/Serialization/ASTReader.h"
45#include "clang/Tooling/CompilationDatabase.h"
46#include "llvm/ADT/ArrayRef.h"
47#include "llvm/ADT/DenseMap.h"
48#include "llvm/ADT/IntrusiveRefCntPtr.h"
49#include "llvm/ADT/STLExtras.h"
50#include "llvm/ADT/SmallString.h"
51#include "llvm/ADT/SmallVector.h"
52#include "llvm/ADT/StringExtras.h"
53#include "llvm/ADT/StringMap.h"
54#include "llvm/ADT/StringRef.h"
55#include "llvm/Support/Casting.h"
56#include "llvm/Support/Error.h"
57#include "llvm/Support/ErrorHandling.h"
58#include "llvm/Support/ErrorOr.h"
59#include "llvm/Support/FormatVariadic.h"
60#include "llvm/Support/MemoryBuffer.h"
61#include "llvm/Support/Path.h"
62#include "llvm/Support/VirtualFileSystem.h"
63#include "llvm/Support/raw_ostream.h"
64#include <cassert>
65#include <chrono>
66#include <cstddef>
67#include <cstdint>
68#include <cstdlib>
69#include <functional>
70#include <memory>
71#include <optional>
72#include <string>
73#include <system_error>
74#include <tuple>
75#include <utility>
76#include <vector>
77
78namespace clang {
79namespace clangd {
80namespace {
81
82bool compileCommandsAreEqual(const tooling::CompileCommand &LHS,
83 const tooling::CompileCommand &RHS) {
84 // We don't check for Output, it should not matter to clangd.
85 return LHS.Directory == RHS.Directory && LHS.Filename == RHS.Filename &&
86 llvm::ArrayRef(LHS.CommandLine).equals(RHS.CommandLine);
87}
88
89class CppFilePreambleCallbacks : public PreambleCallbacks {
90public:
91 CppFilePreambleCallbacks(
92 PathRef File, PreambleBuildStats *Stats, bool ParseForwardingFunctions,
93 std::function<void(CompilerInstance &)> BeforeExecuteCallback)
94 : File(File), Stats(Stats),
95 ParseForwardingFunctions(ParseForwardingFunctions),
96 BeforeExecuteCallback(std::move(BeforeExecuteCallback)) {}
97
98 IncludeStructure takeIncludes() { return std::move(Includes); }
99
100 MainFileMacros takeMacros() { return std::move(Macros); }
101
102 std::vector<PragmaMark> takeMarks() { return std::move(Marks); }
103
104 include_cleaner::PragmaIncludes takePragmaIncludes() {
105 return std::move(Pragmas);
106 }
107
108 std::optional<CapturedASTCtx> takeLife() { return std::move(CapturedCtx); }
109
110 bool isMainFileIncludeGuarded() const { return IsMainFileIncludeGuarded; }
111
112 void AfterExecute(CompilerInstance &CI) override {
113 // As part of the Preamble compilation, ASTConsumer
114 // PrecompilePreambleConsumer/PCHGenerator is setup. This would be called
115 // when Preamble consists of modules. Therefore while capturing AST context,
116 // we have to reset ast consumer and ASTMutationListener.
117 if (CI.getASTReader()) {
118 CI.getASTReader()->setDeserializationListener(nullptr);
119 // This just sets consumer to null when DeserializationListener is null.
120 CI.getASTReader()->StartTranslationUnit(nullptr);
121 }
122 CI.getASTContext().setASTMutationListener(nullptr);
123 CapturedCtx.emplace(CI);
124
125 const SourceManager &SM = CI.getSourceManager();
126 OptionalFileEntryRef MainFE = SM.getFileEntryRefForID(SM.getMainFileID());
127 IsMainFileIncludeGuarded =
128 CI.getPreprocessor().getHeaderSearchInfo().isFileMultipleIncludeGuarded(
129 *MainFE);
130
131 if (Stats) {
132 const ASTContext &AST = CI.getASTContext();
133 Stats->BuildSize = AST.getASTAllocatedMemory();
134 Stats->BuildSize += AST.getSideTableAllocatedMemory();
135 Stats->BuildSize += AST.Idents.getAllocator().getTotalMemory();
136 Stats->BuildSize += AST.Selectors.getTotalMemory();
137
138 Stats->BuildSize += AST.getSourceManager().getContentCacheSize();
139 Stats->BuildSize += AST.getSourceManager().getDataStructureSizes();
140 Stats->BuildSize +=
141 AST.getSourceManager().getMemoryBufferSizes().malloc_bytes;
142
143 const Preprocessor &PP = CI.getPreprocessor();
144 Stats->BuildSize += PP.getTotalMemory();
145 if (PreprocessingRecord *PRec = PP.getPreprocessingRecord())
146 Stats->BuildSize += PRec->getTotalMemory();
147 Stats->BuildSize += PP.getHeaderSearchInfo().getTotalMemory();
148 }
149 }
150
151 void BeforeExecute(CompilerInstance &CI) override {
152 LangOpts = &CI.getLangOpts();
153 SourceMgr = &CI.getSourceManager();
154 PP = &CI.getPreprocessor();
155 Includes.collect(CI);
156 Pragmas.record(CI);
157 if (BeforeExecuteCallback)
158 BeforeExecuteCallback(CI);
159 }
160
161 std::unique_ptr<PPCallbacks> createPPCallbacks() override {
162 assert(SourceMgr && LangOpts && PP &&
163 "SourceMgr, LangOpts and PP must be set at this point");
164
165 return std::make_unique<PPChainedCallbacks>(
166 std::make_unique<CollectMainFileMacros>(*PP, Macros),
167 collectPragmaMarksCallback(*SourceMgr, Marks));
168 }
169
170 bool shouldSkipFunctionBody(Decl *D) override {
171 // Usually we don't need to look inside the bodies of header functions
172 // to understand the program. However when forwarding function like
173 // emplace() forward their arguments to some other function, the
174 // interesting overload resolution happens inside the forwarding
175 // function's body. To provide more meaningful diagnostics,
176 // code completion, and parameter hints we should parse (and later
177 // instantiate) the bodies.
178 if (auto *FT = llvm::dyn_cast<clang::FunctionTemplateDecl>(D)) {
179 if (ParseForwardingFunctions) {
180 // Don't skip parsing the body if it looks like a forwarding function
182 return false;
183 } else {
184 // By default, only take care of make_unique
185 // std::make_unique is trivial, and we diagnose bad constructor calls.
186 if (const auto *II = FT->getDeclName().getAsIdentifierInfo()) {
187 if (II->isStr("make_unique") && FT->isInStdNamespace())
188 return false;
189 }
190 }
191 }
192 return true;
193 }
194
195private:
196 PathRef File;
197 IncludeStructure Includes;
198 include_cleaner::PragmaIncludes Pragmas;
199 MainFileMacros Macros;
200 std::vector<PragmaMark> Marks;
201 bool IsMainFileIncludeGuarded = false;
202 const clang::LangOptions *LangOpts = nullptr;
203 const SourceManager *SourceMgr = nullptr;
204 const Preprocessor *PP = nullptr;
205 PreambleBuildStats *Stats;
206 bool ParseForwardingFunctions;
207 std::function<void(CompilerInstance &)> BeforeExecuteCallback;
208 std::optional<CapturedASTCtx> CapturedCtx;
209};
210
211// Represents directives other than includes, where basic textual information is
212// enough.
213struct TextualPPDirective {
214 unsigned DirectiveLine;
215 // Full text that's representing the directive, including the `#`.
216 std::string Text;
217 unsigned Offset;
218 tok::PPKeywordKind Directive = tok::PPKeywordKind::pp_not_keyword;
219 // Name of the macro being defined in the case of a #define directive.
220 std::string MacroName;
221
222 bool operator==(const TextualPPDirective &RHS) const {
223 return std::tie(DirectiveLine, Offset, Text) ==
224 std::tie(RHS.DirectiveLine, RHS.Offset, RHS.Text);
225 }
226};
227
228// Formats a PP directive consisting of Prefix (e.g. "#define ") and Body ("X
229// 10"). The formatting is copied so that the tokens in Body have PresumedLocs
230// with correct columns and lines.
231std::string spellDirective(llvm::StringRef Prefix,
232 CharSourceRange DirectiveRange,
233 const LangOptions &LangOpts, const SourceManager &SM,
234 unsigned &DirectiveLine, unsigned &Offset) {
235 std::string SpelledDirective;
236 llvm::raw_string_ostream OS(SpelledDirective);
237 OS << Prefix;
238
239 // Make sure DirectiveRange is a char range and doesn't contain macro ids.
240 DirectiveRange = SM.getExpansionRange(DirectiveRange);
241 if (DirectiveRange.isTokenRange()) {
242 DirectiveRange.setEnd(
243 Lexer::getLocForEndOfToken(DirectiveRange.getEnd(), 0, SM, LangOpts));
244 }
245
246 auto DecompLoc = SM.getDecomposedLoc(DirectiveRange.getBegin());
247 DirectiveLine = SM.getLineNumber(DecompLoc.first, DecompLoc.second);
248 Offset = DecompLoc.second;
249 auto TargetColumn = SM.getColumnNumber(DecompLoc.first, DecompLoc.second) - 1;
250
251 // Pad with spaces before DirectiveRange to make sure it will be on right
252 // column when patched.
253 if (Prefix.size() <= TargetColumn) {
254 // There is enough space for Prefix and space before directive, use it.
255 // We try to squeeze the Prefix into the same line whenever we can, as
256 // putting onto a separate line won't work at the beginning of the file.
257 OS << std::string(TargetColumn - Prefix.size(), ' ');
258 } else {
259 // Prefix was longer than the space we had. We produce e.g.:
260 // #line N-1
261 // #define \
262 // X 10
263 OS << "\\\n" << std::string(TargetColumn, ' ');
264 // Decrement because we put an additional line break before
265 // DirectiveRange.begin().
266 --DirectiveLine;
267 }
268 OS << toSourceCode(SM, DirectiveRange.getAsRange());
269 return OS.str();
270}
271
272// Collects #define directives inside the main file.
273struct DirectiveCollector : public PPCallbacks {
274 DirectiveCollector(const Preprocessor &PP,
275 std::vector<TextualPPDirective> &TextualDirectives)
276 : LangOpts(PP.getLangOpts()), SM(PP.getSourceManager()),
277 TextualDirectives(TextualDirectives) {}
278
279 void FileChanged(SourceLocation Loc, FileChangeReason Reason,
280 SrcMgr::CharacteristicKind FileType,
281 FileID PrevFID) override {
282 InMainFile = SM.isWrittenInMainFile(Loc);
283 }
284
285 void MacroDefined(const Token &MacroNameTok,
286 const MacroDirective *MD) override {
287 if (!InMainFile)
288 return;
289 TextualDirectives.emplace_back();
290 TextualPPDirective &TD = TextualDirectives.back();
291 TD.Directive = tok::pp_define;
292 TD.MacroName = MacroNameTok.getIdentifierInfo()->getName().str();
293
294 const auto *MI = MD->getMacroInfo();
295 TD.Text =
296 spellDirective("#define ",
297 CharSourceRange::getTokenRange(
298 MI->getDefinitionLoc(), MI->getDefinitionEndLoc()),
299 LangOpts, SM, TD.DirectiveLine, TD.Offset);
300 }
301
302private:
303 bool InMainFile = true;
304 const LangOptions &LangOpts;
305 const SourceManager &SM;
306 std::vector<TextualPPDirective> &TextualDirectives;
307};
308
309struct ScannedPreamble {
310 std::vector<Inclusion> Includes;
311 std::vector<TextualPPDirective> TextualDirectives;
312 // Literal lines of the preamble contents.
313 std::vector<llvm::StringRef> Lines;
314 PreambleBounds Bounds = {0, false};
315 std::vector<PragmaMark> Marks;
316 MainFileMacros Macros;
317};
318
319/// Scans the preprocessor directives in the preamble section of the file by
320/// running preprocessor over \p Contents. Returned includes do not contain
321/// resolved paths. \p Cmd is used to build the compiler invocation, which might
322/// stat/read files.
323llvm::Expected<ScannedPreamble> scanPreamble(llvm::StringRef Contents,
324 const tooling::CompileCommand &Cmd,
325 bool SkipPreambleBuild) {
326 class EmptyFS : public ThreadsafeFS {
327 private:
328 llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> viewImpl() const override {
329 return new llvm::vfs::InMemoryFileSystem;
330 }
331 };
332 EmptyFS FS;
333 // Build and run Preprocessor over the preamble.
334 ParseInputs PI;
335 // Memory buffers below expect null-terminated && non-null strings. So make
336 // sure to always use PI.Contents!
337 PI.Contents = Contents.str();
338 PI.TFS = &FS;
339 PI.CompileCommand = Cmd;
340 IgnoringDiagConsumer IgnoreDiags;
341 auto CI = buildCompilerInvocation(PI, IgnoreDiags);
342 if (!CI)
343 return error("failed to create compiler invocation");
344 CI->getDiagnosticOpts().IgnoreWarnings = true;
345 auto ContentsBuffer = llvm::MemoryBuffer::getMemBuffer(PI.Contents);
346 // This means we're scanning (though not preprocessing) the preamble section
347 // twice. However, it's important to precisely follow the preamble bounds used
348 // elsewhere.
349 auto Bounds = computePreambleBounds(CI->getLangOpts(), *ContentsBuffer,
350 SkipPreambleBuild);
351 auto PreambleContents = llvm::MemoryBuffer::getMemBufferCopy(
352 llvm::StringRef(PI.Contents).take_front(Bounds.Size));
353 auto Clang = prepareCompilerInstance(
354 std::move(CI), nullptr, std::move(PreambleContents),
355 // Provide an empty FS to prevent preprocessor from performing IO. This
356 // also implies missing resolved paths for includes.
357 FS.view(std::nullopt), IgnoreDiags);
358 if (Clang->getFrontendOpts().Inputs.empty())
359 return error("compiler instance had no inputs");
360 // We are only interested in main file includes.
361 Clang->getPreprocessorOpts().SingleFileParseMode = true;
362 Clang->getPreprocessorOpts().UsePredefines = false;
363 PreprocessOnlyAction Action;
364 if (!Action.BeginSourceFile(*Clang, Clang->getFrontendOpts().Inputs[0]))
365 return error("failed BeginSourceFile");
366 Preprocessor &PP = Clang->getPreprocessor();
367 const auto &SM = PP.getSourceManager();
368 IncludeStructure Includes;
369 Includes.collect(*Clang);
370 ScannedPreamble SP;
371 SP.Bounds = Bounds;
372 PP.addPPCallbacks(
373 std::make_unique<DirectiveCollector>(PP, SP.TextualDirectives));
374 PP.addPPCallbacks(collectPragmaMarksCallback(SM, SP.Marks));
375 PP.addPPCallbacks(std::make_unique<CollectMainFileMacros>(PP, SP.Macros));
376 if (llvm::Error Err = Action.Execute())
377 return std::move(Err);
378 Action.EndSourceFile();
379 SP.Includes = std::move(Includes.MainFileIncludes);
380 llvm::append_range(SP.Lines, llvm::split(Contents, "\n"));
381 return SP;
382}
383
384const char *spellingForIncDirective(tok::PPKeywordKind IncludeDirective) {
385 switch (IncludeDirective) {
386 case tok::pp_include:
387 return "include";
388 case tok::pp_import:
389 return "import";
390 case tok::pp_include_next:
391 return "include_next";
392 default:
393 break;
394 }
395 llvm_unreachable("not an include directive");
396}
397
398// Accumulating wall time timer. Similar to llvm::Timer, but much cheaper,
399// it only tracks wall time.
400// Since this is a generic timer, We may want to move this to support/ if we
401// find a use case outside of FS time tracking.
402class WallTimer {
403public:
404 WallTimer() : TotalTime(std::chrono::steady_clock::duration::zero()) {}
405 // [Re-]Start the timer.
406 void startTimer() { StartTime = std::chrono::steady_clock::now(); }
407 // Stop the timer and update total time.
408 void stopTimer() {
409 TotalTime += std::chrono::steady_clock::now() - StartTime;
410 }
411 // Return total time, in seconds.
412 double getTime() { return std::chrono::duration<double>(TotalTime).count(); }
413
414private:
415 std::chrono::steady_clock::duration TotalTime;
416 std::chrono::steady_clock::time_point StartTime;
417};
418
419class WallTimerRegion {
420public:
421 WallTimerRegion(WallTimer &T) : T(T) { T.startTimer(); }
422 ~WallTimerRegion() { T.stopTimer(); }
423
424private:
425 WallTimer &T;
426};
427
428// Used by TimerFS, tracks time spent in status() and getBuffer() calls while
429// proxying to underlying File implementation.
430class TimerFile : public llvm::vfs::File {
431public:
432 TimerFile(WallTimer &Timer, std::unique_ptr<File> InnerFile)
433 : Timer(Timer), InnerFile(std::move(InnerFile)) {}
434
435 llvm::ErrorOr<llvm::vfs::Status> status() override {
436 WallTimerRegion T(Timer);
437 return InnerFile->status();
438 }
439 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
440 getBuffer(const Twine &Name, int64_t FileSize, bool RequiresNullTerminator,
441 bool IsVolatile) override {
442 WallTimerRegion T(Timer);
443 return InnerFile->getBuffer(Name, FileSize, RequiresNullTerminator,
444 IsVolatile);
445 }
446 std::error_code close() override {
447 WallTimerRegion T(Timer);
448 return InnerFile->close();
449 }
450
451private:
452 WallTimer &Timer;
453 std::unique_ptr<llvm::vfs::File> InnerFile;
454};
455
456// A wrapper for FileSystems that tracks the amount of time spent in status()
457// and openFileForRead() calls.
458class TimerFS : public llvm::vfs::ProxyFileSystem {
459public:
460 TimerFS(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS)
461 : ProxyFileSystem(std::move(FS)) {}
462
463 llvm::ErrorOr<std::unique_ptr<llvm::vfs::File>>
464 openFileForRead(const llvm::Twine &Path) override {
465 WallTimerRegion T(Timer);
466 auto FileOr = getUnderlyingFS().openFileForRead(Path);
467 if (!FileOr)
468 return FileOr;
469 return std::make_unique<TimerFile>(Timer, std::move(FileOr.get()));
470 }
471
472 llvm::ErrorOr<llvm::vfs::Status> status(const llvm::Twine &Path) override {
473 WallTimerRegion T(Timer);
474 return getUnderlyingFS().status(Path);
475 }
476
477 double getTime() { return Timer.getTime(); }
478
479private:
480 WallTimer Timer;
481};
482
483// Helpers for patching diagnostics between two versions of file contents.
484class DiagPatcher {
485 llvm::ArrayRef<llvm::StringRef> OldLines;
486 llvm::ArrayRef<llvm::StringRef> CurrentLines;
487 llvm::StringMap<llvm::SmallVector<int>> CurrentContentsToLine;
488
489 // Translates a range from old lines to current lines.
490 // Finds the consecutive set of lines that corresponds to the same contents in
491 // old and current, and applies the same translation to the range.
492 // Returns true if translation succeeded.
493 bool translateRange(Range &R) {
494 int OldStart = R.start.line;
495 int OldEnd = R.end.line;
496 assert(OldStart <= OldEnd);
497
498 size_t RangeLen = OldEnd - OldStart + 1;
499 auto RangeContents = OldLines.slice(OldStart).take_front(RangeLen);
500 // Make sure the whole range is covered in old contents.
501 if (RangeContents.size() < RangeLen)
502 return false;
503
504 std::optional<int> Closest;
505 for (int AlternateLine : CurrentContentsToLine.lookup(RangeContents[0])) {
506 // Check if AlternateLine matches all lines in the range.
507 if (RangeContents !=
508 CurrentLines.slice(AlternateLine).take_front(RangeLen))
509 continue;
510 int Delta = AlternateLine - OldStart;
511 if (!Closest.has_value() || abs(Delta) < abs(*Closest))
512 Closest = Delta;
513 }
514 // Couldn't find any viable matches in the current contents.
515 if (!Closest.has_value())
516 return false;
517 R.start.line += *Closest;
518 R.end.line += *Closest;
519 return true;
520 }
521
522 // Translates a Note by patching its range when inside main file. Returns true
523 // on success.
524 bool translateNote(Note &N) {
525 if (!N.InsideMainFile)
526 return true;
527 if (translateRange(N.Range))
528 return true;
529 return false;
530 }
531
532 // Tries to translate all the edit ranges inside the fix. Returns true on
533 // success. On failure fixes might be in an invalid state.
534 bool translateFix(Fix &F) {
535 return llvm::all_of(
536 F.Edits, [this](TextEdit &E) { return translateRange(E.range); });
537 }
538
539public:
540 DiagPatcher(llvm::ArrayRef<llvm::StringRef> OldLines,
541 llvm::ArrayRef<llvm::StringRef> CurrentLines) {
542 this->OldLines = OldLines;
543 this->CurrentLines = CurrentLines;
544 for (int Line = 0, E = CurrentLines.size(); Line != E; ++Line) {
545 llvm::StringRef Contents = CurrentLines[Line];
546 CurrentContentsToLine[Contents].push_back(Line);
547 }
548 }
549 // Translate diagnostic by moving its main range to new location (if inside
550 // the main file). Preserve all the notes and fixes that can be translated to
551 // new contents.
552 // Drops the whole diagnostic if main range can't be patched.
553 std::optional<Diag> translateDiag(const Diag &D) {
554 Range NewRange = D.Range;
555 // Patch range if it's inside main file.
556 if (D.InsideMainFile && !translateRange(NewRange)) {
557 // Drop the diagnostic if we couldn't patch the range.
558 return std::nullopt;
559 }
560
561 Diag NewD = D;
562 NewD.Range = NewRange;
563 // Translate ranges inside notes and fixes too, dropping the ones that are
564 // no longer relevant.
565 llvm::erase_if(NewD.Notes, [this](Note &N) { return !translateNote(N); });
566 llvm::erase_if(NewD.Fixes, [this](Fix &F) { return !translateFix(F); });
567 return NewD;
568 }
569};
570} // namespace
571
572std::shared_ptr<const PreambleData>
573buildPreamble(PathRef FileName, CompilerInvocation CI,
574 const ParseInputs &Inputs, bool StoreInMemory,
575 PreambleParsedCallback PreambleCallback,
576 PreambleBuildStats *Stats) {
577 // Note that we don't need to copy the input contents, preamble can live
578 // without those.
579 auto ContentsBuffer =
580 llvm::MemoryBuffer::getMemBuffer(Inputs.Contents, FileName);
581 auto Bounds = computePreambleBounds(CI.getLangOpts(), *ContentsBuffer,
582 Inputs.Opts.SkipPreambleBuild);
583
584 trace::Span Tracer("BuildPreamble");
585 SPAN_ATTACH(Tracer, "File", FileName);
586 std::vector<std::unique_ptr<FeatureModule::ASTListener>> ASTListeners;
587 if (Inputs.FeatureModules) {
588 for (auto &M : *Inputs.FeatureModules) {
589 if (auto Listener = M.astListeners())
590 ASTListeners.emplace_back(std::move(Listener));
591 }
592 }
593 StoreDiags PreambleDiagnostics;
594 PreambleDiagnostics.setDiagCallback(
595 [&ASTListeners](const clang::Diagnostic &D, clangd::Diag &Diag) {
596 for (const auto &L : ASTListeners)
597 L->sawDiagnostic(D, Diag);
598 });
599 auto VFS = Inputs.TFS->view(Inputs.CompileCommand.Directory);
600 llvm::IntrusiveRefCntPtr<DiagnosticsEngine> PreambleDiagsEngine =
601 CompilerInstance::createDiagnostics(*VFS, CI.getDiagnosticOpts(),
602 &PreambleDiagnostics,
603 /*ShouldOwnClient=*/false);
604 PreambleDiagnostics.setLevelAdjuster([&](DiagnosticsEngine::Level DiagLevel,
605 const clang::Diagnostic &Info) {
606 switch (Info.getID()) {
607 case diag::warn_no_newline_eof:
608 // If the preamble doesn't span the whole file, drop the no newline at
609 // eof warning.
610 return Bounds.Size != ContentsBuffer->getBufferSize()
611 ? DiagnosticsEngine::Level::Ignored
612 : DiagLevel;
613 }
614 return DiagLevel;
615 });
616
617 // Skip function bodies when building the preamble to speed up building
618 // the preamble and make it smaller.
619 assert(!CI.getFrontendOpts().SkipFunctionBodies);
620 CI.getFrontendOpts().SkipFunctionBodies = true;
621 // We don't want to write comment locations into PCH. They are racy and slow
622 // to read back. We rely on dynamic index for the comments instead.
623 CI.getPreprocessorOpts().WriteCommentListToPCH = false;
624
625 CppFilePreambleCallbacks CapturedInfo(
626 FileName, Stats, Inputs.Opts.PreambleParseForwardingFunctions,
627 [&ASTListeners](CompilerInstance &CI) {
628 for (const auto &L : ASTListeners)
629 L->beforeExecute(CI);
630 });
631 llvm::SmallString<32> AbsFileName(FileName);
632 VFS->makeAbsolute(AbsFileName);
633 auto StatCache = std::make_shared<PreambleFileStatusCache>(AbsFileName);
634 auto StatCacheFS = StatCache->getProducingFS(VFS);
635 llvm::IntrusiveRefCntPtr<TimerFS> TimedFS(new TimerFS(StatCacheFS));
636
637 WallTimer PreambleTimer;
638 PreambleTimer.startTimer();
639 auto BuiltPreamble = PrecompiledPreamble::Build(
640 CI, ContentsBuffer.get(), Bounds, PreambleDiagsEngine,
641 Stats ? TimedFS : StatCacheFS, std::make_shared<PCHContainerOperations>(),
642 StoreInMemory, /*StoragePath=*/"", CapturedInfo);
643
644 PreambleTimer.stopTimer();
645
646 // We have to setup DiagnosticConsumer that will be alife
647 // while preamble callback is executed
648 PreambleDiagsEngine->setClient(new IgnoringDiagConsumer, true);
649 // Reset references to ref-counted-ptrs before executing the callbacks, to
650 // prevent resetting them concurrently.
651 PreambleDiagsEngine.reset();
652
653 // When building the AST for the main file, we do want the function
654 // bodies.
655 CI.getFrontendOpts().SkipFunctionBodies = false;
656
657 if (Stats != nullptr) {
658 Stats->TotalBuildTime = PreambleTimer.getTime();
659 Stats->FileSystemTime = TimedFS->getTime();
660 Stats->SerializedSize = BuiltPreamble ? BuiltPreamble->getSize() : 0;
661 }
662
663 if (BuiltPreamble) {
664 log("Built preamble of size {0} for file {1} version {2} in {3} seconds",
665 BuiltPreamble->getSize(), FileName, Inputs.Version,
666 PreambleTimer.getTime());
667 std::vector<Diag> Diags = PreambleDiagnostics.take();
668 auto Result = std::make_shared<PreambleData>(std::move(*BuiltPreamble));
669 Result->Version = Inputs.Version;
670 Result->CompileCommand = Inputs.CompileCommand;
671 Result->Diags = std::move(Diags);
672 Result->Includes = CapturedInfo.takeIncludes();
673 Result->Pragmas = std::make_shared<const include_cleaner::PragmaIncludes>(
674 CapturedInfo.takePragmaIncludes());
675
676 if (Inputs.ModulesManager) {
677 WallTimer PrerequisiteModuleTimer;
678 PrerequisiteModuleTimer.startTimer();
679 Result->RequiredModules =
681 *Inputs.TFS);
682 PrerequisiteModuleTimer.stopTimer();
683
684 log("Built prerequisite modules for file {0} in {1} seconds", FileName,
685 PrerequisiteModuleTimer.getTime());
686 }
687
688 Result->Macros = CapturedInfo.takeMacros();
689 Result->Marks = CapturedInfo.takeMarks();
690 Result->StatCache = std::move(StatCache);
691 Result->MainIsIncludeGuarded = CapturedInfo.isMainFileIncludeGuarded();
692 // Move the options instead of copying them. The invocation doesn't need
693 // them anymore.
694 Result->TargetOpts =
695 std::make_unique<TargetOptions>(std::move(CI.getTargetOpts()));
696 if (PreambleCallback) {
697 trace::Span Tracer("Running PreambleCallback");
698 auto Ctx = CapturedInfo.takeLife();
699 // Stat cache is thread safe only when there are no producers. Hence
700 // change the VFS underneath to a consuming fs.
701 Ctx->getFileManager().setVirtualFileSystem(
702 Result->StatCache->getConsumingFS(VFS));
703 // While extending the life of FileMgr and VFS, StatCache should also be
704 // extended.
705 Ctx->setStatCache(Result->StatCache);
706
707 PreambleCallback(std::move(*Ctx), Result->Pragmas);
708 }
709 return Result;
710 }
711
712 elog("Could not build a preamble for file {0} version {1}: {2}", FileName,
713 Inputs.Version, BuiltPreamble.getError().message());
714 for (const Diag &D : PreambleDiagnostics.take()) {
715 if (D.Severity < DiagnosticsEngine::Error)
716 continue;
717 // Not an ideal way to show errors, but better than nothing!
718 elog(" error: {0}", D.Message);
719 }
720 return nullptr;
721}
722
724 const ParseInputs &Inputs, PathRef FileName,
725 const CompilerInvocation &CI) {
726 auto ContentsBuffer =
727 llvm::MemoryBuffer::getMemBuffer(Inputs.Contents, FileName);
728 auto Bounds = computePreambleBounds(CI.getLangOpts(), *ContentsBuffer,
729 Inputs.Opts.SkipPreambleBuild);
730 auto VFS = Inputs.TFS->view(Inputs.CompileCommand.Directory);
731 return compileCommandsAreEqual(Inputs.CompileCommand,
732 Preamble.CompileCommand) &&
733 Preamble.Preamble.CanReuse(CI, *ContentsBuffer, Bounds, *VFS) &&
734 (!Preamble.RequiredModules ||
735 Preamble.RequiredModules->canReuse(CI, VFS));
736}
737
738void escapeBackslashAndQuotes(llvm::StringRef Text, llvm::raw_ostream &OS) {
739 for (char C : Text) {
740 switch (C) {
741 case '\\':
742 case '"':
743 OS << '\\';
744 break;
745 default:
746 break;
747 }
748 OS << C;
749 }
750}
751
752// Translate diagnostics from baseline into modified for the lines that have the
753// same spelling.
754static std::vector<Diag> patchDiags(llvm::ArrayRef<Diag> BaselineDiags,
755 const ScannedPreamble &BaselineScan,
756 const ScannedPreamble &ModifiedScan) {
757 std::vector<Diag> PatchedDiags;
758 if (BaselineDiags.empty())
759 return PatchedDiags;
760 DiagPatcher Patcher(BaselineScan.Lines, ModifiedScan.Lines);
761 for (auto &D : BaselineDiags) {
762 if (auto NewD = Patcher.translateDiag(D))
763 PatchedDiags.emplace_back(std::move(*NewD));
764 }
765 return PatchedDiags;
766}
767
768static std::string getPatchName(llvm::StringRef FileName) {
769 // This shouldn't coincide with any real file name.
770 llvm::SmallString<128> PatchName;
771 llvm::sys::path::append(PatchName, llvm::sys::path::parent_path(FileName),
773 return PatchName.str().str();
774}
775
776PreamblePatch PreamblePatch::create(llvm::StringRef FileName,
777 const ParseInputs &Modified,
778 const PreambleData &Baseline,
779 PatchType PatchType) {
780 trace::Span Tracer("CreatePreamblePatch");
781 SPAN_ATTACH(Tracer, "File", FileName);
782 assert(llvm::sys::path::is_absolute(FileName) && "relative FileName!");
783 // First scan preprocessor directives in Baseline and Modified. These will be
784 // used to figure out newly added directives in Modified. Scanning can fail,
785 // the code just bails out and creates an empty patch in such cases, as:
786 // - If scanning for Baseline fails, no knowledge of existing includes hence
787 // patch will contain all the includes in Modified. Leading to rebuild of
788 // whole preamble, which is terribly slow.
789 // - If scanning for Modified fails, cannot figure out newly added ones so
790 // there's nothing to do but generate an empty patch.
791 auto BaselineScan =
792 scanPreamble(Baseline.Preamble.getContents(), Modified.CompileCommand,
793 Modified.Opts.SkipPreambleBuild);
794 if (!BaselineScan) {
795 elog("Failed to scan baseline of {0}: {1}", FileName,
796 BaselineScan.takeError());
797 return PreamblePatch::unmodified(Baseline);
798 }
799 auto ModifiedScan = scanPreamble(Modified.Contents, Modified.CompileCommand,
800 Modified.Opts.SkipPreambleBuild);
801 if (!ModifiedScan) {
802 elog("Failed to scan modified contents of {0}: {1}", FileName,
803 ModifiedScan.takeError());
804 return PreamblePatch::unmodified(Baseline);
805 }
806
807 bool IncludesChanged = BaselineScan->Includes != ModifiedScan->Includes;
808 bool DirectivesChanged =
809 BaselineScan->TextualDirectives != ModifiedScan->TextualDirectives;
810 if ((PatchType == PatchType::MacroDirectives || !IncludesChanged) &&
811 !DirectivesChanged)
812 return PreamblePatch::unmodified(Baseline);
813
814 PreamblePatch PP;
815 PP.Baseline = &Baseline;
816 PP.PatchFileName = getPatchName(FileName);
817 PP.ModifiedBounds = ModifiedScan->Bounds;
818
819 llvm::raw_string_ostream Patch(PP.PatchContents);
820 // Set default filename for subsequent #line directives
821 Patch << "#line 0 \"";
822 // FileName part of a line directive is subject to backslash escaping, which
823 // might lead to problems on windows especially.
824 escapeBackslashAndQuotes(FileName, Patch);
825 Patch << "\"\n";
826
827 if (IncludesChanged && PatchType == PatchType::All) {
828 // We are only interested in newly added includes, record the ones in
829 // Baseline for exclusion.
830 llvm::DenseMap<std::pair<tok::PPKeywordKind, llvm::StringRef>,
831 const Inclusion *>
832 ExistingIncludes;
833 for (const auto &Inc : Baseline.Includes.MainFileIncludes)
834 ExistingIncludes[{Inc.Directive, Inc.Written}] = &Inc;
835 // There might be includes coming from disabled regions, record these for
836 // exclusion too. note that we don't have resolved paths for those.
837 for (const auto &Inc : BaselineScan->Includes)
838 ExistingIncludes.try_emplace({Inc.Directive, Inc.Written});
839 // Calculate extra includes that needs to be inserted.
840 for (auto &Inc : ModifiedScan->Includes) {
841 auto It = ExistingIncludes.find({Inc.Directive, Inc.Written});
842 // Include already present in the baseline preamble. Set resolved path and
843 // put into preamble includes.
844 if (It != ExistingIncludes.end()) {
845 if (It->second) {
846 // If this header is included in an active region of the baseline
847 // preamble, preserve it.
848 auto &PatchedInc = PP.PreambleIncludes.emplace_back();
849 // Copy everything from existing include, apart from the location,
850 // when it's coming from baseline preamble.
851 PatchedInc = *It->second;
852 PatchedInc.HashLine = Inc.HashLine;
853 PatchedInc.HashOffset = Inc.HashOffset;
854 }
855 continue;
856 }
857 // Include is new in the modified preamble. Inject it into the patch and
858 // use #line to set the presumed location to where it is spelled.
859 auto LineCol = offsetToClangLineColumn(Modified.Contents, Inc.HashOffset);
860 Patch << llvm::formatv("#line {0}\n", LineCol.first);
861 Patch << llvm::formatv(
862 "#{0} {1}\n", spellingForIncDirective(Inc.Directive), Inc.Written);
863 }
864 } else {
865 // Make sure we have the full set of includes available even when we're not
866 // patching. As these are used by features we provide afterwards like hover,
867 // go-to-def or include-cleaner when preamble is stale.
868 PP.PreambleIncludes = Baseline.Includes.MainFileIncludes;
869 }
870
871 if (DirectivesChanged) {
872 // We need to patch all the directives, since they are order dependent. e.g:
873 // #define BAR(X) NEW(X) // Newly introduced in Modified
874 // #define BAR(X) OLD(X) // Exists in the Baseline
875 //
876 // If we've patched only the first directive, the macro definition would've
877 // been wrong for the rest of the file, since patch is applied after the
878 // baseline preamble.
879 //
880 // Note that we deliberately ignore conditional directives and undefs to
881 // reduce complexity. The former might cause problems because scanning is
882 // imprecise and might pick directives from disabled regions.
883 for (const auto &TD : ModifiedScan->TextualDirectives) {
884 // Introduce an #undef directive before #defines to suppress any
885 // re-definition warnings.
886 if (TD.Directive == tok::pp_define)
887 Patch << "#undef " << TD.MacroName << '\n';
888 Patch << "#line " << TD.DirectiveLine << '\n';
889 Patch << TD.Text << '\n';
890 }
891 }
892
893 PP.PatchedDiags = patchDiags(Baseline.Diags, *BaselineScan, *ModifiedScan);
894 PP.PatchedMarks = std::move(ModifiedScan->Marks);
895 PP.PatchedMacros = std::move(ModifiedScan->Macros);
896 dlog("Created preamble patch: {0}", Patch.str());
897 return PP;
898}
899
900PreamblePatch PreamblePatch::createFullPatch(llvm::StringRef FileName,
901 const ParseInputs &Modified,
902 const PreambleData &Baseline) {
903 return create(FileName, Modified, Baseline, PatchType::All);
904}
905
906PreamblePatch PreamblePatch::createMacroPatch(llvm::StringRef FileName,
907 const ParseInputs &Modified,
908 const PreambleData &Baseline) {
909 return create(FileName, Modified, Baseline, PatchType::MacroDirectives);
910}
911
912void PreamblePatch::apply(CompilerInvocation &CI) const {
913 // Make sure the compilation uses same target opts as the preamble. Clang has
914 // no guarantees around using arbitrary options when reusing PCHs, and
915 // different target opts can result in crashes, see
916 // ParsedASTTest.PreambleWithDifferentTarget.
917 // Make sure this is a deep copy, as the same Baseline might be used
918 // concurrently.
919 CI.getTargetOpts() = *Baseline->TargetOpts;
920
921 // No need to map an empty file.
922 if (PatchContents.empty())
923 return;
924 auto &PPOpts = CI.getPreprocessorOpts();
925 auto PatchBuffer =
926 // we copy here to ensure contents are still valid if CI outlives the
927 // PreamblePatch.
928 llvm::MemoryBuffer::getMemBufferCopy(PatchContents, PatchFileName);
929 // CI will take care of the lifetime of the buffer.
930 PPOpts.addRemappedFile(PatchFileName, PatchBuffer.release());
931 // The patch will be parsed after loading the preamble ast and before parsing
932 // the main file.
933 PPOpts.Includes.push_back(PatchFileName);
934}
935
936std::vector<Inclusion> PreamblePatch::preambleIncludes() const {
937 return PreambleIncludes;
938}
939
941 PreamblePatch PP;
942 PP.Baseline = &Preamble;
943 PP.PreambleIncludes = Preamble.Includes.MainFileIncludes;
944 PP.ModifiedBounds = Preamble.Preamble.getBounds();
945 PP.PatchedDiags = Preamble.Diags;
946 return PP;
947}
948
949llvm::ArrayRef<PragmaMark> PreamblePatch::marks() const {
950 if (PatchContents.empty())
951 return Baseline->Marks;
952 return PatchedMarks;
953}
954
956 if (PatchContents.empty())
957 return Baseline->Macros;
958 return PatchedMacros;
959}
960
961OptionalFileEntryRef PreamblePatch::getPatchEntry(llvm::StringRef MainFilePath,
962 const SourceManager &SM) {
963 auto PatchFilePath = getPatchName(MainFilePath);
964 return SM.getFileManager().getOptionalFileRef(PatchFilePath);
965}
966
967PreambleBounds computePreambleBounds(const LangOptions &LangOpts,
968 const llvm::MemoryBufferRef &Buffer,
969 bool SkipPreambleBuild) {
970 return SkipPreambleBuild ? PreambleBounds(0, false)
971 : ComputePreambleBounds(LangOpts, Buffer, 0);
972}
973} // namespace clangd
974} // namespace clang
static cl::opt< bool > Fix("fix", desc(R"( Apply suggested fixes. Without -fix-errors clang-tidy will bail out if any compilation errors were found. )"), cl::init(false), cl::cat(ClangTidyCategory))
#define dlog(...)
Definition Logger.h:101
#define SPAN_ATTACH(S, Name, Expr)
Attach a key-value pair to a Span event.
Definition Trace.h:164
void collect(const CompilerInstance &CI)
Definition Headers.cpp:178
std::unique_ptr< PrerequisiteModules > buildPrerequisiteModulesFor(PathRef File, const ThreadsafeFS &TFS)
static OptionalFileEntryRef getPatchEntry(llvm::StringRef MainFilePath, const SourceManager &SM)
Returns the FileEntry for the preamble patch of MainFilePath in SM, if any.
Definition Preamble.cpp:961
const MainFileMacros & mainFileMacros() const
Definition Preamble.cpp:955
llvm::ArrayRef< PragmaMark > marks() const
Definition Preamble.cpp:949
void apply(CompilerInvocation &CI) const
Adjusts CI (which compiles the modified inputs) to be used with the baseline preamble.
Definition Preamble.cpp:912
static PreamblePatch unmodified(const PreambleData &Preamble)
Preamble is used verbatim.
Definition Preamble.cpp:940
static PreamblePatch createMacroPatch(llvm::StringRef FileName, const ParseInputs &Modified, const PreambleData &Baseline)
Definition Preamble.cpp:906
static PreamblePatch createFullPatch(llvm::StringRef FileName, const ParseInputs &Modified, const PreambleData &Baseline)
Builds a patch that contains new PP directives introduced to the preamble section of Modified compare...
Definition Preamble.cpp:900
static constexpr llvm::StringLiteral HeaderName
Definition Preamble.h:217
std::vector< Inclusion > preambleIncludes() const
Returns include directives from the Modified preamble that were resolved using the Baseline preamble.
Definition Preamble.cpp:936
StoreDiags collects the diagnostics that can later be reported by clangd.
void setLevelAdjuster(LevelAdjuster Adjuster)
If set, this allows the client of this class to adjust the level of diagnostics, such as promoting wa...
std::vector< Diag > take(const clang::tidy::ClangTidyContext *Tidy=nullptr)
void setDiagCallback(DiagCallback CB)
Invokes a callback every time a diagnostics is completely formed.
Wrapper for vfs::FileSystem for use in multithreaded programs like clangd.
llvm::IntrusiveRefCntPtr< llvm::vfs::FileSystem > view(std::nullopt_t CWD) const
Obtain a vfs::FileSystem with an arbitrary initial working directory.
Records an event whose duration is the lifetime of the Span object.
Definition Trace.h:143
FIXME: Skip testing on windows temporarily due to the different escaping code mode.
Definition AST.cpp:44
bool isLikelyForwardingFunction(const FunctionTemplateDecl *FT)
Heuristic that checks if FT is likely to be forwarding a parameter pack to another function (e....
Definition AST.cpp:1043
@ Info
An information message.
Definition Protocol.h:738
static std::string getPatchName(llvm::StringRef FileName)
Definition Preamble.cpp:768
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:96
llvm::Error error(std::error_code EC, const char *Fmt, Ts &&... Vals)
Definition Logger.h:79
bool operator==(const Inclusion &LHS, const Inclusion &RHS)
Definition Headers.cpp:356
std::unique_ptr< PPCallbacks > collectPragmaMarksCallback(const SourceManager &SM, std::vector< PragmaMark > &Out)
Collect all pragma marks from the main file.
bool isPreambleCompatible(const PreambleData &Preamble, const ParseInputs &Inputs, PathRef FileName, const CompilerInvocation &CI)
Returns true if Preamble is reusable for Inputs.
Definition Preamble.cpp:723
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:573
std::unique_ptr< CompilerInstance > prepareCompilerInstance(std::unique_ptr< clang::CompilerInvocation > CI, const PrecompiledPreamble *Preamble, std::unique_ptr< llvm::MemoryBuffer > Buffer, llvm::IntrusiveRefCntPtr< llvm::vfs::FileSystem > VFS, DiagnosticConsumer &DiagsClient)
Definition Compiler.cpp:131
void log(const char *Fmt, Ts &&... Vals)
Definition Logger.h:67
llvm::StringRef toSourceCode(const SourceManager &SM, SourceRange R)
Returns the source code covered by the source range.
llvm::StringRef PathRef
A typedef to represent a ref to file path.
Definition Path.h:29
std::string Path
A typedef to represent a file path.
Definition Path.h:26
std::pair< size_t, size_t > offsetToClangLineColumn(llvm::StringRef Code, size_t Offset)
static std::vector< Diag > patchDiags(llvm::ArrayRef< Diag > BaselineDiags, const ScannedPreamble &BaselineScan, const ScannedPreamble &ModifiedScan)
Definition Preamble.cpp:754
void escapeBackslashAndQuotes(llvm::StringRef Text, llvm::raw_ostream &OS)
Definition Preamble.cpp:738
std::function< void(CapturedASTCtx ASTCtx, std::shared_ptr< const include_cleaner::PragmaIncludes >)> PreambleParsedCallback
Definition Preamble.h:130
void elog(const char *Fmt, Ts &&... Vals)
Definition Logger.h:61
PreambleBounds computePreambleBounds(const LangOptions &LangOpts, const llvm::MemoryBufferRef &Buffer, bool SkipPreambleBuild)
Definition Preamble.cpp:967
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
A top-level diagnostic that may have Notes and Fixes.
Definition Diagnostics.h:98
Information required to run clang, e.g. to parse AST or do code completion.
Definition Compiler.h:51
tooling::CompileCommand CompileCommand
Definition Compiler.h:52
const ThreadsafeFS * TFS
Definition Compiler.h:53
FeatureModuleSet * FeatureModules
Definition Compiler.h:65
ModulesBuilder * ModulesManager
Definition Compiler.h:67
Timings and statistics from the premble build.
Definition Preamble.h:137
double FileSystemTime
Time spent in filesystem operations during the build, in seconds.
Definition Preamble.h:141
double TotalBuildTime
Total wall time it took to build preamble, in seconds.
Definition Preamble.h:139
size_t SerializedSize
The serialized size of the preamble.
Definition Preamble.h:149
The parsed preamble and associated data.
Definition Preamble.h:97