Reformatted a comment.
Hi klimek,
http://llvm-reviews.chandlerc.com/D2481
CHANGE SINCE LAST DIFF
http://llvm-reviews.chandlerc.com/D2481?vs=6287&id=6327#toc
Files:
clang-tidy/ClangTidy.cpp
clang-tidy/ClangTidy.h
clang-tidy/ClangTidyDiagnosticConsumer.h
Index: clang-tidy/ClangTidy.cpp
===================================================================
--- clang-tidy/ClangTidy.cpp
+++ clang-tidy/ClangTidy.cpp
@@ -26,58 +26,60 @@
#include "clang/Lex/Preprocessor.h"
#include "clang/Frontend/ASTConsumers.h"
#include "clang/Frontend/CompilerInstance.h"
-#include "clang/Frontend/FrontendActions.h"
+#include "clang/Frontend/MultiplexConsumer.h"
#include "clang/Frontend/TextDiagnosticPrinter.h"
#include "clang/Rewrite/Frontend/FixItRewriter.h"
#include "clang/Rewrite/Frontend/FrontendActions.h"
-#include "clang/StaticAnalyzer/Frontend/FrontendActions.h"
#include "clang/Tooling/Tooling.h"
#include "clang/Tooling/Refactoring.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Signals.h"
#include <algorithm>
#include <vector>
+// FIXME: Move AnalysisConsumer to include/clang/StaticAnalyzer/Frontend.
+#include "../../../lib/StaticAnalyzer/Frontend/AnalysisConsumer.h"
using namespace clang::ast_matchers;
using namespace clang::driver;
using namespace clang::tooling;
using namespace llvm;
namespace clang {
namespace tidy {
-namespace {
-/// \brief A combined ASTConsumer that forwards calls to two different
-/// consumers.
-///
-/// FIXME: This currently forwards just enough methods for the static analyzer
-/// and the \c MatchFinder's consumer to work; expand this to all methods of
-/// ASTConsumer and put it into a common location.
-class CombiningASTConsumer : public ASTConsumer {
-public:
- CombiningASTConsumer(ASTConsumer *Consumer1, ASTConsumer *Consumer2)
- : Consumer1(Consumer1), Consumer2(Consumer2) {}
+ClangTidyAction::ClangTidyAction(ClangTidyAction::CheckersList AnalyzerCheckers,
+ SmallVectorImpl<ClangTidyCheck *> &Checks,
+ ClangTidyContext &Context, MatchFinder &Finder)
+ : AnalyzerCheckers(AnalyzerCheckers), Checks(Checks), Context(Context),
+ Finder(Finder) {}
+
+clang::ASTConsumer *
+ClangTidyAction::CreateASTConsumer(clang::CompilerInstance &Compiler,
+ StringRef File) {
+ Context.setSourceManager(&Compiler.getSourceManager());
+ for (SmallVectorImpl<ClangTidyCheck *>::iterator I = Checks.begin(),
+ E = Checks.end();
+ I != E; ++I)
+ (*I)->registerPPCallbacks(Compiler);
+
+ AnalyzerOptionsRef Options = Compiler.getAnalyzerOpts();
+ Options->CheckersControlList = AnalyzerCheckers;
+ Options->AnalysisStoreOpt = RegionStoreModel;
+ Options->AnalysisDiagOpt = PD_TEXT;
+ Options->AnalyzeNestedBlocks = true;
+ Options->eagerlyAssumeBinOpBifurcation = true;
+ ASTConsumer *Consumers[] = {
+ Finder.newASTConsumer(),
+ ento::CreateAnalysisConsumer(Compiler.getPreprocessor(),
+ Compiler.getFrontendOpts().OutputFile, Options,
+ Compiler.getFrontendOpts().Plugins)
+ };
+ return new MultiplexConsumer(Consumers);
+}
- virtual void Initialize(ASTContext &Context) LLVM_OVERRIDE {
- Consumer1->Initialize(Context);
- Consumer2->Initialize(Context);
- }
- virtual bool HandleTopLevelDecl(DeclGroupRef D) LLVM_OVERRIDE {
- return Consumer1->HandleTopLevelDecl(D) && Consumer2->HandleTopLevelDecl(D);
- }
- virtual void HandleTopLevelDeclInObjCContainer(DeclGroupRef D) LLVM_OVERRIDE {
- Consumer1->HandleTopLevelDeclInObjCContainer(D);
- Consumer2->HandleTopLevelDeclInObjCContainer(D);
- }
- virtual void HandleTranslationUnit(ASTContext &Context) LLVM_OVERRIDE {
- Consumer1->HandleTranslationUnit(Context);
- Consumer2->HandleTranslationUnit(Context);
- }
+namespace {
-private:
- llvm::OwningPtr<ASTConsumer> Consumer1;
- llvm::OwningPtr<ASTConsumer> Consumer2;
-};
+static const char *AnalyzerCheckerNamePrefix = "clang-analyzer-";
static StringRef StaticAnalyzerCheckers[] = {
#define GET_CHECKERS
@@ -88,82 +90,6 @@
#undef GET_CHECKERS
};
-static const char *AnalyzerCheckerNamePrefix = "clang-analyzer-";
-
-/// \brief Action that runs clang-tidy and static analyzer checks.
-///
-/// FIXME: Note that this inherits from \c AnalysisAction as this is the only
-/// way we can currently get to AnalysisAction::CreateASTConsumer. Ideally
-/// we'd want to build a more generic way to use \c FrontendAction based
-/// checkers in clang-tidy, but that needs some preparation work first.
-class ClangTidyAction : public ento::AnalysisAction {
-public:
- ClangTidyAction(ChecksFilter &Filter,
- SmallVectorImpl<ClangTidyCheck *> &Checks,
- ClangTidyContext &Context, MatchFinder &Finder)
- : Filter(Filter), Checks(Checks), Context(Context), Finder(Finder) {}
-
- typedef std::vector<std::pair<std::string, bool> > CheckersList;
- void fillCheckersControlList(CheckersList &List) {
- ArrayRef<StringRef> Checkers(StaticAnalyzerCheckers);
-
- bool AnalyzerChecksEnabled = false;
- for (unsigned i = 0; i < Checkers.size(); ++i) {
- std::string Checker((AnalyzerCheckerNamePrefix + Checkers[i]).str());
- AnalyzerChecksEnabled |=
- Filter.IsCheckEnabled(Checker) && !Checkers[i].startswith("debug");
- }
-
- if (!AnalyzerChecksEnabled)
- return;
-
- // Run our regex against all possible static analyzer checkers.
- // Note that debug checkers print values / run programs to visualize the CFG
- // and are thus not applicable to clang-tidy in general.
- // Always add all core checkers if any other static analyzer checks are
- // enabled. This is currently necessary, as other path sensitive checks rely
- // on the core checkers.
- for (unsigned i = 0; i < Checkers.size(); ++i) {
- std::string Checker((AnalyzerCheckerNamePrefix + Checkers[i]).str());
-
- if (Checkers[i].startswith("core") ||
- (!Checkers[i].startswith("debug") && Filter.IsCheckEnabled(Checker)))
- List.push_back(std::make_pair(Checkers[i], true));
- }
- }
-
-private:
- clang::ASTConsumer *CreateASTConsumer(clang::CompilerInstance &Compiler,
- StringRef File) LLVM_OVERRIDE {
- AnalyzerOptionsRef Options = Compiler.getAnalyzerOpts();
- fillCheckersControlList(Options->CheckersControlList);
- Options->AnalysisStoreOpt = RegionStoreModel;
- Options->AnalysisDiagOpt = PD_TEXT;
- Options->AnalyzeNestedBlocks = true;
- Options->eagerlyAssumeBinOpBifurcation = true;
- return new CombiningASTConsumer(
- Finder.newASTConsumer(),
- ento::AnalysisAction::CreateASTConsumer(Compiler, File));
- }
-
- virtual bool BeginSourceFileAction(CompilerInstance &Compiler,
- llvm::StringRef Filename) LLVM_OVERRIDE {
- if (!ento::AnalysisAction::BeginSourceFileAction(Compiler, Filename))
- return false;
- Context.setSourceManager(&Compiler.getSourceManager());
- for (SmallVectorImpl<ClangTidyCheck *>::iterator I = Checks.begin(),
- E = Checks.end();
- I != E; ++I)
- (*I)->registerPPCallbacks(Compiler);
- return true;
- }
-
- ChecksFilter &Filter;
- SmallVectorImpl<ClangTidyCheck *> &Checks;
- ClangTidyContext &Context;
- MatchFinder &Finder;
-};
-
class ClangTidyActionFactory : public FrontendActionFactory {
public:
ClangTidyActionFactory(StringRef EnableChecksRegex,
@@ -189,7 +115,8 @@
}
virtual FrontendAction *create() {
- return new ClangTidyAction(Filter, Checks, Context, Finder);
+ return new ClangTidyAction(getCheckersControlList(), Checks, Context,
+ Finder);
}
std::vector<std::string> getCheckNames() {
@@ -202,9 +129,7 @@
CheckNames.push_back(I->first);
}
- ClangTidyAction Action(Filter, Checks, Context, Finder);
- ClangTidyAction::CheckersList AnalyzerChecks;
- Action.fillCheckersControlList(AnalyzerChecks);
+ ClangTidyAction::CheckersList AnalyzerChecks = getCheckersControlList();
for (ClangTidyAction::CheckersList::const_iterator
I = AnalyzerChecks.begin(),
E = AnalyzerChecks.end();
@@ -216,6 +141,37 @@
}
private:
+ ClangTidyAction::CheckersList getCheckersControlList() {
+ ClangTidyAction::CheckersList List;
+ ArrayRef<StringRef> Checkers(StaticAnalyzerCheckers);
+
+ bool AnalyzerChecksEnabled = false;
+ for (unsigned i = 0; i < Checkers.size(); ++i) {
+ std::string Checker((AnalyzerCheckerNamePrefix + Checkers[i]).str());
+ AnalyzerChecksEnabled |=
+ Filter.IsCheckEnabled(Checker) && !Checkers[i].startswith("debug");
+ }
+
+ if (AnalyzerChecksEnabled) {
+ // Run our regex against all possible static analyzer checkers. Note that
+ // debug checkers print values / run programs to visualize the CFG and are
+ // thus not applicable to clang-tidy in general.
+ //
+ // Always add all core checkers if any other static analyzer checks are
+ // enabled. This is currently necessary, as other path sensitive checks
+ // rely on the core checkers.
+ for (unsigned i = 0; i < Checkers.size(); ++i) {
+ std::string Checker((AnalyzerCheckerNamePrefix + Checkers[i]).str());
+
+ if (Checkers[i].startswith("core") ||
+ (!Checkers[i].startswith("debug") &&
+ Filter.IsCheckEnabled(Checker)))
+ List.push_back(std::make_pair(Checkers[i], true));
+ }
+ }
+ return List;
+ }
+
ChecksFilter Filter;
SmallVector<ClangTidyCheck *, 8> Checks;
ClangTidyContext &Context;
Index: clang-tidy/ClangTidy.h
===================================================================
--- clang-tidy/ClangTidy.h
+++ clang-tidy/ClangTidy.h
@@ -13,6 +13,7 @@
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/SourceManager.h"
+#include "clang/Frontend/FrontendActions.h"
#include "clang/Tooling/Refactoring.h"
#include "ClangTidyDiagnosticConsumer.h"
@@ -101,6 +102,29 @@
std::vector<std::string> getCheckNames(StringRef EnableChecksRegex,
StringRef DisableChecksRegex);
+/// \brief Action that runs clang-tidy and static analyzer checks.
+///
+/// FIXME: Ideally we'd want to build a more generic way to use
+/// \c FrontendAction based checkers in clang-tidy, but that needs some
+/// preparation work first.
+class ClangTidyAction : public ASTFrontendAction {
+public:
+ typedef std::vector<std::pair<std::string, bool> > CheckersList;
+
+ ClangTidyAction(CheckersList AnalyzerCheckers,
+ SmallVectorImpl<ClangTidyCheck *> &Checks,
+ ClangTidyContext &Context, ast_matchers::MatchFinder &Finder);
+
+ clang::ASTConsumer *CreateASTConsumer(clang::CompilerInstance &Compiler,
+ StringRef File) LLVM_OVERRIDE;
+
+private:
+ CheckersList AnalyzerCheckers;
+ SmallVectorImpl<ClangTidyCheck *> &Checks;
+ ClangTidyContext &Context;
+ ast_matchers::MatchFinder &Finder;
+};
+
/// \brief Returns an action factory that runs the specified clang-tidy checks.
tooling::FrontendActionFactory *
createClangTidyActionFactory(StringRef EnableChecksRegex,
Index: clang-tidy/ClangTidyDiagnosticConsumer.h
===================================================================
--- clang-tidy/ClangTidyDiagnosticConsumer.h
+++ clang-tidy/ClangTidyDiagnosticConsumer.h
@@ -65,7 +65,8 @@
/// \endcode
class ClangTidyContext {
public:
- ClangTidyContext(SmallVectorImpl<ClangTidyError> *Errors) : Errors(Errors) {}
+ ClangTidyContext(SmallVectorImpl<ClangTidyError> *Errors)
+ : Errors(Errors), DiagEngine(0) {}
/// \brief Report any errors detected using this method.
///
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits