diff --git a/clang/include/clang/Analysis/PathSensitive/ValueManager.h b/clang/include/clang/Analysis/PathSensitive/ValueManager.h index 89af975de7af..b86f4e875304 100644 --- a/clang/include/clang/Analysis/PathSensitive/ValueManager.h +++ b/clang/include/clang/Analysis/PathSensitive/ValueManager.h @@ -81,7 +81,7 @@ public: SVal makeZeroArrayIndex(); /// GetRegionValueSymbolVal - make a unique symbol for value of R. - SVal getRegionValueSymbolVal(const MemRegion* R); + SVal getRegionValueSymbolVal(const MemRegion* R, QualType T = QualType()); SVal getConjuredSymbolVal(const Expr *E, unsigned Count); SVal getConjuredSymbolVal(const Expr* E, QualType T, unsigned Count); diff --git a/clang/lib/Analysis/RegionStore.cpp b/clang/lib/Analysis/RegionStore.cpp index d67fa84c7137..af8c7c9a9b2d 100644 --- a/clang/lib/Analysis/RegionStore.cpp +++ b/clang/lib/Analysis/RegionStore.cpp @@ -584,6 +584,7 @@ SVal RegionStoreManager::getSizeInElements(const GRState *state, QualType VarTy = VR->getValueType(getContext()); uint64_t EleSize = getContext().getTypeSize(EleTy); uint64_t VarSize = getContext().getTypeSize(VarTy); + assert(VarSize != 0); return NonLoc::MakeIntVal(getBasicVals(), VarSize / EleSize, false); } @@ -710,15 +711,18 @@ RegionStoreManager::CastRegion(const GRState *state, const MemRegion* R, uint64_t ObjTySize = getContext().getTypeSize(ObjTy); if ((PointeeTySize > 0 && PointeeTySize < ObjTySize) || - (ObjTy->isAggregateType() && PointeeTy->isScalarType())) { + (ObjTy->isAggregateType() && PointeeTy->isScalarType()) || + ObjTySize == 0 /* R has 'void*' type. */) { // Record the cast type of the region. state = setCastType(state, R, ToTy); SVal Idx = ValMgr.makeZeroArrayIndex(); ElementRegion* ER = MRMgr.getElementRegion(PointeeTy, Idx,R,getContext()); return CastResult(state, ER); - } else + } else { + state = setCastType(state, R, ToTy); return CastResult(state, R); + } } if (isa(R)) { @@ -930,14 +934,22 @@ SVal RegionStoreManager::Retrieve(const GRState *state, Loc L, QualType T) { return UndefinedVal(); } + // If the region is already cast to another type, use that type to create the + // symbol value. + if (const QualType *p = state->get(R)) { + QualType T = *p; + RTy = T->getAsPointerType()->getPointeeType(); + } + // All other integer values are symbolic. if (Loc::IsLocType(RTy) || RTy->isIntegerType()) - return ValMgr.getRegionValueSymbolVal(R); + return ValMgr.getRegionValueSymbolVal(R, RTy); else return UnknownVal(); } -SVal RegionStoreManager::RetrieveStruct(const GRState *state, const TypedRegion* R){ +SVal RegionStoreManager::RetrieveStruct(const GRState *state, + const TypedRegion* R){ QualType T = R->getValueType(getContext()); assert(T->isStructureType()); @@ -1220,8 +1232,8 @@ const GRState *RegionStoreManager::RemoveRegionView(const GRState *state, return state->set(Base, RVFactory.Remove(*d, View)); } -const GRState *RegionStoreManager::setCastType(const GRState *state, const MemRegion* R, - QualType T) { +const GRState *RegionStoreManager::setCastType(const GRState *state, + const MemRegion* R, QualType T) { return state->set(R, T); } diff --git a/clang/lib/Analysis/SVals.cpp b/clang/lib/Analysis/SVals.cpp index e19b16867b39..285d51e506c3 100644 --- a/clang/lib/Analysis/SVals.cpp +++ b/clang/lib/Analysis/SVals.cpp @@ -322,11 +322,12 @@ NonLoc NonLoc::MakeCompoundVal(QualType T, llvm::ImmutableList Vals, return nonloc::CompoundVal(BasicVals.getCompoundValData(T, Vals)); } -SVal ValueManager::getRegionValueSymbolVal(const MemRegion* R) { +SVal ValueManager::getRegionValueSymbolVal(const MemRegion* R, QualType T) { SymbolRef sym = SymMgr.getRegionValueSymbol(R); if (const TypedRegion* TR = dyn_cast(R)) { - QualType T = TR->getValueType(SymMgr.getContext()); + if (!T.getTypePtr()) + T = TR->getValueType(SymMgr.getContext()); // If T is of function pointer type, create a CodeTextRegion wrapping a // symbol. diff --git a/clang/test/Analysis/casts.c b/clang/test/Analysis/casts.c index 94a1eac0a316..c5fcdd92e1c6 100644 --- a/clang/test/Analysis/casts.c +++ b/clang/test/Analysis/casts.c @@ -14,3 +14,19 @@ void f(int sock) { ; } } + +struct s { + struct s *value; +}; + +// ElementRegion and cast-to pointee type may be of the same size: +// 'struct s **' and 'int'. + +int f1(struct s **pval) { + int *tbool = ((void*)0); + struct s *t = *pval; + pval = &(t->value); + tbool = (int *)pval; + char c = (unsigned char) *tbool; +} +