clang-tools 23.0.0git
ParsedAST.cpp
Go to the documentation of this file.
1//===--- ParsedAST.cpp -------------------------------------------*- C++-*-===//
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 "ParsedAST.h"
14#include "AST.h"
15#include "CollectMacros.h"
16#include "Compiler.h"
17#include "Config.h"
18#include "Diagnostics.h"
19#include "Feature.h"
20#include "FeatureModule.h"
21#include "Headers.h"
22#include "IncludeCleaner.h"
23#include "IncludeFixer.h"
24#include "Preamble.h"
25#include "SourceCode.h"
26#include "TidyProvider.h"
27#include "clang-include-cleaner/Record.h"
28#include "index/Symbol.h"
29#include "support/Logger.h"
30#include "support/Path.h"
31#include "support/Trace.h"
32#include "clang/AST/ASTContext.h"
33#include "clang/AST/Decl.h"
34#include "clang/AST/DeclGroup.h"
35#include "clang/AST/ExternalASTSource.h"
36#include "clang/ASTMatchers/ASTMatchFinder.h"
37#include "clang/Basic/Diagnostic.h"
38#include "clang/Basic/DiagnosticIDs.h"
39#include "clang/Basic/DiagnosticSema.h"
40#include "clang/Basic/FileEntry.h"
41#include "clang/Basic/LLVM.h"
42#include "clang/Basic/LangOptions.h"
43#include "clang/Basic/SourceLocation.h"
44#include "clang/Basic/SourceManager.h"
45#include "clang/Basic/TokenKinds.h"
46#include "clang/Frontend/CompilerInstance.h"
47#include "clang/Frontend/CompilerInvocation.h"
48#include "clang/Frontend/FrontendActions.h"
49#include "clang/Frontend/FrontendOptions.h"
50#include "clang/Frontend/PrecompiledPreamble.h"
51#include "clang/Lex/Lexer.h"
52#include "clang/Lex/PPCallbacks.h"
53#include "clang/Lex/Preprocessor.h"
54#include "clang/Sema/HeuristicResolver.h"
55#include "clang/Serialization/ASTWriter.h"
56#include "clang/Tooling/CompilationDatabase.h"
57#include "clang/Tooling/Core/Diagnostic.h"
58#include "clang/Tooling/Syntax/Tokens.h"
59#include "llvm/ADT/ArrayRef.h"
60#include "llvm/ADT/DenseMap.h"
61#include "llvm/ADT/DenseSet.h"
62#include "llvm/ADT/STLExtras.h"
63#include "llvm/ADT/STLFunctionalExtras.h"
64#include "llvm/ADT/SmallVector.h"
65#include "llvm/ADT/StringRef.h"
66#include "llvm/Support/Error.h"
67#include "llvm/Support/MemoryBuffer.h"
68#include <cassert>
69#include <cstddef>
70#include <iterator>
71#include <memory>
72#include <optional>
73#include <string>
74#include <tuple>
75#include <utility>
76#include <vector>
77
78// Force the linker to link in Clang-tidy modules.
79// clangd doesn't support the static analyzer.
80#if CLANGD_TIDY_CHECKS
81#define CLANG_TIDY_DISABLE_STATIC_ANALYZER_CHECKS
83#endif
84
85namespace clang {
86namespace clangd {
87namespace {
88
89template <class T> std::size_t getUsedBytes(const std::vector<T> &Vec) {
90 return Vec.capacity() * sizeof(T);
91}
92
93class DeclTrackingASTConsumer : public ASTConsumer {
94public:
95 DeclTrackingASTConsumer(std::vector<Decl *> &TopLevelDecls)
96 : TopLevelDecls(TopLevelDecls) {}
97
98 bool HandleTopLevelDecl(DeclGroupRef DG) override {
99 for (Decl *D : DG) {
100 auto &SM = D->getASTContext().getSourceManager();
101 if (!isInsideMainFile(D->getLocation(), SM))
102 continue;
103 if (const NamedDecl *ND = dyn_cast<NamedDecl>(D))
105 continue;
106
107 // ObjCMethodDecl are not actually top-level decls.
108 if (isa<ObjCMethodDecl>(D))
109 continue;
110
111 TopLevelDecls.push_back(D);
112 }
113 return true;
114 }
115
116private:
117 std::vector<Decl *> &TopLevelDecls;
118};
119
120class ClangdFrontendAction : public SyntaxOnlyAction {
121public:
122 std::vector<Decl *> takeTopLevelDecls() { return std::move(TopLevelDecls); }
123
124protected:
125 std::unique_ptr<ASTConsumer>
126 CreateASTConsumer(CompilerInstance &CI, llvm::StringRef InFile) override {
127 return std::make_unique<DeclTrackingASTConsumer>(/*ref*/ TopLevelDecls);
128 }
129
130private:
131 std::vector<Decl *> TopLevelDecls;
132};
133
134// When using a preamble, only preprocessor events outside its bounds are seen.
135// This is almost what we want: replaying transitive preprocessing wastes time.
136// However this confuses clang-tidy checks: they don't see any #includes!
137// So we replay the *non-transitive* #includes that appear in the main-file.
138// It would be nice to replay other events (macro definitions, ifdefs etc) but
139// this addresses the most common cases fairly cheaply.
140class ReplayPreamble : private PPCallbacks {
141public:
142 // Attach preprocessor hooks such that preamble events will be injected at
143 // the appropriate time.
144 // Events will be delivered to the *currently registered* PP callbacks.
145 static void attach(std::vector<Inclusion> Includes,
146 const MainFileMacros Macros, CompilerInstance &Clang,
147 const PreambleBounds &PB) {
148 auto &PP = Clang.getPreprocessor();
149 auto *ExistingCallbacks = PP.getPPCallbacks();
150 // No need to replay events if nobody is listening.
151 if (!ExistingCallbacks)
152 return;
153 PP.addPPCallbacks(std::unique_ptr<PPCallbacks>(new ReplayPreamble(
154 std::move(Includes), std::move(Macros), ExistingCallbacks,
155 Clang.getSourceManager(), PP, Clang.getLangOpts(), PB)));
156 // We're relying on the fact that addPPCallbacks keeps the old PPCallbacks
157 // around, creating a chaining wrapper. Guard against other implementations.
158 assert(PP.getPPCallbacks() != ExistingCallbacks &&
159 "Expected chaining implementation");
160 }
161
162private:
163 ReplayPreamble(std::vector<Inclusion> Includes, MainFileMacros Macros,
164 PPCallbacks *Delegate, const SourceManager &SM,
165 Preprocessor &PP, const LangOptions &LangOpts,
166 const PreambleBounds &PB)
167 : Includes(std::move(Includes)), Macros(std::move(Macros)),
168 Delegate(Delegate), SM(SM), PP(PP) {
169 // Only tokenize the preamble section of the main file, as we are not
170 // interested in the rest of the tokens.
171 MainFileTokens = syntax::tokenize(
172 syntax::FileRange(SM.getMainFileID(), 0, PB.Size), SM, LangOpts);
173 }
174
175 // In a normal compile, the preamble traverses the following structure:
176 //
177 // mainfile.cpp
178 // <built-in>
179 // ... macro definitions like __cplusplus ...
180 // <command-line>
181 // ... macro definitions for args like -Dfoo=bar ...
182 // "header1.h"
183 // ... header file contents ...
184 // "header2.h"
185 // ... header file contents ...
186 // ... main file contents ...
187 //
188 // When using a preamble, the "header1" and "header2" subtrees get skipped.
189 // We insert them right after the built-in header, which still appears.
190 void FileChanged(SourceLocation Loc, FileChangeReason Reason,
191 SrcMgr::CharacteristicKind Kind, FileID PrevFID) override {
192 // It'd be nice if there was a better way to identify built-in headers...
193 if (Reason == FileChangeReason::ExitFile &&
194 SM.getBufferOrFake(PrevFID).getBufferIdentifier() == "<built-in>")
195 replay();
196 }
197
198 void replay() {
199 // Replay macro definitions from the preamble region of the main file,
200 // so that clang-tidy checks can observe them.
201 for (const auto &[SID, Refs] : Macros.MacroRefs) {
202 for (const auto &Ref : Refs) {
203 if (!Ref.IsDefinition)
204 continue;
205 auto Loc = SM.getComposedLoc(SM.getMainFileID(), Ref.StartOffset);
206 Token Tok;
207 if (Lexer::getRawToken(Loc, Tok, SM, PP.getLangOpts(), false))
208 continue;
209 if (auto *II = PP.getIdentifierInfo(Tok.getRawIdentifier())) {
210 Tok.setIdentifierInfo(II);
211 Tok.setKind(tok::identifier);
212 if (auto *MD = PP.getLocalMacroDirective(II))
213 Delegate->MacroDefined(Tok, MD);
214 }
215 }
216 }
217 for (const auto &Inc : Includes) {
218 OptionalFileEntryRef File;
219 if (Inc.Resolved != "")
220 File = expectedToOptional(SM.getFileManager().getFileRef(Inc.Resolved));
221
222 // Re-lex the #include directive to find its interesting parts.
223 auto HashLoc = SM.getComposedLoc(SM.getMainFileID(), Inc.HashOffset);
224 auto HashTok = llvm::partition_point(MainFileTokens,
225 [&HashLoc](const syntax::Token &T) {
226 return T.location() < HashLoc;
227 });
228 assert(HashTok != MainFileTokens.end() && HashTok->kind() == tok::hash);
229
230 auto IncludeTok = std::next(HashTok);
231 assert(IncludeTok != MainFileTokens.end());
232
233 auto FileTok = std::next(IncludeTok);
234 assert(FileTok != MainFileTokens.end());
235
236 // Create a fake import/include token, none of the callers seem to care
237 // about clang::Token::Flags.
238 Token SynthesizedIncludeTok;
239 SynthesizedIncludeTok.startToken();
240 SynthesizedIncludeTok.setLocation(IncludeTok->location());
241 SynthesizedIncludeTok.setLength(IncludeTok->length());
242 SynthesizedIncludeTok.setKind(tok::raw_identifier);
243 SynthesizedIncludeTok.setRawIdentifierData(IncludeTok->text(SM).data());
244 PP.LookUpIdentifierInfo(SynthesizedIncludeTok);
245
246 // Same here, create a fake one for Filename, including angles or quotes.
247 Token SynthesizedFilenameTok;
248 SynthesizedFilenameTok.startToken();
249 SynthesizedFilenameTok.setLocation(FileTok->location());
250 // Note that we can't make use of FileTok->length/text in here as in the
251 // case of angled includes this will contain tok::less instead of
252 // filename. Whereas Inc.Written contains the full header name including
253 // quotes/angles.
254 SynthesizedFilenameTok.setLength(Inc.Written.length());
255 SynthesizedFilenameTok.setKind(tok::header_name);
256 SynthesizedFilenameTok.setLiteralData(Inc.Written.data());
257
258 llvm::StringRef WrittenFilename =
259 llvm::StringRef(Inc.Written).drop_front().drop_back();
260 Delegate->InclusionDirective(
261 HashTok->location(), SynthesizedIncludeTok, WrittenFilename,
262 Inc.Written.front() == '<',
263 syntax::FileRange(SM, SynthesizedFilenameTok.getLocation(),
264 SynthesizedFilenameTok.getEndLoc())
265 .toCharRange(SM),
266 File, "SearchPath", "RelPath",
267 /*SuggestedModule=*/nullptr, /*ModuleImported=*/false, Inc.FileKind);
268 if (File)
269 Delegate->FileSkipped(*File, SynthesizedFilenameTok, Inc.FileKind);
270 }
271 }
272
273 const std::vector<Inclusion> Includes;
274 const MainFileMacros Macros;
275 PPCallbacks *Delegate;
276 const SourceManager &SM;
277 Preprocessor &PP;
278 std::vector<syntax::Token> MainFileTokens;
279};
280
281// Filter for clang diagnostics groups enabled by CTOptions.Checks.
282//
283// These are check names like clang-diagnostics-unused.
284// Note that unlike -Wunused, clang-diagnostics-unused does not imply
285// subcategories like clang-diagnostics-unused-function.
286//
287// This is used to determine which diagnostics can be enabled by ExtraArgs in
288// the clang-tidy configuration.
289class TidyDiagnosticGroups {
290 // Whether all diagnostic groups are enabled by default.
291 // True if we've seen clang-diagnostic-*.
292 bool Default = false;
293 // Set of diag::Group whose enablement != Default.
294 // If Default is false, this is foo where we've seen clang-diagnostic-foo.
295 llvm::DenseSet<unsigned> Exceptions;
296
297public:
298 TidyDiagnosticGroups(llvm::StringRef Checks) {
299 constexpr llvm::StringLiteral CDPrefix = "clang-diagnostic-";
300
301 llvm::StringRef Check;
302 while (!Checks.empty()) {
303 std::tie(Check, Checks) = Checks.split(',');
304 Check = Check.trim();
305
306 if (Check.empty())
307 continue;
308
309 bool Enable = !Check.consume_front("-");
310 bool Glob = Check.consume_back("*");
311 if (Glob) {
312 // Is this clang-diagnostic-*, or *, or so?
313 // (We ignore all other types of globs).
314 if (CDPrefix.starts_with(Check)) {
315 Default = Enable;
316 Exceptions.clear();
317 }
318 continue;
319 }
320
321 // In "*,clang-diagnostic-foo", the latter is a no-op.
322 if (Default == Enable)
323 continue;
324 // The only non-glob entries we care about are clang-diagnostic-foo.
325 if (!Check.consume_front(CDPrefix))
326 continue;
327
328 if (auto Group = DiagnosticIDs::getGroupForWarningOption(Check))
329 Exceptions.insert(static_cast<unsigned>(*Group));
330 }
331 }
332
333 bool operator()(diag::Group GroupID) const {
334 return Exceptions.contains(static_cast<unsigned>(GroupID)) ? !Default
335 : Default;
336 }
337};
338
339// Find -W<group> and -Wno-<group> options in ExtraArgs and apply them to Diags.
340//
341// This is used to handle ExtraArgs in clang-tidy configuration.
342// We don't use clang's standard handling of this as we want slightly different
343// behavior (e.g. we want to exclude these from -Wno-error).
344void applyWarningOptions(llvm::ArrayRef<std::string> ExtraArgs,
345 llvm::function_ref<bool(diag::Group)> EnabledGroups,
346 DiagnosticsEngine &Diags) {
347 for (llvm::StringRef Group : ExtraArgs) {
348 // Only handle args that are of the form -W[no-]<group>.
349 // Other flags are possible but rare and deliberately out of scope.
350 llvm::SmallVector<diag::kind> Members;
351 if (!Group.consume_front("-W") || Group.empty())
352 continue;
353 bool Enable = !Group.consume_front("no-");
354 if (Diags.getDiagnosticIDs()->getDiagnosticsInGroup(
355 diag::Flavor::WarningOrError, Group, Members))
356 continue;
357
358 // Upgrade (or downgrade) the severity of each diagnostic in the group.
359 // If -Werror is on, newly added warnings will be treated as errors.
360 // We don't want this, so keep track of them to fix afterwards.
361 bool NeedsWerrorExclusion = false;
362 for (diag::kind ID : Members) {
363 if (Enable) {
364 if (Diags.getDiagnosticLevel(ID, SourceLocation()) <
365 DiagnosticsEngine::Warning) {
366 auto Group = Diags.getDiagnosticIDs()->getGroupForDiag(ID);
367 if (!Group || !EnabledGroups(*Group))
368 continue;
369 Diags.setSeverity(ID, diag::Severity::Warning, SourceLocation());
370 if (Diags.getWarningsAsErrors())
371 NeedsWerrorExclusion = true;
372 }
373 } else {
374 Diags.setSeverity(ID, diag::Severity::Ignored, SourceLocation());
375 }
376 }
377 if (NeedsWerrorExclusion) {
378 // FIXME: there's no API to suppress -Werror for single diagnostics.
379 // In some cases with sub-groups, we may end up erroneously
380 // downgrading diagnostics that were -Werror in the compile command.
381 Diags.setDiagnosticGroupWarningAsError(Group, false);
382 }
383 }
384}
385
386std::vector<Diag> getIncludeCleanerDiags(ParsedAST &AST, llvm::StringRef Code,
387 const ThreadsafeFS &TFS) {
388 auto &Cfg = Config::current();
389 if (Cfg.Diagnostics.SuppressAll)
390 return {};
391 bool SuppressMissing =
392 Cfg.Diagnostics.Suppress.contains("missing-includes") ||
393 Cfg.Diagnostics.MissingIncludes == Config::IncludesPolicy::None;
394 bool SuppressUnused =
395 Cfg.Diagnostics.Suppress.contains("unused-includes") ||
396 Cfg.Diagnostics.UnusedIncludes == Config::IncludesPolicy::None;
397 if (SuppressMissing && SuppressUnused)
398 return {};
399 auto Findings = computeIncludeCleanerFindings(
400 AST, Cfg.Diagnostics.Includes.AnalyzeAngledIncludes);
401 if (SuppressMissing)
402 Findings.MissingIncludes.clear();
403 if (SuppressUnused)
404 Findings.UnusedIncludes.clear();
406 AST, Code, Findings, TFS, Cfg.Diagnostics.Includes.IgnoreHeader,
407 Cfg.Style.AngledHeaders, Cfg.Style.QuotedHeaders);
408}
409
410tidy::ClangTidyCheckFactories
411filterFastTidyChecks(const tidy::ClangTidyCheckFactories &All,
413 if (Policy == Config::FastCheckPolicy::None)
414 return All;
415 bool AllowUnknown = Policy == Config::FastCheckPolicy::Loose;
416 tidy::ClangTidyCheckFactories Fast;
417 for (const auto &Factory : All) {
418 if (isFastTidyCheck(Factory.getKey()).value_or(AllowUnknown))
419 Fast.registerCheckFactory(Factory.first(), Factory.second);
420 }
421 return Fast;
422}
423
424} // namespace
425
426std::optional<ParsedAST>
427ParsedAST::build(llvm::StringRef Filename, const ParseInputs &Inputs,
428 std::unique_ptr<clang::CompilerInvocation> CI,
429 llvm::ArrayRef<Diag> CompilerInvocationDiags,
430 std::shared_ptr<const PreambleData> Preamble) {
431 trace::Span Tracer("BuildAST");
432 SPAN_ATTACH(Tracer, "File", Filename);
433 const Config &Cfg = Config::current();
434
435 auto VFS = Inputs.TFS->view(Inputs.CompileCommand.Directory);
436 if (Preamble && Preamble->StatCache)
437 VFS = Preamble->StatCache->getConsumingFS(std::move(VFS));
438
439 assert(CI);
440
441 if (CI->getFrontendOpts().Inputs.size() > 0) {
442 auto Lang = CI->getFrontendOpts().Inputs[0].getKind().getLanguage();
443 if (Lang == Language::Asm || Lang == Language::LLVM_IR) {
444 elog("Clangd does not support assembly or IR source files");
445 return std::nullopt;
446 }
447 }
448
449 // Command-line parsing sets DisableFree to true by default, but we don't want
450 // to leak memory in clangd.
451 CI->getFrontendOpts().DisableFree = false;
452 const PrecompiledPreamble *PreamblePCH =
453 Preamble ? &Preamble->Preamble : nullptr;
454
455 // This is on-by-default in windows to allow parsing SDK headers, but it
456 // breaks many features. Disable it for the main-file (not preamble).
457 CI->getLangOpts().DelayedTemplateParsing = false;
458
459 std::vector<std::unique_ptr<FeatureModule::ASTListener>> ASTListeners;
460 if (Inputs.FeatureModules) {
461 for (auto &M : *Inputs.FeatureModules) {
462 if (auto Listener = M.astListeners())
463 ASTListeners.emplace_back(std::move(Listener));
464 }
465 }
466 StoreDiags ASTDiags;
467 ASTDiags.setDiagCallback(
468 [&ASTListeners](const clang::Diagnostic &D, clangd::Diag &Diag) {
469 for (const auto &L : ASTListeners)
470 L->sawDiagnostic(D, Diag);
471 });
472
473 // Adjust header search options to load the built module files recorded
474 // in RequiredModules.
475 if (Preamble && Preamble->RequiredModules)
476 Preamble->RequiredModules->adjustHeaderSearchOptions(
477 CI->getHeaderSearchOpts());
478
479 std::optional<PreamblePatch> Patch;
480 // We might use an ignoring diagnostic consumer if they are going to be
481 // dropped later on to not pay for extra latency by processing them.
482 DiagnosticConsumer *DiagConsumer = &ASTDiags;
483 IgnoreDiagnostics DropDiags;
484 if (Preamble) {
485 Patch = PreamblePatch::createFullPatch(Filename, Inputs, *Preamble);
486 Patch->apply(*CI);
487 }
488 auto Clang = prepareCompilerInstance(
489 std::move(CI), Inputs.Opts.SkipPreambleBuild ? nullptr : PreamblePCH,
490 llvm::MemoryBuffer::getMemBufferCopy(Inputs.Contents, Filename), VFS,
491 *DiagConsumer);
492
493 if (!Clang) {
494 // The last diagnostic contains information about the reason of this
495 // failure.
496 std::vector<Diag> Diags(ASTDiags.take());
497 elog("Failed to prepare a compiler instance: {0}",
498 !Diags.empty() ? static_cast<DiagBase &>(Diags.back()).Message
499 : "unknown error");
500 return std::nullopt;
501 }
502 tidy::ClangTidyOptions ClangTidyOpts;
503 {
504 trace::Span Tracer("ClangTidyOpts");
505 ClangTidyOpts = getTidyOptionsForFile(Inputs.ClangTidyProvider, Filename);
506 dlog("ClangTidy configuration for file {0}: {1}", Filename,
507 tidy::configurationAsText(ClangTidyOpts));
508
509 // If clang-tidy is configured to emit clang warnings, we should too.
510 //
511 // Such clang-tidy configuration consists of two parts:
512 // - ExtraArgs: ["-Wfoo"] causes clang to produce the warnings
513 // - Checks: "clang-diagnostic-foo" prevents clang-tidy filtering them out
514 //
515 // In clang-tidy, diagnostics are emitted if they pass both checks.
516 // When groups contain subgroups, -Wparent includes the child, but
517 // clang-diagnostic-parent does not.
518 //
519 // We *don't* want to change the compile command directly. This can have
520 // too many unexpected effects: breaking the command, interactions with
521 // -- and -Werror, etc. Besides, we've already parsed the command.
522 // Instead we parse the -W<group> flags and handle them directly.
523 //
524 // Similarly, we don't want to use Checks to filter clang diagnostics after
525 // they are generated, as this spreads clang-tidy emulation everywhere.
526 // Instead, we just use these to filter which extra diagnostics we enable.
527 auto &Diags = Clang->getDiagnostics();
528 TidyDiagnosticGroups TidyGroups(ClangTidyOpts.Checks ? *ClangTidyOpts.Checks
529 : llvm::StringRef());
530 if (ClangTidyOpts.ExtraArgsBefore)
531 applyWarningOptions(*ClangTidyOpts.ExtraArgsBefore, TidyGroups, Diags);
532 if (ClangTidyOpts.ExtraArgs)
533 applyWarningOptions(*ClangTidyOpts.ExtraArgs, TidyGroups, Diags);
534 }
535
536 auto Action = std::make_unique<ClangdFrontendAction>();
537 const FrontendInputFile &MainInput = Clang->getFrontendOpts().Inputs[0];
538 if (!Action->BeginSourceFile(*Clang, MainInput)) {
539 elog("BeginSourceFile() failed when building AST for {0}",
540 MainInput.getFile());
541 return std::nullopt;
542 }
543 // If we saw an include guard in the preamble section of the main file,
544 // mark the main-file as include-guarded.
545 // This information is part of the HeaderFileInfo but is not loaded from the
546 // preamble as the file's size is part of its identity and may have changed.
547 // (The rest of HeaderFileInfo is not relevant for our purposes).
548 if (Preamble && Preamble->MainIsIncludeGuarded) {
549 const SourceManager &SM = Clang->getSourceManager();
550 OptionalFileEntryRef MainFE = SM.getFileEntryRefForID(SM.getMainFileID());
551 Clang->getPreprocessor().getHeaderSearchInfo().MarkFileIncludeOnce(*MainFE);
552 }
553
554 // Set up ClangTidy. Must happen after BeginSourceFile() so ASTContext exists.
555 // Clang-tidy has some limitations to ensure reasonable performance:
556 // - checks don't see all preprocessor events in the preamble
557 // - matchers run only over the main-file top-level decls (and can't see
558 // ancestors outside this scope).
559 // In practice almost all checks work well without modifications.
560 std::vector<std::unique_ptr<tidy::ClangTidyCheck>> CTChecks;
561 ast_matchers::MatchFinder CTFinder;
562 std::optional<tidy::ClangTidyContext> CTContext;
563 // Must outlive FixIncludes.
564 auto BuildDir = VFS->getCurrentWorkingDirectory();
565 std::optional<IncludeFixer> FixIncludes;
566 llvm::DenseMap<diag::kind, DiagnosticsEngine::Level> OverriddenSeverity;
567 // No need to run clang-tidy or IncludeFixerif we are not going to surface
568 // diagnostics.
569 {
570 trace::Span Tracer("ClangTidyInit");
571 static const auto *AllCTFactories = [] {
572 auto *CTFactories = new tidy::ClangTidyCheckFactories;
573 for (const auto &E : tidy::ClangTidyModuleRegistry::entries())
574 E.instantiate()->addCheckFactories(*CTFactories);
575 return CTFactories;
576 }();
577 tidy::ClangTidyCheckFactories FastFactories = filterFastTidyChecks(
578 *AllCTFactories, Cfg.Diagnostics.ClangTidy.FastCheckFilter);
579 CTContext.emplace(std::make_unique<tidy::DefaultOptionsProvider>(
580 tidy::ClangTidyGlobalOptions(), ClangTidyOpts));
581 // The lifetime of DiagnosticOptions is managed by \c Clang.
582 CTContext->setDiagnosticsEngine(nullptr, &Clang->getDiagnostics());
583 CTContext->setASTContext(&Clang->getASTContext());
584 CTContext->setCurrentFile(Filename);
585 CTContext->setSelfContainedDiags(true);
586 CTChecks = FastFactories.createChecksForLanguage(&*CTContext);
587 Preprocessor *PP = &Clang->getPreprocessor();
588 for (const auto &Check : CTChecks) {
589 Check->registerPPCallbacks(Clang->getSourceManager(), PP, PP);
590 Check->registerMatchers(&CTFinder);
591 }
592
593 // Clang only corrects typos for use of undeclared functions in C if that
594 // use is an error. Include fixer relies on typo correction, so pretend
595 // this is an error. (The actual typo correction is nice too).
596 // We restore the original severity in the level adjuster.
597 // FIXME: It would be better to have a real API for this, but what?
598 for (auto ID : {diag::ext_implicit_function_decl_c99,
599 diag::ext_implicit_lib_function_decl,
600 diag::ext_implicit_lib_function_decl_c99,
601 diag::warn_implicit_function_decl}) {
602 OverriddenSeverity.try_emplace(
603 ID, Clang->getDiagnostics().getDiagnosticLevel(ID, SourceLocation()));
604 Clang->getDiagnostics().setSeverity(ID, diag::Severity::Error,
605 SourceLocation());
606 }
607
608 ASTDiags.setLevelAdjuster([&](DiagnosticsEngine::Level DiagLevel,
609 const clang::Diagnostic &Info) {
610 auto It = OverriddenSeverity.find(Info.getID());
611 if (It != OverriddenSeverity.end())
612 DiagLevel = It->second;
613
614 if (!CTChecks.empty()) {
615 std::string CheckName = CTContext->getCheckName(Info.getID());
616 bool IsClangTidyDiag = !CheckName.empty();
617 if (IsClangTidyDiag) {
618 if (Cfg.Diagnostics.Suppress.contains(CheckName))
619 return DiagnosticsEngine::Ignored;
620 // Check for suppression comment. Skip the check for diagnostics not
621 // in the main file, because we don't want that function to query the
622 // source buffer for preamble files. For the same reason, we ask
623 // shouldSuppressDiagnostic to avoid I/O.
624 // We let suppression comments take precedence over warning-as-error
625 // to match clang-tidy's behaviour.
626 bool IsInsideMainFile =
627 Info.hasSourceManager() &&
628 isInsideMainFile(Info.getLocation(), Info.getSourceManager());
629 SmallVector<tooling::Diagnostic, 1> TidySuppressedErrors;
630 if (IsInsideMainFile && CTContext->shouldSuppressDiagnostic(
631 DiagLevel, Info, TidySuppressedErrors,
632 /*AllowIO=*/false,
633 /*EnableNolintBlocks=*/true)) {
634 // FIXME: should we expose the suppression error (invalid use of
635 // NOLINT comments)?
636 return DiagnosticsEngine::Ignored;
637 }
638 if (!CTContext->getOptions().SystemHeaders.value_or(false) &&
639 Info.hasSourceManager() &&
640 Info.getSourceManager().isInSystemMacro(Info.getLocation()))
641 return DiagnosticsEngine::Ignored;
642
643 // Check for warning-as-error.
644 if (DiagLevel == DiagnosticsEngine::Warning &&
645 CTContext->treatAsError(CheckName)) {
646 return DiagnosticsEngine::Error;
647 }
648 }
649 }
650 return DiagLevel;
651 });
652
653 // Add IncludeFixer which can recover diagnostics caused by missing includes
654 // (e.g. incomplete type) and attach include insertion fixes to diagnostics.
655 if (Inputs.Index && !BuildDir.getError()) {
656 auto Style =
657 getFormatStyleForFile(Filename, Inputs.Contents, *Inputs.TFS, false);
658 auto Inserter = std::make_shared<IncludeInserter>(
659 Filename, Inputs.Contents, Style, BuildDir.get(),
660 &Clang->getPreprocessor().getHeaderSearchInfo(),
662 ArrayRef<Inclusion> MainFileIncludes;
663 if (Preamble) {
664 MainFileIncludes = Preamble->Includes.MainFileIncludes;
665 for (const auto &Inc : Preamble->Includes.MainFileIncludes)
666 Inserter->addExisting(Inc);
667 }
668 // FIXME: Consider piping through ASTSignals to fetch this to handle the
669 // case where a header file contains ObjC decls but no #imports.
670 Symbol::IncludeDirective Directive =
672 ? preferredIncludeDirective(Filename, Clang->getLangOpts(),
673 MainFileIncludes, {})
675 FixIncludes.emplace(Filename, Inserter, *Inputs.Index,
676 /*IndexRequestLimit=*/5, Directive);
677 ASTDiags.contributeFixes([&FixIncludes](DiagnosticsEngine::Level DiagLevl,
678 const clang::Diagnostic &Info) {
679 return FixIncludes->fix(DiagLevl, Info);
680 });
681 Clang->setExternalSemaSource(FixIncludes->unresolvedNameRecorder());
682 }
683 }
684
685 IncludeStructure Includes;
686 include_cleaner::PragmaIncludes PI;
687 // If we are using a preamble, copy existing includes.
688 if (Preamble) {
689 Includes = Preamble->Includes;
690 Includes.MainFileIncludes = Patch->preambleIncludes();
691 // Replay the preamble includes so that clang-tidy checks can see them.
692 ReplayPreamble::attach(Patch->preambleIncludes(), Patch->mainFileMacros(),
693 *Clang, Patch->modifiedBounds());
694 PI = *Preamble->Pragmas;
695 }
696 // Important: collectIncludeStructure is registered *after* ReplayPreamble!
697 // Otherwise we would collect the replayed includes again...
698 // (We can't *just* use the replayed includes, they don't have Resolved path).
699 Includes.collect(*Clang);
700 // Same for pragma-includes, we're already inheriting preamble includes, so we
701 // should only receive callbacks for non-preamble mainfile includes.
702 PI.record(*Clang);
703 // Copy over the macros in the preamble region of the main file, and combine
704 // with non-preamble macros below.
705 MainFileMacros Macros;
706 std::vector<PragmaMark> Marks;
707 if (Preamble) {
708 Macros = Patch->mainFileMacros();
709 Marks = Patch->marks();
710 }
711 auto &PP = Clang->getPreprocessor();
712 auto MacroCollector = std::make_unique<CollectMainFileMacros>(PP, Macros);
713 auto *MacroCollectorPtr = MacroCollector.get(); // so we can call doneParse()
714 PP.addPPCallbacks(std::move(MacroCollector));
715
716 PP.addPPCallbacks(
717 collectPragmaMarksCallback(Clang->getSourceManager(), Marks));
718
719 // FIXME: Attach a comment handler to take care of
720 // keep/export/no_include etc. IWYU pragmas.
721
722 // Collect tokens of the main file.
723 syntax::TokenCollector CollectTokens(PP);
724
725 // To remain consistent with preamble builds, these callbacks must be called
726 // exactly here, after preprocessor is initialized and BeginSourceFile() was
727 // called already.
728 for (const auto &L : ASTListeners)
729 L->beforeExecute(*Clang);
730
731 if (llvm::Error Err = Action->Execute())
732 log("Execute() failed when building AST for {0}: {1}", MainInput.getFile(),
733 toString(std::move(Err)));
734
735 // Disable the macro collector for the remainder of this function, e.g.
736 // clang-tidy checkers.
737 MacroCollectorPtr->doneParse();
738
739 // We have to consume the tokens before running clang-tidy to avoid collecting
740 // tokens from running the preprocessor inside the checks (only
741 // modernize-use-trailing-return-type does that today).
742 syntax::TokenBuffer Tokens = std::move(CollectTokens).consume();
743 // Makes SelectionTree build much faster.
744 Tokens.indexExpandedTokens();
745 std::vector<Decl *> ParsedDecls = Action->takeTopLevelDecls();
746 // AST traversals should exclude the preamble, to avoid performance cliffs.
747 Clang->getASTContext().setTraversalScope(ParsedDecls);
748 if (!CTChecks.empty()) {
749 // Run the AST-dependent part of the clang-tidy checks.
750 // (The preprocessor part ran already, via PPCallbacks).
751 trace::Span Tracer("ClangTidyMatch");
752 CTFinder.matchAST(Clang->getASTContext());
753 }
754
755 // XXX: This is messy: clang-tidy checks flush some diagnostics at EOF.
756 // However Action->EndSourceFile() would destroy the ASTContext!
757 // So just inform the preprocessor of EOF, while keeping everything alive.
758 PP.EndSourceFile();
759 // UnitDiagsConsumer is local, we can not store it in CompilerInstance that
760 // has a longer lifetime.
761 Clang->getDiagnostics().setClient(new IgnoreDiagnostics);
762 // CompilerInstance won't run this callback, do it directly.
763 ASTDiags.EndSourceFile();
764
765 std::vector<Diag> Diags = CompilerInvocationDiags;
766 // FIXME: Also skip generation of diagnostics altogether to speed up ast
767 // builds when we are patching a stale preamble.
768 // Add diagnostics from the preamble, if any.
769 if (Preamble)
770 llvm::append_range(Diags, Patch->patchedDiags());
771 // Finally, add diagnostics coming from the AST.
772 {
773 std::vector<Diag> D = ASTDiags.take(&*CTContext);
774 Diags.insert(Diags.end(), D.begin(), D.end());
775 }
776 ParsedAST Result(Filename, Inputs.Version, std::move(Preamble),
777 std::move(Clang), std::move(Action), std::move(Tokens),
778 std::move(Macros), std::move(Marks), std::move(ParsedDecls),
779 std::move(Diags), std::move(Includes), std::move(PI));
780 llvm::move(getIncludeCleanerDiags(Result, Inputs.Contents, *Inputs.TFS),
781 std::back_inserter(Result.Diags));
782 return std::move(Result);
783}
784
785ParsedAST::ParsedAST(ParsedAST &&Other) = default;
786
787ParsedAST &ParsedAST::operator=(ParsedAST &&Other) = default;
788
790 if (Action) {
791 // We already notified the PP of end-of-file earlier, so detach it first.
792 // We must keep it alive until after EndSourceFile(), Sema relies on this.
793 auto PP = Clang->getPreprocessorPtr(); // Keep PP alive for now.
794 Clang->setPreprocessor(nullptr); // Detach so we don't send EOF again.
795 Action->EndSourceFile(); // Destroy ASTContext and Sema.
796 // Now Sema is gone, it's safe for PP to go out of scope.
797 }
798}
799
800ASTContext &ParsedAST::getASTContext() { return Clang->getASTContext(); }
801
802const ASTContext &ParsedAST::getASTContext() const {
803 return Clang->getASTContext();
804}
805
806Sema &ParsedAST::getSema() { return Clang->getSema(); }
807
808Preprocessor &ParsedAST::getPreprocessor() { return Clang->getPreprocessor(); }
809
810std::shared_ptr<Preprocessor> ParsedAST::getPreprocessorPtr() {
811 return Clang->getPreprocessorPtr();
812}
813
814const Preprocessor &ParsedAST::getPreprocessor() const {
815 return Clang->getPreprocessor();
816}
817
818llvm::ArrayRef<Decl *> ParsedAST::getLocalTopLevelDecls() {
819 return LocalTopLevelDecls;
820}
821
822llvm::ArrayRef<const Decl *> ParsedAST::getLocalTopLevelDecls() const {
823 return LocalTopLevelDecls;
824}
825
826const MainFileMacros &ParsedAST::getMacros() const { return Macros; }
827const std::vector<PragmaMark> &ParsedAST::getMarks() const { return Marks; }
828
829std::size_t ParsedAST::getUsedBytes() const {
830 auto &AST = getASTContext();
831 // FIXME(ibiryukov): we do not account for the dynamically allocated part of
832 // Message and Fixes inside each diagnostic.
833 std::size_t Total =
834 clangd::getUsedBytes(LocalTopLevelDecls) + clangd::getUsedBytes(Diags);
835
836 // FIXME: the rest of the function is almost a direct copy-paste from
837 // libclang's clang_getCXTUResourceUsage. We could share the implementation.
838
839 // Sum up various allocators inside the ast context and the preprocessor.
840 Total += AST.getASTAllocatedMemory();
841 Total += AST.getSideTableAllocatedMemory();
842 Total += AST.Idents.getAllocator().getTotalMemory();
843 Total += AST.Selectors.getTotalMemory();
844
845 Total += AST.getSourceManager().getContentCacheSize();
846 Total += AST.getSourceManager().getDataStructureSizes();
847 Total += AST.getSourceManager().getMemoryBufferSizes().malloc_bytes;
848
849 if (ExternalASTSource *Ext = AST.getExternalSource())
850 Total += Ext->getMemoryBufferSizes().malloc_bytes;
851
852 const Preprocessor &PP = getPreprocessor();
853 Total += PP.getTotalMemory();
854 if (PreprocessingRecord *PRec = PP.getPreprocessingRecord())
855 Total += PRec->getTotalMemory();
856 Total += PP.getHeaderSearchInfo().getTotalMemory();
857
858 return Total;
859}
860
862 return Includes;
863}
864
865ParsedAST::ParsedAST(PathRef TUPath, llvm::StringRef Version,
866 std::shared_ptr<const PreambleData> Preamble,
867 std::unique_ptr<CompilerInstance> Clang,
868 std::unique_ptr<FrontendAction> Action,
869 syntax::TokenBuffer Tokens, MainFileMacros Macros,
870 std::vector<PragmaMark> Marks,
871 std::vector<Decl *> LocalTopLevelDecls,
872 std::vector<Diag> Diags, IncludeStructure Includes,
873 include_cleaner::PragmaIncludes PI)
874 : TUPath(TUPath), Version(Version), Preamble(std::move(Preamble)),
875 Clang(std::move(Clang)), Action(std::move(Action)),
876 Tokens(std::move(Tokens)), Macros(std::move(Macros)),
877 Marks(std::move(Marks)), Diags(std::move(Diags)),
878 LocalTopLevelDecls(std::move(LocalTopLevelDecls)),
879 Includes(std::move(Includes)), PI(std::move(PI)),
880 Resolver(std::make_unique<HeuristicResolver>(getASTContext())) {
881 assert(this->Clang);
882 assert(this->Action);
883}
884
885const include_cleaner::PragmaIncludes &ParsedAST::getPragmaIncludes() const {
886 return PI;
887}
888
889std::optional<llvm::StringRef> ParsedAST::preambleVersion() const {
890 if (!Preamble)
891 return std::nullopt;
892 return llvm::StringRef(Preamble->Version);
893}
894
895llvm::ArrayRef<Diag> ParsedAST::getDiagnostics() const { return Diags; }
896} // namespace clangd
897} // namespace clang
static cl::opt< std::string > Checks("checks", desc(R"( Comma-separated list of globs with optional '-' prefix. Globs are processed in order of appearance in the list. Globs without '-' prefix add checks with matching names to the set, globs with the '-' prefix remove checks with matching names from the set of enabled checks. This option's value is appended to the value of the 'Checks' option in .clang-tidy file, if any. )"), cl::init(""), cl::cat(ClangTidyCategory))
Include Cleaner is clangd functionality for providing diagnostics for misuse of transitive headers an...
#define dlog(...)
Definition Logger.h:101
static GeneratorRegistry::Add< MDGenerator > MD(MDGenerator::Format, "Generator for MD output.")
#define SPAN_ATTACH(S, Name, Expr)
Attach a key-value pair to a Span event.
Definition Trace.h:164
void collect(const CompilerInstance &CI)
Definition Headers.cpp:178
Stores and provides access to parsed AST.
Definition ParsedAST.h:46
std::size_t getUsedBytes() const
Returns the estimated size of the AST and the accessory structures, in bytes.
std::optional< llvm::StringRef > preambleVersion() const
Returns the version of the ParseInputs used to build Preamble part of this AST.
const include_cleaner::PragmaIncludes & getPragmaIncludes() const
Returns the PramaIncludes for preamble + main file includes.
const std::vector< PragmaMark > & getMarks() const
Gets all pragma marks in the main file.
ASTContext & getASTContext()
Note that the returned ast will not contain decls from the preamble that were not deserialized during...
static std::optional< ParsedAST > build(llvm::StringRef Filename, const ParseInputs &Inputs, std::unique_ptr< clang::CompilerInvocation > CI, llvm::ArrayRef< Diag > CompilerInvocationDiags, std::shared_ptr< const PreambleData > Preamble)
Attempts to run Clang and store the parsed AST.
llvm::ArrayRef< Diag > getDiagnostics() const
std::shared_ptr< Preprocessor > getPreprocessorPtr()
Preprocessor & getPreprocessor()
ArrayRef< Decl * > getLocalTopLevelDecls()
This function returns top-level decls present in the main file of the AST.
ParsedAST & operator=(ParsedAST &&Other)
const IncludeStructure & getIncludeStructure() const
ParsedAST(ParsedAST &&Other)
const MainFileMacros & getMacros() const
Gets all macro references (definition, expansions) present in the main file, including those in the p...
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:900
StoreDiags collects the diagnostics that can later be reported by clangd.
void contributeFixes(DiagFixer Fixer)
If set, possibly adds fixes for diagnostics using Fixer.
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.
void EndSourceFile() override
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
A collection of ClangTidyCheckFactory instances.
std::vector< std::unique_ptr< ClangTidyCheck > > createChecksForLanguage(ClangTidyContext *Context) const
Create instances of checks that are enabled for the current Language.
FIXME: Skip testing on windows temporarily due to the different escaping code mode.
Definition AST.cpp:44
@ Info
An information message.
Definition Protocol.h:755
bool isInsideMainFile(SourceLocation Loc, const SourceManager &SM)
Returns true iff Loc is inside the main file.
static const char * toString(OffsetEncoding OE)
std::unique_ptr< PPCallbacks > collectPragmaMarksCallback(const SourceManager &SM, std::vector< PragmaMark > &Out)
Collect all pragma marks from the main file.
std::optional< bool > isFastTidyCheck(llvm::StringRef Check)
Returns if Check is known-fast, known-slow, or its speed is unknown.
Symbol::IncludeDirective preferredIncludeDirective(llvm::StringRef FileName, const LangOptions &LangOpts, ArrayRef< Inclusion > MainFileIncludes, ArrayRef< const Decl * > TopLevelDecls)
Infer the include directive to use for the given FileName.
Definition AST.cpp:386
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
IncludeCleanerFindings computeIncludeCleanerFindings(ParsedAST &AST, bool AnalyzeAngledIncludes)
llvm::StringRef PathRef
A typedef to represent a ref to file path.
Definition Path.h:29
tidy::ClangTidyOptions getTidyOptionsForFile(TidyProviderRef Provider, llvm::StringRef Filename)
bool isImplicitTemplateInstantiation(const NamedDecl *D)
Indicates if D is a template instantiation implicitly generated by the compiler, e....
Definition AST.cpp:183
std::vector< Diag > issueIncludeCleanerDiagnostics(ParsedAST &AST, llvm::StringRef Code, const IncludeCleanerFindings &Findings, const ThreadsafeFS &TFS, HeaderFilter IgnoreHeaders, HeaderFilter AngledHeaders, HeaderFilter QuotedHeaders)
void elog(const char *Fmt, Ts &&... Vals)
Definition Logger.h:61
format::FormatStyle getFormatStyleForFile(llvm::StringRef File, llvm::StringRef Content, const ThreadsafeFS &TFS, bool FormatFile)
Choose the clang-format style we should apply to a certain file.
std::string configurationAsText(const ClangTidyOptions &Options)
Serializes configuration to a YAML-encoded string.
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Settings that express user/project preferences and control clangd behavior.
Definition Config.h:45
struct clang::clangd::Config::@314053012031341203055315320366267371313202370174 Style
Style of the codebase.
FastCheckPolicy FastCheckFilter
Definition Config.h:113
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:106
struct clang::clangd::Config::@343034053122374337352226322054223376344037116252::@107156241027253143221327255130274177352007274355 ClangTidy
Configures what clang-tidy checks to run and options to use with them.
std::vector< std::function< bool(llvm::StringRef)> > QuotedHeaders
Definition Config.h:135
std::vector< std::function< bool(llvm::StringRef)> > AngledHeaders
Definition Config.h:136
Contains basic information about a diagnostic.
Definition Diagnostics.h:58
A top-level diagnostic that may have Notes and Fixes.
Definition Diagnostics.h:98
Information required to run clang, e.g. to parse AST or do code completion.
Definition Compiler.h:51
TidyProviderRef ClangTidyProvider
Definition Compiler.h:63
tooling::CompileCommand CompileCommand
Definition Compiler.h:52
const ThreadsafeFS * TFS
Definition Compiler.h:53
FeatureModuleSet * FeatureModules
Definition Compiler.h:65
const SymbolIndex * Index
Definition Compiler.h:61
@ Include
#include "header.h"
Definition Symbol.h:93
Contains options for clang-tidy.
std::optional< std::string > Checks
Checks filter.
std::optional< ArgList > ExtraArgsBefore
Add extra compilation arguments to the start of the list.
std::optional< ArgList > ExtraArgs
Add extra compilation arguments to the end of the list.