clang-tools  4.0.0
ClangTidy.cpp
Go to the documentation of this file.
1 //===--- tools/extra/clang-tidy/ClangTidy.cpp - Clang tidy tool -----------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 ///
10 /// \file This file implements a clang-tidy tool.
11 ///
12 /// This tool uses the Clang Tooling infrastructure, see
13 /// http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html
14 /// for details on setting it up with LLVM source tree.
15 ///
16 //===----------------------------------------------------------------------===//
17 
18 #include "ClangTidy.h"
21 #include "clang/AST/ASTConsumer.h"
22 #include "clang/AST/ASTContext.h"
23 #include "clang/AST/Decl.h"
24 #include "clang/ASTMatchers/ASTMatchFinder.h"
25 #include "clang/Format/Format.h"
26 #include "clang/Frontend/ASTConsumers.h"
27 #include "clang/Frontend/CompilerInstance.h"
28 #include "clang/Frontend/FrontendActions.h"
29 #include "clang/Frontend/FrontendDiagnostic.h"
30 #include "clang/Frontend/MultiplexConsumer.h"
31 #include "clang/Frontend/TextDiagnosticPrinter.h"
32 #include "clang/Lex/PPCallbacks.h"
33 #include "clang/Lex/Preprocessor.h"
34 #include "clang/Rewrite/Frontend/FixItRewriter.h"
35 #include "clang/Rewrite/Frontend/FrontendActions.h"
36 #include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
37 #include "clang/StaticAnalyzer/Frontend/AnalysisConsumer.h"
38 #include "clang/Tooling/DiagnosticsYaml.h"
39 #include "clang/Tooling/Refactoring.h"
40 #include "clang/Tooling/ReplacementsYaml.h"
41 #include "clang/Tooling/Tooling.h"
42 #include "llvm/Support/Process.h"
43 #include "llvm/Support/Signals.h"
44 #include <algorithm>
45 #include <utility>
46 
47 using namespace clang::ast_matchers;
48 using namespace clang::driver;
49 using namespace clang::tooling;
50 using namespace llvm;
51 
52 LLVM_INSTANTIATE_REGISTRY(clang::tidy::ClangTidyModuleRegistry)
53 
54 namespace clang {
55 namespace tidy {
56 
57 namespace {
58 static const char *AnalyzerCheckNamePrefix = "clang-analyzer-";
59 
60 class AnalyzerDiagnosticConsumer : public ento::PathDiagnosticConsumer {
61 public:
62  AnalyzerDiagnosticConsumer(ClangTidyContext &Context) : Context(Context) {}
63 
64  void FlushDiagnosticsImpl(std::vector<const ento::PathDiagnostic *> &Diags,
65  FilesMade *filesMade) override {
66  for (const ento::PathDiagnostic *PD : Diags) {
67  SmallString<64> CheckName(AnalyzerCheckNamePrefix);
68  CheckName += PD->getCheckName();
69  Context.diag(CheckName, PD->getLocation().asLocation(),
70  PD->getShortDescription())
71  << PD->path.back()->getRanges();
72 
73  for (const auto &DiagPiece :
74  PD->path.flatten(/*ShouldFlattenMacros=*/true)) {
75  Context.diag(CheckName, DiagPiece->getLocation().asLocation(),
76  DiagPiece->getString(), DiagnosticIDs::Note)
77  << DiagPiece->getRanges();
78  }
79  }
80  }
81 
82  StringRef getName() const override { return "ClangTidyDiags"; }
83  bool supportsLogicalOpControlFlow() const override { return true; }
84  bool supportsCrossFileDiagnostics() const override { return true; }
85 
86 private:
87  ClangTidyContext &Context;
88 };
89 
90 class ErrorReporter {
91 public:
92  ErrorReporter(bool ApplyFixes, StringRef FormatStyle)
93  : Files(FileSystemOptions()), DiagOpts(new DiagnosticOptions()),
94  DiagPrinter(new TextDiagnosticPrinter(llvm::outs(), &*DiagOpts)),
95  Diags(IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs), &*DiagOpts,
96  DiagPrinter),
97  SourceMgr(Diags, Files), ApplyFixes(ApplyFixes), TotalFixes(0),
98  AppliedFixes(0), WarningsAsErrors(0), FormatStyle(FormatStyle) {
99  DiagOpts->ShowColors = llvm::sys::Process::StandardOutHasColors();
100  DiagPrinter->BeginSourceFile(LangOpts);
101  }
102 
103  SourceManager &getSourceManager() { return SourceMgr; }
104 
105  void reportDiagnostic(const ClangTidyError &Error) {
106  const tooling::DiagnosticMessage &Message = Error.Message;
107  SourceLocation Loc = getLocation(Message.FilePath, Message.FileOffset);
108  // Contains a pair for each attempted fix: location and whether the fix was
109  // applied successfully.
110  SmallVector<std::pair<SourceLocation, bool>, 4> FixLocations;
111  {
112  auto Level = static_cast<DiagnosticsEngine::Level>(Error.DiagLevel);
113  std::string Name = Error.DiagnosticName;
114  if (Error.IsWarningAsError) {
115  Name += ",-warnings-as-errors";
116  Level = DiagnosticsEngine::Error;
118  }
119  auto Diag = Diags.Report(Loc, Diags.getCustomDiagID(Level, "%0 [%1]"))
120  << Message.Message << Name;
121  for (const auto &FileAndReplacements : Error.Fix) {
122  for (const auto &Repl : FileAndReplacements.second) {
123  // Retrieve the source range for applicable fixes. Macro definitions
124  // on the command line have locations in a virtual buffer and don't
125  // have valid file paths and are therefore not applicable.
126  SourceRange Range;
127  SourceLocation FixLoc;
128  ++TotalFixes;
129  bool CanBeApplied = false;
130  if (Repl.isApplicable()) {
131  SmallString<128> FixAbsoluteFilePath = Repl.getFilePath();
132  Files.makeAbsolutePath(FixAbsoluteFilePath);
133  if (ApplyFixes) {
134  tooling::Replacement R(FixAbsoluteFilePath, Repl.getOffset(),
135  Repl.getLength(),
136  Repl.getReplacementText());
137  Replacements &Replacements = FileReplacements[R.getFilePath()];
138  llvm::Error Err = Replacements.add(R);
139  if (Err) {
140  // FIXME: Implement better conflict handling.
141  llvm::errs() << "Trying to resolve conflict: "
142  << llvm::toString(std::move(Err)) << "\n";
143  unsigned NewOffset =
144  Replacements.getShiftedCodePosition(R.getOffset());
145  unsigned NewLength = Replacements.getShiftedCodePosition(
146  R.getOffset() + R.getLength()) -
147  NewOffset;
148  if (NewLength == R.getLength()) {
149  R = Replacement(R.getFilePath(), NewOffset, NewLength,
150  R.getReplacementText());
151  Replacements = Replacements.merge(tooling::Replacements(R));
152  CanBeApplied = true;
153  ++AppliedFixes;
154  } else {
155  llvm::errs()
156  << "Can't resolve conflict, skipping the replacement.\n";
157  }
158 
159  } else {
160  CanBeApplied = true;
161  ++AppliedFixes;
162  }
163  }
164  FixLoc = getLocation(FixAbsoluteFilePath, Repl.getOffset());
165  SourceLocation FixEndLoc =
166  FixLoc.getLocWithOffset(Repl.getLength());
167  Range = SourceRange(FixLoc, FixEndLoc);
168  Diag << FixItHint::CreateReplacement(Range,
169  Repl.getReplacementText());
170  }
171 
172  if (ApplyFixes)
173  FixLocations.push_back(std::make_pair(FixLoc, CanBeApplied));
174  }
175  }
176  }
177  for (auto Fix : FixLocations) {
178  Diags.Report(Fix.first, Fix.second ? diag::note_fixit_applied
179  : diag::note_fixit_failed);
180  }
181  for (const auto &Note : Error.Notes)
182  reportNote(Note);
183  }
184 
185  void Finish() {
186  // FIXME: Run clang-format on changes.
187  if (ApplyFixes && TotalFixes > 0) {
188  Rewriter Rewrite(SourceMgr, LangOpts);
189  for (const auto &FileAndReplacements : FileReplacements) {
190  StringRef File = FileAndReplacements.first();
191  llvm::ErrorOr<std::unique_ptr<MemoryBuffer>> Buffer =
192  SourceMgr.getFileManager().getBufferForFile(File);
193  if (!Buffer) {
194  llvm::errs() << "Can't get buffer for file " << File << ": "
195  << Buffer.getError().message() << "\n";
196  // FIXME: Maybe don't apply fixes for other files as well.
197  continue;
198  }
199  StringRef Code = Buffer.get()->getBuffer();
200  format::FormatStyle Style = format::getStyle("file", File, FormatStyle);
201  llvm::Expected<Replacements> CleanReplacements =
202  format::cleanupAroundReplacements(Code, FileAndReplacements.second,
203  Style);
204  if (!CleanReplacements) {
205  llvm::errs() << llvm::toString(CleanReplacements.takeError()) << "\n";
206  continue;
207  }
208  if (!tooling::applyAllReplacements(CleanReplacements.get(), Rewrite)) {
209  llvm::errs() << "Can't apply replacements for file " << File << "\n";
210  }
211  }
212  if (Rewrite.overwriteChangedFiles()) {
213  llvm::errs() << "clang-tidy failed to apply suggested fixes.\n";
214  } else {
215  llvm::errs() << "clang-tidy applied " << AppliedFixes << " of "
216  << TotalFixes << " suggested fixes.\n";
217  }
218  }
219  }
220 
221  unsigned getWarningsAsErrorsCount() const { return WarningsAsErrors; }
222 
223 private:
224  SourceLocation getLocation(StringRef FilePath, unsigned Offset) {
225  if (FilePath.empty())
226  return SourceLocation();
227 
228  const FileEntry *File = SourceMgr.getFileManager().getFile(FilePath);
229  FileID ID = SourceMgr.createFileID(File, SourceLocation(), SrcMgr::C_User);
230  return SourceMgr.getLocForStartOfFile(ID).getLocWithOffset(Offset);
231  }
232 
233  void reportNote(const tooling::DiagnosticMessage &Message) {
234  SourceLocation Loc = getLocation(Message.FilePath, Message.FileOffset);
235  Diags.Report(Loc, Diags.getCustomDiagID(DiagnosticsEngine::Note, "%0"))
236  << Message.Message;
237  }
238 
239  FileManager Files;
240  LangOptions LangOpts; // FIXME: use langopts from each original file
241  IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts;
243  DiagnosticsEngine Diags;
244  SourceManager SourceMgr;
245  llvm::StringMap<Replacements> FileReplacements;
247  unsigned TotalFixes;
248  unsigned AppliedFixes;
250  StringRef FormatStyle;
251 };
252 
253 class ClangTidyASTConsumer : public MultiplexConsumer {
254 public:
255  ClangTidyASTConsumer(std::vector<std::unique_ptr<ASTConsumer>> Consumers,
256  std::unique_ptr<ast_matchers::MatchFinder> Finder,
257  std::vector<std::unique_ptr<ClangTidyCheck>> Checks)
258  : MultiplexConsumer(std::move(Consumers)), Finder(std::move(Finder)),
259  Checks(std::move(Checks)) {}
260 
261 private:
262  std::unique_ptr<ast_matchers::MatchFinder> Finder;
263  std::vector<std::unique_ptr<ClangTidyCheck>> Checks;
264 };
265 
266 } // namespace
267 
268 ClangTidyASTConsumerFactory::ClangTidyASTConsumerFactory(
270  : Context(Context), CheckFactories(new ClangTidyCheckFactories) {
271  for (ClangTidyModuleRegistry::iterator I = ClangTidyModuleRegistry::begin(),
272  E = ClangTidyModuleRegistry::end();
273  I != E; ++I) {
274  std::unique_ptr<ClangTidyModule> Module(I->instantiate());
275  Module->addCheckFactories(*CheckFactories);
276  }
277 }
278 
280  AnalyzerOptionsRef AnalyzerOptions) {
281  StringRef AnalyzerPrefix(AnalyzerCheckNamePrefix);
282  for (const auto &Opt : Opts.CheckOptions) {
283  StringRef OptName(Opt.first);
284  if (!OptName.startswith(AnalyzerPrefix))
285  continue;
286  AnalyzerOptions->Config[OptName.substr(AnalyzerPrefix.size())] = Opt.second;
287  }
288 }
289 
290 typedef std::vector<std::pair<std::string, bool>> CheckersList;
291 
293  CheckersList List;
294 
295  const auto &RegisteredCheckers =
296  AnalyzerOptions::getRegisteredCheckers(/*IncludeExperimental=*/false);
297  bool AnalyzerChecksEnabled = false;
298  for (StringRef CheckName : RegisteredCheckers) {
299  std::string ClangTidyCheckName((AnalyzerCheckNamePrefix + CheckName).str());
300  AnalyzerChecksEnabled |= Filter.contains(ClangTidyCheckName);
301  }
302 
303  if (!AnalyzerChecksEnabled)
304  return List;
305 
306  // List all static analyzer checkers that our filter enables.
307  //
308  // Always add all core checkers if any other static analyzer check is enabled.
309  // This is currently necessary, as other path sensitive checks rely on the
310  // core checkers.
311  for (StringRef CheckName : RegisteredCheckers) {
312  std::string ClangTidyCheckName((AnalyzerCheckNamePrefix + CheckName).str());
313 
314  if (CheckName.startswith("core") || Filter.contains(ClangTidyCheckName))
315  List.emplace_back(CheckName, true);
316  }
317  return List;
318 }
319 
320 std::unique_ptr<clang::ASTConsumer>
322  clang::CompilerInstance &Compiler, StringRef File) {
323  // FIXME: Move this to a separate method, so that CreateASTConsumer doesn't
324  // modify Compiler.
325  Context.setSourceManager(&Compiler.getSourceManager());
326  Context.setCurrentFile(File);
327  Context.setASTContext(&Compiler.getASTContext());
328 
329  auto WorkingDir = Compiler.getSourceManager()
330  .getFileManager()
331  .getVirtualFileSystem()
332  ->getCurrentWorkingDirectory();
333  if (WorkingDir)
334  Context.setCurrentBuildDirectory(WorkingDir.get());
335 
336  std::vector<std::unique_ptr<ClangTidyCheck>> Checks;
337  CheckFactories->createChecks(&Context, Checks);
338 
339  ast_matchers::MatchFinder::MatchFinderOptions FinderOptions;
340  if (auto *P = Context.getCheckProfileData())
341  FinderOptions.CheckProfiling.emplace(P->Records);
342 
343  std::unique_ptr<ast_matchers::MatchFinder> Finder(
344  new ast_matchers::MatchFinder(std::move(FinderOptions)));
345 
346  for (auto &Check : Checks) {
347  Check->registerMatchers(&*Finder);
348  Check->registerPPCallbacks(Compiler);
349  }
350 
351  std::vector<std::unique_ptr<ASTConsumer>> Consumers;
352  if (!Checks.empty())
353  Consumers.push_back(Finder->newASTConsumer());
354 
355  AnalyzerOptionsRef AnalyzerOptions = Compiler.getAnalyzerOpts();
356  // FIXME: Remove this option once clang's cfg-temporary-dtors option defaults
357  // to true.
358  AnalyzerOptions->Config["cfg-temporary-dtors"] =
359  Context.getOptions().AnalyzeTemporaryDtors ? "true" : "false";
360 
361  GlobList &Filter = Context.getChecksFilter();
362  AnalyzerOptions->CheckersControlList = getCheckersControlList(Filter);
363  if (!AnalyzerOptions->CheckersControlList.empty()) {
364  setStaticAnalyzerCheckerOpts(Context.getOptions(), AnalyzerOptions);
365  AnalyzerOptions->AnalysisStoreOpt = RegionStoreModel;
366  AnalyzerOptions->AnalysisDiagOpt = PD_NONE;
367  AnalyzerOptions->AnalyzeNestedBlocks = true;
368  AnalyzerOptions->eagerlyAssumeBinOpBifurcation = true;
369  std::unique_ptr<ento::AnalysisASTConsumer> AnalysisConsumer =
370  ento::CreateAnalysisConsumer(Compiler);
371  AnalysisConsumer->AddDiagnosticConsumer(
372  new AnalyzerDiagnosticConsumer(Context));
373  Consumers.push_back(std::move(AnalysisConsumer));
374  }
375  return llvm::make_unique<ClangTidyASTConsumer>(
376  std::move(Consumers), std::move(Finder), std::move(Checks));
377 }
378 
379 std::vector<std::string> ClangTidyASTConsumerFactory::getCheckNames() {
380  std::vector<std::string> CheckNames;
381  GlobList &Filter = Context.getChecksFilter();
382  for (const auto &CheckFactory : *CheckFactories) {
383  if (Filter.contains(CheckFactory.first))
384  CheckNames.push_back(CheckFactory.first);
385  }
386 
387  for (const auto &AnalyzerCheck : getCheckersControlList(Filter))
388  CheckNames.push_back(AnalyzerCheckNamePrefix + AnalyzerCheck.first);
389 
390  std::sort(CheckNames.begin(), CheckNames.end());
391  return CheckNames;
392 }
393 
396  std::vector<std::unique_ptr<ClangTidyCheck>> Checks;
397  CheckFactories->createChecks(&Context, Checks);
398  for (const auto &Check : Checks)
399  Check->storeOptions(Options);
400  return Options;
401 }
402 
403 DiagnosticBuilder ClangTidyCheck::diag(SourceLocation Loc, StringRef Message,
404  DiagnosticIDs::Level Level) {
405  return Context->diag(CheckName, Loc, Message, Level);
406 }
407 
408 void ClangTidyCheck::run(const ast_matchers::MatchFinder::MatchResult &Result) {
409  Context->setSourceManager(Result.SourceManager);
410  check(Result);
411 }
412 
413 OptionsView::OptionsView(StringRef CheckName,
414  const ClangTidyOptions::OptionMap &CheckOptions)
415  : NamePrefix(CheckName.str() + "."), CheckOptions(CheckOptions) {}
416 
417 std::string OptionsView::get(StringRef LocalName, StringRef Default) const {
418  const auto &Iter = CheckOptions.find(NamePrefix + LocalName.str());
419  if (Iter != CheckOptions.end())
420  return Iter->second;
421  return Default;
422 }
423 
424 std::string OptionsView::getLocalOrGlobal(StringRef LocalName,
425  StringRef Default) const {
426  auto Iter = CheckOptions.find(NamePrefix + LocalName.str());
427  if (Iter != CheckOptions.end())
428  return Iter->second;
429  // Fallback to global setting, if present.
430  Iter = CheckOptions.find(LocalName.str());
431  if (Iter != CheckOptions.end())
432  return Iter->second;
433  return Default;
434 }
435 
437  StringRef LocalName, StringRef Value) const {
438  Options[NamePrefix + LocalName.str()] = Value;
439 }
440 
442  StringRef LocalName, int64_t Value) const {
443  store(Options, LocalName, llvm::itostr(Value));
444 }
445 
446 std::vector<std::string> getCheckNames(const ClangTidyOptions &Options) {
448  llvm::make_unique<DefaultOptionsProvider>(ClangTidyGlobalOptions(),
449  Options));
450  ClangTidyASTConsumerFactory Factory(Context);
451  return Factory.getCheckNames();
452 }
453 
456  llvm::make_unique<DefaultOptionsProvider>(ClangTidyGlobalOptions(),
457  Options));
458  ClangTidyASTConsumerFactory Factory(Context);
459  return Factory.getCheckOptions();
460 }
461 
462 ClangTidyStats
463 runClangTidy(std::unique_ptr<ClangTidyOptionsProvider> OptionsProvider,
464  const CompilationDatabase &Compilations,
465  ArrayRef<std::string> InputFiles,
466  std::vector<ClangTidyError> *Errors, ProfileData *Profile) {
467  ClangTool Tool(Compilations, InputFiles);
468  clang::tidy::ClangTidyContext Context(std::move(OptionsProvider));
469 
470  // Add extra arguments passed by the clang-tidy command-line.
471  ArgumentsAdjuster PerFileExtraArgumentsInserter =
472  [&Context](const CommandLineArguments &Args, StringRef Filename) {
474  CommandLineArguments AdjustedArgs = Args;
475  if (Opts.ExtraArgsBefore) {
476  auto I = AdjustedArgs.begin();
477  if (I != AdjustedArgs.end() && !StringRef(*I).startswith("-"))
478  ++I; // Skip compiler binary name, if it is there.
479  AdjustedArgs.insert(I, Opts.ExtraArgsBefore->begin(),
480  Opts.ExtraArgsBefore->end());
481  }
482  if (Opts.ExtraArgs)
483  AdjustedArgs.insert(AdjustedArgs.end(), Opts.ExtraArgs->begin(),
484  Opts.ExtraArgs->end());
485  return AdjustedArgs;
486  };
487 
488  // Remove plugins arguments.
489  ArgumentsAdjuster PluginArgumentsRemover =
490  [&Context](const CommandLineArguments &Args, StringRef Filename) {
491  CommandLineArguments AdjustedArgs;
492  for (size_t I = 0, E = Args.size(); I < E; ++I) {
493  if (I + 4 < Args.size() && Args[I] == "-Xclang" &&
494  (Args[I + 1] == "-load" || Args[I + 1] == "-add-plugin" ||
495  StringRef(Args[I + 1]).startswith("-plugin-arg-")) &&
496  Args[I + 2] == "-Xclang") {
497  I += 3;
498  } else
499  AdjustedArgs.push_back(Args[I]);
500  }
501  return AdjustedArgs;
502  };
503 
504  Tool.appendArgumentsAdjuster(PerFileExtraArgumentsInserter);
505  Tool.appendArgumentsAdjuster(PluginArgumentsRemover);
506  if (Profile)
507  Context.setCheckProfileData(Profile);
508 
509  ClangTidyDiagnosticConsumer DiagConsumer(Context);
510 
511  Tool.setDiagnosticConsumer(&DiagConsumer);
512 
513  class ActionFactory : public FrontendActionFactory {
514  public:
515  ActionFactory(ClangTidyContext &Context) : ConsumerFactory(Context) {}
516  FrontendAction *create() override { return new Action(&ConsumerFactory); }
517 
518  private:
519  class Action : public ASTFrontendAction {
520  public:
521  Action(ClangTidyASTConsumerFactory *Factory) : Factory(Factory) {}
522  std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &Compiler,
523  StringRef File) override {
524  return Factory->CreateASTConsumer(Compiler, File);
525  }
526 
527  private:
529  };
530 
531  ClangTidyASTConsumerFactory ConsumerFactory;
532  };
533 
534  ActionFactory Factory(Context);
535  Tool.run(&Factory);
536  *Errors = Context.getErrors();
537  return Context.getStats();
538 }
539 
540 void handleErrors(const std::vector<ClangTidyError> &Errors, bool Fix,
541  StringRef FormatStyle, unsigned &WarningsAsErrorsCount) {
542  ErrorReporter Reporter(Fix, FormatStyle);
543  vfs::FileSystem &FileSystem =
544  *Reporter.getSourceManager().getFileManager().getVirtualFileSystem();
545  auto InitialWorkingDir = FileSystem.getCurrentWorkingDirectory();
546  if (!InitialWorkingDir)
547  llvm::report_fatal_error("Cannot get current working path.");
548 
549  for (const ClangTidyError &Error : Errors) {
550  if (!Error.BuildDirectory.empty()) {
551  // By default, the working directory of file system is the current
552  // clang-tidy running directory.
553  //
554  // Change the directory to the one used during the analysis.
555  FileSystem.setCurrentWorkingDirectory(Error.BuildDirectory);
556  }
557  Reporter.reportDiagnostic(Error);
558  // Return to the initial directory to correctly resolve next Error.
559  FileSystem.setCurrentWorkingDirectory(InitialWorkingDir.get());
560  }
561  Reporter.Finish();
562  WarningsAsErrorsCount += Reporter.getWarningsAsErrorsCount();
563 }
564 
565 void exportReplacements(const llvm::StringRef MainFilePath,
566  const std::vector<ClangTidyError> &Errors,
567  raw_ostream &OS) {
568  TranslationUnitDiagnostics TUD;
569  TUD.MainSourceFile = MainFilePath;
570  for (const auto &Error : Errors) {
571  tooling::Diagnostic Diag = Error;
572  TUD.Diagnostics.insert(TUD.Diagnostics.end(), Diag);
573  }
574 
575  yaml::Output YAML(OS);
576  YAML << TUD;
577 }
578 
579 } // namespace tidy
580 } // namespace clang
SourceLocation Loc
'#' location in the include directive
std::vector< std::string > getCheckNames()
Get the list of enabled checks.
Definition: ClangTidy.cpp:379
SetLongJmpCheck & Check
const std::string Name
Definition: USRFinder.cpp:164
llvm::Optional< ArgList > ExtraArgs
Add extra compilation arguments to the end of the list.
LangOptions LangOpts
Definition: ClangTidy.cpp:240
Read-only set of strings represented as a list of positive and negative globs.
llvm::StringMap< Replacements > FileReplacements
Definition: ClangTidy.cpp:245
std::unique_ptr< ast_matchers::MatchFinder > Finder
Definition: ClangTidy.cpp:262
ClangTidyOptions::OptionMap getCheckOptions()
Get the union of options from all checks.
Definition: ClangTidy.cpp:394
std::vector< std::unique_ptr< ClangTidyCheck > > Checks
Definition: ClangTidy.cpp:263
HeaderHandle File
bool contains(StringRef S)
Returns true if the pattern matches S.
static llvm::StringRef toString(SpecialMemberFunctionsCheck::SpecialMemberFunctionKind K)
ClangTidyOptions::OptionMap getCheckOptions(const ClangTidyOptions &Options)
Returns the effective check-specific options.
Definition: ClangTidy.cpp:454
Contains options for clang-tidy.
unsigned AppliedFixes
Definition: ClangTidy.cpp:248
A collection of ClangTidyCheckFactory instances.
const std::vector< ClangTidyError > & getErrors() const
Returns all collected errors.
OptionMap CheckOptions
Key-value mapping used to store check-specific options.
SourceManager SourceMgr
Definition: ClangTidy.cpp:244
std::string get(StringRef LocalName, StringRef Default) const
Read a named option from the Context.
Definition: ClangTidy.cpp:417
llvm::Optional< ArgList > ExtraArgsBefore
Add extra compilation arguments to the start of the list.
ClangTidyOptions getOptionsForFile(StringRef File) const
Returns options for File.
void setCurrentFile(StringRef File)
Should be called when starting to process new translation unit.
const ClangTidyOptions & getOptions() const
Returns options for CurrentFile.
std::string Filename
Filename as a string.
DiagnosticBuilder diag(StringRef CheckName, SourceLocation Loc, StringRef Message, DiagnosticIDs::Level Level=DiagnosticIDs::Warning)
Report any errors detected using this method.
void setCheckProfileData(ProfileData *Profile)
Set the output struct for profile data.
ClangTidyStats runClangTidy(std::unique_ptr< ClangTidyOptionsProvider > OptionsProvider, const CompilationDatabase &Compilations, ArrayRef< std::string > InputFiles, std::vector< ClangTidyError > *Errors, ProfileData *Profile)
Definition: ClangTidy.cpp:463
std::string getLocalOrGlobal(StringRef LocalName, StringRef Default) const
Read a named option from the Context.
Definition: ClangTidy.cpp:424
void setASTContext(ASTContext *Context)
Sets ASTContext for the current translation unit.
A diagnostic consumer that turns each Diagnostic into a SourceManager-independent ClangTidyError...
void store(ClangTidyOptions::OptionMap &Options, StringRef LocalName, StringRef Value) const
Stores an option with the check-local name LocalName with string value Value to Options.
Definition: ClangTidy.cpp:436
std::map< std::string, std::string > OptionMap
std::vector< std::string > getCheckNames(const ClangTidyOptions &Options)
Fills the list of check names that are enabled when the provided filters are applied.
Definition: ClangTidy.cpp:446
std::vector< std::pair< std::string, bool > > CheckersList
Definition: ClangTidy.cpp:290
static void setStaticAnalyzerCheckerOpts(const ClangTidyOptions &Opts, AnalyzerOptionsRef AnalyzerOptions)
Definition: ClangTidy.cpp:279
unsigned WarningsAsErrors
Definition: ClangTidy.cpp:249
void setSourceManager(SourceManager *SourceMgr)
Sets the SourceManager of the used DiagnosticsEngine.
OptionsView(StringRef CheckName, const ClangTidyOptions::OptionMap &CheckOptions)
Initializes the instance using CheckName + "." as a prefix.
Definition: ClangTidy.cpp:413
llvm::Optional< bool > AnalyzeTemporaryDtors
Turns on temporary destructor-based analysis.
void exportReplacements(const llvm::StringRef MainFilePath, const std::vector< ClangTidyError > &Errors, raw_ostream &OS)
Definition: ClangTidy.cpp:565
const ClangTidyStats & getStats() const
Returns ClangTidyStats containing issued and ignored diagnostic counters.
CharSourceRange Range
SourceRange for the file name.
bool ApplyFixes
Definition: ClangTidy.cpp:246
A detected error complete with information to display diagnostic and automatic fix.
IntrusiveRefCntPtr< DiagnosticOptions > DiagOpts
Definition: ClangTidy.cpp:241
ClangTidyContext & Context
Definition: ClangTidy.cpp:87
static CheckersList getCheckersControlList(GlobList &Filter)
Definition: ClangTidy.cpp:292
Every ClangTidyCheck reports errors through a DiagnosticsEngine provided by this context.
llvm::Registry< ClangTidyModule > ClangTidyModuleRegistry
std::unique_ptr< clang::ASTConsumer > CreateASTConsumer(clang::CompilerInstance &Compiler, StringRef File)
Returns an ASTConsumer that runs the specified clang-tidy checks.
Definition: ClangTidy.cpp:321
FileManager Files
Definition: ClangTidy.cpp:239
static cl::opt< bool > Fix("fix", cl::desc(R"( Apply suggested fixes. Without -fix-errors clang-tidy will bail out if any compilation errors were found. )"), cl::init(false), cl::cat(ClangTidyCategory))
void setCurrentBuildDirectory(StringRef BuildDirectory)
Should be called when starting to process new translation unit.
bool applyAllReplacements(const std::vector< tooling::Replacement > &Replaces, Rewriter &Rewrite)
virtual void check(const ast_matchers::MatchFinder::MatchResult &Result)
ClangTidyChecks that register ASTMatchers should do the actual work in here.
Definition: ClangTidy.h:163
GlobList & getChecksFilter()
Returns check filter for the CurrentFile.
DiagnosticsEngine Diags
Definition: ClangTidy.cpp:243
unsigned TotalFixes
Definition: ClangTidy.cpp:247
Container for clang-tidy profiling data.
DiagnosticBuilder diag(SourceLocation Loc, StringRef Description, DiagnosticIDs::Level Level=DiagnosticIDs::Warning)
Add a diagnostic with the check's name.
Definition: ClangTidy.cpp:403
StringRef FormatStyle
Definition: ClangTidy.cpp:250
const NamedDecl * Result
Definition: USRFinder.cpp:162
void handleErrors(const std::vector< ClangTidyError > &Errors, bool Fix, StringRef FormatStyle, unsigned &WarningsAsErrorsCount)
Displays the found Errors to the users.
Definition: ClangTidy.cpp:540
DiagnosticConsumer * DiagPrinter
Definition: ClangTidy.cpp:242