[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