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