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

Jordan Rose jordan_rose at apple.com
Thu Nov 14 09:16:14 PST 2013


On Nov 14, 2013, at 7:49 , Manuel Klimek <klimek at google.com> wrote:

> 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;

While I’m always happy when the analyzer gets more use, the text mode is something we haven’t ever really supported or worked on productizing—it’s always been a lo-fi output format that’s not guaranteed for anything besides debugging. Shipping a tool that reports paths in text mode is a big step, and there could easily be QoI issues we haven’t had to care about until now. (Also, sometimes paths are dozens of notes long.)

Additionally, the analyzer is not expected to do sensible things without the “core" checkers enabled if you’re running any path-sensitive checks. At some point I’ll fix things so that that’s automatic, but for now please always include “core” in the control list.

> +    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 \
> 
> 
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits





More information about the cfe-commits mailing list