2013-07-29 16:19:24 +08:00
|
|
|
//===--- tools/extra/clang-tidy/ClangTidy.cpp - Clang tidy tool -----------===//
|
|
|
|
//
|
2019-01-19 16:50:56 +08:00
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
2013-07-29 16:19:24 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
///
|
|
|
|
/// \file This file implements a clang-tidy tool.
|
|
|
|
///
|
|
|
|
/// This tool uses the Clang Tooling infrastructure, see
|
|
|
|
/// http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html
|
|
|
|
/// for details on setting it up with LLVM source tree.
|
|
|
|
///
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "ClangTidy.h"
|
|
|
|
#include "ClangTidyDiagnosticConsumer.h"
|
|
|
|
#include "ClangTidyModuleRegistry.h"
|
[clang-tidy] Profile is a per-AST (per-TU) data.
Summary:
As discussed in D45931, currently, profiling output of clang-tidy is somewhat not great.
It outputs one profile at the end of the execution, and that profile contains the data
from the last TU that was processed. So if the tool run on multiple TU's, the data is
not accumulated, it is simply discarded.
It would be nice to improve this.
This differential is the first step - make this profiling info per-TU,
and output it after the tool has finished processing each TU.
In particular, when `ClangTidyASTConsumer` destructor runs.
Next step will be to add a CSV (JSON?) printer to store said profiles under user-specified directory prefix.
Reviewers: alexfh, sbenza
Reviewed By: alexfh
Subscribers: Eugene.Zelenko, mgorny, xazax.hun, mgrang, klimek, cfe-commits
Tags: #clang-tools-extra
Differential Revision: https://reviews.llvm.org/D46504
llvm-svn: 331763
2018-05-08 21:14:21 +08:00
|
|
|
#include "ClangTidyProfiling.h"
|
2019-03-22 21:42:48 +08:00
|
|
|
#include "ExpandModularHeadersPPCallbacks.h"
|
2013-07-29 16:19:24 +08:00
|
|
|
#include "clang/AST/ASTConsumer.h"
|
|
|
|
#include "clang/AST/ASTContext.h"
|
|
|
|
#include "clang/AST/Decl.h"
|
|
|
|
#include "clang/ASTMatchers/ASTMatchFinder.h"
|
2018-10-02 04:24:22 +08:00
|
|
|
#include "clang/Config/config.h"
|
2016-10-18 01:25:02 +08:00
|
|
|
#include "clang/Format/Format.h"
|
2013-07-29 16:19:24 +08:00
|
|
|
#include "clang/Frontend/ASTConsumers.h"
|
|
|
|
#include "clang/Frontend/CompilerInstance.h"
|
|
|
|
#include "clang/Frontend/FrontendActions.h"
|
2014-03-27 18:24:11 +08:00
|
|
|
#include "clang/Frontend/FrontendDiagnostic.h"
|
2014-01-03 17:31:57 +08:00
|
|
|
#include "clang/Frontend/MultiplexConsumer.h"
|
2013-07-29 16:19:24 +08:00
|
|
|
#include "clang/Frontend/TextDiagnosticPrinter.h"
|
2014-01-08 04:05:01 +08:00
|
|
|
#include "clang/Lex/PPCallbacks.h"
|
|
|
|
#include "clang/Lex/Preprocessor.h"
|
2019-10-15 04:15:01 +08:00
|
|
|
#include "clang/Lex/PreprocessorOptions.h"
|
2013-07-29 16:19:24 +08:00
|
|
|
#include "clang/Rewrite/Frontend/FixItRewriter.h"
|
|
|
|
#include "clang/Rewrite/Frontend/FrontendActions.h"
|
[clang-tidy] Add fix descriptions to clang-tidy checks.
Summary:
Motivation/Context: in the code review system integrating with clang-tidy,
clang-tidy doesn't provide a human-readable description of the fix. Usually
developers have to preview a code diff (before vs after apply the fix) to
understand what the fix does before applying a fix.
This patch proposes that each clang-tidy check provides a short and
actional fix description that can be shown in the UI, so that users can know
what the fix does without previewing diff.
This patch extends clang-tidy framework to support fix descriptions (will add implementations for
existing checks in the future). Fix descriptions and fixes are emitted via diagnostic::Note (rather than
attaching the main warning diagnostic).
Before this patch:
```
void MyCheck::check(...) {
...
diag(loc, "my check warning") << FixtItHint::CreateReplacement(...);
}
```
After:
```
void MyCheck::check(...) {
...
diag(loc, "my check warning"); // Emit a check warning
diag(loc, "fix description", DiagnosticIDs::Note) << FixtItHint::CreateReplacement(...); // Emit a diagnostic note and a fix
}
```
Reviewers: sammccall, alexfh
Reviewed By: alexfh
Subscribers: MyDeveloperDay, Eugene.Zelenko, aaron.ballman, JonasToth, xazax.hun, jdoerfert, cfe-commits
Tags: #clang-tools-extra, #clang
Differential Revision: https://reviews.llvm.org/D59932
llvm-svn: 358576
2019-04-17 20:53:59 +08:00
|
|
|
#include "clang/Tooling/Core/Diagnostic.h"
|
2017-01-03 22:36:13 +08:00
|
|
|
#include "clang/Tooling/DiagnosticsYaml.h"
|
2013-07-29 16:19:24 +08:00
|
|
|
#include "clang/Tooling/Refactoring.h"
|
2014-09-04 18:31:23 +08:00
|
|
|
#include "clang/Tooling/ReplacementsYaml.h"
|
2014-01-08 04:05:01 +08:00
|
|
|
#include "clang/Tooling/Tooling.h"
|
2014-02-06 22:50:10 +08:00
|
|
|
#include "llvm/Support/Process.h"
|
2013-07-29 16:19:24 +08:00
|
|
|
#include "llvm/Support/Signals.h"
|
Clang-tidy: added --disable-checks, --list-checks options.
Summary:
Allow disabling checks by regex. By default, disable alpha.* checks,
that are not particularly good tested (e.g. IdempotentOperationChecker, see
http://llvm-reviews.chandlerc.com/D2427).
Fixed a bug, that would disable all analyzer checks, when using a regex more
strict, than 'clang-analyzer-', for example --checks='clang-analyzer-deadcode-'.
Added --list-checks to list all enabled checks. This is useful to test specific
values in --checks/--disable-checks.
Reviewers: djasper, klimek
Reviewed By: klimek
CC: cfe-commits, klimek
Differential Revision: http://llvm-reviews.chandlerc.com/D2444
llvm-svn: 197717
2013-12-20 03:57:05 +08:00
|
|
|
#include <algorithm>
|
2014-03-27 18:24:11 +08:00
|
|
|
#include <utility>
|
2013-07-29 16:19:24 +08:00
|
|
|
|
2019-09-12 04:54:27 +08:00
|
|
|
#if CLANG_ENABLE_STATIC_ANALYZER
|
|
|
|
#include "clang/Analysis/PathDiagnostic.h"
|
|
|
|
#include "clang/StaticAnalyzer/Frontend/AnalysisConsumer.h"
|
|
|
|
#endif // CLANG_ENABLE_STATIC_ANALYZER
|
|
|
|
|
2013-07-29 16:19:24 +08:00
|
|
|
using namespace clang::ast_matchers;
|
|
|
|
using namespace clang::driver;
|
|
|
|
using namespace clang::tooling;
|
|
|
|
using namespace llvm;
|
|
|
|
|
2016-08-05 19:01:08 +08:00
|
|
|
LLVM_INSTANTIATE_REGISTRY(clang::tidy::ClangTidyModuleRegistry)
|
2014-07-03 22:12:47 +08:00
|
|
|
|
2013-07-29 16:19:24 +08:00
|
|
|
namespace clang {
|
|
|
|
namespace tidy {
|
2013-11-14 23:49:44 +08:00
|
|
|
|
2014-01-03 17:31:57 +08:00
|
|
|
namespace {
|
2018-10-02 04:24:22 +08:00
|
|
|
#if CLANG_ENABLE_STATIC_ANALYZER
|
2014-02-06 22:50:10 +08:00
|
|
|
static const char *AnalyzerCheckNamePrefix = "clang-analyzer-";
|
2013-11-14 23:49:44 +08:00
|
|
|
|
2014-02-06 22:50:10 +08:00
|
|
|
class AnalyzerDiagnosticConsumer : public ento::PathDiagnosticConsumer {
|
|
|
|
public:
|
|
|
|
AnalyzerDiagnosticConsumer(ClangTidyContext &Context) : Context(Context) {}
|
|
|
|
|
2014-02-27 21:14:51 +08:00
|
|
|
void FlushDiagnosticsImpl(std::vector<const ento::PathDiagnostic *> &Diags,
|
2014-03-02 18:20:11 +08:00
|
|
|
FilesMade *filesMade) override {
|
2014-03-06 18:17:46 +08:00
|
|
|
for (const ento::PathDiagnostic *PD : Diags) {
|
2014-02-12 17:52:07 +08:00
|
|
|
SmallString<64> CheckName(AnalyzerCheckNamePrefix);
|
2019-09-13 05:18:44 +08:00
|
|
|
CheckName += PD->getCheckerName();
|
2014-03-06 21:24:28 +08:00
|
|
|
Context.diag(CheckName, PD->getLocation().asLocation(),
|
|
|
|
PD->getShortDescription())
|
|
|
|
<< PD->path.back()->getRanges();
|
2014-02-06 22:50:10 +08:00
|
|
|
|
2014-03-06 18:17:46 +08:00
|
|
|
for (const auto &DiagPiece :
|
|
|
|
PD->path.flatten(/*ShouldFlattenMacros=*/true)) {
|
2014-03-06 21:24:28 +08:00
|
|
|
Context.diag(CheckName, DiagPiece->getLocation().asLocation(),
|
|
|
|
DiagPiece->getString(), DiagnosticIDs::Note)
|
|
|
|
<< DiagPiece->getRanges();
|
2014-02-06 22:50:10 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-03-02 18:20:11 +08:00
|
|
|
StringRef getName() const override { return "ClangTidyDiags"; }
|
|
|
|
bool supportsLogicalOpControlFlow() const override { return true; }
|
|
|
|
bool supportsCrossFileDiagnostics() const override { return true; }
|
2014-02-06 22:50:10 +08:00
|
|
|
|
|
|
|
private:
|
|
|
|
ClangTidyContext &Context;
|
|
|
|
};
|
2018-10-02 04:24:22 +08:00
|
|
|
#endif // CLANG_ENABLE_STATIC_ANALYZER
|
2014-02-06 22:50:10 +08:00
|
|
|
|
2014-03-27 18:24:11 +08:00
|
|
|
class ErrorReporter {
|
|
|
|
public:
|
2018-01-23 20:31:06 +08:00
|
|
|
ErrorReporter(ClangTidyContext &Context, bool ApplyFixes,
|
2018-10-10 21:27:25 +08:00
|
|
|
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> BaseFS)
|
2018-01-23 20:31:06 +08:00
|
|
|
: Files(FileSystemOptions(), BaseFS), DiagOpts(new DiagnosticOptions()),
|
2014-03-27 18:24:11 +08:00
|
|
|
DiagPrinter(new TextDiagnosticPrinter(llvm::outs(), &*DiagOpts)),
|
|
|
|
Diags(IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs), &*DiagOpts,
|
|
|
|
DiagPrinter),
|
2017-04-06 21:41:29 +08:00
|
|
|
SourceMgr(Diags, Files), Context(Context), ApplyFixes(ApplyFixes),
|
|
|
|
TotalFixes(0), AppliedFixes(0), WarningsAsErrors(0) {
|
2014-03-27 18:24:11 +08:00
|
|
|
DiagOpts->ShowColors = llvm::sys::Process::StandardOutHasColors();
|
|
|
|
DiagPrinter->BeginSourceFile(LangOpts);
|
|
|
|
}
|
|
|
|
|
2016-04-06 22:07:51 +08:00
|
|
|
SourceManager &getSourceManager() { return SourceMgr; }
|
2016-02-26 17:19:33 +08:00
|
|
|
|
2014-07-02 23:05:04 +08:00
|
|
|
void reportDiagnostic(const ClangTidyError &Error) {
|
2017-01-03 22:36:13 +08:00
|
|
|
const tooling::DiagnosticMessage &Message = Error.Message;
|
2014-03-27 18:24:11 +08:00
|
|
|
SourceLocation Loc = getLocation(Message.FilePath, Message.FileOffset);
|
|
|
|
// Contains a pair for each attempted fix: location and whether the fix was
|
|
|
|
// applied successfully.
|
|
|
|
SmallVector<std::pair<SourceLocation, bool>, 4> FixLocations;
|
|
|
|
{
|
2014-07-02 23:05:04 +08:00
|
|
|
auto Level = static_cast<DiagnosticsEngine::Level>(Error.DiagLevel);
|
2017-01-03 22:36:13 +08:00
|
|
|
std::string Name = Error.DiagnosticName;
|
2016-01-14 01:36:41 +08:00
|
|
|
if (Error.IsWarningAsError) {
|
|
|
|
Name += ",-warnings-as-errors";
|
|
|
|
Level = DiagnosticsEngine::Error;
|
|
|
|
WarningsAsErrors++;
|
|
|
|
}
|
2015-11-16 21:06:15 +08:00
|
|
|
auto Diag = Diags.Report(Loc, Diags.getCustomDiagID(Level, "%0 [%1]"))
|
2016-01-14 01:36:41 +08:00
|
|
|
<< Message.Message << Name;
|
[clang-tidy] Add fix descriptions to clang-tidy checks.
Summary:
Motivation/Context: in the code review system integrating with clang-tidy,
clang-tidy doesn't provide a human-readable description of the fix. Usually
developers have to preview a code diff (before vs after apply the fix) to
understand what the fix does before applying a fix.
This patch proposes that each clang-tidy check provides a short and
actional fix description that can be shown in the UI, so that users can know
what the fix does without previewing diff.
This patch extends clang-tidy framework to support fix descriptions (will add implementations for
existing checks in the future). Fix descriptions and fixes are emitted via diagnostic::Note (rather than
attaching the main warning diagnostic).
Before this patch:
```
void MyCheck::check(...) {
...
diag(loc, "my check warning") << FixtItHint::CreateReplacement(...);
}
```
After:
```
void MyCheck::check(...) {
...
diag(loc, "my check warning"); // Emit a check warning
diag(loc, "fix description", DiagnosticIDs::Note) << FixtItHint::CreateReplacement(...); // Emit a diagnostic note and a fix
}
```
Reviewers: sammccall, alexfh
Reviewed By: alexfh
Subscribers: MyDeveloperDay, Eugene.Zelenko, aaron.ballman, JonasToth, xazax.hun, jdoerfert, cfe-commits
Tags: #clang-tools-extra, #clang
Differential Revision: https://reviews.llvm.org/D59932
llvm-svn: 358576
2019-04-17 20:53:59 +08:00
|
|
|
// FIXME: explore options to support interactive fix selection.
|
|
|
|
const llvm::StringMap<Replacements> *ChosenFix = selectFirstFix(Error);
|
|
|
|
if (ApplyFixes && ChosenFix) {
|
|
|
|
for (const auto &FileAndReplacements : *ChosenFix) {
|
|
|
|
for (const auto &Repl : FileAndReplacements.second) {
|
|
|
|
++TotalFixes;
|
|
|
|
bool CanBeApplied = false;
|
2019-04-18 22:18:14 +08:00
|
|
|
if (!Repl.isApplicable())
|
|
|
|
continue;
|
|
|
|
SourceLocation FixLoc;
|
|
|
|
SmallString<128> FixAbsoluteFilePath = Repl.getFilePath();
|
|
|
|
Files.makeAbsolutePath(FixAbsoluteFilePath);
|
|
|
|
tooling::Replacement R(FixAbsoluteFilePath, Repl.getOffset(),
|
|
|
|
Repl.getLength(), Repl.getReplacementText());
|
|
|
|
Replacements &Replacements = FileReplacements[R.getFilePath()];
|
|
|
|
llvm::Error Err = Replacements.add(R);
|
|
|
|
if (Err) {
|
|
|
|
// FIXME: Implement better conflict handling.
|
|
|
|
llvm::errs() << "Trying to resolve conflict: "
|
|
|
|
<< llvm::toString(std::move(Err)) << "\n";
|
|
|
|
unsigned NewOffset =
|
|
|
|
Replacements.getShiftedCodePosition(R.getOffset());
|
|
|
|
unsigned NewLength = Replacements.getShiftedCodePosition(
|
|
|
|
R.getOffset() + R.getLength()) -
|
|
|
|
NewOffset;
|
|
|
|
if (NewLength == R.getLength()) {
|
|
|
|
R = Replacement(R.getFilePath(), NewOffset, NewLength,
|
|
|
|
R.getReplacementText());
|
|
|
|
Replacements = Replacements.merge(tooling::Replacements(R));
|
2016-10-18 01:25:02 +08:00
|
|
|
CanBeApplied = true;
|
|
|
|
++AppliedFixes;
|
2019-04-18 22:18:14 +08:00
|
|
|
} else {
|
|
|
|
llvm::errs()
|
|
|
|
<< "Can't resolve conflict, skipping the replacement.\n";
|
2016-10-18 01:25:02 +08:00
|
|
|
}
|
2019-04-18 22:18:14 +08:00
|
|
|
} else {
|
|
|
|
CanBeApplied = true;
|
|
|
|
++AppliedFixes;
|
2016-10-18 01:25:02 +08:00
|
|
|
}
|
2019-04-18 22:18:14 +08:00
|
|
|
FixLoc = getLocation(FixAbsoluteFilePath, Repl.getOffset());
|
|
|
|
FixLocations.push_back(std::make_pair(FixLoc, CanBeApplied));
|
2016-08-09 15:54:49 +08:00
|
|
|
}
|
2014-03-27 18:24:11 +08:00
|
|
|
}
|
|
|
|
}
|
[clang-tidy] Add fix descriptions to clang-tidy checks.
Summary:
Motivation/Context: in the code review system integrating with clang-tidy,
clang-tidy doesn't provide a human-readable description of the fix. Usually
developers have to preview a code diff (before vs after apply the fix) to
understand what the fix does before applying a fix.
This patch proposes that each clang-tidy check provides a short and
actional fix description that can be shown in the UI, so that users can know
what the fix does without previewing diff.
This patch extends clang-tidy framework to support fix descriptions (will add implementations for
existing checks in the future). Fix descriptions and fixes are emitted via diagnostic::Note (rather than
attaching the main warning diagnostic).
Before this patch:
```
void MyCheck::check(...) {
...
diag(loc, "my check warning") << FixtItHint::CreateReplacement(...);
}
```
After:
```
void MyCheck::check(...) {
...
diag(loc, "my check warning"); // Emit a check warning
diag(loc, "fix description", DiagnosticIDs::Note) << FixtItHint::CreateReplacement(...); // Emit a diagnostic note and a fix
}
```
Reviewers: sammccall, alexfh
Reviewed By: alexfh
Subscribers: MyDeveloperDay, Eugene.Zelenko, aaron.ballman, JonasToth, xazax.hun, jdoerfert, cfe-commits
Tags: #clang-tools-extra, #clang
Differential Revision: https://reviews.llvm.org/D59932
llvm-svn: 358576
2019-04-17 20:53:59 +08:00
|
|
|
reportFix(Diag, Error.Message.Fix);
|
2014-03-27 18:24:11 +08:00
|
|
|
}
|
|
|
|
for (auto Fix : FixLocations) {
|
|
|
|
Diags.Report(Fix.first, Fix.second ? diag::note_fixit_applied
|
|
|
|
: diag::note_fixit_failed);
|
|
|
|
}
|
2017-01-03 22:36:13 +08:00
|
|
|
for (const auto &Note : Error.Notes)
|
2014-07-02 23:05:04 +08:00
|
|
|
reportNote(Note);
|
2014-03-27 18:24:11 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void Finish() {
|
|
|
|
if (ApplyFixes && TotalFixes > 0) {
|
2016-10-18 01:25:02 +08:00
|
|
|
Rewriter Rewrite(SourceMgr, LangOpts);
|
|
|
|
for (const auto &FileAndReplacements : FileReplacements) {
|
|
|
|
StringRef File = FileAndReplacements.first();
|
|
|
|
llvm::ErrorOr<std::unique_ptr<MemoryBuffer>> Buffer =
|
|
|
|
SourceMgr.getFileManager().getBufferForFile(File);
|
|
|
|
if (!Buffer) {
|
|
|
|
llvm::errs() << "Can't get buffer for file " << File << ": "
|
|
|
|
<< Buffer.getError().message() << "\n";
|
|
|
|
// FIXME: Maybe don't apply fixes for other files as well.
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
StringRef Code = Buffer.get()->getBuffer();
|
2017-04-06 21:41:29 +08:00
|
|
|
auto Style = format::getStyle(
|
|
|
|
*Context.getOptionsForFile(File).FormatStyle, File, "none");
|
2017-01-17 08:13:32 +08:00
|
|
|
if (!Style) {
|
|
|
|
llvm::errs() << llvm::toString(Style.takeError()) << "\n";
|
|
|
|
continue;
|
|
|
|
}
|
2017-03-03 19:16:34 +08:00
|
|
|
llvm::Expected<tooling::Replacements> Replacements =
|
2016-10-18 01:25:02 +08:00
|
|
|
format::cleanupAroundReplacements(Code, FileAndReplacements.second,
|
2017-01-17 08:13:32 +08:00
|
|
|
*Style);
|
2017-03-03 19:16:34 +08:00
|
|
|
if (!Replacements) {
|
|
|
|
llvm::errs() << llvm::toString(Replacements.takeError()) << "\n";
|
2016-10-18 01:25:02 +08:00
|
|
|
continue;
|
|
|
|
}
|
2017-03-03 19:16:34 +08:00
|
|
|
if (llvm::Expected<tooling::Replacements> FormattedReplacements =
|
|
|
|
format::formatReplacements(Code, *Replacements, *Style)) {
|
|
|
|
Replacements = std::move(FormattedReplacements);
|
|
|
|
if (!Replacements)
|
|
|
|
llvm_unreachable("!Replacements");
|
|
|
|
} else {
|
|
|
|
llvm::errs() << llvm::toString(FormattedReplacements.takeError())
|
|
|
|
<< ". Skipping formatting.\n";
|
|
|
|
}
|
|
|
|
if (!tooling::applyAllReplacements(Replacements.get(), Rewrite)) {
|
2016-10-18 01:25:02 +08:00
|
|
|
llvm::errs() << "Can't apply replacements for file " << File << "\n";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (Rewrite.overwriteChangedFiles()) {
|
|
|
|
llvm::errs() << "clang-tidy failed to apply suggested fixes.\n";
|
|
|
|
} else {
|
|
|
|
llvm::errs() << "clang-tidy applied " << AppliedFixes << " of "
|
|
|
|
<< TotalFixes << " suggested fixes.\n";
|
|
|
|
}
|
2014-03-27 18:24:11 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-01-14 01:36:41 +08:00
|
|
|
unsigned getWarningsAsErrorsCount() const { return WarningsAsErrors; }
|
|
|
|
|
2014-03-27 18:24:11 +08:00
|
|
|
private:
|
|
|
|
SourceLocation getLocation(StringRef FilePath, unsigned Offset) {
|
|
|
|
if (FilePath.empty())
|
|
|
|
return SourceLocation();
|
|
|
|
|
2019-08-02 05:32:01 +08:00
|
|
|
auto File = SourceMgr.getFileManager().getFile(FilePath);
|
|
|
|
if (!File)
|
|
|
|
return SourceLocation();
|
|
|
|
|
|
|
|
FileID ID = SourceMgr.getOrCreateFileID(*File, SrcMgr::C_User);
|
2014-03-27 18:24:11 +08:00
|
|
|
return SourceMgr.getLocForStartOfFile(ID).getLocWithOffset(Offset);
|
|
|
|
}
|
|
|
|
|
[clang-tidy] Add fix descriptions to clang-tidy checks.
Summary:
Motivation/Context: in the code review system integrating with clang-tidy,
clang-tidy doesn't provide a human-readable description of the fix. Usually
developers have to preview a code diff (before vs after apply the fix) to
understand what the fix does before applying a fix.
This patch proposes that each clang-tidy check provides a short and
actional fix description that can be shown in the UI, so that users can know
what the fix does without previewing diff.
This patch extends clang-tidy framework to support fix descriptions (will add implementations for
existing checks in the future). Fix descriptions and fixes are emitted via diagnostic::Note (rather than
attaching the main warning diagnostic).
Before this patch:
```
void MyCheck::check(...) {
...
diag(loc, "my check warning") << FixtItHint::CreateReplacement(...);
}
```
After:
```
void MyCheck::check(...) {
...
diag(loc, "my check warning"); // Emit a check warning
diag(loc, "fix description", DiagnosticIDs::Note) << FixtItHint::CreateReplacement(...); // Emit a diagnostic note and a fix
}
```
Reviewers: sammccall, alexfh
Reviewed By: alexfh
Subscribers: MyDeveloperDay, Eugene.Zelenko, aaron.ballman, JonasToth, xazax.hun, jdoerfert, cfe-commits
Tags: #clang-tools-extra, #clang
Differential Revision: https://reviews.llvm.org/D59932
llvm-svn: 358576
2019-04-17 20:53:59 +08:00
|
|
|
void reportFix(const DiagnosticBuilder &Diag,
|
|
|
|
const llvm::StringMap<Replacements> &Fix) {
|
|
|
|
for (const auto &FileAndReplacements : Fix) {
|
|
|
|
for (const auto &Repl : FileAndReplacements.second) {
|
|
|
|
if (!Repl.isApplicable())
|
|
|
|
continue;
|
|
|
|
SmallString<128> FixAbsoluteFilePath = Repl.getFilePath();
|
|
|
|
Files.makeAbsolutePath(FixAbsoluteFilePath);
|
|
|
|
SourceLocation FixLoc =
|
|
|
|
getLocation(FixAbsoluteFilePath, Repl.getOffset());
|
|
|
|
SourceLocation FixEndLoc = FixLoc.getLocWithOffset(Repl.getLength());
|
|
|
|
// Retrieve the source range for applicable fixes. Macro definitions
|
|
|
|
// on the command line have locations in a virtual buffer and don't
|
|
|
|
// have valid file paths and are therefore not applicable.
|
|
|
|
CharSourceRange Range =
|
|
|
|
CharSourceRange::getCharRange(SourceRange(FixLoc, FixEndLoc));
|
|
|
|
Diag << FixItHint::CreateReplacement(Range, Repl.getReplacementText());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-01-03 22:36:13 +08:00
|
|
|
void reportNote(const tooling::DiagnosticMessage &Message) {
|
2014-07-02 23:05:04 +08:00
|
|
|
SourceLocation Loc = getLocation(Message.FilePath, Message.FileOffset);
|
[clang-tidy] Add fix descriptions to clang-tidy checks.
Summary:
Motivation/Context: in the code review system integrating with clang-tidy,
clang-tidy doesn't provide a human-readable description of the fix. Usually
developers have to preview a code diff (before vs after apply the fix) to
understand what the fix does before applying a fix.
This patch proposes that each clang-tidy check provides a short and
actional fix description that can be shown in the UI, so that users can know
what the fix does without previewing diff.
This patch extends clang-tidy framework to support fix descriptions (will add implementations for
existing checks in the future). Fix descriptions and fixes are emitted via diagnostic::Note (rather than
attaching the main warning diagnostic).
Before this patch:
```
void MyCheck::check(...) {
...
diag(loc, "my check warning") << FixtItHint::CreateReplacement(...);
}
```
After:
```
void MyCheck::check(...) {
...
diag(loc, "my check warning"); // Emit a check warning
diag(loc, "fix description", DiagnosticIDs::Note) << FixtItHint::CreateReplacement(...); // Emit a diagnostic note and a fix
}
```
Reviewers: sammccall, alexfh
Reviewed By: alexfh
Subscribers: MyDeveloperDay, Eugene.Zelenko, aaron.ballman, JonasToth, xazax.hun, jdoerfert, cfe-commits
Tags: #clang-tools-extra, #clang
Differential Revision: https://reviews.llvm.org/D59932
llvm-svn: 358576
2019-04-17 20:53:59 +08:00
|
|
|
auto Diag =
|
|
|
|
Diags.Report(Loc, Diags.getCustomDiagID(DiagnosticsEngine::Note, "%0"))
|
2014-07-02 23:05:04 +08:00
|
|
|
<< Message.Message;
|
[clang-tidy] Add fix descriptions to clang-tidy checks.
Summary:
Motivation/Context: in the code review system integrating with clang-tidy,
clang-tidy doesn't provide a human-readable description of the fix. Usually
developers have to preview a code diff (before vs after apply the fix) to
understand what the fix does before applying a fix.
This patch proposes that each clang-tidy check provides a short and
actional fix description that can be shown in the UI, so that users can know
what the fix does without previewing diff.
This patch extends clang-tidy framework to support fix descriptions (will add implementations for
existing checks in the future). Fix descriptions and fixes are emitted via diagnostic::Note (rather than
attaching the main warning diagnostic).
Before this patch:
```
void MyCheck::check(...) {
...
diag(loc, "my check warning") << FixtItHint::CreateReplacement(...);
}
```
After:
```
void MyCheck::check(...) {
...
diag(loc, "my check warning"); // Emit a check warning
diag(loc, "fix description", DiagnosticIDs::Note) << FixtItHint::CreateReplacement(...); // Emit a diagnostic note and a fix
}
```
Reviewers: sammccall, alexfh
Reviewed By: alexfh
Subscribers: MyDeveloperDay, Eugene.Zelenko, aaron.ballman, JonasToth, xazax.hun, jdoerfert, cfe-commits
Tags: #clang-tools-extra, #clang
Differential Revision: https://reviews.llvm.org/D59932
llvm-svn: 358576
2019-04-17 20:53:59 +08:00
|
|
|
reportFix(Diag, Message.Fix);
|
2014-07-02 23:05:04 +08:00
|
|
|
}
|
|
|
|
|
2014-03-27 18:24:11 +08:00
|
|
|
FileManager Files;
|
|
|
|
LangOptions LangOpts; // FIXME: use langopts from each original file
|
|
|
|
IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts;
|
|
|
|
DiagnosticConsumer *DiagPrinter;
|
|
|
|
DiagnosticsEngine Diags;
|
|
|
|
SourceManager SourceMgr;
|
2016-10-18 01:25:02 +08:00
|
|
|
llvm::StringMap<Replacements> FileReplacements;
|
2017-04-06 21:41:29 +08:00
|
|
|
ClangTidyContext &Context;
|
2014-03-27 18:24:11 +08:00
|
|
|
bool ApplyFixes;
|
2014-03-27 22:53:37 +08:00
|
|
|
unsigned TotalFixes;
|
|
|
|
unsigned AppliedFixes;
|
2016-01-14 01:36:41 +08:00
|
|
|
unsigned WarningsAsErrors;
|
2014-03-27 18:24:11 +08:00
|
|
|
};
|
|
|
|
|
2014-06-05 21:31:45 +08:00
|
|
|
class ClangTidyASTConsumer : public MultiplexConsumer {
|
|
|
|
public:
|
2014-08-11 03:56:59 +08:00
|
|
|
ClangTidyASTConsumer(std::vector<std::unique_ptr<ASTConsumer>> Consumers,
|
[clang-tidy] Profile is a per-AST (per-TU) data.
Summary:
As discussed in D45931, currently, profiling output of clang-tidy is somewhat not great.
It outputs one profile at the end of the execution, and that profile contains the data
from the last TU that was processed. So if the tool run on multiple TU's, the data is
not accumulated, it is simply discarded.
It would be nice to improve this.
This differential is the first step - make this profiling info per-TU,
and output it after the tool has finished processing each TU.
In particular, when `ClangTidyASTConsumer` destructor runs.
Next step will be to add a CSV (JSON?) printer to store said profiles under user-specified directory prefix.
Reviewers: alexfh, sbenza
Reviewed By: alexfh
Subscribers: Eugene.Zelenko, mgorny, xazax.hun, mgrang, klimek, cfe-commits
Tags: #clang-tools-extra
Differential Revision: https://reviews.llvm.org/D46504
llvm-svn: 331763
2018-05-08 21:14:21 +08:00
|
|
|
std::unique_ptr<ClangTidyProfiling> Profiling,
|
2014-06-05 21:31:45 +08:00
|
|
|
std::unique_ptr<ast_matchers::MatchFinder> Finder,
|
|
|
|
std::vector<std::unique_ptr<ClangTidyCheck>> Checks)
|
[clang-tidy] Profile is a per-AST (per-TU) data.
Summary:
As discussed in D45931, currently, profiling output of clang-tidy is somewhat not great.
It outputs one profile at the end of the execution, and that profile contains the data
from the last TU that was processed. So if the tool run on multiple TU's, the data is
not accumulated, it is simply discarded.
It would be nice to improve this.
This differential is the first step - make this profiling info per-TU,
and output it after the tool has finished processing each TU.
In particular, when `ClangTidyASTConsumer` destructor runs.
Next step will be to add a CSV (JSON?) printer to store said profiles under user-specified directory prefix.
Reviewers: alexfh, sbenza
Reviewed By: alexfh
Subscribers: Eugene.Zelenko, mgorny, xazax.hun, mgrang, klimek, cfe-commits
Tags: #clang-tools-extra
Differential Revision: https://reviews.llvm.org/D46504
llvm-svn: 331763
2018-05-08 21:14:21 +08:00
|
|
|
: MultiplexConsumer(std::move(Consumers)),
|
|
|
|
Profiling(std::move(Profiling)), Finder(std::move(Finder)),
|
2014-06-05 21:31:45 +08:00
|
|
|
Checks(std::move(Checks)) {}
|
|
|
|
|
|
|
|
private:
|
[clang-tidy] Profile is a per-AST (per-TU) data.
Summary:
As discussed in D45931, currently, profiling output of clang-tidy is somewhat not great.
It outputs one profile at the end of the execution, and that profile contains the data
from the last TU that was processed. So if the tool run on multiple TU's, the data is
not accumulated, it is simply discarded.
It would be nice to improve this.
This differential is the first step - make this profiling info per-TU,
and output it after the tool has finished processing each TU.
In particular, when `ClangTidyASTConsumer` destructor runs.
Next step will be to add a CSV (JSON?) printer to store said profiles under user-specified directory prefix.
Reviewers: alexfh, sbenza
Reviewed By: alexfh
Subscribers: Eugene.Zelenko, mgorny, xazax.hun, mgrang, klimek, cfe-commits
Tags: #clang-tools-extra
Differential Revision: https://reviews.llvm.org/D46504
llvm-svn: 331763
2018-05-08 21:14:21 +08:00
|
|
|
// Destructor order matters! Profiling must be destructed last.
|
|
|
|
// Or at least after Finder.
|
|
|
|
std::unique_ptr<ClangTidyProfiling> Profiling;
|
2014-06-05 21:31:45 +08:00
|
|
|
std::unique_ptr<ast_matchers::MatchFinder> Finder;
|
|
|
|
std::vector<std::unique_ptr<ClangTidyCheck>> Checks;
|
|
|
|
};
|
|
|
|
|
2014-01-03 17:31:57 +08:00
|
|
|
} // namespace
|
Clang-tidy: added --disable-checks, --list-checks options.
Summary:
Allow disabling checks by regex. By default, disable alpha.* checks,
that are not particularly good tested (e.g. IdempotentOperationChecker, see
http://llvm-reviews.chandlerc.com/D2427).
Fixed a bug, that would disable all analyzer checks, when using a regex more
strict, than 'clang-analyzer-', for example --checks='clang-analyzer-deadcode-'.
Added --list-checks to list all enabled checks. This is useful to test specific
values in --checks/--disable-checks.
Reviewers: djasper, klimek
Reviewed By: klimek
CC: cfe-commits, klimek
Differential Revision: http://llvm-reviews.chandlerc.com/D2444
llvm-svn: 197717
2013-12-20 03:57:05 +08:00
|
|
|
|
2014-01-03 17:31:57 +08:00
|
|
|
ClangTidyASTConsumerFactory::ClangTidyASTConsumerFactory(
|
2019-03-22 21:42:48 +08:00
|
|
|
ClangTidyContext &Context,
|
|
|
|
IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> OverlayFS)
|
|
|
|
: Context(Context), OverlayFS(OverlayFS),
|
|
|
|
CheckFactories(new ClangTidyCheckFactories) {
|
2019-11-22 19:22:40 +08:00
|
|
|
for (ClangTidyModuleRegistry::entry E : ClangTidyModuleRegistry::entries()) {
|
|
|
|
std::unique_ptr<ClangTidyModule> Module = E.instantiate();
|
2014-01-03 17:31:57 +08:00
|
|
|
Module->addCheckFactories(*CheckFactories);
|
|
|
|
}
|
|
|
|
}
|
2013-11-14 23:49:44 +08:00
|
|
|
|
2018-10-02 04:24:22 +08:00
|
|
|
#if CLANG_ENABLE_STATIC_ANALYZER
|
2015-03-12 01:25:22 +08:00
|
|
|
static void setStaticAnalyzerCheckerOpts(const ClangTidyOptions &Opts,
|
|
|
|
AnalyzerOptionsRef AnalyzerOptions) {
|
|
|
|
StringRef AnalyzerPrefix(AnalyzerCheckNamePrefix);
|
|
|
|
for (const auto &Opt : Opts.CheckOptions) {
|
|
|
|
StringRef OptName(Opt.first);
|
|
|
|
if (!OptName.startswith(AnalyzerPrefix))
|
|
|
|
continue;
|
|
|
|
AnalyzerOptions->Config[OptName.substr(AnalyzerPrefix.size())] = Opt.second;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-11-08 15:43:42 +08:00
|
|
|
typedef std::vector<std::pair<std::string, bool>> CheckersList;
|
|
|
|
|
2019-08-16 09:53:14 +08:00
|
|
|
static CheckersList getAnalyzerCheckersAndPackages(ClangTidyContext &Context,
|
|
|
|
bool IncludeExperimental) {
|
2016-11-08 15:43:42 +08:00
|
|
|
CheckersList List;
|
|
|
|
|
|
|
|
const auto &RegisteredCheckers =
|
[clang-tidy] Add a flag to enable alpha checkers
Summary: The alpha checkers can already be enabled using the clang driver, this allows them to be enabled using the clang-tidy as well. This can make it easier to test the alpha checkers with projects which already support the compile_commands.json. It will also allow more people to give feedback and patches about the alpha checkers since they can run it as part of clang tidy checks.
Reviewers: aaron.ballman, hokein, ilya-biryukov, alexfh, lebedev.ri, xbolva00
Reviewed By: aaron.ballman, alexfh, lebedev.ri, xbolva00
Subscribers: xbolva00, NoQ, dcoughlin, lebedev.ri, xazax.hun, cfe-commits
Patch by Paul Fultz II!
Differential Revision: https://reviews.llvm.org/D46159
llvm-svn: 332609
2018-05-17 22:04:27 +08:00
|
|
|
AnalyzerOptions::getRegisteredCheckers(IncludeExperimental);
|
2016-11-08 15:43:42 +08:00
|
|
|
bool AnalyzerChecksEnabled = false;
|
|
|
|
for (StringRef CheckName : RegisteredCheckers) {
|
|
|
|
std::string ClangTidyCheckName((AnalyzerCheckNamePrefix + CheckName).str());
|
2017-05-17 22:39:47 +08:00
|
|
|
AnalyzerChecksEnabled |= Context.isCheckEnabled(ClangTidyCheckName);
|
2016-11-08 15:43:42 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!AnalyzerChecksEnabled)
|
|
|
|
return List;
|
|
|
|
|
|
|
|
// List all static analyzer checkers that our filter enables.
|
|
|
|
//
|
|
|
|
// Always add all core checkers if any other static analyzer check is enabled.
|
|
|
|
// This is currently necessary, as other path sensitive checks rely on the
|
|
|
|
// core checkers.
|
|
|
|
for (StringRef CheckName : RegisteredCheckers) {
|
|
|
|
std::string ClangTidyCheckName((AnalyzerCheckNamePrefix + CheckName).str());
|
|
|
|
|
2017-05-17 22:39:47 +08:00
|
|
|
if (CheckName.startswith("core") ||
|
|
|
|
Context.isCheckEnabled(ClangTidyCheckName)) {
|
2020-01-29 17:32:04 +08:00
|
|
|
List.emplace_back(std::string(CheckName), true);
|
2017-05-17 22:39:47 +08:00
|
|
|
}
|
2016-11-08 15:43:42 +08:00
|
|
|
}
|
|
|
|
return List;
|
|
|
|
}
|
2018-10-02 04:24:22 +08:00
|
|
|
#endif // CLANG_ENABLE_STATIC_ANALYZER
|
2016-11-08 15:43:42 +08:00
|
|
|
|
2014-08-11 03:56:59 +08:00
|
|
|
std::unique_ptr<clang::ASTConsumer>
|
|
|
|
ClangTidyASTConsumerFactory::CreateASTConsumer(
|
2014-01-03 17:31:57 +08:00
|
|
|
clang::CompilerInstance &Compiler, StringRef File) {
|
|
|
|
// FIXME: Move this to a separate method, so that CreateASTConsumer doesn't
|
|
|
|
// modify Compiler.
|
2019-03-22 21:42:48 +08:00
|
|
|
SourceManager *SM = &Compiler.getSourceManager();
|
|
|
|
Context.setSourceManager(SM);
|
2014-06-05 21:31:45 +08:00
|
|
|
Context.setCurrentFile(File);
|
2014-07-14 22:10:03 +08:00
|
|
|
Context.setASTContext(&Compiler.getASTContext());
|
2014-06-05 21:31:45 +08:00
|
|
|
|
2016-02-26 17:19:33 +08:00
|
|
|
auto WorkingDir = Compiler.getSourceManager()
|
|
|
|
.getFileManager()
|
|
|
|
.getVirtualFileSystem()
|
2019-03-27 06:32:06 +08:00
|
|
|
.getCurrentWorkingDirectory();
|
2016-02-26 17:19:33 +08:00
|
|
|
if (WorkingDir)
|
|
|
|
Context.setCurrentBuildDirectory(WorkingDir.get());
|
|
|
|
|
2019-09-26 21:55:01 +08:00
|
|
|
std::vector<std::unique_ptr<ClangTidyCheck>> Checks =
|
|
|
|
CheckFactories->createChecks(&Context);
|
2014-06-05 21:31:45 +08:00
|
|
|
|
2014-10-24 01:23:20 +08:00
|
|
|
ast_matchers::MatchFinder::MatchFinderOptions FinderOptions;
|
[clang-tidy] Profile is a per-AST (per-TU) data.
Summary:
As discussed in D45931, currently, profiling output of clang-tidy is somewhat not great.
It outputs one profile at the end of the execution, and that profile contains the data
from the last TU that was processed. So if the tool run on multiple TU's, the data is
not accumulated, it is simply discarded.
It would be nice to improve this.
This differential is the first step - make this profiling info per-TU,
and output it after the tool has finished processing each TU.
In particular, when `ClangTidyASTConsumer` destructor runs.
Next step will be to add a CSV (JSON?) printer to store said profiles under user-specified directory prefix.
Reviewers: alexfh, sbenza
Reviewed By: alexfh
Subscribers: Eugene.Zelenko, mgorny, xazax.hun, mgrang, klimek, cfe-commits
Tags: #clang-tools-extra
Differential Revision: https://reviews.llvm.org/D46504
llvm-svn: 331763
2018-05-08 21:14:21 +08:00
|
|
|
|
|
|
|
std::unique_ptr<ClangTidyProfiling> Profiling;
|
|
|
|
if (Context.getEnableProfiling()) {
|
2019-08-15 07:52:23 +08:00
|
|
|
Profiling = std::make_unique<ClangTidyProfiling>(
|
[clang-tidy] Store checks profiling info as JSON files
Summary:
Continuation of D46504.
Example output:
```
$ clang-tidy -enable-check-profile -store-check-profile=. -checks=-*,readability-function-size source.cpp
$ # Note that there won't be timings table printed to the console.
$ cat *.json
{
"file": "/path/to/source.cpp",
"timestamp": "2018-05-16 16:13:18.717446360",
"profile": {
"time.clang-tidy.readability-function-size.wall": 1.0421266555786133e+00,
"time.clang-tidy.readability-function-size.user": 9.2088400000005421e-01,
"time.clang-tidy.readability-function-size.sys": 1.2418899999999974e-01
}
}
```
There are two arguments that control profile storage:
* `-store-check-profile=<prefix>`
By default reports are printed in tabulated format to stderr. When this option
is passed, these per-TU profiles are instead stored as JSON.
If the prefix is not an absolute path, it is considered to be relative to the
directory from where you have run :program:`clang-tidy`. All `.` and `..`
patterns in the path are collapsed, and symlinks are resolved.
Example:
Let's suppose you have a source file named `example.cpp`, located in
`/source` directory.
* If you specify `-store-check-profile=/tmp`, then the profile will be saved
to `/tmp/<timestamp>-example.cpp.json`
* If you run :program:`clang-tidy` from within `/foo` directory, and specify
`-store-check-profile=.`, then the profile will still be saved to
`/foo/<timestamp>-example.cpp.json`
Reviewers: alexfh, sbenza, george.karpenkov, NoQ, aaron.ballman
Reviewed By: alexfh, george.karpenkov, aaron.ballman
Subscribers: Quuxplusone, JonasToth, aaron.ballman, llvm-commits, rja, Eugene.Zelenko, xazax.hun, mgrang, cfe-commits
Tags: #clang-tools-extra
Differential Revision: https://reviews.llvm.org/D46602
llvm-svn: 334101
2018-06-06 23:07:51 +08:00
|
|
|
Context.getProfileStorageParams());
|
[clang-tidy] Profile is a per-AST (per-TU) data.
Summary:
As discussed in D45931, currently, profiling output of clang-tidy is somewhat not great.
It outputs one profile at the end of the execution, and that profile contains the data
from the last TU that was processed. So if the tool run on multiple TU's, the data is
not accumulated, it is simply discarded.
It would be nice to improve this.
This differential is the first step - make this profiling info per-TU,
and output it after the tool has finished processing each TU.
In particular, when `ClangTidyASTConsumer` destructor runs.
Next step will be to add a CSV (JSON?) printer to store said profiles under user-specified directory prefix.
Reviewers: alexfh, sbenza
Reviewed By: alexfh
Subscribers: Eugene.Zelenko, mgorny, xazax.hun, mgrang, klimek, cfe-commits
Tags: #clang-tools-extra
Differential Revision: https://reviews.llvm.org/D46504
llvm-svn: 331763
2018-05-08 21:14:21 +08:00
|
|
|
FinderOptions.CheckProfiling.emplace(Profiling->Records);
|
|
|
|
}
|
2014-10-24 01:23:20 +08:00
|
|
|
|
2014-06-05 21:31:45 +08:00
|
|
|
std::unique_ptr<ast_matchers::MatchFinder> Finder(
|
2014-10-24 01:23:20 +08:00
|
|
|
new ast_matchers::MatchFinder(std::move(FinderOptions)));
|
|
|
|
|
2019-03-22 21:42:48 +08:00
|
|
|
Preprocessor *PP = &Compiler.getPreprocessor();
|
|
|
|
Preprocessor *ModuleExpanderPP = PP;
|
|
|
|
|
|
|
|
if (Context.getLangOpts().Modules && OverlayFS != nullptr) {
|
2019-08-15 07:52:23 +08:00
|
|
|
auto ModuleExpander = std::make_unique<ExpandModularHeadersPPCallbacks>(
|
2019-03-22 21:42:48 +08:00
|
|
|
&Compiler, OverlayFS);
|
|
|
|
ModuleExpanderPP = ModuleExpander->getPreprocessor();
|
|
|
|
PP->addPPCallbacks(std::move(ModuleExpander));
|
|
|
|
}
|
|
|
|
|
2014-06-05 21:31:45 +08:00
|
|
|
for (auto &Check : Checks) {
|
[clang-tidy] Added virtual isLanguageVersionSupported to ClangTidyCheck
Summary:
Motivated by [[ https://bugs.llvm.org/show_bug.cgi?id=45045 | Tune inspections to a specific C++ standard. ]]
Moves the isLanguageVersionSupported virtual function from `MakeSmartPtrCheck` to the base `ClangTidyCheck` class.
This will disable registering matchers or pp callbacks on unsupported language versions for a check.
Having it as a standalone function is cleaner than manually disabling the check in the register function and should hopefully
encourage check developers to actually restrict the check based on language version.
As an added bonus this could enable automatic detection of what language version a check runs on for the purpose of documentation generation
Reviewers: aaron.ballman, gribozavr2, Eugene.Zelenko, JonasToth, alexfh, hokein
Reviewed By: gribozavr2
Subscribers: xazax.hun, jkorous, arphaman, kadircet, usaxena95, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D75289
2020-02-28 21:03:30 +08:00
|
|
|
if (!Check->isLanguageVersionSupported(Context.getLangOpts()))
|
|
|
|
continue;
|
2014-06-05 21:31:45 +08:00
|
|
|
Check->registerMatchers(&*Finder);
|
2019-03-22 21:42:48 +08:00
|
|
|
Check->registerPPCallbacks(*SM, PP, ModuleExpanderPP);
|
2014-06-05 21:31:45 +08:00
|
|
|
}
|
2014-01-03 17:31:57 +08:00
|
|
|
|
2014-08-11 03:56:59 +08:00
|
|
|
std::vector<std::unique_ptr<ASTConsumer>> Consumers;
|
2014-06-05 21:31:45 +08:00
|
|
|
if (!Checks.empty())
|
|
|
|
Consumers.push_back(Finder->newASTConsumer());
|
2014-02-14 00:10:47 +08:00
|
|
|
|
2018-10-02 04:24:22 +08:00
|
|
|
#if CLANG_ENABLE_STATIC_ANALYZER
|
2014-04-30 22:09:24 +08:00
|
|
|
AnalyzerOptionsRef AnalyzerOptions = Compiler.getAnalyzerOpts();
|
2019-08-16 09:53:14 +08:00
|
|
|
AnalyzerOptions->CheckersAndPackages = getAnalyzerCheckersAndPackages(
|
|
|
|
Context, Context.canEnableAnalyzerAlphaCheckers());
|
|
|
|
if (!AnalyzerOptions->CheckersAndPackages.empty()) {
|
2015-03-12 01:25:22 +08:00
|
|
|
setStaticAnalyzerCheckerOpts(Context.getOptions(), AnalyzerOptions);
|
2014-04-30 22:09:24 +08:00
|
|
|
AnalyzerOptions->AnalysisStoreOpt = RegionStoreModel;
|
|
|
|
AnalyzerOptions->AnalysisDiagOpt = PD_NONE;
|
|
|
|
AnalyzerOptions->AnalyzeNestedBlocks = true;
|
|
|
|
AnalyzerOptions->eagerlyAssumeBinOpBifurcation = true;
|
2014-08-11 03:56:59 +08:00
|
|
|
std::unique_ptr<ento::AnalysisASTConsumer> AnalysisConsumer =
|
2014-08-27 23:14:47 +08:00
|
|
|
ento::CreateAnalysisConsumer(Compiler);
|
2014-02-14 00:10:47 +08:00
|
|
|
AnalysisConsumer->AddDiagnosticConsumer(
|
|
|
|
new AnalyzerDiagnosticConsumer(Context));
|
2014-08-11 03:56:59 +08:00
|
|
|
Consumers.push_back(std::move(AnalysisConsumer));
|
2014-02-14 00:10:47 +08:00
|
|
|
}
|
2018-10-02 04:24:22 +08:00
|
|
|
#endif // CLANG_ENABLE_STATIC_ANALYZER
|
2019-08-15 07:52:23 +08:00
|
|
|
return std::make_unique<ClangTidyASTConsumer>(
|
[clang-tidy] Profile is a per-AST (per-TU) data.
Summary:
As discussed in D45931, currently, profiling output of clang-tidy is somewhat not great.
It outputs one profile at the end of the execution, and that profile contains the data
from the last TU that was processed. So if the tool run on multiple TU's, the data is
not accumulated, it is simply discarded.
It would be nice to improve this.
This differential is the first step - make this profiling info per-TU,
and output it after the tool has finished processing each TU.
In particular, when `ClangTidyASTConsumer` destructor runs.
Next step will be to add a CSV (JSON?) printer to store said profiles under user-specified directory prefix.
Reviewers: alexfh, sbenza
Reviewed By: alexfh
Subscribers: Eugene.Zelenko, mgorny, xazax.hun, mgrang, klimek, cfe-commits
Tags: #clang-tools-extra
Differential Revision: https://reviews.llvm.org/D46504
llvm-svn: 331763
2018-05-08 21:14:21 +08:00
|
|
|
std::move(Consumers), std::move(Profiling), std::move(Finder),
|
|
|
|
std::move(Checks));
|
2014-01-03 17:31:57 +08:00
|
|
|
}
|
|
|
|
|
2014-09-12 16:53:36 +08:00
|
|
|
std::vector<std::string> ClangTidyASTConsumerFactory::getCheckNames() {
|
2014-01-03 17:31:57 +08:00
|
|
|
std::vector<std::string> CheckNames;
|
2014-03-06 18:17:46 +08:00
|
|
|
for (const auto &CheckFactory : *CheckFactories) {
|
2017-05-17 22:39:47 +08:00
|
|
|
if (Context.isCheckEnabled(CheckFactory.first))
|
2014-03-06 18:17:46 +08:00
|
|
|
CheckNames.push_back(CheckFactory.first);
|
2013-07-29 16:19:24 +08:00
|
|
|
}
|
|
|
|
|
2018-10-02 04:24:22 +08:00
|
|
|
#if CLANG_ENABLE_STATIC_ANALYZER
|
2019-08-16 09:53:14 +08:00
|
|
|
for (const auto &AnalyzerCheck : getAnalyzerCheckersAndPackages(
|
[clang-tidy] Add a flag to enable alpha checkers
Summary: The alpha checkers can already be enabled using the clang driver, this allows them to be enabled using the clang-tidy as well. This can make it easier to test the alpha checkers with projects which already support the compile_commands.json. It will also allow more people to give feedback and patches about the alpha checkers since they can run it as part of clang tidy checks.
Reviewers: aaron.ballman, hokein, ilya-biryukov, alexfh, lebedev.ri, xbolva00
Reviewed By: aaron.ballman, alexfh, lebedev.ri, xbolva00
Subscribers: xbolva00, NoQ, dcoughlin, lebedev.ri, xazax.hun, cfe-commits
Patch by Paul Fultz II!
Differential Revision: https://reviews.llvm.org/D46159
llvm-svn: 332609
2018-05-17 22:04:27 +08:00
|
|
|
Context, Context.canEnableAnalyzerAlphaCheckers()))
|
2014-03-06 18:17:46 +08:00
|
|
|
CheckNames.push_back(AnalyzerCheckNamePrefix + AnalyzerCheck.first);
|
2018-10-02 04:24:22 +08:00
|
|
|
#endif // CLANG_ENABLE_STATIC_ANALYZER
|
2013-07-29 16:19:24 +08:00
|
|
|
|
2014-01-03 17:31:57 +08:00
|
|
|
std::sort(CheckNames.begin(), CheckNames.end());
|
|
|
|
return CheckNames;
|
|
|
|
}
|
2013-11-14 23:49:44 +08:00
|
|
|
|
2014-09-12 16:53:36 +08:00
|
|
|
ClangTidyOptions::OptionMap ClangTidyASTConsumerFactory::getCheckOptions() {
|
|
|
|
ClangTidyOptions::OptionMap Options;
|
2019-09-26 21:55:01 +08:00
|
|
|
std::vector<std::unique_ptr<ClangTidyCheck>> Checks =
|
|
|
|
CheckFactories->createChecks(&Context);
|
2014-09-12 16:53:36 +08:00
|
|
|
for (const auto &Check : Checks)
|
|
|
|
Check->storeOptions(Options);
|
|
|
|
return Options;
|
|
|
|
}
|
|
|
|
|
[clang-tidy] Add a flag to enable alpha checkers
Summary: The alpha checkers can already be enabled using the clang driver, this allows them to be enabled using the clang-tidy as well. This can make it easier to test the alpha checkers with projects which already support the compile_commands.json. It will also allow more people to give feedback and patches about the alpha checkers since they can run it as part of clang tidy checks.
Reviewers: aaron.ballman, hokein, ilya-biryukov, alexfh, lebedev.ri, xbolva00
Reviewed By: aaron.ballman, alexfh, lebedev.ri, xbolva00
Subscribers: xbolva00, NoQ, dcoughlin, lebedev.ri, xazax.hun, cfe-commits
Patch by Paul Fultz II!
Differential Revision: https://reviews.llvm.org/D46159
llvm-svn: 332609
2018-05-17 22:04:27 +08:00
|
|
|
std::vector<std::string>
|
|
|
|
getCheckNames(const ClangTidyOptions &Options,
|
|
|
|
bool AllowEnablingAnalyzerAlphaCheckers) {
|
2014-06-05 21:31:45 +08:00
|
|
|
clang::tidy::ClangTidyContext Context(
|
2019-08-15 07:52:23 +08:00
|
|
|
std::make_unique<DefaultOptionsProvider>(ClangTidyGlobalOptions(),
|
[clang-tidy] Add a flag to enable alpha checkers
Summary: The alpha checkers can already be enabled using the clang driver, this allows them to be enabled using the clang-tidy as well. This can make it easier to test the alpha checkers with projects which already support the compile_commands.json. It will also allow more people to give feedback and patches about the alpha checkers since they can run it as part of clang tidy checks.
Reviewers: aaron.ballman, hokein, ilya-biryukov, alexfh, lebedev.ri, xbolva00
Reviewed By: aaron.ballman, alexfh, lebedev.ri, xbolva00
Subscribers: xbolva00, NoQ, dcoughlin, lebedev.ri, xazax.hun, cfe-commits
Patch by Paul Fultz II!
Differential Revision: https://reviews.llvm.org/D46159
llvm-svn: 332609
2018-05-17 22:04:27 +08:00
|
|
|
Options),
|
|
|
|
AllowEnablingAnalyzerAlphaCheckers);
|
2014-06-05 21:31:45 +08:00
|
|
|
ClangTidyASTConsumerFactory Factory(Context);
|
2014-09-12 16:53:36 +08:00
|
|
|
return Factory.getCheckNames();
|
|
|
|
}
|
|
|
|
|
[clang-tidy] Add a flag to enable alpha checkers
Summary: The alpha checkers can already be enabled using the clang driver, this allows them to be enabled using the clang-tidy as well. This can make it easier to test the alpha checkers with projects which already support the compile_commands.json. It will also allow more people to give feedback and patches about the alpha checkers since they can run it as part of clang tidy checks.
Reviewers: aaron.ballman, hokein, ilya-biryukov, alexfh, lebedev.ri, xbolva00
Reviewed By: aaron.ballman, alexfh, lebedev.ri, xbolva00
Subscribers: xbolva00, NoQ, dcoughlin, lebedev.ri, xazax.hun, cfe-commits
Patch by Paul Fultz II!
Differential Revision: https://reviews.llvm.org/D46159
llvm-svn: 332609
2018-05-17 22:04:27 +08:00
|
|
|
ClangTidyOptions::OptionMap
|
|
|
|
getCheckOptions(const ClangTidyOptions &Options,
|
|
|
|
bool AllowEnablingAnalyzerAlphaCheckers) {
|
2014-09-12 16:53:36 +08:00
|
|
|
clang::tidy::ClangTidyContext Context(
|
2019-08-15 07:52:23 +08:00
|
|
|
std::make_unique<DefaultOptionsProvider>(ClangTidyGlobalOptions(),
|
[clang-tidy] Add a flag to enable alpha checkers
Summary: The alpha checkers can already be enabled using the clang driver, this allows them to be enabled using the clang-tidy as well. This can make it easier to test the alpha checkers with projects which already support the compile_commands.json. It will also allow more people to give feedback and patches about the alpha checkers since they can run it as part of clang tidy checks.
Reviewers: aaron.ballman, hokein, ilya-biryukov, alexfh, lebedev.ri, xbolva00
Reviewed By: aaron.ballman, alexfh, lebedev.ri, xbolva00
Subscribers: xbolva00, NoQ, dcoughlin, lebedev.ri, xazax.hun, cfe-commits
Patch by Paul Fultz II!
Differential Revision: https://reviews.llvm.org/D46159
llvm-svn: 332609
2018-05-17 22:04:27 +08:00
|
|
|
Options),
|
|
|
|
AllowEnablingAnalyzerAlphaCheckers);
|
2014-09-12 16:53:36 +08:00
|
|
|
ClangTidyASTConsumerFactory Factory(Context);
|
|
|
|
return Factory.getCheckOptions();
|
2013-11-14 23:49:44 +08:00
|
|
|
}
|
|
|
|
|
[clang-tidy] Get ClangTidyContext out of the business of storing diagnostics. NFC
Summary:
Currently ClangTidyContext::diag() sends the diagnostics to a
DiagnosticsEngine, which probably delegates to a ClangTidyDiagnosticsConsumer,
which is supposed to go back and populate ClangTidyContext::Errors.
After this patch, the diagnostics are stored in the ClangTidyDiagnosticsConsumer
itself and can be retrieved from there.
Why?
- the round-trip from context -> engine -> consumer -> context is confusing
and makes it harder to establish layering between these things.
- context does too many things, and makes it hard to use clang-tidy as a library
- everyone who actually wants the diagnostics has access to the ClangTidyDiagnosticsConsumer
The most natural implementation (ClangTidyDiagnosticsConsumer::take()
finalizes diagnostics) causes a test failure: clang-tidy-run-with-database.cpp
asserts that clang-tidy exits successfully when trying to process a file
that doesn't exist.
In clang-tidy today, this happens because finish() is never called, so the
diagnostic is never flushed. This looks like a bug to me.
For now, this patch carefully preserves that behavior, but I'll ping the
authors to see whether it's deliberate and worth preserving.
Reviewers: hokein
Subscribers: xazax.hun, cfe-commits, alexfh
Differential Revision: https://reviews.llvm.org/D53953
llvm-svn: 345961
2018-11-02 18:01:59 +08:00
|
|
|
std::vector<ClangTidyError>
|
|
|
|
runClangTidy(clang::tidy::ClangTidyContext &Context,
|
|
|
|
const CompilationDatabase &Compilations,
|
|
|
|
ArrayRef<std::string> InputFiles,
|
2019-03-22 21:42:48 +08:00
|
|
|
llvm::IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> BaseFS,
|
[clang-tidy] Get ClangTidyContext out of the business of storing diagnostics. NFC
Summary:
Currently ClangTidyContext::diag() sends the diagnostics to a
DiagnosticsEngine, which probably delegates to a ClangTidyDiagnosticsConsumer,
which is supposed to go back and populate ClangTidyContext::Errors.
After this patch, the diagnostics are stored in the ClangTidyDiagnosticsConsumer
itself and can be retrieved from there.
Why?
- the round-trip from context -> engine -> consumer -> context is confusing
and makes it harder to establish layering between these things.
- context does too many things, and makes it hard to use clang-tidy as a library
- everyone who actually wants the diagnostics has access to the ClangTidyDiagnosticsConsumer
The most natural implementation (ClangTidyDiagnosticsConsumer::take()
finalizes diagnostics) causes a test failure: clang-tidy-run-with-database.cpp
asserts that clang-tidy exits successfully when trying to process a file
that doesn't exist.
In clang-tidy today, this happens because finish() is never called, so the
diagnostic is never flushed. This looks like a bug to me.
For now, this patch carefully preserves that behavior, but I'll ping the
authors to see whether it's deliberate and worth preserving.
Reviewers: hokein
Subscribers: xazax.hun, cfe-commits, alexfh
Differential Revision: https://reviews.llvm.org/D53953
llvm-svn: 345961
2018-11-02 18:01:59 +08:00
|
|
|
bool EnableCheckProfile, llvm::StringRef StoreCheckProfile) {
|
2018-01-23 20:31:06 +08:00
|
|
|
ClangTool Tool(Compilations, InputFiles,
|
|
|
|
std::make_shared<PCHContainerOperations>(), BaseFS);
|
2016-04-06 22:07:51 +08:00
|
|
|
|
|
|
|
// Add extra arguments passed by the clang-tidy command-line.
|
|
|
|
ArgumentsAdjuster PerFileExtraArgumentsInserter =
|
|
|
|
[&Context](const CommandLineArguments &Args, StringRef Filename) {
|
|
|
|
ClangTidyOptions Opts = Context.getOptionsForFile(Filename);
|
2016-08-23 22:13:31 +08:00
|
|
|
CommandLineArguments AdjustedArgs = Args;
|
|
|
|
if (Opts.ExtraArgsBefore) {
|
|
|
|
auto I = AdjustedArgs.begin();
|
|
|
|
if (I != AdjustedArgs.end() && !StringRef(*I).startswith("-"))
|
|
|
|
++I; // Skip compiler binary name, if it is there.
|
|
|
|
AdjustedArgs.insert(I, Opts.ExtraArgsBefore->begin(),
|
|
|
|
Opts.ExtraArgsBefore->end());
|
|
|
|
}
|
2016-04-06 22:07:51 +08:00
|
|
|
if (Opts.ExtraArgs)
|
|
|
|
AdjustedArgs.insert(AdjustedArgs.end(), Opts.ExtraArgs->begin(),
|
|
|
|
Opts.ExtraArgs->end());
|
|
|
|
return AdjustedArgs;
|
|
|
|
};
|
|
|
|
|
2015-11-10 00:28:11 +08:00
|
|
|
Tool.appendArgumentsAdjuster(PerFileExtraArgumentsInserter);
|
2019-01-21 18:10:18 +08:00
|
|
|
Tool.appendArgumentsAdjuster(getStripPluginsAdjuster());
|
[clang-tidy] Profile is a per-AST (per-TU) data.
Summary:
As discussed in D45931, currently, profiling output of clang-tidy is somewhat not great.
It outputs one profile at the end of the execution, and that profile contains the data
from the last TU that was processed. So if the tool run on multiple TU's, the data is
not accumulated, it is simply discarded.
It would be nice to improve this.
This differential is the first step - make this profiling info per-TU,
and output it after the tool has finished processing each TU.
In particular, when `ClangTidyASTConsumer` destructor runs.
Next step will be to add a CSV (JSON?) printer to store said profiles under user-specified directory prefix.
Reviewers: alexfh, sbenza
Reviewed By: alexfh
Subscribers: Eugene.Zelenko, mgorny, xazax.hun, mgrang, klimek, cfe-commits
Tags: #clang-tools-extra
Differential Revision: https://reviews.llvm.org/D46504
llvm-svn: 331763
2018-05-08 21:14:21 +08:00
|
|
|
Context.setEnableProfiling(EnableCheckProfile);
|
[clang-tidy] Store checks profiling info as JSON files
Summary:
Continuation of D46504.
Example output:
```
$ clang-tidy -enable-check-profile -store-check-profile=. -checks=-*,readability-function-size source.cpp
$ # Note that there won't be timings table printed to the console.
$ cat *.json
{
"file": "/path/to/source.cpp",
"timestamp": "2018-05-16 16:13:18.717446360",
"profile": {
"time.clang-tidy.readability-function-size.wall": 1.0421266555786133e+00,
"time.clang-tidy.readability-function-size.user": 9.2088400000005421e-01,
"time.clang-tidy.readability-function-size.sys": 1.2418899999999974e-01
}
}
```
There are two arguments that control profile storage:
* `-store-check-profile=<prefix>`
By default reports are printed in tabulated format to stderr. When this option
is passed, these per-TU profiles are instead stored as JSON.
If the prefix is not an absolute path, it is considered to be relative to the
directory from where you have run :program:`clang-tidy`. All `.` and `..`
patterns in the path are collapsed, and symlinks are resolved.
Example:
Let's suppose you have a source file named `example.cpp`, located in
`/source` directory.
* If you specify `-store-check-profile=/tmp`, then the profile will be saved
to `/tmp/<timestamp>-example.cpp.json`
* If you run :program:`clang-tidy` from within `/foo` directory, and specify
`-store-check-profile=.`, then the profile will still be saved to
`/foo/<timestamp>-example.cpp.json`
Reviewers: alexfh, sbenza, george.karpenkov, NoQ, aaron.ballman
Reviewed By: alexfh, george.karpenkov, aaron.ballman
Subscribers: Quuxplusone, JonasToth, aaron.ballman, llvm-commits, rja, Eugene.Zelenko, xazax.hun, mgrang, cfe-commits
Tags: #clang-tools-extra
Differential Revision: https://reviews.llvm.org/D46602
llvm-svn: 334101
2018-06-06 23:07:51 +08:00
|
|
|
Context.setProfileStoragePrefix(StoreCheckProfile);
|
2014-10-24 01:23:20 +08:00
|
|
|
|
2013-07-29 16:19:24 +08:00
|
|
|
ClangTidyDiagnosticConsumer DiagConsumer(Context);
|
2018-11-09 01:42:16 +08:00
|
|
|
DiagnosticsEngine DE(new DiagnosticIDs(), new DiagnosticOptions(),
|
|
|
|
&DiagConsumer, /*ShouldOwnClient=*/false);
|
|
|
|
Context.setDiagnosticsEngine(&DE);
|
2013-11-14 23:49:44 +08:00
|
|
|
Tool.setDiagnosticConsumer(&DiagConsumer);
|
2014-01-03 17:31:57 +08:00
|
|
|
|
|
|
|
class ActionFactory : public FrontendActionFactory {
|
|
|
|
public:
|
2019-03-22 21:42:48 +08:00
|
|
|
ActionFactory(ClangTidyContext &Context,
|
|
|
|
IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> BaseFS)
|
|
|
|
: ConsumerFactory(Context, BaseFS) {}
|
2019-08-30 00:38:36 +08:00
|
|
|
std::unique_ptr<FrontendAction> create() override {
|
|
|
|
return std::make_unique<Action>(&ConsumerFactory);
|
|
|
|
}
|
2014-01-03 17:31:57 +08:00
|
|
|
|
2018-05-04 02:26:39 +08:00
|
|
|
bool runInvocation(std::shared_ptr<CompilerInvocation> Invocation,
|
|
|
|
FileManager *Files,
|
|
|
|
std::shared_ptr<PCHContainerOperations> PCHContainerOps,
|
|
|
|
DiagnosticConsumer *DiagConsumer) override {
|
2019-10-15 04:15:01 +08:00
|
|
|
// Explicitly ask to define __clang_analyzer__ macro.
|
|
|
|
Invocation->getPreprocessorOpts().SetUpStaticAnalyzer = true;
|
2018-05-04 02:26:39 +08:00
|
|
|
return FrontendActionFactory::runInvocation(
|
|
|
|
Invocation, Files, PCHContainerOps, DiagConsumer);
|
|
|
|
}
|
|
|
|
|
2014-01-03 17:31:57 +08:00
|
|
|
private:
|
|
|
|
class Action : public ASTFrontendAction {
|
|
|
|
public:
|
|
|
|
Action(ClangTidyASTConsumerFactory *Factory) : Factory(Factory) {}
|
2014-08-11 03:56:59 +08:00
|
|
|
std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &Compiler,
|
|
|
|
StringRef File) override {
|
2014-01-03 17:31:57 +08:00
|
|
|
return Factory->CreateASTConsumer(Compiler, File);
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
ClangTidyASTConsumerFactory *Factory;
|
|
|
|
};
|
|
|
|
|
2014-07-24 18:23:33 +08:00
|
|
|
ClangTidyASTConsumerFactory ConsumerFactory;
|
2014-01-03 17:31:57 +08:00
|
|
|
};
|
|
|
|
|
2019-03-22 21:42:48 +08:00
|
|
|
ActionFactory Factory(Context, BaseFS);
|
2014-07-24 18:23:33 +08:00
|
|
|
Tool.run(&Factory);
|
[clang-tidy] Get ClangTidyContext out of the business of storing diagnostics. NFC
Summary:
Currently ClangTidyContext::diag() sends the diagnostics to a
DiagnosticsEngine, which probably delegates to a ClangTidyDiagnosticsConsumer,
which is supposed to go back and populate ClangTidyContext::Errors.
After this patch, the diagnostics are stored in the ClangTidyDiagnosticsConsumer
itself and can be retrieved from there.
Why?
- the round-trip from context -> engine -> consumer -> context is confusing
and makes it harder to establish layering between these things.
- context does too many things, and makes it hard to use clang-tidy as a library
- everyone who actually wants the diagnostics has access to the ClangTidyDiagnosticsConsumer
The most natural implementation (ClangTidyDiagnosticsConsumer::take()
finalizes diagnostics) causes a test failure: clang-tidy-run-with-database.cpp
asserts that clang-tidy exits successfully when trying to process a file
that doesn't exist.
In clang-tidy today, this happens because finish() is never called, so the
diagnostic is never flushed. This looks like a bug to me.
For now, this patch carefully preserves that behavior, but I'll ping the
authors to see whether it's deliberate and worth preserving.
Reviewers: hokein
Subscribers: xazax.hun, cfe-commits, alexfh
Differential Revision: https://reviews.llvm.org/D53953
llvm-svn: 345961
2018-11-02 18:01:59 +08:00
|
|
|
return DiagConsumer.take();
|
2013-11-14 23:49:44 +08:00
|
|
|
}
|
2013-07-29 16:19:24 +08:00
|
|
|
|
[clang-tidy] Get ClangTidyContext out of the business of storing diagnostics. NFC
Summary:
Currently ClangTidyContext::diag() sends the diagnostics to a
DiagnosticsEngine, which probably delegates to a ClangTidyDiagnosticsConsumer,
which is supposed to go back and populate ClangTidyContext::Errors.
After this patch, the diagnostics are stored in the ClangTidyDiagnosticsConsumer
itself and can be retrieved from there.
Why?
- the round-trip from context -> engine -> consumer -> context is confusing
and makes it harder to establish layering between these things.
- context does too many things, and makes it hard to use clang-tidy as a library
- everyone who actually wants the diagnostics has access to the ClangTidyDiagnosticsConsumer
The most natural implementation (ClangTidyDiagnosticsConsumer::take()
finalizes diagnostics) causes a test failure: clang-tidy-run-with-database.cpp
asserts that clang-tidy exits successfully when trying to process a file
that doesn't exist.
In clang-tidy today, this happens because finish() is never called, so the
diagnostic is never flushed. This looks like a bug to me.
For now, this patch carefully preserves that behavior, but I'll ping the
authors to see whether it's deliberate and worth preserving.
Reviewers: hokein
Subscribers: xazax.hun, cfe-commits, alexfh
Differential Revision: https://reviews.llvm.org/D53953
llvm-svn: 345961
2018-11-02 18:01:59 +08:00
|
|
|
void handleErrors(llvm::ArrayRef<ClangTidyError> Errors,
|
|
|
|
ClangTidyContext &Context, bool Fix,
|
2018-01-23 20:31:06 +08:00
|
|
|
unsigned &WarningsAsErrorsCount,
|
2018-10-10 21:27:25 +08:00
|
|
|
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> BaseFS) {
|
2018-01-23 20:31:06 +08:00
|
|
|
ErrorReporter Reporter(Context, Fix, BaseFS);
|
2018-10-10 21:27:25 +08:00
|
|
|
llvm::vfs::FileSystem &FileSystem =
|
2019-03-27 06:32:06 +08:00
|
|
|
Reporter.getSourceManager().getFileManager().getVirtualFileSystem();
|
2016-02-26 17:19:33 +08:00
|
|
|
auto InitialWorkingDir = FileSystem.getCurrentWorkingDirectory();
|
|
|
|
if (!InitialWorkingDir)
|
|
|
|
llvm::report_fatal_error("Cannot get current working path.");
|
|
|
|
|
[clang-tidy] Get ClangTidyContext out of the business of storing diagnostics. NFC
Summary:
Currently ClangTidyContext::diag() sends the diagnostics to a
DiagnosticsEngine, which probably delegates to a ClangTidyDiagnosticsConsumer,
which is supposed to go back and populate ClangTidyContext::Errors.
After this patch, the diagnostics are stored in the ClangTidyDiagnosticsConsumer
itself and can be retrieved from there.
Why?
- the round-trip from context -> engine -> consumer -> context is confusing
and makes it harder to establish layering between these things.
- context does too many things, and makes it hard to use clang-tidy as a library
- everyone who actually wants the diagnostics has access to the ClangTidyDiagnosticsConsumer
The most natural implementation (ClangTidyDiagnosticsConsumer::take()
finalizes diagnostics) causes a test failure: clang-tidy-run-with-database.cpp
asserts that clang-tidy exits successfully when trying to process a file
that doesn't exist.
In clang-tidy today, this happens because finish() is never called, so the
diagnostic is never flushed. This looks like a bug to me.
For now, this patch carefully preserves that behavior, but I'll ping the
authors to see whether it's deliberate and worth preserving.
Reviewers: hokein
Subscribers: xazax.hun, cfe-commits, alexfh
Differential Revision: https://reviews.llvm.org/D53953
llvm-svn: 345961
2018-11-02 18:01:59 +08:00
|
|
|
for (const ClangTidyError &Error : Errors) {
|
2016-02-26 17:19:33 +08:00
|
|
|
if (!Error.BuildDirectory.empty()) {
|
|
|
|
// By default, the working directory of file system is the current
|
|
|
|
// clang-tidy running directory.
|
|
|
|
//
|
|
|
|
// Change the directory to the one used during the analysis.
|
|
|
|
FileSystem.setCurrentWorkingDirectory(Error.BuildDirectory);
|
|
|
|
}
|
2014-07-02 23:05:04 +08:00
|
|
|
Reporter.reportDiagnostic(Error);
|
2016-02-26 17:19:33 +08:00
|
|
|
// Return to the initial directory to correctly resolve next Error.
|
|
|
|
FileSystem.setCurrentWorkingDirectory(InitialWorkingDir.get());
|
|
|
|
}
|
2014-03-27 18:24:11 +08:00
|
|
|
Reporter.Finish();
|
2016-01-14 01:36:41 +08:00
|
|
|
WarningsAsErrorsCount += Reporter.getWarningsAsErrorsCount();
|
2013-07-29 16:19:24 +08:00
|
|
|
}
|
|
|
|
|
2017-01-03 22:36:13 +08:00
|
|
|
void exportReplacements(const llvm::StringRef MainFilePath,
|
|
|
|
const std::vector<ClangTidyError> &Errors,
|
2014-09-04 18:31:23 +08:00
|
|
|
raw_ostream &OS) {
|
2017-01-03 22:36:13 +08:00
|
|
|
TranslationUnitDiagnostics TUD;
|
2020-01-29 03:23:46 +08:00
|
|
|
TUD.MainSourceFile = std::string(MainFilePath);
|
2017-01-03 22:36:13 +08:00
|
|
|
for (const auto &Error : Errors) {
|
|
|
|
tooling::Diagnostic Diag = Error;
|
|
|
|
TUD.Diagnostics.insert(TUD.Diagnostics.end(), Diag);
|
2016-08-09 15:54:49 +08:00
|
|
|
}
|
2014-09-04 18:31:23 +08:00
|
|
|
|
|
|
|
yaml::Output YAML(OS);
|
2017-01-03 22:36:13 +08:00
|
|
|
YAML << TUD;
|
2014-09-04 18:31:23 +08:00
|
|
|
}
|
|
|
|
|
2013-07-29 16:19:24 +08:00
|
|
|
} // namespace tidy
|
|
|
|
} // namespace clang
|