Hi klimek,

This patch depends on patches D2556 and D2557.

http://llvm-reviews.chandlerc.com/D2620

Files:
  clang-tidy/ClangTidy.cpp
  clang-tidy/ClangTidyDiagnosticConsumer.cpp
  clang-tidy/ClangTidyDiagnosticConsumer.h
  test/clang-tidy/static-analyzer.cpp
Index: clang-tidy/ClangTidy.cpp
===================================================================
--- clang-tidy/ClangTidy.cpp
+++ clang-tidy/ClangTidy.cpp
@@ -59,6 +59,57 @@
 #undef GET_CHECKERS
 };
 
+class AnalyzerDiagnosticConsumer : public ento::PathDiagnosticConsumer {
+public:
+  AnalyzerDiagnosticConsumer(ClangTidyContext &Context) : Context(Context) {}
+
+  virtual void
+  FlushDiagnosticsImpl(std::vector<const ento::PathDiagnostic *> &Diags,
+                       FilesMade *filesMade) LLVM_OVERRIDE {
+    for (std::vector<const ento::PathDiagnostic *>::iterator I = Diags.begin(),
+                                                             E = Diags.end();
+         I != E; ++I) {
+      const ento::PathDiagnostic *PD = *I;
+      SmallString<64> CheckerName(AnalyzerCheckerNamePrefix);
+      CheckerName += PD->getCheckerName();
+      addRanges(Context.diag(CheckerName, PD->getLocation().asLocation(),
+                             PD->getShortDescription()),
+                PD->path.back()->getRanges());
+
+      ento::PathPieces FlatPath =
+          PD->path.flatten(/*ShouldFlattenMacros=*/true);
+      for (ento::PathPieces::const_iterator PI = FlatPath.begin(),
+                                            PE = FlatPath.end();
+           PI != PE; ++PI) {
+        addRanges(Context.diag(CheckerName, (*PI)->getLocation().asLocation(),
+                               (*PI)->getString(), DiagnosticsEngine::Note),
+                  (*PI)->getRanges());
+      }
+    }
+  }
+
+  virtual StringRef getName() const { return "ClangTidyDiags"; }
+
+  virtual bool supportsLogicalOpControlFlow() const LLVM_OVERRIDE {
+    return true;
+  }
+  virtual bool supportsCrossFileDiagnostics() const LLVM_OVERRIDE {
+    return true;
+  }
+
+private:
+  ClangTidyContext &Context;
+
+  // FIXME: Convert to operator<<(DiagnosticBuilder&, ArrayRef<SourceRange>).
+  static const DiagnosticBuilder &addRanges(const DiagnosticBuilder &DB,
+                                            ArrayRef<SourceRange> Ranges) {
+    for (ArrayRef<SourceRange>::iterator I = Ranges.begin(), E = Ranges.end();
+         I != E; ++I)
+      DB << *I;
+    return DB;
+  }
+};
+
 } // namespace
 
 ClangTidyASTConsumerFactory::ClangTidyASTConsumerFactory(
@@ -103,15 +154,15 @@
   AnalyzerOptionsRef Options = Compiler.getAnalyzerOpts();
   Options->CheckersControlList = getCheckersControlList();
   Options->AnalysisStoreOpt = RegionStoreModel;
-  Options->AnalysisDiagOpt = PD_TEXT;
+  Options->AnalysisDiagOpt = PD_NONE;
   Options->AnalyzeNestedBlocks = true;
   Options->eagerlyAssumeBinOpBifurcation = true;
-  ASTConsumer *Consumers[] = {
-    Finder.newASTConsumer(),
-    ento::CreateAnalysisConsumer(Compiler.getPreprocessor(),
-                                 Compiler.getFrontendOpts().OutputFile, Options,
-                                 Compiler.getFrontendOpts().Plugins)
-  };
+  ento::AnalysisASTConsumer *AnalysisConsumer = ento::CreateAnalysisConsumer(
+      Compiler.getPreprocessor(), Compiler.getFrontendOpts().OutputFile,
+      Options, Compiler.getFrontendOpts().Plugins);
+  AnalysisConsumer->AddDiagnosticConsumer(
+      new AnalyzerDiagnosticConsumer(Context));
+  ASTConsumer *Consumers[] = { Finder.newASTConsumer(), AnalysisConsumer };
   return new MultiplexConsumer(Consumers);
 }
 
@@ -240,21 +291,16 @@
 static void reportDiagnostic(const ClangTidyMessage &Message,
                              SourceManager &SourceMgr,
                              DiagnosticsEngine::Level Level,
-                             DiagnosticsEngine &Diags,
-                             StringRef CheckName = "") {
+                             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);
   }
-  if (CheckName.empty())
-    Diags.Report(Loc, Diags.getCustomDiagID(Level, Message.Message));
-  else
-    Diags.Report(Loc, Diags.getCustomDiagID(Level, (Message.Message + " [" +
-                                                    CheckName + "]").str()));
+  Diags.Report(Loc, Diags.getCustomDiagID(Level, Message.Message));
 }
 
 void handleErrors(SmallVectorImpl<ClangTidyError> &Errors, bool Fix) {
@@ -270,8 +316,7 @@
   for (SmallVectorImpl<ClangTidyError>::iterator I = Errors.begin(),
                                                  E = Errors.end();
        I != E; ++I) {
-    reportDiagnostic(I->Message, SourceMgr, DiagnosticsEngine::Warning, Diags,
-                     I->CheckName);
+    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);
     }
Index: clang-tidy/ClangTidyDiagnosticConsumer.cpp
===================================================================
--- clang-tidy/ClangTidyDiagnosticConsumer.cpp
+++ clang-tidy/ClangTidyDiagnosticConsumer.cpp
@@ -37,11 +37,11 @@
                                const ClangTidyMessage &Message)
     : CheckName(CheckName), Message(Message) {}
 
-DiagnosticBuilder ClangTidyContext::diag(StringRef CheckName,
-                                         SourceLocation Loc,
-                                         StringRef Message) {
-  unsigned ID =
-      DiagEngine->getCustomDiagID(DiagnosticsEngine::Warning, Message);
+DiagnosticBuilder ClangTidyContext::diag(
+    StringRef CheckName, SourceLocation Loc, StringRef Message,
+    DiagnosticsEngine::Level Level /* = DiagnosticsEngine::Warning*/) {
+  unsigned ID = DiagEngine->getCustomDiagID(
+      Level, (Message + " [" + CheckName + "]").str());
   if (CheckNamesByDiagnosticID.count(ID) == 0)
     CheckNamesByDiagnosticID.insert(std::make_pair(ID, CheckName.str()));
   return DiagEngine->Report(Loc, ID);
@@ -80,10 +80,6 @@
 void ClangTidyDiagnosticConsumer::HandleDiagnostic(
     DiagnosticsEngine::Level DiagLevel, const Diagnostic &Info) {
   // FIXME: Demultiplex diagnostics.
-  // FIXME: Ensure that we don't get notes from user code related to errors
-  // from non-user code.
-  if (Diags->getSourceManager().isInSystemHeader(Info.getLocation()))
-    return;
   if (DiagLevel != DiagnosticsEngine::Note) {
     Errors.push_back(
         ClangTidyError(Context.getCheckName(Info.getID()), getMessage(Info)));
@@ -93,12 +89,18 @@
     Errors.back().Notes.push_back(getMessage(Info));
   }
   addFixes(Info, Errors.back());
+
+  RelatesToUserCode.resize(Errors.size());
+  if (!Diags->getSourceManager().isInSystemHeader(Info.getLocation())) {
+    RelatesToUserCode[Errors.size() - 1] = true;
+  }
 }
 
 // Flushes the internal diagnostics buffer to the ClangTidyContext.
 void ClangTidyDiagnosticConsumer::finish() {
   for (unsigned i = 0, e = Errors.size(); i != e; ++i) {
-    Context.storeError(Errors[i]);
+    if (RelatesToUserCode[i])
+      Context.storeError(Errors[i]);
   }
   Errors.clear();
 }
Index: clang-tidy/ClangTidyDiagnosticConsumer.h
===================================================================
--- clang-tidy/ClangTidyDiagnosticConsumer.h
+++ clang-tidy/ClangTidyDiagnosticConsumer.h
@@ -74,8 +74,9 @@
   /// 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(StringRef CheckName, SourceLocation Loc,
-                         StringRef Message);
+  DiagnosticBuilder
+  diag(StringRef CheckName, SourceLocation Loc, StringRef Message,
+       DiagnosticsEngine::Level Level = DiagnosticsEngine::Warning);
 
   /// \brief Sets the \c DiagnosticsEngine so that Diagnostics can be generated
   /// correctly.
@@ -128,6 +129,7 @@
   ClangTidyContext &Context;
   OwningPtr<DiagnosticsEngine> Diags;
   SmallVector<ClangTidyError, 8> Errors;
+  SmallVector<bool, 8> RelatesToUserCode;
 };
 
 } // end namespace tidy
Index: test/clang-tidy/static-analyzer.cpp
===================================================================
--- test/clang-tidy/static-analyzer.cpp
+++ test/clang-tidy/static-analyzer.cpp
@@ -1,8 +1,17 @@
-// RUN: clang-tidy %s -checks='clang-analyzer-cplusplus' -- | FileCheck %s
+// RUN: clang-tidy %s -checks='clang-analyzer-' -- | FileCheck %s
+extern void *malloc(unsigned long);
+extern void free(void *);
 
 void f() {
   int *p = new int(42);
   delete p;
   delete p;
-  // CHECK: warning: Attempt to free released memory
+  // CHECK: warning: Attempt to free released memory [clang-analyzer-cplusplus.NewDelete]
+}
+
+void g() {
+  void *q = malloc(132);
+  free(q);
+  free(q);
+  // CHECK: warning: Attempt to free released memory [clang-analyzer-unix.Malloc]
 }
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to