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

Manuel Klimek klimek at google.com
Fri Nov 15 03:24:08 PST 2013


On Thu, Nov 14, 2013 at 6:16 PM, Jordan Rose <jordan_rose at apple.com> wrote:

>
> 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.)
>

I'm not too concerned about this - we had Pavel running the static analyzer
on all our code, outputting to text format, and analyzing the results, and
I don't remember the text format ever being an issue. I don't really have a
good idea what other format we'd want to use - our main use case is
overlaying the warnings in various steps of our workflow.

If we run into problems with the static analyzer's text output, and you say
it's not mean to be "production ready", would that mean you wouldn't want
to accept patches to make it production ready? :)


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

What would be a good test case for a path sensitive check that relies on
core?
I implemented your suggestion in r194807, but didn't find a good way to
test...

Thanks,
/Manuel


>
> > +    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
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20131115/e998d4b5/attachment.html>


More information about the cfe-commits mailing list