]> granicus.if.org Git - clang/commitdiff
Added line number diagnostics to indicate the allocation site of the leaked object.
authorTed Kremenek <kremenek@apple.com>
Thu, 1 May 2008 23:13:35 +0000 (23:13 +0000)
committerTed Kremenek <kremenek@apple.com>
Thu, 1 May 2008 23:13:35 +0000 (23:13 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@50553 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Analysis/PathSensitive/BugReporter.h
lib/Analysis/BugReporter.cpp
lib/Analysis/CFRefCount.cpp

index b823906364b67166d522f9b60167e6a1a7dd1167..714e8883693f37fd78c8b023eeabc4eab996cbc8 100644 (file)
@@ -143,6 +143,8 @@ public:
   
   ASTContext& getContext() { return Ctx; }
   
+  SourceManager& getSourceManager() { return Ctx.getSourceManager(); }
+  
   ExplodedGraph<ValueState>& getGraph();
 
   GRExprEngine& getEngine() { return Eng; }
index 785e4cf4ae7ef1768e48fa1a081aa09d37dfa144..0ec1a35b681dbdac973dc25a72d89249b4e7c7e8 100644 (file)
@@ -112,10 +112,8 @@ BugReport::getEndPath(BugReporter& BR,
   if (!S)
     return NULL;
   
-  FullSourceLoc L(S->getLocStart(), BR.getContext().getSourceManager());  
-
-  PathDiagnosticPiece* P =
-    new PathDiagnosticPiece(L, getDescription());
+  FullSourceLoc L(S->getLocStart(), BR.getContext().getSourceManager());
+  PathDiagnosticPiece* P = new PathDiagnosticPiece(L, getDescription());
   
   const SourceRange *Beg, *End;
   getRanges(BR, Beg, End);  
index ea036f047b3afe115aa8724ba8e595504fccb71a..104391c13a7cccf1367bff31806291a8aa7d1b04 100644 (file)
@@ -14,6 +14,7 @@
 
 #include "GRSimpleVals.h"
 #include "clang/Basic/LangOptions.h"
+#include "clang/Basic/SourceManager.h"
 #include "clang/Analysis/PathSensitive/ValueState.h"
 #include "clang/Analysis/PathDiagnostic.h"
 #include "clang/Analysis/LocalCheckers.h"
@@ -1446,7 +1447,7 @@ namespace {
     
     CFRefCount& getTF() { return TF; }
     
-    virtual bool ReportRanges() const { return true; }
+    virtual bool isLeak() const { return false; }
   };
   
   class VISIBILITY_HIDDEN UseAfterRelease : public CFRefBug {
@@ -1494,7 +1495,7 @@ namespace {
     
     virtual void EmitWarnings(BugReporter& BR);
     virtual void GetErrorNodes(std::vector<ExplodedNode<ValueState>*>& Nodes);
-    virtual bool ReportRanges() const { return false; }
+    virtual bool isLeak() const { return true; }
   };
   
   //===---------===//
@@ -1519,7 +1520,7 @@ namespace {
     virtual void getRanges(BugReporter& BR, const SourceRange*& beg,           
                            const SourceRange*& end) {
       
-      if (getBugType().ReportRanges())
+      if (getBugType().isLeak())
         RangedBugReport::getRanges(BR, beg, end);
       else {
         beg = 0;
@@ -1527,6 +1528,9 @@ namespace {
       }
     }
     
+    virtual PathDiagnosticPiece* getEndPath(BugReporter& BR,
+                                            ExplodedNode<ValueState>* N);
+    
     virtual std::pair<const char**,const char**> getExtraDescriptiveText();
     
     virtual PathDiagnosticPiece* VisitNode(ExplodedNode<ValueState>* N,
@@ -1699,6 +1703,52 @@ PathDiagnosticPiece* CFRefReport::VisitNode(ExplodedNode<ValueState>* N,
   return P;
 }
 
+PathDiagnosticPiece* CFRefReport::getEndPath(BugReporter& BR,
+                                             ExplodedNode<ValueState>* N) {
+  
+  if (!getBugType().isLeak())
+    return RangedBugReport::getEndPath(BR, N);
+
+  // We are a leak.  Walk up the graph to get to the first node where the
+  // symbol appeared.
+  
+  ExplodedNode<ValueState>* Last = N;
+  typedef CFRefCount::RefBindings RefBindings;
+    
+  // Find the first node that referred to the tracked symbol.
+  
+  while (N) {
+    ValueState* St = N->getState();
+    RefBindings B = RefBindings((RefBindings::TreeTy*) St->CheckerState);
+
+    if (!B.SlimFind(Sym))
+      break;
+        
+    Last = N;
+    N = N->pred_empty() ? NULL : *(N->pred_begin());    
+  }
+  
+  // Get the location.
+  
+  assert (Last);
+  Stmt* FirstStmt = cast<PostStmt>(Last->getLocation()).getStmt();
+
+  unsigned Line =
+   BR.getSourceManager().getLogicalLineNumber(FirstStmt->getLocStart());
+
+  // FIXME: Also get the name of the variable.
+  
+  std::ostringstream os;
+  os << "Object allocated on line " << Line << " is leaked.";
+  
+  Stmt* S = getStmt(BR);
+  assert (S);  
+  FullSourceLoc L(S->getLocStart(), BR.getContext().getSourceManager());    
+  PathDiagnosticPiece* P = new PathDiagnosticPiece(L, os.str());
+    
+  return P;  
+}
+
 void UseAfterRelease::EmitWarnings(BugReporter& BR) {
 
   for (CFRefCount::use_after_iterator I = TF.use_after_begin(),