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