diff options
-rw-r--r-- | include/clang/Analysis/PathSensitive/MemRegion.h | 1 | ||||
-rw-r--r-- | include/clang/Analysis/PathSensitive/SVals.h | 3 | ||||
-rw-r--r-- | include/clang/Analysis/PathSensitive/Store.h | 5 | ||||
-rw-r--r-- | lib/Analysis/CFRefCount.cpp | 30 | ||||
-rw-r--r-- | lib/Analysis/RegionStore.cpp | 17 | ||||
-rw-r--r-- | lib/Analysis/SVals.cpp | 25 | ||||
-rw-r--r-- | test/Analysis/array-struct.c | 10 |
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; +} |