aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/Analysis/PathSensitive/MemRegion.h1
-rw-r--r--include/clang/Analysis/PathSensitive/SVals.h3
-rw-r--r--include/clang/Analysis/PathSensitive/Store.h5
-rw-r--r--lib/Analysis/CFRefCount.cpp30
-rw-r--r--lib/Analysis/RegionStore.cpp17
-rw-r--r--lib/Analysis/SVals.cpp25
-rw-r--r--test/Analysis/array-struct.c10
7 files changed, 77 insertions, 14 deletions
diff --git a/include/clang/Analysis/PathSensitive/MemRegion.h b/include/clang/Analysis/PathSensitive/MemRegion.h
index 831da268b1..0e8da2aee3 100644
--- a/include/clang/Analysis/PathSensitive/MemRegion.h
+++ b/include/clang/Analysis/PathSensitive/MemRegion.h
@@ -217,6 +217,7 @@ public:
}
bool isDeclared() const { return codekind == Declared; }
+ bool isSymbolic() const { return codekind == Symbolic; }
const FunctionDecl* getDecl() const {
assert(codekind == Declared);
diff --git a/include/clang/Analysis/PathSensitive/SVals.h b/include/clang/Analysis/PathSensitive/SVals.h
index 70c0d09a03..ee6d4dcf1f 100644
--- a/include/clang/Analysis/PathSensitive/SVals.h
+++ b/include/clang/Analysis/PathSensitive/SVals.h
@@ -90,6 +90,9 @@ public:
bool isZeroConstant() const;
+ /// hasConjuredSymbol - If this SVal wraps a conjured symbol, return true;
+ bool hasConjuredSymbol() const;
+
/// getAsFunctionDecl - If this SVal is a MemRegionVal and wraps a
/// CodeTextRegion wrapping a FunctionDecl, return that FunctionDecl.
/// Otherwise return 0.
diff --git a/include/clang/Analysis/PathSensitive/Store.h b/include/clang/Analysis/PathSensitive/Store.h
index 5c1422549e..adcb2f76e0 100644
--- a/include/clang/Analysis/PathSensitive/Store.h
+++ b/include/clang/Analysis/PathSensitive/Store.h
@@ -161,6 +161,11 @@ public:
return St;
}
+ virtual const GRState* setDefaultValue(const GRState* St,
+ const MemRegion* R, SVal V) {
+ return St;
+ }
+
virtual void print(Store store, std::ostream& Out,
const char* nl, const char *sep) = 0;
diff --git a/lib/Analysis/CFRefCount.cpp b/lib/Analysis/CFRefCount.cpp
index 5120d4f0fc..dc9602a7b2 100644
--- a/lib/Analysis/CFRefCount.cpp
+++ b/lib/Analysis/CFRefCount.cpp
@@ -1721,7 +1721,7 @@ private:
void ProcessNonLeakError(ExplodedNodeSet<GRState>& Dst,
GRStmtNodeBuilder<GRState>& Builder,
- Expr* NodeExpr, Expr* ErrorExpr,
+ Expr* NodeExpr, Expr* ErrorExpr,
ExplodedNode<GRState>* Pred,
const GRState* St,
RefVal::Kind hasErr, SymbolRef Sym);
@@ -1767,7 +1767,7 @@ public:
Expr* Ex,
Expr* Receiver,
const RetainSummary& Summ,
- ExprIterator arg_beg, ExprIterator arg_end,
+ ExprIterator arg_beg, ExprIterator arg_end,
ExplodedNode<GRState>* Pred);
virtual void EvalCall(ExplodedNodeSet<GRState>& Dst,
@@ -1995,7 +1995,7 @@ namespace {
CFRefReport(CFRefBug& D, const CFRefCount &tf,
ExplodedNode<GRState> *n, SymbolRef sym, const char* endText)
- : RangedBugReport(D, D.getDescription(), endText, n), Sym(sym), TF(tf) {}
+ : RangedBugReport(D, D.getDescription(), endText, n), Sym(sym), TF(tf) {}
virtual ~CFRefReport() {}
@@ -2302,7 +2302,7 @@ PathDiagnosticPiece* CFRefReport::VisitNode(const ExplodedNode<GRState>* N,
if (PrevV.getAutoreleaseCount() == CurrV.getAutoreleaseCount())
return 0;
- assert(PrevV.getAutoreleaseCount() < CurrV.getAutoreleaseCount());
+ assert(PrevV.getAutoreleaseCount() < CurrV.getAutoreleaseCount());
os << "Object sent -autorelease message";
break;
}
@@ -2623,8 +2623,10 @@ void CFRefCount::EvalSummary(ExplodedNodeSet<GRState>& Dst,
ExplodedNode<GRState>* Pred) {
// Get the state.
- GRStateRef state(Builder.GetState(Pred), Eng.getStateManager());
- ASTContext& Ctx = Eng.getStateManager().getContext();
+ GRStateManager& StateMgr = Eng.getStateManager();
+ GRStateRef state(Builder.GetState(Pred), StateMgr);
+ ASTContext& Ctx = StateMgr.getContext();
+ ValueManager &ValMgr = Eng.getValueManager();
// Evaluate the effect of the arguments.
RefVal::Kind hasErr = (RefVal::Kind) 0;
@@ -2680,7 +2682,7 @@ void CFRefCount::EvalSummary(ExplodedNodeSet<GRState>& Dst,
// with an interface to StoreManager so that this logic can be
// approriately delegated to the respective StoreManagers while
// still allowing us to do checker-specific logic (e.g.,
- // invalidating reference counts), probably via callbacks.
+ // invalidating reference counts), probably via callbacks.
if (ER->getElementType()->isIntegralType()) {
const MemRegion *superReg = ER->getSuperRegion();
if (isa<VarRegion>(superReg) || isa<FieldRegion>(superReg) ||
@@ -2730,15 +2732,21 @@ void CFRefCount::EvalSummary(ExplodedNodeSet<GRState>& Dst,
QualType FT = FD->getType();
if (Loc::IsLocType(FT) ||
- (FT->isIntegerType() && FT->isScalarType())) {
+ (FT->isIntegerType() && FT->isScalarType())) {
const FieldRegion* FR = MRMgr.getFieldRegion(FD, R);
- ValueManager &ValMgr = Eng.getValueManager();
+
SVal V = ValMgr.getConjuredSymbolVal(*I, FT, Count);
state = state.BindLoc(Loc::MakeVal(FR), V);
}
}
- }
- else {
+ } else if (const ArrayType *AT = Ctx.getAsArrayType(T)) {
+ // Set the default value of the array to conjured symbol.
+ StoreManager& StoreMgr = Eng.getStateManager().getStoreManager();
+ SVal V = ValMgr.getConjuredSymbolVal(*I, AT->getElementType(),
+ Count);
+ state = GRStateRef(StoreMgr.setDefaultValue(state, R, V),
+ StateMgr);
+ } else {
// Just blast away other values.
state = state.BindLoc(*MR, UnknownVal());
}
diff --git a/lib/Analysis/RegionStore.cpp b/lib/Analysis/RegionStore.cpp
index 9d29a90b3e..440080db7e 100644
--- a/lib/Analysis/RegionStore.cpp
+++ b/lib/Analysis/RegionStore.cpp
@@ -276,7 +276,7 @@ public:
void iterBindings(Store store, BindingsHandler& f) {
// FIXME: Implement.
}
-
+ const GRState* setDefaultValue(const GRState* St, const MemRegion* R, SVal V);
private:
const GRState* BindArray(const GRState* St, const TypedRegion* R, SVal V);
@@ -759,8 +759,13 @@ SVal RegionStoreManager::Retrieve(const GRState* St, Loc L, QualType T) {
const MemRegion* SuperR = cast<SubRegion>(R)->getSuperRegion();
GRStateTrait<RegionDefaultValue>::lookup_type D =
state.get<RegionDefaultValue>(SuperR);
- if (D)
- return *D;
+ if (D) {
+ // If the default value is symbolic, we need to create a new symbol.
+ if (D->hasConjuredSymbol())
+ return ValMgr.getRegionValueSymbolVal(R);
+ else
+ return *D;
+ }
}
if (const ObjCIvarRegion *IVR = dyn_cast<ObjCIvarRegion>(R)) {
@@ -1274,3 +1279,9 @@ const GRState* RegionStoreManager::setCastType(const GRState* St,
GRStateRef state(St, StateMgr);
return state.set<RegionCasts>(R, T);
}
+
+const GRState* RegionStoreManager::setDefaultValue(const GRState* St,
+ const MemRegion* R, SVal V) {
+ GRStateRef state(St, StateMgr);
+ return state.set<RegionDefaultValue>(R, V);
+}
diff --git a/lib/Analysis/SVals.cpp b/lib/Analysis/SVals.cpp
index e10ea8952a..e19b16867b 100644
--- a/lib/Analysis/SVals.cpp
+++ b/lib/Analysis/SVals.cpp
@@ -30,6 +30,31 @@ using llvm::APSInt;
// Utility methods.
//===----------------------------------------------------------------------===//
+bool SVal::hasConjuredSymbol() const {
+ if (const nonloc::SymbolVal* SV = dyn_cast<nonloc::SymbolVal>(this)) {
+ SymbolRef sym = SV->getSymbol();
+ if (isa<SymbolConjured>(sym))
+ return true;
+ }
+
+ if (const loc::MemRegionVal *RV = dyn_cast<loc::MemRegionVal>(this)) {
+ const MemRegion *R = RV->getRegion();
+ if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R)) {
+ SymbolRef sym = SR->getSymbol();
+ if (isa<SymbolConjured>(sym))
+ return true;
+ } else if (const CodeTextRegion *CTR = dyn_cast<CodeTextRegion>(R)) {
+ if (CTR->isSymbolic()) {
+ SymbolRef sym = CTR->getSymbol();
+ if (isa<SymbolConjured>(sym))
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
const FunctionDecl* SVal::getAsFunctionDecl() const {
if (const loc::MemRegionVal* X = dyn_cast<loc::MemRegionVal>(this)) {
const MemRegion* R = X->getRegion();
diff --git a/test/Analysis/array-struct.c b/test/Analysis/array-struct.c
index 2b1aea75db..318f92f907 100644
--- a/test/Analysis/array-struct.c
+++ b/test/Analysis/array-struct.c
@@ -132,3 +132,13 @@ static struct s3 opt;
void f14() {
struct s3 my_opt = opt;
}
+
+void bar(int*);
+
+// Test if the array is correctly invalidated.
+void f15() {
+ int a[10];
+ bar(a);
+ if (a[1]) // no-warning
+ 1;
+}