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