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>
324scanPreamble(llvm::StringRef Contents, const tooling::CompileCommand &Cmd) {
325 class EmptyFS : public ThreadsafeFS {
326 private:
327 llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> viewImpl() const override {
328 return new llvm::vfs::InMemoryFileSystem;
329 }
330 };
331 EmptyFS FS;
332 // Build and run Preprocessor over the preamble.
333 ParseInputs PI;
334 // Memory buffers below expect null-terminated && non-null strings. So make
335 // sure to always use PI.Contents!
336 PI.Contents = Contents.str();
337 PI.TFS = &FS;
338 PI.CompileCommand = Cmd;
339 IgnoringDiagConsumer IgnoreDiags;
340 auto CI = buildCompilerInvocation(PI, IgnoreDiags);
341 if (!CI)
342 return error("failed to create compiler invocation");
343 CI->getDiagnosticOpts().IgnoreWarnings = true;
344 auto ContentsBuffer = llvm::MemoryBuffer::getMemBuffer(PI.Contents);
345 // This means we're scanning (though not preprocessing) the preamble section
346 // twice. However, it's important to precisely follow the preamble bounds used
347 // elsewhere.
348 auto Bounds = ComputePreambleBounds(CI->getLangOpts(), *ContentsBuffer, 0);
349 auto PreambleContents = llvm::MemoryBuffer::getMemBufferCopy(
350 llvm::StringRef(PI.Contents).take_front(Bounds.Size));
351 auto Clang = prepareCompilerInstance(
352 std::move(CI), nullptr, std::move(PreambleContents),
353 // Provide an empty FS to prevent preprocessor from performing IO. This
354 // also implies missing resolved paths for includes.
355 FS.view(std::nullopt), IgnoreDiags);
356 if (Clang->getFrontendOpts().Inputs.empty())
357 return error("compiler instance had no inputs");
358 // We are only interested in main file includes.
359 Clang->getPreprocessorOpts().SingleFileParseMode = true;
360 Clang->getPreprocessorOpts().UsePredefines = false;
361 PreprocessOnlyAction Action;
362 if (!Action.BeginSourceFile(*Clang, Clang->getFrontendOpts().Inputs[0]))
363 return error("failed BeginSourceFile");
364 Preprocessor &PP = Clang->getPreprocessor();
365 const auto &SM = PP.getSourceManager();
366 IncludeStructure Includes;
367 Includes.collect(*Clang);
368 ScannedPreamble SP;
369 SP.Bounds = Bounds;
370 PP.addPPCallbacks(
371 std::make_unique<DirectiveCollector>(PP, SP.TextualDirectives));
372 PP.addPPCallbacks(collectPragmaMarksCallback(SM, SP.Marks));
373 PP.addPPCallbacks(std::make_unique<CollectMainFileMacros>(PP, SP.Macros));
374 if (llvm::Error Err = Action.Execute())
375 return std::move(Err);
376 Action.EndSourceFile();
377 SP.Includes = std::move(Includes.MainFileIncludes);
378 llvm::append_range(SP.Lines, llvm::split(Contents, "\n"));
379 return SP;
380}
381
382const char *spellingForIncDirective(tok::PPKeywordKind IncludeDirective) {
383 switch (IncludeDirective) {
384 case tok::pp_include:
385 return "include";
386 case tok::pp_import:
387 return "import";
388 case tok::pp_include_next:
389 return "include_next";
390 default:
391 break;
392 }
393 llvm_unreachable("not an include directive");
394}
395
396// Accumulating wall time timer. Similar to llvm::Timer, but much cheaper,
397// it only tracks wall time.
398// Since this is a generic timer, We may want to move this to support/ if we
399// find a use case outside of FS time tracking.
400class WallTimer {
401public:
402 WallTimer() : TotalTime(std::chrono::steady_clock::duration::zero()) {}
403 // [Re-]Start the timer.
404 void startTimer() { StartTime = std::chrono::steady_clock::now(); }
405 // Stop the timer and update total time.
406 void stopTimer() {
407 TotalTime += std::chrono::steady_clock::now() - StartTime;
408 }
409 // Return total time, in seconds.
410 double getTime() { return std::chrono::duration<double>(TotalTime).count(); }
411
412private:
413 std::chrono::steady_clock::duration TotalTime;
414 std::chrono::steady_clock::time_point StartTime;
415};
416
417class WallTimerRegion {
418public:
419 WallTimerRegion(WallTimer &T) : T(T) { T.startTimer(); }
420 ~WallTimerRegion() { T.stopTimer(); }
421
422private:
423 WallTimer &T;
424};
425
426// Used by TimerFS, tracks time spent in status() and getBuffer() calls while
427// proxying to underlying File implementation.
428class TimerFile : public llvm::vfs::File {
429public:
430 TimerFile(WallTimer &Timer, std::unique_ptr<File> InnerFile)
431 : Timer(Timer), InnerFile(std::move(InnerFile)) {}
432
433 llvm::ErrorOr<llvm::vfs::Status> status() override {
434 WallTimerRegion T(Timer);
435 return InnerFile->status();
436 }
437 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
438 getBuffer(const Twine &Name, int64_t FileSize, bool RequiresNullTerminator,
439 bool IsVolatile) override {
440 WallTimerRegion T(Timer);
441 return InnerFile->getBuffer(Name, FileSize, RequiresNullTerminator,
442 IsVolatile);
443 }
444 std::error_code close() override {
445 WallTimerRegion T(Timer);
446 return InnerFile->close();
447 }
448
449private:
450 WallTimer &Timer;
451 std::unique_ptr<llvm::vfs::File> InnerFile;
452};
453
454// A wrapper for FileSystems that tracks the amount of time spent in status()
455// and openFileForRead() calls.
456class TimerFS : public llvm::vfs::ProxyFileSystem {
457public:
458 TimerFS(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS)
459 : ProxyFileSystem(std::move(FS)) {}
460
461 llvm::ErrorOr<std::unique_ptr<llvm::vfs::File>>
462 openFileForRead(const llvm::Twine &Path) override {
463 WallTimerRegion T(Timer);
464 auto FileOr = getUnderlyingFS().openFileForRead(Path);
465 if (!FileOr)
466 return FileOr;
467 return std::make_unique<TimerFile>(Timer, std::move(FileOr.get()));
468 }
469
470 llvm::ErrorOr<llvm::vfs::Status> status(const llvm::Twine &Path) override {
471 WallTimerRegion T(Timer);
472 return getUnderlyingFS().status(Path);
473 }
474
475 double getTime() { return Timer.getTime(); }
476
477private:
478 WallTimer Timer;
479};
480
481// Helpers for patching diagnostics between two versions of file contents.
482class DiagPatcher {
483 llvm::ArrayRef<llvm::StringRef> OldLines;
484 llvm::ArrayRef<llvm::StringRef> CurrentLines;
485 llvm::StringMap<llvm::SmallVector<int>> CurrentContentsToLine;
486
487 // Translates a range from old lines to current lines.
488 // Finds the consecutive set of lines that corresponds to the same contents in
489 // old and current, and applies the same translation to the range.
490 // Returns true if translation succeeded.
491 bool translateRange(Range &R) {
492 int OldStart = R.start.line;
493 int OldEnd = R.end.line;
494 assert(OldStart <= OldEnd);
495
496 size_t RangeLen = OldEnd - OldStart + 1;
497 auto RangeContents = OldLines.slice(OldStart).take_front(RangeLen);
498 // Make sure the whole range is covered in old contents.
499 if (RangeContents.size() < RangeLen)
500 return false;
501
502 std::optional<int> Closest;
503 for (int AlternateLine : CurrentContentsToLine.lookup(RangeContents[0])) {
504 // Check if AlternateLine matches all lines in the range.
505 if (RangeContents !=
506 CurrentLines.slice(AlternateLine).take_front(RangeLen))
507 continue;
508 int Delta = AlternateLine - OldStart;
509 if (!Closest.has_value() || abs(Delta) < abs(*Closest))
510 Closest = Delta;
511 }
512 // Couldn't find any viable matches in the current contents.
513 if (!Closest.has_value())
514 return false;
515 R.start.line += *Closest;
516 R.end.line += *Closest;
517 return true;
518 }
519
520 // Translates a Note by patching its range when inside main file. Returns true
521 // on success.
522 bool translateNote(Note &N) {
523 if (!N.InsideMainFile)
524 return true;
525 if (translateRange(N.Range))
526 return true;
527 return false;
528 }
529
530 // Tries to translate all the edit ranges inside the fix. Returns true on
531 // success. On failure fixes might be in an invalid state.
532 bool translateFix(Fix &F) {
533 return llvm::all_of(
534 F.Edits, [this](TextEdit &E) { return translateRange(E.range); });
535 }
536
537public:
538 DiagPatcher(llvm::ArrayRef<llvm::StringRef> OldLines,
539 llvm::ArrayRef<llvm::StringRef> CurrentLines) {
540 this->OldLines = OldLines;
541 this->CurrentLines = CurrentLines;
542 for (int Line = 0, E = CurrentLines.size(); Line != E; ++Line) {
543 llvm::StringRef Contents = CurrentLines[Line];
544 CurrentContentsToLine[Contents].push_back(Line);
545 }
546 }
547 // Translate diagnostic by moving its main range to new location (if inside
548 // the main file). Preserve all the notes and fixes that can be translated to
549 // new contents.
550 // Drops the whole diagnostic if main range can't be patched.
551 std::optional<Diag> translateDiag(const Diag &D) {
552 Range NewRange = D.Range;
553 // Patch range if it's inside main file.
554 if (D.InsideMainFile && !translateRange(NewRange)) {
555 // Drop the diagnostic if we couldn't patch the range.
556 return std::nullopt;
557 }
558
559 Diag NewD = D;
560 NewD.Range = NewRange;
561 // Translate ranges inside notes and fixes too, dropping the ones that are
562 // no longer relevant.
563 llvm::erase_if(NewD.Notes, [this](Note &N) { return !translateNote(N); });
564 llvm::erase_if(NewD.Fixes, [this](Fix &F) { return !translateFix(F); });
565 return NewD;
566 }
567};
568} // namespace
569
570std::shared_ptr<const PreambleData>
571buildPreamble(PathRef FileName, CompilerInvocation CI,
572 const ParseInputs &Inputs, bool StoreInMemory,
573 PreambleParsedCallback PreambleCallback,
574 PreambleBuildStats *Stats) {
575 // Note that we don't need to copy the input contents, preamble can live
576 // without those.
577 auto ContentsBuffer =
578 llvm::MemoryBuffer::getMemBuffer(Inputs.Contents, FileName);
579 auto Bounds = ComputePreambleBounds(CI.getLangOpts(), *ContentsBuffer, 0);
580
581 trace::Span Tracer("BuildPreamble");
582 SPAN_ATTACH(Tracer, "File", FileName);
583 std::vector<std::unique_ptr<FeatureModule::ASTListener>> ASTListeners;
584 if (Inputs.FeatureModules) {
585 for (auto &M : *Inputs.FeatureModules) {
586 if (auto Listener = M.astListeners())
587 ASTListeners.emplace_back(std::move(Listener));
588 }
589 }
590 StoreDiags PreambleDiagnostics;
591 PreambleDiagnostics.setDiagCallback(
592 [&ASTListeners](const clang::Diagnostic &D, clangd::Diag &Diag) {
593 for (const auto &L : ASTListeners)
594 L->sawDiagnostic(D, Diag);
595 });
596 auto VFS = Inputs.TFS->view(Inputs.CompileCommand.Directory);
597 llvm::IntrusiveRefCntPtr<DiagnosticsEngine> PreambleDiagsEngine =
598 CompilerInstance::createDiagnostics(*VFS, CI.getDiagnosticOpts(),
599 &PreambleDiagnostics,
600 /*ShouldOwnClient=*/false);
601 PreambleDiagnostics.setLevelAdjuster([&](DiagnosticsEngine::Level DiagLevel,
602 const clang::Diagnostic &Info) {
603 switch (Info.getID()) {
604 case diag::warn_no_newline_eof:
605 // If the preamble doesn't span the whole file, drop the no newline at
606 // eof warning.
607 return Bounds.Size != ContentsBuffer->getBufferSize()
608 ? DiagnosticsEngine::Level::Ignored
609 : DiagLevel;
610 }
611 return DiagLevel;
612 });
613
614 // Skip function bodies when building the preamble to speed up building
615 // the preamble and make it smaller.
616 assert(!CI.getFrontendOpts().SkipFunctionBodies);
617 CI.getFrontendOpts().SkipFunctionBodies = true;
618 // We don't want to write comment locations into PCH. They are racy and slow
619 // to read back. We rely on dynamic index for the comments instead.
620 CI.getPreprocessorOpts().WriteCommentListToPCH = false;
621
622 CppFilePreambleCallbacks CapturedInfo(
623 FileName, Stats, Inputs.Opts.PreambleParseForwardingFunctions,
624 [&ASTListeners](CompilerInstance &CI) {
625 for (const auto &L : ASTListeners)
626 L->beforeExecute(CI);
627 });
628 llvm::SmallString<32> AbsFileName(FileName);
629 VFS->makeAbsolute(AbsFileName);
630 auto StatCache = std::make_shared<PreambleFileStatusCache>(AbsFileName);
631 auto StatCacheFS = StatCache->getProducingFS(VFS);
632 llvm::IntrusiveRefCntPtr<TimerFS> TimedFS(new TimerFS(StatCacheFS));
633
634 WallTimer PreambleTimer;
635 PreambleTimer.startTimer();
636 auto BuiltPreamble = PrecompiledPreamble::Build(
637 CI, ContentsBuffer.get(), Bounds, PreambleDiagsEngine,
638 Stats ? TimedFS : StatCacheFS, std::make_shared<PCHContainerOperations>(),
639 StoreInMemory, /*StoragePath=*/"", CapturedInfo);
640
641 PreambleTimer.stopTimer();
642
643 // We have to setup DiagnosticConsumer that will be alife
644 // while preamble callback is executed
645 PreambleDiagsEngine->setClient(new IgnoringDiagConsumer, true);
646 // Reset references to ref-counted-ptrs before executing the callbacks, to
647 // prevent resetting them concurrently.
648 PreambleDiagsEngine.reset();
649
650 // When building the AST for the main file, we do want the function
651 // bodies.
652 CI.getFrontendOpts().SkipFunctionBodies = false;
653
654 if (Stats != nullptr) {
655 Stats->TotalBuildTime = PreambleTimer.getTime();
656 Stats->FileSystemTime = TimedFS->getTime();
657 Stats->SerializedSize = BuiltPreamble ? BuiltPreamble->getSize() : 0;
658 }
659
660 if (BuiltPreamble) {
661 log("Built preamble of size {0} for file {1} version {2} in {3} seconds",
662 BuiltPreamble->getSize(), FileName, Inputs.Version,
663 PreambleTimer.getTime());
664 std::vector<Diag> Diags = PreambleDiagnostics.take();
665 auto Result = std::make_shared<PreambleData>(std::move(*BuiltPreamble));
666 Result->Version = Inputs.Version;
667 Result->CompileCommand = Inputs.CompileCommand;
668 Result->Diags = std::move(Diags);
669 Result->Includes = CapturedInfo.takeIncludes();
670 Result->Pragmas = std::make_shared<const include_cleaner::PragmaIncludes>(
671 CapturedInfo.takePragmaIncludes());
672
673 if (Inputs.ModulesManager) {
674 WallTimer PrerequisiteModuleTimer;
675 PrerequisiteModuleTimer.startTimer();
676 Result->RequiredModules =
678 *Inputs.TFS);
679 PrerequisiteModuleTimer.stopTimer();
680
681 log("Built prerequisite modules for file {0} in {1} seconds", FileName,
682 PrerequisiteModuleTimer.getTime());
683 }
684
685 Result->Macros = CapturedInfo.takeMacros();
686 Result->Marks = CapturedInfo.takeMarks();
687 Result->StatCache = std::move(StatCache);
688 Result->MainIsIncludeGuarded = CapturedInfo.isMainFileIncludeGuarded();
689 // Move the options instead of copying them. The invocation doesn't need
690 // them anymore.
691 Result->TargetOpts =
692 std::make_unique<TargetOptions>(std::move(CI.getTargetOpts()));
693 if (PreambleCallback) {
694 trace::Span Tracer("Running PreambleCallback");
695 auto Ctx = CapturedInfo.takeLife();
696 // Stat cache is thread safe only when there are no producers. Hence
697 // change the VFS underneath to a consuming fs.
698 Ctx->getFileManager().setVirtualFileSystem(
699 Result->StatCache->getConsumingFS(VFS));
700 // While extending the life of FileMgr and VFS, StatCache should also be
701 // extended.
702 Ctx->setStatCache(Result->StatCache);
703
704 PreambleCallback(std::move(*Ctx), Result->Pragmas);
705 }
706 return Result;
707 }
708
709 elog("Could not build a preamble for file {0} version {1}: {2}", FileName,
710 Inputs.Version, BuiltPreamble.getError().message());
711 for (const Diag &D : PreambleDiagnostics.take()) {
712 if (D.Severity < DiagnosticsEngine::Error)
713 continue;
714 // Not an ideal way to show errors, but better than nothing!
715 elog(" error: {0}", D.Message);
716 }
717 return nullptr;
718}
719
721 const ParseInputs &Inputs, PathRef FileName,
722 const CompilerInvocation &CI) {
723 auto ContentsBuffer =
724 llvm::MemoryBuffer::getMemBuffer(Inputs.Contents, FileName);
725 auto Bounds = ComputePreambleBounds(CI.getLangOpts(), *ContentsBuffer, 0);
726 auto VFS = Inputs.TFS->view(Inputs.CompileCommand.Directory);
727 return compileCommandsAreEqual(Inputs.CompileCommand,
728 Preamble.CompileCommand) &&
729 Preamble.Preamble.CanReuse(CI, *ContentsBuffer, Bounds, *VFS) &&
730 (!Preamble.RequiredModules ||
731 Preamble.RequiredModules->canReuse(CI, VFS));
732}
733
734void escapeBackslashAndQuotes(llvm::StringRef Text, llvm::raw_ostream &OS) {
735 for (char C : Text) {
736 switch (C) {
737 case '\\':
738 case '"':
739 OS << '\\';
740 break;
741 default:
742 break;
743 }
744 OS << C;
745 }
746}
747
748// Translate diagnostics from baseline into modified for the lines that have the
749// same spelling.
750static std::vector<Diag> patchDiags(llvm::ArrayRef<Diag> BaselineDiags,
751 const ScannedPreamble &BaselineScan,
752 const ScannedPreamble &ModifiedScan) {
753 std::vector<Diag> PatchedDiags;
754 if (BaselineDiags.empty())
755 return PatchedDiags;
756 DiagPatcher Patcher(BaselineScan.Lines, ModifiedScan.Lines);
757 for (auto &D : BaselineDiags) {
758 if (auto NewD = Patcher.translateDiag(D))
759 PatchedDiags.emplace_back(std::move(*NewD));
760 }
761 return PatchedDiags;
762}
763
764static std::string getPatchName(llvm::StringRef FileName) {
765 // This shouldn't coincide with any real file name.
766 llvm::SmallString<128> PatchName;
767 llvm::sys::path::append(PatchName, llvm::sys::path::parent_path(FileName),
769 return PatchName.str().str();
770}
771
772PreamblePatch PreamblePatch::create(llvm::StringRef FileName,
773 const ParseInputs &Modified,
774 const PreambleData &Baseline,
775 PatchType PatchType) {
776 trace::Span Tracer("CreatePreamblePatch");
777 SPAN_ATTACH(Tracer, "File", FileName);
778 assert(llvm::sys::path::is_absolute(FileName) && "relative FileName!");
779 // First scan preprocessor directives in Baseline and Modified. These will be
780 // used to figure out newly added directives in Modified. Scanning can fail,
781 // the code just bails out and creates an empty patch in such cases, as:
782 // - If scanning for Baseline fails, no knowledge of existing includes hence
783 // patch will contain all the includes in Modified. Leading to rebuild of
784 // whole preamble, which is terribly slow.
785 // - If scanning for Modified fails, cannot figure out newly added ones so
786 // there's nothing to do but generate an empty patch.
787 auto BaselineScan =
788 scanPreamble(Baseline.Preamble.getContents(), Modified.CompileCommand);
789 if (!BaselineScan) {
790 elog("Failed to scan baseline of {0}: {1}", FileName,
791 BaselineScan.takeError());
792 return PreamblePatch::unmodified(Baseline);
793 }
794 auto ModifiedScan = scanPreamble(Modified.Contents, Modified.CompileCommand);
795 if (!ModifiedScan) {
796 elog("Failed to scan modified contents of {0}: {1}", FileName,
797 ModifiedScan.takeError());
798 return PreamblePatch::unmodified(Baseline);
799 }
800
801 bool IncludesChanged = BaselineScan->Includes != ModifiedScan->Includes;
802 bool DirectivesChanged =
803 BaselineScan->TextualDirectives != ModifiedScan->TextualDirectives;
804 if ((PatchType == PatchType::MacroDirectives || !IncludesChanged) &&
805 !DirectivesChanged)
806 return PreamblePatch::unmodified(Baseline);
807
808 PreamblePatch PP;
809 PP.Baseline = &Baseline;
810 PP.PatchFileName = getPatchName(FileName);
811 PP.ModifiedBounds = ModifiedScan->Bounds;
812
813 llvm::raw_string_ostream Patch(PP.PatchContents);
814 // Set default filename for subsequent #line directives
815 Patch << "#line 0 \"";
816 // FileName part of a line directive is subject to backslash escaping, which
817 // might lead to problems on windows especially.
818 escapeBackslashAndQuotes(FileName, Patch);
819 Patch << "\"\n";
820
821 if (IncludesChanged && PatchType == PatchType::All) {
822 // We are only interested in newly added includes, record the ones in
823 // Baseline for exclusion.
824 llvm::DenseMap<std::pair<tok::PPKeywordKind, llvm::StringRef>,
825 const Inclusion *>
826 ExistingIncludes;
827 for (const auto &Inc : Baseline.Includes.MainFileIncludes)
828 ExistingIncludes[{Inc.Directive, Inc.Written}] = &Inc;
829 // There might be includes coming from disabled regions, record these for
830 // exclusion too. note that we don't have resolved paths for those.
831 for (const auto &Inc : BaselineScan->Includes)
832 ExistingIncludes.try_emplace({Inc.Directive, Inc.Written});
833 // Calculate extra includes that needs to be inserted.
834 for (auto &Inc : ModifiedScan->Includes) {
835 auto It = ExistingIncludes.find({Inc.Directive, Inc.Written});
836 // Include already present in the baseline preamble. Set resolved path and
837 // put into preamble includes.
838 if (It != ExistingIncludes.end()) {
839 if (It->second) {
840 // If this header is included in an active region of the baseline
841 // preamble, preserve it.
842 auto &PatchedInc = PP.PreambleIncludes.emplace_back();
843 // Copy everything from existing include, apart from the location,
844 // when it's coming from baseline preamble.
845 PatchedInc = *It->second;
846 PatchedInc.HashLine = Inc.HashLine;
847 PatchedInc.HashOffset = Inc.HashOffset;
848 }
849 continue;
850 }
851 // Include is new in the modified preamble. Inject it into the patch and
852 // use #line to set the presumed location to where it is spelled.
853 auto LineCol = offsetToClangLineColumn(Modified.Contents, Inc.HashOffset);
854 Patch << llvm::formatv("#line {0}\n", LineCol.first);
855 Patch << llvm::formatv(
856 "#{0} {1}\n", spellingForIncDirective(Inc.Directive), Inc.Written);
857 }
858 } else {
859 // Make sure we have the full set of includes available even when we're not
860 // patching. As these are used by features we provide afterwards like hover,
861 // go-to-def or include-cleaner when preamble is stale.
862 PP.PreambleIncludes = Baseline.Includes.MainFileIncludes;
863 }
864
865 if (DirectivesChanged) {
866 // We need to patch all the directives, since they are order dependent. e.g:
867 // #define BAR(X) NEW(X) // Newly introduced in Modified
868 // #define BAR(X) OLD(X) // Exists in the Baseline
869 //
870 // If we've patched only the first directive, the macro definition would've
871 // been wrong for the rest of the file, since patch is applied after the
872 // baseline preamble.
873 //
874 // Note that we deliberately ignore conditional directives and undefs to
875 // reduce complexity. The former might cause problems because scanning is
876 // imprecise and might pick directives from disabled regions.
877 for (const auto &TD : ModifiedScan->TextualDirectives) {
878 // Introduce an #undef directive before #defines to suppress any
879 // re-definition warnings.
880 if (TD.Directive == tok::pp_define)
881 Patch << "#undef " << TD.MacroName << '\n';
882 Patch << "#line " << TD.DirectiveLine << '\n';
883 Patch << TD.Text << '\n';
884 }
885 }
886
887 PP.PatchedDiags = patchDiags(Baseline.Diags, *BaselineScan, *ModifiedScan);
888 PP.PatchedMarks = std::move(ModifiedScan->Marks);
889 PP.PatchedMacros = std::move(ModifiedScan->Macros);
890 dlog("Created preamble patch: {0}", Patch.str());
891 return PP;
892}
893
894PreamblePatch PreamblePatch::createFullPatch(llvm::StringRef FileName,
895 const ParseInputs &Modified,
896 const PreambleData &Baseline) {
897 return create(FileName, Modified, Baseline, PatchType::All);
898}
899
900PreamblePatch PreamblePatch::createMacroPatch(llvm::StringRef FileName,
901 const ParseInputs &Modified,
902 const PreambleData &Baseline) {
903 return create(FileName, Modified, Baseline, PatchType::MacroDirectives);
904}
905
906void PreamblePatch::apply(CompilerInvocation &CI) const {
907 // Make sure the compilation uses same target opts as the preamble. Clang has
908 // no guarantees around using arbitrary options when reusing PCHs, and
909 // different target opts can result in crashes, see
910 // ParsedASTTest.PreambleWithDifferentTarget.
911 // Make sure this is a deep copy, as the same Baseline might be used
912 // concurrently.
913 CI.getTargetOpts() = *Baseline->TargetOpts;
914
915 // No need to map an empty file.
916 if (PatchContents.empty())
917 return;
918 auto &PPOpts = CI.getPreprocessorOpts();
919 auto PatchBuffer =
920 // we copy here to ensure contents are still valid if CI outlives the
921 // PreamblePatch.
922 llvm::MemoryBuffer::getMemBufferCopy(PatchContents, PatchFileName);
923 // CI will take care of the lifetime of the buffer.
924 PPOpts.addRemappedFile(PatchFileName, PatchBuffer.release());
925 // The patch will be parsed after loading the preamble ast and before parsing
926 // the main file.
927 PPOpts.Includes.push_back(PatchFileName);
928}
929
930std::vector<Inclusion> PreamblePatch::preambleIncludes() const {
931 return PreambleIncludes;
932}
933
935 PreamblePatch PP;
936 PP.Baseline = &Preamble;
937 PP.PreambleIncludes = Preamble.Includes.MainFileIncludes;
938 PP.ModifiedBounds = Preamble.Preamble.getBounds();
939 PP.PatchedDiags = Preamble.Diags;
940 return PP;
941}
942
943llvm::ArrayRef<PragmaMark> PreamblePatch::marks() const {
944 if (PatchContents.empty())
945 return Baseline->Marks;
946 return PatchedMarks;
947}
948
950 if (PatchContents.empty())
951 return Baseline->Macros;
952 return PatchedMacros;
953}
954
955OptionalFileEntryRef PreamblePatch::getPatchEntry(llvm::StringRef MainFilePath,
956 const SourceManager &SM) {
957 auto PatchFilePath = getPatchName(MainFilePath);
958 return SM.getFileManager().getOptionalFileRef(PatchFilePath);
959}
960} // namespace clangd
961} // 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:955
const MainFileMacros & mainFileMacros() const
Definition Preamble.cpp:949
llvm::ArrayRef< PragmaMark > marks() const
Definition Preamble.cpp:943
void apply(CompilerInvocation &CI) const
Adjusts CI (which compiles the modified inputs) to be used with the baseline preamble.
Definition Preamble.cpp:906
static PreamblePatch unmodified(const PreambleData &Preamble)
Preamble is used verbatim.
Definition Preamble.cpp:934
static PreamblePatch createMacroPatch(llvm::StringRef FileName, const ParseInputs &Modified, const PreambleData &Baseline)
Definition Preamble.cpp:900
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:894
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:930
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:764
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:720
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:571
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:750
void escapeBackslashAndQuotes(llvm::StringRef Text, llvm::raw_ostream &OS)
Definition Preamble.cpp:734
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
===– 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: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