10 #include "../clang-tidy/ClangTidyDiagnosticConsumer.h" 11 #include "../clang-tidy/ClangTidyModuleRegistry.h" 21 #include "clang/AST/ASTContext.h" 22 #include "clang/Basic/LangOptions.h" 23 #include "clang/Basic/SourceManager.h" 24 #include "clang/Basic/TokenKinds.h" 25 #include "clang/Frontend/CompilerInstance.h" 26 #include "clang/Frontend/CompilerInvocation.h" 27 #include "clang/Frontend/FrontendActions.h" 28 #include "clang/Frontend/Utils.h" 29 #include "clang/Index/IndexDataConsumer.h" 30 #include "clang/Index/IndexingAction.h" 31 #include "clang/Lex/Lexer.h" 32 #include "clang/Lex/MacroInfo.h" 33 #include "clang/Lex/Preprocessor.h" 34 #include "clang/Lex/PreprocessorOptions.h" 35 #include "clang/Sema/Sema.h" 36 #include "clang/Serialization/ASTWriter.h" 37 #include "clang/Serialization/PCHContainerOperations.h" 38 #include "clang/Tooling/CompilationDatabase.h" 39 #include "clang/Tooling/Syntax/Tokens.h" 40 #include "llvm/ADT/ArrayRef.h" 41 #include "llvm/ADT/STLExtras.h" 42 #include "llvm/ADT/SmallString.h" 43 #include "llvm/ADT/SmallVector.h" 44 #include "llvm/Support/raw_ostream.h" 52 bool compileCommandsAreEqual(
const tooling::CompileCommand &LHS,
53 const tooling::CompileCommand &RHS) {
55 return LHS.Directory == RHS.Directory && LHS.Filename == RHS.Filename &&
56 llvm::makeArrayRef(LHS.CommandLine).equals(RHS.CommandLine);
59 template <
class T> std::size_t getUsedBytes(
const std::vector<T> &Vec) {
60 return Vec.capacity() *
sizeof(T);
63 class DeclTrackingASTConsumer :
public ASTConsumer {
65 DeclTrackingASTConsumer(std::vector<Decl *> &TopLevelDecls)
66 : TopLevelDecls(TopLevelDecls) {}
68 bool HandleTopLevelDecl(DeclGroupRef DG)
override {
70 auto &SM =
D->getASTContext().getSourceManager();
75 if (isa<ObjCMethodDecl>(
D))
78 TopLevelDecls.push_back(
D);
84 std::vector<Decl *> &TopLevelDecls;
89 std::vector<Decl *> takeTopLevelDecls() {
return std::move(TopLevelDecls); }
92 std::unique_ptr<ASTConsumer>
93 CreateASTConsumer(CompilerInstance &CI, llvm::StringRef InFile)
override {
94 return llvm::make_unique<DeclTrackingASTConsumer>( TopLevelDecls);
98 std::vector<Decl *> TopLevelDecls;
103 explicit CollectMainFileMacros(
const SourceManager &SM,
104 std::vector<std::string> *Out)
105 : SM(SM), Out(Out) {}
107 void FileChanged(SourceLocation
Loc, FileChangeReason,
108 SrcMgr::CharacteristicKind, FileID Prev) {
109 InMainFile = SM.isWrittenInMainFile(Loc);
112 void MacroDefined(
const Token &MacroName,
const MacroDirective *
MD) {
114 MainFileMacros.insert(MacroName.getIdentifierInfo()->getName());
117 void EndOfMainFile() {
118 for (
const auto &
Entry : MainFileMacros)
119 Out->push_back(
Entry.getKey());
124 const SourceManager &SM;
125 bool InMainFile =
true;
126 llvm::StringSet<> MainFileMacros;
127 std::vector<std::string> *Out;
130 class CppFilePreambleCallbacks :
public PreambleCallbacks {
133 : File(File), ParsedCallback(ParsedCallback) {
136 IncludeStructure takeIncludes() {
return std::move(Includes); }
138 std::vector<std::string> takeMainFileMacros() {
139 return std::move(MainFileMacros);
142 CanonicalIncludes takeCanonicalIncludes() {
return std::move(CanonIncludes); }
144 void AfterExecute(CompilerInstance &CI)
override {
147 trace::Span Tracer(
"Running PreambleCallback");
148 ParsedCallback(CI.getASTContext(), CI.getPreprocessorPtr(), CanonIncludes);
151 void BeforeExecute(CompilerInstance &CI)
override {
153 SourceMgr = &CI.getSourceManager();
156 std::unique_ptr<PPCallbacks> createPPCallbacks()
override {
157 assert(SourceMgr &&
"SourceMgr must be set at this point");
158 return llvm::make_unique<PPChainedCallbacks>(
160 llvm::make_unique<CollectMainFileMacros>(*SourceMgr, &MainFileMacros));
163 CommentHandler *getCommentHandler()
override {
165 return IWYUHandler.get();
171 IncludeStructure Includes;
172 CanonicalIncludes CanonIncludes;
173 std::vector<std::string> MainFileMacros;
174 std::unique_ptr<CommentHandler> IWYUHandler =
nullptr;
175 SourceManager *SourceMgr =
nullptr;
189 static void attach(
const IncludeStructure &Includes,
190 CompilerInstance &Clang) {
191 auto &PP = Clang.getPreprocessor();
192 auto *ExistingCallbacks = PP.getPPCallbacks();
194 if (!ExistingCallbacks)
196 PP.addPPCallbacks(std::unique_ptr<PPCallbacks>(
197 new ReplayPreamble(Includes, ExistingCallbacks,
198 Clang.getSourceManager(), PP, Clang.getLangOpts())));
201 assert(PP.getPPCallbacks() != ExistingCallbacks &&
202 "Expected chaining implementation");
206 ReplayPreamble(
const IncludeStructure &Includes,
PPCallbacks *Delegate,
207 const SourceManager &SM, Preprocessor &PP,
208 const LangOptions &LangOpts)
209 : Includes(Includes), Delegate(Delegate), SM(SM), PP(PP),
210 LangOpts(LangOpts) {}
227 void FileChanged(SourceLocation Loc, FileChangeReason Reason,
228 SrcMgr::CharacteristicKind
Kind, FileID PrevFID)
override {
230 if (Reason == FileChangeReason::ExitFile &&
231 SM.getBuffer(PrevFID)->getBufferIdentifier() ==
"<built-in>")
236 for (
const auto &Inc : Includes.MainFileIncludes) {
237 const FileEntry *
File =
nullptr;
238 if (Inc.Resolved !=
"")
239 File = SM.getFileManager().getFile(Inc.Resolved);
241 llvm::StringRef WrittenFilename =
242 llvm::StringRef(Inc.Written).drop_front().drop_back();
243 bool Angled = llvm::StringRef(Inc.Written).startswith(
"<");
246 llvm::StringRef
Src = SM.getBufferData(SM.getMainFileID());
247 Lexer RawLexer(SM.getLocForStartOfFile(SM.getMainFileID()), LangOpts,
248 Src.begin(), Src.begin() + Inc.HashOffset, Src.end());
249 Token HashTok, IncludeTok, FilenameTok;
250 RawLexer.LexFromRawLexer(HashTok);
251 assert(HashTok.getKind() == tok::hash);
252 RawLexer.setParsingPreprocessorDirective(
true);
253 RawLexer.LexFromRawLexer(IncludeTok);
254 IdentifierInfo *II = PP.getIdentifierInfo(IncludeTok.getRawIdentifier());
255 IncludeTok.setIdentifierInfo(II);
256 IncludeTok.setKind(II->getTokenID());
257 RawLexer.LexIncludeFilename(FilenameTok);
259 Delegate->InclusionDirective(
260 HashTok.getLocation(), IncludeTok, WrittenFilename, Angled,
261 CharSourceRange::getCharRange(FilenameTok.getLocation(),
262 FilenameTok.getEndLoc()),
263 File,
"SearchPath",
"RelPath",
nullptr, Inc.FileKind);
265 Delegate->FileSkipped(*File, FilenameTok, Inc.FileKind);
267 llvm::SmallString<1> UnusedRecovery;
268 Delegate->FileNotFound(WrittenFilename, UnusedRecovery);
273 const IncludeStructure &Includes;
275 const SourceManager &SM;
277 const LangOptions &LangOpts;
283 AST.
getASTContext().getTranslationUnitDecl()->dump(OS,
true);
286 llvm::Optional<ParsedAST>
288 std::shared_ptr<const PreambleData>
Preamble,
289 std::unique_ptr<llvm::MemoryBuffer> Buffer,
290 llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem>
VFS,
295 CI->getFrontendOpts().DisableFree =
false;
296 const PrecompiledPreamble *PreamblePCH =
297 Preamble ? &Preamble->Preamble :
nullptr;
300 std::string Content = Buffer->getBuffer();
303 std::move(Buffer), VFS, ASTDiags);
307 auto Action = llvm::make_unique<ClangdFrontendAction>();
308 const FrontendInputFile &MainInput = Clang->getFrontendOpts().Inputs[0];
309 if (!
Action->BeginSourceFile(*Clang, MainInput)) {
310 log(
"BeginSourceFile() failed when building AST for {0}",
311 MainInput.getFile());
321 std::vector<std::unique_ptr<tidy::ClangTidyCheck>> CTChecks;
322 ast_matchers::MatchFinder CTFinder;
323 llvm::Optional<tidy::ClangTidyContext> CTContext;
326 dlog(
"ClangTidy configuration for file {0}: {1}", MainInput.getFile(),
329 for (
const auto &E : tidy::ClangTidyModuleRegistry::entries())
330 E.instantiate()->addCheckFactories(CTFactories);
331 CTContext.emplace(llvm::make_unique<tidy::DefaultOptionsProvider>(
333 CTContext->setDiagnosticsEngine(&Clang->getDiagnostics());
334 CTContext->setASTContext(&Clang->getASTContext());
335 CTContext->setCurrentFile(MainInput.getFile());
336 CTFactories.
createChecks(CTContext.getPointer(), CTChecks);
338 const clang::Diagnostic &
Info) {
340 std::string CheckName = CTContext->getCheckName(Info.getID());
341 bool IsClangTidyDiag = !CheckName.empty();
342 if (IsClangTidyDiag) {
347 CTContext->treatAsError(CheckName)) {
356 bool IsInsideMainFile =
357 Info.hasSourceManager() &&
360 DiagLevel, Info, *CTContext,
362 return DiagnosticsEngine::Ignored;
368 Preprocessor *PP = &Clang->getPreprocessor();
369 for (
const auto &Check : CTChecks) {
372 Check->registerPPCallbacks(Clang->getSourceManager(), PP, PP);
373 Check->registerMatchers(&CTFinder);
379 llvm::Optional<IncludeFixer> FixIncludes;
380 auto BuildDir = VFS->getCurrentWorkingDirectory();
383 auto Inserter = std::make_shared<IncludeInserter>(
384 MainInput.getFile(), Content, Style, BuildDir.get(),
385 &Clang->getPreprocessor().getHeaderSearchInfo());
387 for (
const auto &Inc : Preamble->Includes.MainFileIncludes)
388 Inserter->addExisting(Inc);
390 FixIncludes.emplace(MainInput.getFile(), Inserter, *
Index,
392 ASTDiags.
contributeFixes([&FixIncludes](DiagnosticsEngine::Level DiagLevl,
393 const clang::Diagnostic &
Info) {
394 return FixIncludes->fix(DiagLevl, Info);
396 Clang->setExternalSemaSource(FixIncludes->unresolvedNameRecorder());
404 ReplayPreamble::attach(Includes, *Clang);
408 Clang->getPreprocessor().addPPCallbacks(
415 CanonIncludes = Preamble->CanonIncludes;
418 std::unique_ptr<CommentHandler> IWYUHandler =
420 Clang->getPreprocessor().addCommentHandler(IWYUHandler.get());
423 syntax::TokenCollector CollectTokens(Clang->getPreprocessor());
426 log(
"Execute() failed when building AST for {0}: {1}", MainInput.getFile(),
432 syntax::TokenBuffer
Tokens = std::move(CollectTokens).consume();
433 std::vector<Decl *> ParsedDecls =
Action->takeTopLevelDecls();
435 Clang->getASTContext().setTraversalScope(ParsedDecls);
440 CTFinder.matchAST(Clang->getASTContext());
451 Clang->getPreprocessor().EndSourceFile();
453 std::vector<Diag> Diags = ASTDiags.
take(CTContext.getPointer());
456 Diags.insert(Diags.begin(), Preamble->Diags.begin(), Preamble->Diags.end());
457 return ParsedAST(std::move(Preamble), std::move(Clang), std::move(
Action),
458 std::move(Tokens), std::move(ParsedDecls), std::move(Diags),
459 std::move(Includes), std::move(CanonIncludes));
470 auto PP = Clang->getPreprocessorPtr();
471 Clang->setPreprocessor(
nullptr);
480 return Clang->getASTContext();
486 return Clang->getPreprocessorPtr();
490 return Clang->getPreprocessor();
494 return LocalTopLevelDecls;
500 auto &
AST = getASTContext();
504 clangd::getUsedBytes(LocalTopLevelDecls) + clangd::getUsedBytes(Diags);
510 Total +=
AST.getASTAllocatedMemory();
511 Total +=
AST.getSideTableAllocatedMemory();
512 Total +=
AST.Idents.getAllocator().getTotalMemory();
513 Total +=
AST.Selectors.getTotalMemory();
515 Total +=
AST.getSourceManager().getContentCacheSize();
516 Total +=
AST.getSourceManager().getDataStructureSizes();
517 Total +=
AST.getSourceManager().getMemoryBufferSizes().malloc_bytes;
519 if (ExternalASTSource *Ext =
AST.getExternalSource())
520 Total += Ext->getMemoryBufferSizes().malloc_bytes;
522 const Preprocessor &PP = getPreprocessor();
523 Total += PP.getTotalMemory();
524 if (PreprocessingRecord *PRec = PP.getPreprocessingRecord())
525 Total += PRec->getTotalMemory();
526 Total += PP.getHeaderSearchInfo().getTotalMemory();
536 return CanonIncludes;
541 std::vector<std::string> MainFileMacros,
542 std::unique_ptr<PreambleFileStatusCache> StatCache,
544 : Preamble(std::move(Preamble)), Diags(std::move(Diags)),
545 Includes(std::move(Includes)), MainFileMacros(std::move(MainFileMacros)),
546 StatCache(std::move(StatCache)), CanonIncludes(std::move(CanonIncludes)) {
550 std::unique_ptr<CompilerInstance> Clang,
551 std::unique_ptr<FrontendAction>
Action,
552 syntax::TokenBuffer
Tokens,
553 std::vector<Decl *> LocalTopLevelDecls,
556 :
Preamble(std::move(Preamble)), Clang(std::move(Clang)),
558 Diags(std::move(Diags)),
559 LocalTopLevelDecls(std::move(LocalTopLevelDecls)),
562 assert(this->Action);
565 std::shared_ptr<const PreambleData>
567 std::shared_ptr<const PreambleData> OldPreamble,
568 const tooling::CompileCommand &OldCompileCommand,
573 auto ContentsBuffer = llvm::MemoryBuffer::getMemBuffer(Inputs.
Contents);
575 ComputePreambleBounds(*CI.getLangOpts(), ContentsBuffer.get(), 0);
578 compileCommandsAreEqual(Inputs.
CompileCommand, OldCompileCommand) &&
579 OldPreamble->Preamble.CanReuse(CI, ContentsBuffer.get(), Bounds,
581 vlog(
"Reusing preamble for file {0}", llvm::Twine(FileName));
584 vlog(
"Preamble for file {0} cannot be reused. Attempting to rebuild it.",
590 llvm::IntrusiveRefCntPtr<DiagnosticsEngine> PreambleDiagsEngine =
591 CompilerInstance::createDiagnostics(&CI.getDiagnosticOpts(),
592 &PreambleDiagnostics,
false);
596 assert(!CI.getFrontendOpts().SkipFunctionBodies);
597 CI.getFrontendOpts().SkipFunctionBodies =
true;
600 CI.getPreprocessorOpts().WriteCommentListToPCH =
false;
602 CppFilePreambleCallbacks SerializedDeclsCollector(FileName, PreambleCallback);
603 if (Inputs.
FS->setCurrentWorkingDirectory(Inputs.
CompileCommand.Directory)) {
604 log(
"Couldn't set working directory when building the preamble.");
609 llvm::SmallString<32> AbsFileName(FileName);
610 Inputs.
FS->makeAbsolute(AbsFileName);
611 auto StatCache = llvm::make_unique<PreambleFileStatusCache>(AbsFileName);
612 auto BuiltPreamble = PrecompiledPreamble::Build(
613 CI, ContentsBuffer.get(), Bounds, *PreambleDiagsEngine,
615 std::make_shared<PCHContainerOperations>(), StoreInMemory,
616 SerializedDeclsCollector);
620 CI.getFrontendOpts().SkipFunctionBodies =
false;
623 vlog(
"Built preamble of size {0} for file {1}", BuiltPreamble->getSize(),
625 std::vector<Diag> Diags = PreambleDiagnostics.
take();
626 return std::make_shared<PreambleData>(
627 std::move(*BuiltPreamble), std::move(Diags),
628 SerializedDeclsCollector.takeIncludes(),
629 SerializedDeclsCollector.takeMainFileMacros(), std::move(
StatCache),
630 SerializedDeclsCollector.takeCanonicalIncludes());
632 elog(
"Could not build a preamble for file {0}", FileName);
637 llvm::Optional<ParsedAST>
640 std::shared_ptr<const PreambleData> Preamble) {
644 auto VFS = Inputs.
FS;
645 if (Preamble && Preamble->StatCache)
646 VFS = Preamble->StatCache->getConsumingFS(std::move(
VFS));
648 log(
"Couldn't set working directory when building the preamble.");
655 llvm::MemoryBuffer::getMemBufferCopy(Inputs.
Contents),
660 const Position &Pos,
const FileID FID) {
662 const SourceManager &SourceMgr = AST.getSourceManager();
665 log(
"getBeginningOfIdentifier: {0}",
Offset.takeError());
666 return SourceLocation();
678 SourceLocation InputLoc = SourceMgr.getComposedLoc(FID, *
Offset);
680 return SourceMgr.getMacroArgExpandedLocation(InputLoc);
681 SourceLocation Before = SourceMgr.getComposedLoc(FID, *
Offset - 1);
683 Before = Lexer::GetBeginningOfToken(Before, SourceMgr, AST.getLangOpts());
685 if (Before.isValid() &&
686 !Lexer::getRawToken(Before, Tok, SourceMgr, AST.getLangOpts(),
false) &&
687 Tok.is(tok::raw_identifier))
688 return SourceMgr.getMacroArgExpandedLocation(Before);
689 return SourceMgr.getMacroArgExpandedLocation(InputLoc);
695 #define LINK_TIDY_MODULE(X) \ 696 extern volatile int X##ModuleAnchorSource; \ 697 static int LLVM_ATTRIBUTE_UNUSED X##ModuleAnchorDestination = \ 698 X##ModuleAnchorSource 716 #undef LINK_TIDY_MODULE std::unique_ptr< CommentHandler > collectIWYUHeaderMaps(CanonicalIncludes *Includes)
Returns a CommentHandler that parses pragma comment on include files to determine when we should incl...
SourceLocation Loc
'#' location in the include directive
bool ShouldSuppressDiagnostic(DiagnosticsEngine::Level DiagLevel, const Diagnostic &Info, ClangTidyContext &Context, bool CheckMacroExpansion)
Check whether a given diagnostic should be suppressed due to the presence of a "NOLINT" suppression c...
StoreDiags collects the diagnostics that can later be reported by clangd.
ParsedAST & operator=(ParsedAST &&Other)
Preprocessor & getPreprocessor()
llvm::IntrusiveRefCntPtr< llvm::vfs::FileSystem > VFS
void dumpAST(ParsedAST &AST, llvm::raw_ostream &OS)
For testing/debugging purposes.
static llvm::Optional< ParsedAST > build(std::unique_ptr< clang::CompilerInvocation > CI, std::shared_ptr< const PreambleData > Preamble, std::unique_ptr< llvm::MemoryBuffer > Buffer, IntrusiveRefCntPtr< llvm::vfs::FileSystem > VFS, const SymbolIndex *Index, const ParseOptions &Opts)
Attempts to run Clang and store parsed AST.
void contributeFixes(DiagFixer Fixer)
If set, possibly adds fixes for diagnostics using Fixer.
Interface for symbol indexes that can be used for searching or matching symbols among a set of symbol...
bool isInsideMainFile(SourceLocation Loc, const SourceManager &SM)
Returns true iff Loc is inside the main file.
bool SuggestMissingIncludes
llvm::StringRef PathRef
A typedef to represent a ref to file path.
ArrayRef< Decl * > getLocalTopLevelDecls()
This function returns top-level decls present in the main file of the AST.
void addSystemHeadersMapping(CanonicalIncludes *Includes, const LangOptions &Language)
Adds mapping for system headers and some special symbols (e.g.
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)
Documents should not be synced at all.
tidy::ClangTidyOptions ClangTidyOpts
A collection of ClangTidyCheckFactory instances.
void vlog(const char *Fmt, Ts &&... Vals)
void elog(const char *Fmt, Ts &&... Vals)
ASTContext & getASTContext()
Note that the returned ast will not contain decls from the preamble that were not deserialized during...
std::size_t getUsedBytes() const
Returns the esitmated size of the AST and the accessory structures, in bytes.
SourceLocation getBeginningOfIdentifier(const ParsedAST &Unit, const Position &Pos, const FileID FID)
Get the beginning SourceLocation at a specified Pos.
std::shared_ptr< const PreambleData > buildPreamble(PathRef FileName, CompilerInvocation &CI, std::shared_ptr< const PreambleData > OldPreamble, const tooling::CompileCommand &OldCompileCommand, const ParseInputs &Inputs, bool StoreInMemory, PreambleParsedCallback PreambleCallback)
Rebuild the preamble for the new inputs unless the old one can be reused.
Maps a definition location onto an #include file, based on a set of filename rules.
const CanonicalIncludes & getCanonicalIncludes() const
CanonicalIncludes CanonIncludes
const IncludeStructure & getIncludeStructure() const
std::unique_ptr< PreambleFileStatusCache > StatCache
#define LINK_TIDY_MODULE(X)
llvm::Expected< size_t > positionToOffset(llvm::StringRef Code, Position P, bool AllowColumnsBeyondLineLength)
Turn a [line, column] pair into an offset in Code.
llvm::unique_function< void()> Action
void createChecks(ClangTidyContext *Context, std::vector< std::unique_ptr< ClangTidyCheck >> &Checks)
Create instances of all checks matching CheckRegexString and store them in Checks.
std::string configurationAsText(const ClangTidyOptions &Options)
Serializes configuration to a YAML-encoded string.
void log(const char *Fmt, Ts &&... Vals)
static const char * toString(OffsetEncoding OE)
std::shared_ptr< Preprocessor > getPreprocessorPtr()
llvm::Optional< ParsedAST > buildAST(PathRef FileName, std::unique_ptr< CompilerInvocation > Invocation, const ParseInputs &Inputs, std::shared_ptr< const PreambleData > Preamble)
Build an AST from provided user inputs.
format::FormatStyle getFormatStyleForFile(llvm::StringRef File, llvm::StringRef Content, llvm::vfs::FileSystem *FS)
Choose the clang-format style we should apply to a certain file.
Stores and provides access to parsed AST.
std::function< void(ASTContext &, std::shared_ptr< clang::Preprocessor >, const CanonicalIncludes &)> PreambleParsedCallback
const PreambleData * Preamble
std::unique_ptr< PPCallbacks > collectIncludeStructureCallback(const SourceManager &SM, IncludeStructure *Out)
Returns a PPCallback that visits all inclusions in the main file.
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
static GeneratorRegistry::Add< MDGenerator > MD(MDGenerator::Format, "Generator for MD output.")
void EndSourceFile() override
std::vector< Diag > Diags
PrecompiledPreamble Preamble
IncludeStructure Includes
void setLevelAdjuster(LevelAdjuster Adjuster)
If set, this allows the client of this class to adjust the level of diagnostics, such as promoting wa...
Records an event whose duration is the lifetime of the Span object.
PreambleData(PrecompiledPreamble Preamble, std::vector< Diag > Diags, IncludeStructure Includes, std::vector< std::string > MainFileMacros, std::unique_ptr< PreambleFileStatusCache > StatCache, CanonicalIncludes CanonIncludes)
#define SPAN_ATTACH(S, Name, Expr)
Attach a key-value pair to a Span event.
ParsedAST(ParsedAST &&Other)
std::vector< Diag > take(const clang::tidy::ClangTidyContext *Tidy=nullptr)
const std::vector< Diag > & getDiagnostics() const
const SymbolIndex * Index