From 08a2ede018e57e1bff0a4b3ee8dee5d5144897d5 Mon Sep 17 00:00:00 2001 From: Zhongxing Xu Date: Tue, 12 May 2009 10:10:00 +0000 Subject: [PATCH] Add logic for invalidating array region to CFRefCount.cpp. When invalidating array region, set its default value to conjured symbol. When retrieving its element, create new region value symbol for the element. Also fix some 80 columns violations. llvm-svn: 71548 --- .../clang/Analysis/PathSensitive/MemRegion.h | 1 + .../clang/Analysis/PathSensitive/SVals.h | 3 ++ .../clang/Analysis/PathSensitive/Store.h | 5 ++++ clang/lib/Analysis/CFRefCount.cpp | 30 ++++++++++++------- clang/lib/Analysis/RegionStore.cpp | 17 +++++++++-- clang/lib/Analysis/SVals.cpp | 25 ++++++++++++++++ clang/test/Analysis/array-struct.c | 10 +++++++ 7 files changed, 77 insertions(+), 14 deletions(-) diff --git a/clang/include/clang/Analysis/PathSensitive/MemRegion.h b/clang/include/clang/Analysis/PathSensitive/MemRegion.h index 831da268b168..0e8da2aee318 100644 --- a/clang/include/clang/Analysis/PathSensitive/MemRegion.h +++ b/clang/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/clang/include/clang/Analysis/PathSensitive/SVals.h b/clang/include/clang/Analysis/PathSensitive/SVals.h index 70c0d09a0347..ee6d4dcf1f37 100644 --- a/clang/include/clang/Analysis/PathSensitive/SVals.h +++ b/clang/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/clang/include/clang/Analysis/PathSensitive/Store.h b/clang/include/clang/Analysis/PathSensitive/Store.h index 5c1422549e2d..adcb2f76e0f3 100644 --- a/clang/include/clang/Analysis/PathSensitive/Store.h +++ b/clang/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/clang/lib/Analysis/CFRefCount.cpp b/clang/lib/Analysis/CFRefCount.cpp index 5120d4f0fc50..dc9602a7b280 100644 --- a/clang/lib/Analysis/CFRefCount.cpp +++ b/clang/lib/Analysis/CFRefCount.cpp @@ -1721,7 +1721,7 @@ private: void ProcessNonLeakError(ExplodedNodeSet& Dst, GRStmtNodeBuilder& Builder, - Expr* NodeExpr, Expr* ErrorExpr, + Expr* NodeExpr, Expr* ErrorExpr, ExplodedNode* 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* Pred); virtual void EvalCall(ExplodedNodeSet& Dst, @@ -1995,7 +1995,7 @@ namespace { CFRefReport(CFRefBug& D, const CFRefCount &tf, ExplodedNode *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* 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& Dst, ExplodedNode* 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& 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(superReg) || isa(superReg) || @@ -2730,15 +2732,21 @@ void CFRefCount::EvalSummary(ExplodedNodeSet& 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/clang/lib/Analysis/RegionStore.cpp b/clang/lib/Analysis/RegionStore.cpp index 9d29a90b3e76..440080db7e0c 100644 --- a/clang/lib/Analysis/RegionStore.cpp +++ b/clang/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(R)->getSuperRegion(); GRStateTrait::lookup_type D = state.get(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(R)) { @@ -1274,3 +1279,9 @@ const GRState* RegionStoreManager::setCastType(const GRState* St, GRStateRef state(St, StateMgr); return state.set(R, T); } + +const GRState* RegionStoreManager::setDefaultValue(const GRState* St, + const MemRegion* R, SVal V) { + GRStateRef state(St, StateMgr); + return state.set(R, V); +} diff --git a/clang/lib/Analysis/SVals.cpp b/clang/lib/Analysis/SVals.cpp index e10ea8952aa2..e19b16867b39 100644 --- a/clang/lib/Analysis/SVals.cpp +++ b/clang/lib/Analysis/SVals.cpp @@ -30,6 +30,31 @@ using llvm::APSInt; // Utility methods. //===----------------------------------------------------------------------===// +bool SVal::hasConjuredSymbol() const { + if (const nonloc::SymbolVal* SV = dyn_cast(this)) { + SymbolRef sym = SV->getSymbol(); + if (isa(sym)) + return true; + } + + if (const loc::MemRegionVal *RV = dyn_cast(this)) { + const MemRegion *R = RV->getRegion(); + if (const SymbolicRegion *SR = dyn_cast(R)) { + SymbolRef sym = SR->getSymbol(); + if (isa(sym)) + return true; + } else if (const CodeTextRegion *CTR = dyn_cast(R)) { + if (CTR->isSymbolic()) { + SymbolRef sym = CTR->getSymbol(); + if (isa(sym)) + return true; + } + } + } + + return false; +} + const FunctionDecl* SVal::getAsFunctionDecl() const { if (const loc::MemRegionVal* X = dyn_cast(this)) { const MemRegion* R = X->getRegion(); diff --git a/clang/test/Analysis/array-struct.c b/clang/test/Analysis/array-struct.c index 2b1aea75db0a..318f92f907ee 100644 --- a/clang/test/Analysis/array-struct.c +++ b/clang/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; +}