clang-tools 22.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 const Config &Cfg = Config::current();
602 PreambleDiagnostics.setLevelAdjuster([&](DiagnosticsEngine::Level DiagLevel,
603 const clang::Diagnostic &Info) {
604 if (Cfg.Diagnostics.SuppressAll ||
606 CI.getLangOpts()))
607 return DiagnosticsEngine::Ignored;
608 switch (Info.getID()) {
609 case diag::warn_no_newline_eof:
610 // If the preamble doesn't span the whole file, drop the no newline at
611 // eof warning.
612 return Bounds.Size != ContentsBuffer->getBufferSize()
613 ? DiagnosticsEngine::Level::Ignored
614 : DiagLevel;
615 }
616 return DiagLevel;
617 });
618
619 // Skip function bodies when building the preamble to speed up building
620 // the preamble and make it smaller.
621 assert(!CI.getFrontendOpts().SkipFunctionBodies);
622 CI.getFrontendOpts().SkipFunctionBodies = true;
623 // We don't want to write comment locations into PCH. They are racy and slow
624 // to read back. We rely on dynamic index for the comments instead.
625 CI.getPreprocessorOpts().WriteCommentListToPCH = false;
626
627 CppFilePreambleCallbacks CapturedInfo(
628 FileName, Stats, Inputs.Opts.PreambleParseForwardingFunctions,
629 [&ASTListeners](CompilerInstance &CI) {
630 for (const auto &L : ASTListeners)
631 L->beforeExecute(CI);
632 });
633 llvm::SmallString<32> AbsFileName(FileName);
634 VFS->makeAbsolute(AbsFileName);
635 auto StatCache = std::make_shared<PreambleFileStatusCache>(AbsFileName);
636 auto StatCacheFS = StatCache->getProducingFS(VFS);
637 llvm::IntrusiveRefCntPtr<TimerFS> TimedFS(new TimerFS(StatCacheFS));
638
639 WallTimer PreambleTimer;
640 PreambleTimer.startTimer();
641 auto BuiltPreamble = PrecompiledPreamble::Build(
642 CI, ContentsBuffer.get(), Bounds, PreambleDiagsEngine,
643 Stats ? TimedFS : StatCacheFS, std::make_shared<PCHContainerOperations>(),
644 StoreInMemory, /*StoragePath=*/"", CapturedInfo);
645
646 PreambleTimer.stopTimer();
647
648 // We have to setup DiagnosticConsumer that will be alife
649 // while preamble callback is executed
650 PreambleDiagsEngine->setClient(new IgnoringDiagConsumer, true);
651 // Reset references to ref-counted-ptrs before executing the callbacks, to
652 // prevent resetting them concurrently.
653 PreambleDiagsEngine.reset();
654
655 // When building the AST for the main file, we do want the function
656 // bodies.
657 CI.getFrontendOpts().SkipFunctionBodies = false;
658
659 if (Stats != nullptr) {
660 Stats->TotalBuildTime = PreambleTimer.getTime();
661 Stats->FileSystemTime = TimedFS->getTime();
662 Stats->SerializedSize = BuiltPreamble ? BuiltPreamble->getSize() : 0;
663 }
664
665 if (BuiltPreamble) {
666 log("Built preamble of size {0} for file {1} version {2} in {3} seconds",
667 BuiltPreamble->getSize(), FileName, Inputs.Version,
668 PreambleTimer.getTime());
669 std::vector<Diag> Diags = PreambleDiagnostics.take();
670 auto Result = std::make_shared<PreambleData>(std::move(*BuiltPreamble));
671 Result->Version = Inputs.Version;
672 Result->CompileCommand = Inputs.CompileCommand;
673 Result->Diags = std::move(Diags);
674 Result->Includes = CapturedInfo.takeIncludes();
675 Result->Pragmas = std::make_shared<const include_cleaner::PragmaIncludes>(
676 CapturedInfo.takePragmaIncludes());
677
678 if (Inputs.ModulesManager) {
679 WallTimer PrerequisiteModuleTimer;
680 PrerequisiteModuleTimer.startTimer();
681 Result->RequiredModules =
683 *Inputs.TFS);
684 PrerequisiteModuleTimer.stopTimer();
685
686 log("Built prerequisite modules for file {0} in {1} seconds", FileName,
687 PrerequisiteModuleTimer.getTime());
688 }
689
690 Result->Macros = CapturedInfo.takeMacros();
691 Result->Marks = CapturedInfo.takeMarks();
692 Result->StatCache = StatCache;
693 Result->MainIsIncludeGuarded = CapturedInfo.isMainFileIncludeGuarded();
694 // Move the options instead of copying them. The invocation doesn't need
695 // them anymore.
696 Result->TargetOpts =
697 std::make_unique<TargetOptions>(std::move(CI.getTargetOpts()));
698 if (PreambleCallback) {
699 trace::Span Tracer("Running PreambleCallback");
700 auto Ctx = CapturedInfo.takeLife();
701 // Stat cache is thread safe only when there are no producers. Hence
702 // change the VFS underneath to a consuming fs.
703 Ctx->getFileManager().setVirtualFileSystem(
704 Result->StatCache->getConsumingFS(VFS));
705 // While extending the life of FileMgr and VFS, StatCache should also be
706 // extended.
707 Ctx->setStatCache(Result->StatCache);
708
709 PreambleCallback(std::move(*Ctx), Result->Pragmas);
710 }
711 return Result;
712 }
713
714 elog("Could not build a preamble for file {0} version {1}: {2}", FileName,
715 Inputs.Version, BuiltPreamble.getError().message());
716 for (const Diag &D : PreambleDiagnostics.take()) {
717 if (D.Severity < DiagnosticsEngine::Error)
718 continue;
719 // Not an ideal way to show errors, but better than nothing!
720 elog(" error: {0}", D.Message);
721 }
722 return nullptr;
723}
724
726 const ParseInputs &Inputs, PathRef FileName,
727 const CompilerInvocation &CI) {
728 auto ContentsBuffer =
729 llvm::MemoryBuffer::getMemBuffer(Inputs.Contents, FileName);
730 auto Bounds = ComputePreambleBounds(CI.getLangOpts(), *ContentsBuffer, 0);
731 auto VFS = Inputs.TFS->view(Inputs.CompileCommand.Directory);
732 return compileCommandsAreEqual(Inputs.CompileCommand,
733 Preamble.CompileCommand) &&
734 Preamble.Preamble.CanReuse(CI, *ContentsBuffer, Bounds, *VFS) &&
735 (!Preamble.RequiredModules ||
736 Preamble.RequiredModules->canReuse(CI, VFS));
737}
738
739void escapeBackslashAndQuotes(llvm::StringRef Text, llvm::raw_ostream &OS) {
740 for (char C : Text) {
741 switch (C) {
742 case '\\':
743 case '"':
744 OS << '\\';
745 break;
746 default:
747 break;
748 }
749 OS << C;
750 }
751}
752
753// Translate diagnostics from baseline into modified for the lines that have the
754// same spelling.
755static std::vector<Diag> patchDiags(llvm::ArrayRef<Diag> BaselineDiags,
756 const ScannedPreamble &BaselineScan,
757 const ScannedPreamble &ModifiedScan) {
758 std::vector<Diag> PatchedDiags;
759 if (BaselineDiags.empty())
760 return PatchedDiags;
761 DiagPatcher Patcher(BaselineScan.Lines, ModifiedScan.Lines);
762 for (auto &D : BaselineDiags) {
763 if (auto NewD = Patcher.translateDiag(D))
764 PatchedDiags.emplace_back(std::move(*NewD));
765 }
766 return PatchedDiags;
767}
768
769static std::string getPatchName(llvm::StringRef FileName) {
770 // This shouldn't coincide with any real file name.
771 llvm::SmallString<128> PatchName;
772 llvm::sys::path::append(PatchName, llvm::sys::path::parent_path(FileName),
774 return PatchName.str().str();
775}
776
777PreamblePatch PreamblePatch::create(llvm::StringRef FileName,
778 const ParseInputs &Modified,
779 const PreambleData &Baseline,
780 PatchType PatchType) {
781 trace::Span Tracer("CreatePreamblePatch");
782 SPAN_ATTACH(Tracer, "File", FileName);
783 assert(llvm::sys::path::is_absolute(FileName) && "relative FileName!");
784 // First scan preprocessor directives in Baseline and Modified. These will be
785 // used to figure out newly added directives in Modified. Scanning can fail,
786 // the code just bails out and creates an empty patch in such cases, as:
787 // - If scanning for Baseline fails, no knowledge of existing includes hence
788 // patch will contain all the includes in Modified. Leading to rebuild of
789 // whole preamble, which is terribly slow.
790 // - If scanning for Modified fails, cannot figure out newly added ones so
791 // there's nothing to do but generate an empty patch.
792 auto BaselineScan =
793 scanPreamble(Baseline.Preamble.getContents(), Modified.CompileCommand);
794 if (!BaselineScan) {
795 elog("Failed to scan baseline of {0}: {1}", FileName,
796 BaselineScan.takeError());
797 return PreamblePatch::unmodified(Baseline);
798 }
799 auto ModifiedScan = scanPreamble(Modified.Contents, Modified.CompileCommand);
800 if (!ModifiedScan) {
801 elog("Failed to scan modified contents of {0}: {1}", FileName,
802 ModifiedScan.takeError());
803 return PreamblePatch::unmodified(Baseline);
804 }
805
806 bool IncludesChanged = BaselineScan->Includes != ModifiedScan->Includes;
807 bool DirectivesChanged =
808 BaselineScan->TextualDirectives != ModifiedScan->TextualDirectives;
809 if ((PatchType == PatchType::MacroDirectives || !IncludesChanged) &&
810 !DirectivesChanged)
811 return PreamblePatch::unmodified(Baseline);
812
813 PreamblePatch PP;
814 PP.Baseline = &Baseline;
815 PP.PatchFileName = getPatchName(FileName);
816 PP.ModifiedBounds = ModifiedScan->Bounds;
817
818 llvm::raw_string_ostream Patch(PP.PatchContents);
819 // Set default filename for subsequent #line directives
820 Patch << "#line 0 \"";
821 // FileName part of a line directive is subject to backslash escaping, which
822 // might lead to problems on windows especially.
823 escapeBackslashAndQuotes(FileName, Patch);
824 Patch << "\"\n";
825
826 if (IncludesChanged && PatchType == PatchType::All) {
827 // We are only interested in newly added includes, record the ones in
828 // Baseline for exclusion.
829 llvm::DenseMap<std::pair<tok::PPKeywordKind, llvm::StringRef>,
830 const Inclusion *>
831 ExistingIncludes;
832 for (const auto &Inc : Baseline.Includes.MainFileIncludes)
833 ExistingIncludes[{Inc.Directive, Inc.Written}] = &Inc;
834 // There might be includes coming from disabled regions, record these for
835 // exclusion too. note that we don't have resolved paths for those.
836 for (const auto &Inc : BaselineScan->Includes)
837 ExistingIncludes.try_emplace({Inc.Directive, Inc.Written});
838 // Calculate extra includes that needs to be inserted.
839 for (auto &Inc : ModifiedScan->Includes) {
840 auto It = ExistingIncludes.find({Inc.Directive, Inc.Written});
841 // Include already present in the baseline preamble. Set resolved path and
842 // put into preamble includes.
843 if (It != ExistingIncludes.end()) {
844 if (It->second) {
845 // If this header is included in an active region of the baseline
846 // preamble, preserve it.
847 auto &PatchedInc = PP.PreambleIncludes.emplace_back();
848 // Copy everything from existing include, apart from the location,
849 // when it's coming from baseline preamble.
850 PatchedInc = *It->second;
851 PatchedInc.HashLine = Inc.HashLine;
852 PatchedInc.HashOffset = Inc.HashOffset;
853 }
854 continue;
855 }
856 // Include is new in the modified preamble. Inject it into the patch and
857 // use #line to set the presumed location to where it is spelled.
858 auto LineCol = offsetToClangLineColumn(Modified.Contents, Inc.HashOffset);
859 Patch << llvm::formatv("#line {0}\n", LineCol.first);
860 Patch << llvm::formatv(
861 "#{0} {1}\n", spellingForIncDirective(Inc.Directive), Inc.Written);
862 }
863 } else {
864 // Make sure we have the full set of includes available even when we're not
865 // patching. As these are used by features we provide afterwards like hover,
866 // go-to-def or include-cleaner when preamble is stale.
867 PP.PreambleIncludes = Baseline.Includes.MainFileIncludes;
868 }
869
870 if (DirectivesChanged) {
871 // We need to patch all the directives, since they are order dependent. e.g:
872 // #define BAR(X) NEW(X) // Newly introduced in Modified
873 // #define BAR(X) OLD(X) // Exists in the Baseline
874 //
875 // If we've patched only the first directive, the macro definition would've
876 // been wrong for the rest of the file, since patch is applied after the
877 // baseline preamble.
878 //
879 // Note that we deliberately ignore conditional directives and undefs to
880 // reduce complexity. The former might cause problems because scanning is
881 // imprecise and might pick directives from disabled regions.
882 for (const auto &TD : ModifiedScan->TextualDirectives) {
883 // Introduce an #undef directive before #defines to suppress any
884 // re-definition warnings.
885 if (TD.Directive == tok::pp_define)
886 Patch << "#undef " << TD.MacroName << '\n';
887 Patch << "#line " << TD.DirectiveLine << '\n';
888 Patch << TD.Text << '\n';
889 }
890 }
891
892 PP.PatchedDiags = patchDiags(Baseline.Diags, *BaselineScan, *ModifiedScan);
893 PP.PatchedMarks = std::move(ModifiedScan->Marks);
894 PP.PatchedMacros = std::move(ModifiedScan->Macros);
895 dlog("Created preamble patch: {0}", Patch.str());
896 return PP;
897}
898
899PreamblePatch PreamblePatch::createFullPatch(llvm::StringRef FileName,
900 const ParseInputs &Modified,
901 const PreambleData &Baseline) {
902 return create(FileName, Modified, Baseline, PatchType::All);
903}
904
905PreamblePatch PreamblePatch::createMacroPatch(llvm::StringRef FileName,
906 const ParseInputs &Modified,
907 const PreambleData &Baseline) {
908 return create(FileName, Modified, Baseline, PatchType::MacroDirectives);
909}
910
911void PreamblePatch::apply(CompilerInvocation &CI) const {
912 // Make sure the compilation uses same target opts as the preamble. Clang has
913 // no guarantees around using arbitrary options when reusing PCHs, and
914 // different target opts can result in crashes, see
915 // ParsedASTTest.PreambleWithDifferentTarget.
916 // Make sure this is a deep copy, as the same Baseline might be used
917 // concurrently.
918 CI.getTargetOpts() = *Baseline->TargetOpts;
919
920 // No need to map an empty file.
921 if (PatchContents.empty())
922 return;
923 auto &PPOpts = CI.getPreprocessorOpts();
924 auto PatchBuffer =
925 // we copy here to ensure contents are still valid if CI outlives the
926 // PreamblePatch.
927 llvm::MemoryBuffer::getMemBufferCopy(PatchContents, PatchFileName);
928 // CI will take care of the lifetime of the buffer.
929 PPOpts.addRemappedFile(PatchFileName, PatchBuffer.release());
930 // The patch will be parsed after loading the preamble ast and before parsing
931 // the main file.
932 PPOpts.Includes.push_back(PatchFileName);
933}
934
935std::vector<Inclusion> PreamblePatch::preambleIncludes() const {
936 return PreambleIncludes;
937}
938
940 PreamblePatch PP;
941 PP.Baseline = &Preamble;
942 PP.PreambleIncludes = Preamble.Includes.MainFileIncludes;
943 PP.ModifiedBounds = Preamble.Preamble.getBounds();
944 PP.PatchedDiags = Preamble.Diags;
945 return PP;
946}
947
948llvm::ArrayRef<PragmaMark> PreamblePatch::marks() const {
949 if (PatchContents.empty())
950 return Baseline->Marks;
951 return PatchedMarks;
952}
953
955 if (PatchContents.empty())
956 return Baseline->Macros;
957 return PatchedMacros;
958}
959
960OptionalFileEntryRef PreamblePatch::getPatchEntry(llvm::StringRef MainFilePath,
961 const SourceManager &SM) {
962 auto PatchFilePath = getPatchName(MainFilePath);
963 return SM.getFileManager().getOptionalFileRef(PatchFilePath);
964}
965} // namespace clangd
966} // 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:960
const MainFileMacros & mainFileMacros() const
Definition Preamble.cpp:954
llvm::ArrayRef< PragmaMark > marks() const
Definition Preamble.cpp:948
void apply(CompilerInvocation &CI) const
Adjusts CI (which compiles the modified inputs) to be used with the baseline preamble.
Definition Preamble.cpp:911
static PreamblePatch unmodified(const PreambleData &Preamble)
Preamble is used verbatim.
Definition Preamble.cpp:939
static PreamblePatch createMacroPatch(llvm::StringRef FileName, const ParseInputs &Modified, const PreambleData &Baseline)
Definition Preamble.cpp:905
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:899
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:935
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 isDiagnosticSuppressed(const clang::Diagnostic &Diag, const llvm::StringSet<> &Suppress, const LangOptions &LangOpts)
Determine whether a (non-clang-tidy) diagnostic is suppressed by config.
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:1042
@ Info
An information message.
Definition Protocol.h:738
static std::string getPatchName(llvm::StringRef FileName)
Definition Preamble.cpp:769
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:725
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:755
void escapeBackslashAndQuotes(llvm::StringRef Text, llvm::raw_ostream &OS)
Definition Preamble.cpp:739
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++ -*-===//
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
struct clang::clangd::Config::@343034053122374337352226322054223376344037116252 Diagnostics
Controls warnings and errors when parsing code.
llvm::StringSet Suppress
Definition Config.h:105
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