[cfe-commits] r64534 - in /cfe/trunk: include/clang/Analysis/PathSensitive/Environment.h include/clang/Analysis/PathSensitive/GRState.h include/clang/Analysis/PathSensitive/SymbolManager.h lib/Analysis/CFRefCount.cpp lib/Analysis/Environment.cpp lib/Analysis/GRState.cpp lib/Analysis/SymbolManager.cpp test/Analysis/rdar-6582778-basic-store.c

Ted Kremenek kremenek at apple.com
Fri Feb 13 19:16:11 PST 2009


Author: kremenek
Date: Fri Feb 13 21:16:10 2009
New Revision: 64534

URL: http://llvm.org/viewvc/llvm-project?rev=64534&view=rev
Log:
Added GRStateManager::scanReachableSymbols(), a method which scans the reachable
symbols from an SVal.

- Fixed a bug in EnvironmentManager::RemoveDeadBindings() where it did not mark
  live all the symbols reachable from a live block-level expression.

- Fixed a bug in the retain/release checker where it did not stop tracking
  symbols that 'escaped' via compound literals being assigned to something the
  BasicStoreManager didn't reason about.

Added:
    cfe/trunk/test/Analysis/rdar-6582778-basic-store.c
Modified:
    cfe/trunk/include/clang/Analysis/PathSensitive/Environment.h
    cfe/trunk/include/clang/Analysis/PathSensitive/GRState.h
    cfe/trunk/include/clang/Analysis/PathSensitive/SymbolManager.h
    cfe/trunk/lib/Analysis/CFRefCount.cpp
    cfe/trunk/lib/Analysis/Environment.cpp
    cfe/trunk/lib/Analysis/GRState.cpp
    cfe/trunk/lib/Analysis/SymbolManager.cpp

Modified: cfe/trunk/include/clang/Analysis/PathSensitive/Environment.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/PathSensitive/Environment.h?rev=64534&r1=64533&r2=64534&view=diff

==============================================================================
--- cfe/trunk/include/clang/Analysis/PathSensitive/Environment.h (original)
+++ cfe/trunk/include/clang/Analysis/PathSensitive/Environment.h Fri Feb 13 21:16:10 2009
@@ -141,6 +141,7 @@
 
   Environment
   RemoveDeadBindings(Environment Env, Stmt* Loc, SymbolReaper& SymReaper,
+                     GRStateManager& StateMgr,
                      llvm::SmallVectorImpl<const MemRegion*>& DRoots);
 
 };

Modified: cfe/trunk/include/clang/Analysis/PathSensitive/GRState.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/PathSensitive/GRState.h?rev=64534&r1=64533&r2=64534&view=diff

==============================================================================
--- cfe/trunk/include/clang/Analysis/PathSensitive/GRState.h (original)
+++ cfe/trunk/include/clang/Analysis/PathSensitive/GRState.h Fri Feb 13 21:16:10 2009
@@ -610,6 +610,9 @@
   void EndPath(const GRState* St) {
     ConstraintMgr->EndPath(St);
   }
+
+  bool scanReachableSymbols(nonloc::CompoundVal val, SymbolVisitor& vistor);
+  bool scanReachableSymbols(SVal val, SymbolVisitor& visitor);
 };
   
 //===----------------------------------------------------------------------===//
@@ -732,6 +735,13 @@
     return GRStateRef(Mgr->Assume(St, Cond, Assumption, isFeasible), *Mgr);  
   }
   
+  template <typename CB>
+  CB scanReachableSymbols(SVal val) {
+    CB cb(*this);
+    Mgr->scanReachableSymbols(val, cb);
+    return cb;
+  }
+  
   // Pretty-printing.
   void print(std::ostream& Out, const char* nl = "\n",
              const char *sep = "") const;

Modified: cfe/trunk/include/clang/Analysis/PathSensitive/SymbolManager.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/PathSensitive/SymbolManager.h?rev=64534&r1=64533&r2=64534&view=diff

==============================================================================
--- cfe/trunk/include/clang/Analysis/PathSensitive/SymbolManager.h (original)
+++ cfe/trunk/include/clang/Analysis/PathSensitive/SymbolManager.h Fri Feb 13 21:16:10 2009
@@ -263,6 +263,15 @@
   }
 };
   
+class SymbolVisitor {
+public:
+  // VisitSymbol - A visitor method invoked by
+  //  GRStateManager::scanReachableSymbols.  The method returns \c true if
+  //  symbols should continue be scanned and \c false otherwise.
+  virtual bool VisitSymbol(SymbolRef sym) = 0;
+  virtual ~SymbolVisitor();
+};
+  
 } // end clang namespace
 
 #endif

Modified: cfe/trunk/lib/Analysis/CFRefCount.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/CFRefCount.cpp?rev=64534&r1=64533&r2=64534&view=diff

==============================================================================
--- cfe/trunk/lib/Analysis/CFRefCount.cpp (original)
+++ cfe/trunk/lib/Analysis/CFRefCount.cpp Fri Feb 13 21:16:10 2009
@@ -21,6 +21,7 @@
 #include "clang/Analysis/LocalCheckers.h"
 #include "clang/Analysis/PathDiagnostic.h"
 #include "clang/Analysis/PathSensitive/BugReporter.h"
+#include "clang/Analysis/PathSensitive/SymbolManager.h"
 #include "clang/AST/DeclObjC.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/FoldingSet.h"
@@ -1736,13 +1737,25 @@
   EvalSummary(Dst, Eng, Builder, ME, ME->getReceiver(), Summ,
               ME->arg_begin(), ME->arg_end(), Pred);
 }
+
+namespace {
+class VISIBILITY_HIDDEN StopTrackingCallback : public SymbolVisitor {
+  GRStateRef state;
+public:
+  StopTrackingCallback(GRStateRef st) : state(st) {}
+  GRStateRef getState() { return state; }
+
+  bool VisitSymbol(SymbolRef sym) {
+    state = state.remove<RefBindings>(sym);
+    return true;
+  }
   
-void CFRefCount::EvalBind(GRStmtNodeBuilderRef& B, SVal location, SVal val) {  
-  // Check if we have a binding for "Val" and if we are storing it to something
-  // we don't understand or otherwise the value "escapes" the function.  
-  if (!isa<loc::SymbolVal>(val))
-    return;
+  const GRState* getState() const { return state.getState(); }
+};
+} // end anonymous namespace
   
+
+void CFRefCount::EvalBind(GRStmtNodeBuilderRef& B, SVal location, SVal val) {  
   // Are we storing to something that causes the value to "escape"?  
   bool escapes = false;
   
@@ -1752,7 +1765,6 @@
   // (2) we are binding to a memregion that does not have stack storage
   // (3) we are binding to a memregion with stack storage that the store
   //     does not understand.  
-  SymbolRef Sym = cast<loc::SymbolVal>(val).getSymbol();
   GRStateRef state = B.getState();
 
   if (!isa<loc::MemRegionVal>(location))
@@ -1769,15 +1781,15 @@
     }
   }
 
-  // Our store can represent the binding and we aren't storing to something
-  // that doesn't have local storage.  Just return and have the simulation
-  // state continue as is.  We should also just return if the tracked symbol
-  // is not associated with a reference count.
-  if (!escapes || !state.get<RefBindings>(Sym))
-    return;
+  // If our store can represent the binding and we aren't storing to something
+  // that doesn't have local storage then just return and have the simulation
+  // state continue as is.
+  if (!escapes)
+      return;
 
-  // The tracked object excapes. Stop tracking the object.
-  B.MakeNode(state.remove<RefBindings>(Sym));
+  // Otherwise, find all symbols referenced by 'val' that we are tracking
+  // and stop tracking them.
+  B.MakeNode(state.scanReachableSymbols<StopTrackingCallback>(val).getState());
 }
 
 std::pair<GRStateRef,bool>

Modified: cfe/trunk/lib/Analysis/Environment.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/Environment.cpp?rev=64534&r1=64533&r2=64534&view=diff

==============================================================================
--- cfe/trunk/lib/Analysis/Environment.cpp (original)
+++ cfe/trunk/lib/Analysis/Environment.cpp Fri Feb 13 21:16:10 2009
@@ -10,11 +10,11 @@
 //  This file defined the Environment and EnvironmentManager classes.
 //
 //===----------------------------------------------------------------------===//
-
-#include "clang/Analysis/PathSensitive/Environment.h"
+#include "clang/Analysis/PathSensitive/GRState.h"
 #include "clang/Analysis/Analyses/LiveVariables.h"
 #include "llvm/ADT/ImmutableMap.h"
 #include "llvm/Support/Streams.h"
+#include "llvm/Support/Compiler.h"
 
 using namespace clang;
 
@@ -106,9 +106,19 @@
   return isBlkExpr ? AddBlkExpr(Env, E, V) : AddSubExpr(Env, E, V);
 }
 
+namespace {
+class VISIBILITY_HIDDEN MarkLiveCallback : public SymbolVisitor {
+  SymbolReaper &SymReaper;
+public:
+  MarkLiveCallback(SymbolReaper &symreaper) : SymReaper(symreaper) {}  
+  bool VisitSymbol(SymbolRef sym) { SymReaper.markLive(sym); return true; }
+};
+} // end anonymous namespace
+
 Environment 
 EnvironmentManager::RemoveDeadBindings(Environment Env, Stmt* Loc,
                                        SymbolReaper& SymReaper,
+                                       GRStateManager& StateMgr,
                               llvm::SmallVectorImpl<const MemRegion*>& DRoots) {
   
   // Drop bindings for subexpressions.
@@ -126,11 +136,9 @@
       if (isa<loc::MemRegionVal>(X))
         DRoots.push_back(cast<loc::MemRegionVal>(X).getRegion());
 
-      // Mark all symbols in the block expr's value.
-      for (SVal::symbol_iterator SI = X.symbol_begin(), SE = X.symbol_end();
-           SI != SE; ++SI)
-        SymReaper.markLive(*SI);
-
+      // Mark all symbols in the block expr's value live.
+      MarkLiveCallback cb(SymReaper);
+      StateMgr.scanReachableSymbols(X, cb);
     } else {
       // The block expr is dead.
       SVal X = I.getData();

Modified: cfe/trunk/lib/Analysis/GRState.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/GRState.cpp?rev=64534&r1=64533&r2=64534&view=diff

==============================================================================
--- cfe/trunk/lib/Analysis/GRState.cpp (original)
+++ cfe/trunk/lib/Analysis/GRState.cpp Fri Feb 13 21:16:10 2009
@@ -45,7 +45,7 @@
   llvm::SmallVector<const MemRegion*, 10> RegionRoots;
   GRState NewState = *state;
 
-  NewState.Env = EnvMgr.RemoveDeadBindings(NewState.Env, Loc, SymReaper,
+  NewState.Env = EnvMgr.RemoveDeadBindings(NewState.Env, Loc, SymReaper, *this,
                                            RegionRoots);
 
   // Clean up the store.
@@ -205,6 +205,35 @@
 }
 
 //===----------------------------------------------------------------------===//
+// Utility.
+//===----------------------------------------------------------------------===//
+
+bool GRStateManager::scanReachableSymbols(nonloc::CompoundVal val,
+                                          SymbolVisitor& visitor) {
+  for (nonloc::CompoundVal::iterator I=val.begin(), E=val.end(); I!=E; ++I)
+    if (!scanReachableSymbols(*I, visitor)) return false;
+
+  return true;
+}
+
+bool GRStateManager::scanReachableSymbols(SVal val, SymbolVisitor& visitor) {
+  
+  // FIXME: Scan through through the reachable regions.
+  // if (isa<Loc>(val)) { ... }
+  
+  if (loc::SymbolVal *X = dyn_cast<loc::SymbolVal>(&val))
+    return visitor.VisitSymbol(X->getSymbol());
+  
+  if (nonloc::SymbolVal *X = dyn_cast<nonloc::SymbolVal>(&val))
+    return visitor.VisitSymbol(X->getSymbol());
+  
+  if (nonloc::CompoundVal *X = dyn_cast<nonloc::CompoundVal>(&val))
+    return scanReachableSymbols(*X, visitor);
+  
+  return true;
+}
+
+//===----------------------------------------------------------------------===//
 // Queries.
 //===----------------------------------------------------------------------===//
 

Modified: cfe/trunk/lib/Analysis/SymbolManager.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/SymbolManager.cpp?rev=64534&r1=64533&r2=64534&view=diff

==============================================================================
--- cfe/trunk/lib/Analysis/SymbolManager.cpp (original)
+++ cfe/trunk/lib/Analysis/SymbolManager.cpp Fri Feb 13 21:16:10 2009
@@ -99,4 +99,5 @@
   // the analyzed function/method.
   return isa<SymbolRegionRValue>(SymMgr.getSymbolData(sym));
 }
-  
+
+SymbolVisitor::~SymbolVisitor() {}

Added: cfe/trunk/test/Analysis/rdar-6582778-basic-store.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/rdar-6582778-basic-store.c?rev=64534&view=auto

==============================================================================
--- cfe/trunk/test/Analysis/rdar-6582778-basic-store.c (added)
+++ cfe/trunk/test/Analysis/rdar-6582778-basic-store.c Fri Feb 13 21:16:10 2009
@@ -0,0 +1,22 @@
+// RUN: clang -analyze -checker-cfref -analyzer-store-basic -verify %s
+
+typedef const void * CFTypeRef;
+typedef double CFTimeInterval;
+typedef CFTimeInterval CFAbsoluteTime;
+typedef const struct __CFAllocator * CFAllocatorRef;
+typedef const struct __CFDate * CFDateRef;
+
+extern CFDateRef CFDateCreate(CFAllocatorRef allocator, CFAbsoluteTime at);
+CFAbsoluteTime CFAbsoluteTimeGetCurrent(void);
+
+void f(void) {
+  CFAbsoluteTime t = CFAbsoluteTimeGetCurrent();
+  CFTypeRef vals[] = { CFDateCreate(0, t) }; // no-warning
+}
+
+CFTypeRef global;
+
+void g(void) {
+  CFAbsoluteTime t = CFAbsoluteTimeGetCurrent();
+  global = CFDateCreate(0, t); // no-warning
+}





More information about the cfe-commits mailing list