[clang-tools-extra] r194707 - Make clang's static analyzer checks available through clang-tidy.

Manuel Klimek klimek at google.com
Thu Nov 14 07:49:44 PST 2013


Author: klimek
Date: Thu Nov 14 09:49:44 2013
New Revision: 194707

URL: http://llvm.org/viewvc/llvm-project?rev=194707&view=rev
Log:
Make clang's static analyzer checks available through clang-tidy.

This is implemented in a way that the current static analyzer
architecture allows, in the future we might want to revisit this.

With this change static analyzer checks are available from clang-tidy
by specifying -checks=clang-analyzer-<name>.

This change also fixes the use of the compilation database to allow
clang-tidy to be used like any other clang tool.

Added:
    clang-tools-extra/trunk/test/clang-tidy/static-analyzer.cpp
Modified:
    clang-tools-extra/trunk/clang-tidy/CMakeLists.txt
    clang-tools-extra/trunk/clang-tidy/ClangTidy.cpp
    clang-tools-extra/trunk/clang-tidy/ClangTidy.h
    clang-tools-extra/trunk/clang-tidy/ClangTidyDiagnosticConsumer.h
    clang-tools-extra/trunk/clang-tidy/tool/CMakeLists.txt
    clang-tools-extra/trunk/clang-tidy/tool/ClangTidyMain.cpp
    clang-tools-extra/trunk/clang-tidy/tool/Makefile
    clang-tools-extra/trunk/unittests/clang-tidy/ClangTidyTest.h
    clang-tools-extra/trunk/unittests/clang-tidy/Makefile

Modified: clang-tools-extra/trunk/clang-tidy/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/CMakeLists.txt?rev=194707&r1=194706&r2=194707&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/CMakeLists.txt (original)
+++ clang-tools-extra/trunk/clang-tidy/CMakeLists.txt Thu Nov 14 09:49:44 2013
@@ -14,6 +14,8 @@ target_link_libraries(clangTidy
   clangTooling
   clangBasic
   clangRewriteFrontend
+  clangStaticAnalyzerFrontend
+  clangStaticAnalyzerCheckers
   )
 
 add_subdirectory(tool)

Modified: clang-tools-extra/trunk/clang-tidy/ClangTidy.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/ClangTidy.cpp?rev=194707&r1=194706&r2=194707&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/ClangTidy.cpp (original)
+++ clang-tools-extra/trunk/clang-tidy/ClangTidy.cpp Thu Nov 14 09:49:44 2013
@@ -30,6 +30,7 @@
 #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"
@@ -45,15 +46,83 @@ namespace clang {
 namespace tidy {
 namespace {
 
-class ClangTidyPPAction : public PreprocessOnlyAction {
+/// \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:
-  ClangTidyPPAction(SmallVectorImpl<ClangTidyCheck *> &Checks,
-                    ClangTidyContext &Context)
-      : Checks(Checks), Context(Context) {}
+  CombiningASTConsumer(ASTConsumer *Consumer1, ASTConsumer *Consumer2)
+      : Consumer1(Consumer1), Consumer2(Consumer2) {}
+
+  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);
+  }
+
+private:
+  llvm::OwningPtr<ASTConsumer> Consumer1;
+  llvm::OwningPtr<ASTConsumer> Consumer2;
+};
+
+/// \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 preperation work first.
+class ClangTidyAction : public ento::AnalysisAction {
+public:
+  ClangTidyAction(StringRef CheckRegexString,
+                  SmallVectorImpl<ClangTidyCheck *> &Checks,
+                  ClangTidyContext &Context, MatchFinder &Finder)
+      : CheckRegexString(CheckRegexString), Checks(Checks), Context(Context),
+        Finder(Finder) {}
 
 private:
+  clang::ASTConsumer *CreateASTConsumer(clang::CompilerInstance &Compiler,
+                                        StringRef File) LLVM_OVERRIDE {
+    AnalyzerOptionsRef Options = Compiler.getAnalyzerOpts();
+    llvm::Regex CheckRegex(CheckRegexString);
+
+// 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.
+#define GET_CHECKERS
+#define CHECKER(FULLNAME, CLASS, DESCFILE, HELPTEXT, GROUPINDEX, HIDDEN)       \
+  if (!StringRef(FULLNAME).startswith("debug") &&                              \
+      CheckRegex.match("clang-analyzer-" FULLNAME))                            \
+    Options->CheckersControlList.push_back(std::make_pair(FULLNAME, true));
+#include "../../../lib/StaticAnalyzer/Checkers/Checkers.inc"
+#undef CHECKER
+#undef GET_CHECKERS
+
+    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 file_name) {
+                                     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();
@@ -62,35 +131,61 @@ private:
     return true;
   }
 
+  std::string CheckRegexString;
   SmallVectorImpl<ClangTidyCheck *> &Checks;
   ClangTidyContext &Context;
+  MatchFinder &Finder;
 };
 
-class ClangTidyPPActionFactory : public FrontendActionFactory {
+class ClangTidyActionFactory : public FrontendActionFactory {
 public:
-  ClangTidyPPActionFactory(SmallVectorImpl<ClangTidyCheck *> &Checks,
-                           ClangTidyContext &Context)
-      : Checks(Checks), Context(Context) {}
+  ClangTidyActionFactory(StringRef CheckRegexString, ClangTidyContext &Context)
+      : CheckRegexString(CheckRegexString), Context(Context) {
+    ClangTidyCheckFactories CheckFactories;
+    for (ClangTidyModuleRegistry::iterator I = ClangTidyModuleRegistry::begin(),
+                                           E = ClangTidyModuleRegistry::end();
+         I != E; ++I) {
+      OwningPtr<ClangTidyModule> Module(I->instantiate());
+      Module->addCheckFactories(CheckFactories);
+    }
+
+    SmallVector<ClangTidyCheck *, 16> Checks;
+    CheckFactories.createChecks(CheckRegexString, Checks);
+
+    for (SmallVectorImpl<ClangTidyCheck *>::iterator I = Checks.begin(),
+                                                     E = Checks.end();
+         I != E; ++I) {
+      (*I)->setContext(&Context);
+      (*I)->registerMatchers(&Finder);
+    }
+  }
 
   virtual FrontendAction *create() {
-    return new ClangTidyPPAction(Checks, Context);
+    return new ClangTidyAction(CheckRegexString, Checks, Context, Finder);
   }
 
 private:
-  SmallVectorImpl<ClangTidyCheck *> &Checks;
+  std::string CheckRegexString;
+  SmallVector<ClangTidyCheck *, 8> Checks;
   ClangTidyContext &Context;
+  MatchFinder Finder;
 };
 
 } // namespace
 
-ClangTidyError::ClangTidyError(const SourceManager &Sources, SourceLocation Loc,
-                               StringRef Message,
-                               const tooling::Replacements &Fix)
-    : Message(Message), Fix(Fix) {
+ClangTidyMessage::ClangTidyMessage(StringRef Message) : Message(Message) {}
+
+ClangTidyMessage::ClangTidyMessage(StringRef Message,
+                                   const SourceManager &Sources,
+                                   SourceLocation Loc)
+    : Message(Message) {
   FilePath = Sources.getFilename(Loc);
   FileOffset = Sources.getFileOffset(Loc);
 }
 
+ClangTidyError::ClangTidyError(const ClangTidyMessage &Message)
+    : Message(Message) {}
+
 DiagnosticBuilder ClangTidyContext::Diag(SourceLocation Loc,
                                          StringRef Message) {
   return DiagEngine->Report(
@@ -115,6 +210,11 @@ void ClangTidyCheck::run(const ast_match
   check(Result);
 }
 
+FrontendActionFactory *createClangTidyActionFactory(StringRef CheckRegexString,
+                                                    ClangTidyContext &Context) {
+  return new ClangTidyActionFactory(CheckRegexString, Context);
+}
+
 void runClangTidy(StringRef CheckRegexString,
                   const tooling::CompilationDatabase &Compilations,
                   ArrayRef<std::string> Ranges,
@@ -124,27 +224,24 @@ void runClangTidy(StringRef CheckRegexSt
   ClangTool Tool(Compilations, Ranges);
   clang::tidy::ClangTidyContext Context(Errors);
   ClangTidyDiagnosticConsumer DiagConsumer(Context);
-  ClangTidyCheckFactories CheckFactories;
-  for (ClangTidyModuleRegistry::iterator I = ClangTidyModuleRegistry::begin(),
-                                         E = ClangTidyModuleRegistry::end();
-       I != E; ++I) {
-    OwningPtr<ClangTidyModule> Module(I->instantiate());
-    Module->addCheckFactories(CheckFactories);
-  }
 
-  SmallVector<ClangTidyCheck *, 16> Checks;
-  CheckFactories.createChecks(CheckRegexString, Checks);
+  Tool.setDiagnosticConsumer(&DiagConsumer);
+  Tool.run(createClangTidyActionFactory(CheckRegexString, Context));
+}
 
-  MatchFinder Finder;
-  for (SmallVectorImpl<ClangTidyCheck *>::iterator I = Checks.begin(),
-                                                   E = Checks.end();
-       I != E; ++I) {
-    (*I)->setContext(&Context);
-    (*I)->registerMatchers(&Finder);
+static void reportDiagnostic(const ClangTidyMessage &Message,
+                             SourceManager &SourceMgr,
+                             DiagnosticsEngine::Level Level,
+                             DiagnosticsEngine &Diags) {
+  SourceLocation Loc;
+  if (!Message.FilePath.empty()) {
+    const FileEntry *File =
+        SourceMgr.getFileManager().getFile(Message.FilePath);
+    FileID ID = SourceMgr.createFileID(File, SourceLocation(), SrcMgr::C_User);
+    Loc = SourceMgr.getLocForStartOfFile(ID);
+    Loc = Loc.getLocWithOffset(Message.FileOffset);
   }
-
-  Tool.run(new ClangTidyPPActionFactory(Checks, Context));
-  Tool.run(newFrontendActionFactory(&Finder));
+  Diags.Report(Loc, Diags.getCustomDiagID(Level, Message.Message));
 }
 
 void handleErrors(SmallVectorImpl<ClangTidyError> &Errors, bool Fix) {
@@ -160,11 +257,10 @@ void handleErrors(SmallVectorImpl<ClangT
   for (SmallVectorImpl<ClangTidyError>::iterator I = Errors.begin(),
                                                  E = Errors.end();
        I != E; ++I) {
-    const FileEntry *File = Files.getFile(I->FilePath);
-    FileID ID = SourceMgr.createFileID(File, SourceLocation(), SrcMgr::C_User);
-    SourceLocation Loc = SourceMgr.getLocForStartOfFile(ID);
-    Diags.Report(Loc.getLocWithOffset(I->FileOffset),
-                 Diags.getCustomDiagID(DiagnosticsEngine::Warning, I->Message));
+    reportDiagnostic(I->Message, SourceMgr, DiagnosticsEngine::Warning, Diags);
+    for (unsigned i = 0, e = I->Notes.size(); i != e; ++i) {
+      reportDiagnostic(I->Notes[i], SourceMgr, DiagnosticsEngine::Note, Diags);
+    }
     tooling::applyAllReplacements(I->Fix, Rewrite);
   }
   // FIXME: Run clang-format on changes.

Modified: clang-tools-extra/trunk/clang-tidy/ClangTidy.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/ClangTidy.h?rev=194707&r1=194706&r2=194707&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/ClangTidy.h (original)
+++ clang-tools-extra/trunk/clang-tidy/ClangTidy.h Thu Nov 14 09:49:44 2013
@@ -14,6 +14,7 @@
 #include "clang/Basic/Diagnostic.h"
 #include "clang/Basic/SourceManager.h"
 #include "clang/Tooling/Refactoring.h"
+#include "ClangTidyDiagnosticConsumer.h"
 
 namespace clang {
 
@@ -27,64 +28,6 @@ class CompilationDatabase;
 
 namespace tidy {
 
-/// \brief A detected error complete with information to display diagnostic and
-/// automatic fix.
-///
-/// This is used as an intermediate format to transport Diagnostics without a
-/// dependency on a SourceManager.
-///
-/// FIXME: Make Diagnostics flexible enough to support this directly.
-struct ClangTidyError {
-  ClangTidyError(const SourceManager &Sources, SourceLocation Loc,
-                 StringRef Message, const tooling::Replacements &Fix);
-
-  std::string Message;
-  unsigned FileOffset;
-  std::string FilePath;
-  tooling::Replacements Fix;
-};
-
-/// \brief Every \c ClangTidyCheck reports errors through a \c DiagnosticEngine
-/// provided by this context.
-///
-/// A \c ClangTidyCheck always has access to the active context to report
-/// warnings like:
-/// \code
-/// Context->Diag(Loc, "Single-argument constructors must be explicit")
-///     << FixItHint::CreateInsertion(Loc, "explicit ");
-/// \endcode
-class ClangTidyContext {
-public:
-  ClangTidyContext(SmallVectorImpl<ClangTidyError> *Errors) : Errors(Errors) {}
-
-  /// \brief Report any errors detected using this method.
-  ///
-  /// This is still under heavy development and will likely change towards using
-  /// tablegen'd diagnostic IDs.
-  /// FIXME: Figure out a way to manage ID spaces.
-  DiagnosticBuilder Diag(SourceLocation Loc, StringRef Message);
-
-  /// \brief Sets the \c DiagnosticsEngine so that Diagnostics can be generated
-  /// correctly.
-  ///
-  /// This is called from the \c ClangTidyCheck base class.
-  void setDiagnosticsEngine(DiagnosticsEngine *Engine);
-
-  /// \brief Sets the \c SourceManager of the used \c DiagnosticsEngine.
-  ///
-  /// This is called from the \c ClangTidyCheck base class.
-  void setSourceManager(SourceManager *SourceMgr);
-
-private:
-  friend class ClangTidyDiagnosticConsumer; // Calls storeError().
-
-  /// \brief Store a \c ClangTidyError.
-  void storeError(const ClangTidyError &Error);
-
-  SmallVectorImpl<ClangTidyError> *Errors;
-  DiagnosticsEngine *DiagEngine;
-};
-
 /// \brief Base class for all clang-tidy checks.
 ///
 /// To implement a \c ClangTidyCheck, write a subclass and overwrite some of the
@@ -142,6 +85,11 @@ private:
   virtual void run(const ast_matchers::MatchFinder::MatchResult &Result);
 };
 
+/// \brief Returns an action factory that runs the specified clang-tidy checks.
+tooling::FrontendActionFactory *
+createClangTidyActionFactory(StringRef CheckRegexString,
+                             ClangTidyContext &Context);
+
 /// \brief Run a set of clang-tidy checks on a set of files.
 void runClangTidy(StringRef CheckRegexString,
                   const tooling::CompilationDatabase &Compilations,

Modified: clang-tools-extra/trunk/clang-tidy/ClangTidyDiagnosticConsumer.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/ClangTidyDiagnosticConsumer.h?rev=194707&r1=194706&r2=194707&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/ClangTidyDiagnosticConsumer.h (original)
+++ clang-tools-extra/trunk/clang-tidy/ClangTidyDiagnosticConsumer.h Thu Nov 14 09:49:44 2013
@@ -27,6 +27,74 @@ class CompilationDatabase;
 
 namespace tidy {
 
+/// \brief A message from a clang-tidy check.
+///
+/// Note that this is independent of a \c SourceManager.
+struct ClangTidyMessage {
+  ClangTidyMessage(StringRef Message = "");
+  ClangTidyMessage(StringRef Message, const SourceManager &Sources,
+                   SourceLocation Loc);
+  std::string Message;
+  std::string FilePath;
+  unsigned FileOffset;
+};
+
+/// \brief A detected error complete with information to display diagnostic and
+/// automatic fix.
+///
+/// This is used as an intermediate format to transport Diagnostics without a
+/// dependency on a SourceManager.
+///
+/// FIXME: Make Diagnostics flexible enough to support this directly.
+struct ClangTidyError {
+  ClangTidyError(const ClangTidyMessage &Message);
+
+  ClangTidyMessage Message;
+  tooling::Replacements Fix;
+  SmallVector<ClangTidyMessage, 1> Notes;
+};
+
+/// \brief Every \c ClangTidyCheck reports errors through a \c DiagnosticEngine
+/// provided by this context.
+///
+/// A \c ClangTidyCheck always has access to the active context to report
+/// warnings like:
+/// \code
+/// Context->Diag(Loc, "Single-argument constructors must be explicit")
+///     << FixItHint::CreateInsertion(Loc, "explicit ");
+/// \endcode
+class ClangTidyContext {
+public:
+  ClangTidyContext(SmallVectorImpl<ClangTidyError> *Errors) : Errors(Errors) {}
+
+  /// \brief Report any errors detected using this method.
+  ///
+  /// This is still under heavy development and will likely change towards using
+  /// tablegen'd diagnostic IDs.
+  /// FIXME: Figure out a way to manage ID spaces.
+  DiagnosticBuilder Diag(SourceLocation Loc, StringRef Message);
+
+  /// \brief Sets the \c DiagnosticsEngine so that Diagnostics can be generated
+  /// correctly.
+  ///
+  /// This is called from the \c ClangTidyCheck base class.
+  void setDiagnosticsEngine(DiagnosticsEngine *Engine);
+
+  /// \brief Sets the \c SourceManager of the used \c DiagnosticsEngine.
+  ///
+  /// This is called from the \c ClangTidyCheck base class.
+  void setSourceManager(SourceManager *SourceMgr);
+
+private:
+  friend class ClangTidyDiagnosticConsumer; // Calls storeError().
+
+  /// \brief Store a \c ClangTidyError.
+  void storeError(const ClangTidyError &Error);
+
+  SmallVectorImpl<ClangTidyError> *Errors;
+  DiagnosticsEngine *DiagEngine;
+};
+
 /// \brief A diagnostic consumer that turns each \c Diagnostic into a
 /// \c SourceManager-independent \c ClangTidyError.
 //
@@ -47,22 +115,46 @@ public:
   // library.
   virtual void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
                                 const Diagnostic &Info) {
-    tooling::Replacements Replacements;
+    if (DiagLevel != DiagnosticsEngine::Note) {
+      Errors.push_back(ClangTidyError(getMessage(Info)));
+    } else {
+      Errors.back().Notes.push_back(getMessage(Info));
+    }
+    addFixes(Info, Errors.back());
+  }
+
+  virtual void finish() {
+    for (unsigned i = 0, e = Errors.size(); i != e; ++i) {
+      Context.storeError(Errors[i]);
+    }
+  }
+
+private:
+  void addFixes(const Diagnostic &Info, ClangTidyError &Error) {
+    if (!Info.hasSourceManager())
+      return;
     SourceManager &SourceMgr = Info.getSourceManager();
+    tooling::Replacements Replacements;
     for (unsigned i = 0, e = Info.getNumFixItHints(); i != e; ++i) {
-      Replacements.insert(tooling::Replacement(
+      Error.Fix.insert(tooling::Replacement(
           SourceMgr, Info.getFixItHint(i).RemoveRange.getBegin(), 0,
           Info.getFixItHint(i).CodeToInsert));
     }
+  }
+
+  ClangTidyMessage getMessage(const Diagnostic &Info) const {
     SmallString<100> Buf;
     Info.FormatDiagnostic(Buf);
-    Context.storeError(
-        ClangTidyError(SourceMgr, Info.getLocation(), Buf.str(), Replacements));
+    if (!Info.hasSourceManager()) {
+      return ClangTidyMessage(Buf.str());
+    }
+    return ClangTidyMessage(Buf.str(), Info.getSourceManager(),
+                            Info.getLocation());
   }
 
-private:
   ClangTidyContext &Context;
   OwningPtr<DiagnosticsEngine> Diags;
+  SmallVector<ClangTidyError, 8> Errors;
 };
 
 } // end namespace tidy

Modified: clang-tools-extra/trunk/clang-tidy/tool/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/tool/CMakeLists.txt?rev=194707&r1=194706&r2=194707&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/tool/CMakeLists.txt (original)
+++ clang-tools-extra/trunk/clang-tidy/tool/CMakeLists.txt Thu Nov 14 09:49:44 2013
@@ -13,6 +13,7 @@ target_link_libraries(clang-tidy
   clangTidy
   clangTidyLLVMModule
   clangTidyGoogleModule
+  clangStaticAnalyzerCheckers
   )
 
 install(TARGETS clang-tidy

Modified: clang-tools-extra/trunk/clang-tidy/tool/ClangTidyMain.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/tool/ClangTidyMain.cpp?rev=194707&r1=194706&r2=194707&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/tool/ClangTidyMain.cpp (original)
+++ clang-tools-extra/trunk/clang-tidy/tool/ClangTidyMain.cpp Thu Nov 14 09:49:44 2013
@@ -16,6 +16,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "../ClangTidy.h"
+#include "clang/Tooling/CommonOptionsParser.h"
 #include "llvm/Support/CommandLine.h"
 #include <vector>
 
@@ -26,8 +27,7 @@ using namespace llvm;
 
 cl::OptionCategory ClangTidyCategory("clang-tidy options");
 
-cl::list<std::string>
-Ranges(cl::Positional, cl::desc("<range0> [... <rangeN>]"), cl::OneOrMore);
+static cl::extrahelp CommonHelp(CommonOptionsParser::HelpMessage);
 
 static cl::opt<std::string> Checks(
     "checks",
@@ -39,15 +39,11 @@ static cl::opt<bool> Fix("fix", cl::desc
 // FIXME: Add option to list name/description of all checks.
 
 int main(int argc, const char **argv) {
-  cl::ParseCommandLineOptions(argc, argv, "TBD\n");
-  OwningPtr<clang::tooling::CompilationDatabase> Compilations(
-      FixedCompilationDatabase::loadFromCommandLine(argc, argv));
-  if (!Compilations)
-    return 0;
-  // FIXME: Load other compilation databases.
+  CommonOptionsParser OptionsParser(argc, argv);
 
   SmallVector<clang::tidy::ClangTidyError, 16> Errors;
-  clang::tidy::runClangTidy(Checks, *Compilations, Ranges, &Errors);
+  clang::tidy::runClangTidy(Checks, OptionsParser.getCompilations(),
+                            OptionsParser.getSourcePathList(), &Errors);
   clang::tidy::handleErrors(Errors, Fix);
 
   return 0;

Modified: clang-tools-extra/trunk/clang-tidy/tool/Makefile
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/tool/Makefile?rev=194707&r1=194706&r2=194707&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/tool/Makefile (original)
+++ clang-tools-extra/trunk/clang-tidy/tool/Makefile Thu Nov 14 09:49:44 2013
@@ -17,6 +17,8 @@ TOOL_NO_EXPORTS = 1
 include $(CLANG_LEVEL)/../../Makefile.config
 LINK_COMPONENTS := $(TARGETS_TO_BUILD) asmparser bitreader support mc option
 USEDLIBS = clangTidy.a clangTidyLLVMModule.a clangTidyGoogleModule.a \
+	   clangStaticAnalyzerFrontend.a clangStaticAnalyzerCheckers.a \
+	   clangStaticAnalyzerCore.a \
 	   clangFormat.a clangASTMatchers.a clangTooling.a clangFrontend.a \
 	   clangSerialization.a clangDriver.a clangParse.a clangSema.a \
 	   clangAnalysis.a clangRewriteFrontend.a clangRewriteCore.a \

Added: clang-tools-extra/trunk/test/clang-tidy/static-analyzer.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clang-tidy/static-analyzer.cpp?rev=194707&view=auto
==============================================================================
--- clang-tools-extra/trunk/test/clang-tidy/static-analyzer.cpp (added)
+++ clang-tools-extra/trunk/test/clang-tidy/static-analyzer.cpp Thu Nov 14 09:49:44 2013
@@ -0,0 +1,8 @@
+// RUN: clang-tidy %s -checks='clang-analyzer-cplusplus' -- | FileCheck %s
+
+void f() {
+  int *p = new int(42);
+  delete p;
+  delete p;
+  // CHECK: warning: Attempt to free released memory
+}

Modified: clang-tools-extra/trunk/unittests/clang-tidy/ClangTidyTest.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/unittests/clang-tidy/ClangTidyTest.h?rev=194707&r1=194706&r2=194707&view=diff
==============================================================================
--- clang-tools-extra/trunk/unittests/clang-tidy/ClangTidyTest.h (original)
+++ clang-tools-extra/trunk/unittests/clang-tidy/ClangTidyTest.h Thu Nov 14 09:49:44 2013
@@ -36,6 +36,7 @@ protected:
     OwningPtr<tooling::FrontendActionFactory> Factory(
         tooling::newFrontendActionFactory(&Finder));
     EXPECT_TRUE(tooling::runToolOnCode(Factory->create(), Code));
+    DiagConsumer.finish();
     tooling::Replacements Fixes;
     for (SmallVector<ClangTidyError, 16>::const_iterator I = Errors.begin(),
                                                          E = Errors.end();

Modified: clang-tools-extra/trunk/unittests/clang-tidy/Makefile
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/unittests/clang-tidy/Makefile?rev=194707&r1=194706&r2=194707&view=diff
==============================================================================
--- clang-tools-extra/trunk/unittests/clang-tidy/Makefile (original)
+++ clang-tools-extra/trunk/unittests/clang-tidy/Makefile Thu Nov 14 09:49:44 2013
@@ -14,6 +14,8 @@ TESTNAME = ClangTidy
 LINK_COMPONENTS := asmparser bitreader support MC MCParser option \
 		 TransformUtils
 USEDLIBS = clangTidy.a clangTidyLLVMModule.a clangTidyGoogleModule.a \
+	   clangStaticAnalyzerFrontend.a clangStaticAnalyzerCheckers.a \
+	   clangStaticAnalyzerCore.a \
 	   clangFormat.a clangTooling.a clangFrontend.a clangSerialization.a \
 	   clangDriver.a clangRewriteFrontend.a clangRewriteCore.a \
 	   clangParse.a clangSema.a clangAnalysis.a clangAST.a \





More information about the cfe-commits mailing list