diff options
-rw-r--r-- | include/clang/Analysis/PathSensitive/ValueManager.h | 6 | ||||
-rw-r--r-- | lib/Analysis/BasicStore.cpp | 2 | ||||
-rw-r--r-- | lib/Analysis/CFRefCount.cpp | 2 | ||||
-rw-r--r-- | lib/Analysis/GRExprEngine.cpp | 9 | ||||
-rw-r--r-- | lib/Analysis/RegionStore.cpp | 133 | ||||
-rw-r--r-- | lib/Analysis/ValueManager.cpp | 11 | ||||
-rw-r--r-- | test/Analysis/misc-ps-region-store.m | 12 |
7 files changed, 111 insertions, 64 deletions
diff --git a/include/clang/Analysis/PathSensitive/ValueManager.h b/include/clang/Analysis/PathSensitive/ValueManager.h index 4dd936bb7d..8d162a681c 100644 --- a/include/clang/Analysis/PathSensitive/ValueManager.h +++ b/include/clang/Analysis/PathSensitive/ValueManager.h @@ -104,8 +104,10 @@ public: return UnknownVal(); } - DefinedOrUnknownSVal getConjuredSymbolVal(const Expr *E, unsigned Count); - DefinedOrUnknownSVal getConjuredSymbolVal(const Expr *E, QualType T, + DefinedOrUnknownSVal getConjuredSymbolVal(const void *SymbolTag, + const Expr *E, unsigned Count); + DefinedOrUnknownSVal getConjuredSymbolVal(const void *SymbolTag, + const Expr *E, QualType T, unsigned Count); DefinedOrUnknownSVal getDerivedRegionValueSymbolVal(SymbolRef parentSymbol, diff --git a/lib/Analysis/BasicStore.cpp b/lib/Analysis/BasicStore.cpp index 017399f4fb..e2a19cf834 100644 --- a/lib/Analysis/BasicStore.cpp +++ b/lib/Analysis/BasicStore.cpp @@ -639,7 +639,7 @@ const GRState *BasicStoreManager::InvalidateRegion(const GRState *state, return state; QualType T = cast<TypedRegion>(R)->getValueType(R->getContext()); - SVal V = ValMgr.getConjuredSymbolVal(E, T, Count); + SVal V = ValMgr.getConjuredSymbolVal(R, E, T, Count); return Bind(state, loc::MemRegionVal(R), V); } diff --git a/lib/Analysis/CFRefCount.cpp b/lib/Analysis/CFRefCount.cpp index 970646f764..75bd25cf5b 100644 --- a/lib/Analysis/CFRefCount.cpp +++ b/lib/Analysis/CFRefCount.cpp @@ -2906,7 +2906,7 @@ void CFRefCount::EvalSummary(ExplodedNodeSet& Dst, if (Loc::IsLocType(T) || (T->isIntegerType() && T->isScalarType())) { unsigned Count = Builder.getCurrentBlockCount(); ValueManager &ValMgr = Eng.getValueManager(); - SVal X = ValMgr.getConjuredSymbolVal(Ex, T, Count); + SVal X = ValMgr.getConjuredSymbolVal(NULL, Ex, T, Count); state = state->BindExpr(Ex, X, false); } diff --git a/lib/Analysis/GRExprEngine.cpp b/lib/Analysis/GRExprEngine.cpp index 735949cd4a..dc39d8b041 100644 --- a/lib/Analysis/GRExprEngine.cpp +++ b/lib/Analysis/GRExprEngine.cpp @@ -2203,7 +2203,7 @@ void GRExprEngine::VisitDeclStmt(DeclStmt *DS, ExplodedNode *Pred, // UnknownVal. if (InitVal.isUnknown() || !getConstraintManager().canReasonAbout(InitVal)) { - InitVal = ValMgr.getConjuredSymbolVal(InitEx, Count); + InitVal = ValMgr.getConjuredSymbolVal(NULL, InitEx, Count); } state = state->bindDecl(VD, LC, InitVal); @@ -2608,7 +2608,8 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, ExplodedNode* Pred, // Conjure a new symbol if necessary to recover precision. if (Result.isUnknown() || !getConstraintManager().canReasonAbout(Result)){ DefinedOrUnknownSVal SymVal = - ValMgr.getConjuredSymbolVal(Ex, Builder->getCurrentBlockCount()); + ValMgr.getConjuredSymbolVal(NULL, Ex, + Builder->getCurrentBlockCount()); Result = SymVal; // If the value is a location, ++/-- should always preserve @@ -2812,7 +2813,7 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B, && (Loc::IsLocType(T) || (T->isScalarType() && T->isIntegerType()))) { unsigned Count = Builder->getCurrentBlockCount(); - RightV = ValMgr.getConjuredSymbolVal(B->getRHS(), Count); + RightV = ValMgr.getConjuredSymbolVal(NULL, B->getRHS(), Count); } // Simulate the effects of a "store": bind the value of the RHS @@ -2936,7 +2937,7 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B, // The symbolic value is actually for the type of the left-hand side // expression, not the computation type, as this is the value the // LValue on the LHS will bind to. - LHSVal = ValMgr.getConjuredSymbolVal(B->getRHS(), LTy, Count); + LHSVal = ValMgr.getConjuredSymbolVal(NULL, B->getRHS(), LTy, Count); // However, we need to convert the symbol to the computation type. llvm::tie(state, Result) = SVator.EvalCast(LHSVal, state, CTy, LTy); diff --git a/lib/Analysis/RegionStore.cpp b/lib/Analysis/RegionStore.cpp index 75907da55e..6b7799c505 100644 --- a/lib/Analysis/RegionStore.cpp +++ b/lib/Analysis/RegionStore.cpp @@ -436,69 +436,98 @@ RegionStoreManager::RemoveSubRegionBindings(RegionBindings &B, DVM = DVMFactory.Remove(DVM, R); } - const GRState *RegionStoreManager::InvalidateRegion(const GRState *state, const MemRegion *R, - const Expr *E, + const Expr *Ex, unsigned Count) { ASTContext& Ctx = StateMgr.getContext(); // Strip away casts. R = R->getBaseRegion(); - // Remove the bindings to subregions. - { - // Get the mapping of regions -> subregions. - llvm::OwningPtr<RegionStoreSubRegionMap> - SubRegions(getRegionStoreSubRegionMap(state)); - - RegionBindings B = GetRegionBindings(state->getStore()); - RegionDefaultBindings DVM = state->get<RegionDefaultValue>(); - RegionDefaultBindings::Factory &DVMFactory = - state->get_context<RegionDefaultValue>(); - - RemoveSubRegionBindings(B, DVM, DVMFactory, R, *SubRegions.get()); - state = state->makeWithStore(B.getRoot())->set<RegionDefaultValue>(DVM); - } - - if (!R->isBoundable()) - return state; - - if (isa<AllocaRegion>(R) || isa<SymbolicRegion>(R) || - isa<ObjCObjectRegion>(R)) { - // Invalidate the region by setting its default value to - // conjured symbol. The type of the symbol is irrelavant. - SVal V = ValMgr.getConjuredSymbolVal(E, Ctx.IntTy, Count); - return setDefaultValue(state, R, V); - } - - const TypedRegion *TR = cast<TypedRegion>(R); - QualType T = TR->getValueType(Ctx); - - if (const RecordType *RT = T->getAsStructureType()) { - // FIXME: handle structs with default region value. - const RecordDecl *RD = RT->getDecl()->getDefinition(Ctx); - - // No record definition. There is nothing we can do. - if (!RD) - return state; - - // Invalidate the region by setting its default value to - // conjured symbol. The type of the symbol is irrelavant. - SVal V = ValMgr.getConjuredSymbolVal(E, Ctx.IntTy, Count); - return setDefaultValue(state, R, V); - } + // Get the mapping of regions -> subregions. + llvm::OwningPtr<RegionStoreSubRegionMap> + SubRegions(getRegionStoreSubRegionMap(state)); + + RegionBindings B = GetRegionBindings(state->getStore()); + RegionDefaultBindings DVM = state->get<RegionDefaultValue>(); + RegionDefaultBindings::Factory &DVMFactory = + state->get_context<RegionDefaultValue>(); + + llvm::DenseMap<const MemRegion *, unsigned> Visited; + llvm::SmallVector<const MemRegion *, 10> WorkList; + WorkList.push_back(R); + + while (!WorkList.empty()) { + R = WorkList.back(); + WorkList.pop_back(); + + // Have we visited this region before? + unsigned &visited = Visited[R]; + if (visited) + continue; + visited = 1; + + // Add subregions to work list. + RegionStoreSubRegionMap::iterator I, E; + for (llvm::tie(I, E) = SubRegions->begin_end(R); I!=E; ++I) + WorkList.push_back(*I); + + // Handle region. + if (isa<AllocaRegion>(R) || isa<SymbolicRegion>(R) || + isa<ObjCObjectRegion>(R)) { + // Invalidate the region by setting its default value to + // conjured symbol. The type of the symbol is irrelavant. + DefinedOrUnknownSVal V = ValMgr.getConjuredSymbolVal(R, Ex, Ctx.IntTy, + Count); + DVM = DVMFactory.Add(DVM, R, V); + continue; + } - if (const ArrayType *AT = Ctx.getAsArrayType(T)) { - // Set the default value of the array to conjured symbol. - SVal V = ValMgr.getConjuredSymbolVal(E, AT->getElementType(), - Count); - return setDefaultValue(state, TR, V); + if (!R->isBoundable()) + continue; + + const TypedRegion *TR = cast<TypedRegion>(R); + QualType T = TR->getValueType(Ctx); + + if (const RecordType *RT = T->getAsStructureType()) { + // FIXME: handle structs with default region value. + const RecordDecl *RD = RT->getDecl()->getDefinition(Ctx); + + // No record definition. There is nothing we can do. + if (!RD) + continue; + + // Invalidate the region by setting its default value to + // conjured symbol. The type of the symbol is irrelavant. + DefinedOrUnknownSVal V = ValMgr.getConjuredSymbolVal(R, Ex, Ctx.IntTy, + Count); + DVM = DVMFactory.Add(DVM, R, V); + continue; + } + + if (const ArrayType *AT = Ctx.getAsArrayType(T)) { + // Set the default value of the array to conjured symbol. + DefinedOrUnknownSVal V = + ValMgr.getConjuredSymbolVal(R, Ex, AT->getElementType(), Count); + DVM = DVMFactory.Add(DVM, R, V); + continue; + } + + // Get the old binding. Is it a region? If so, add it to the worklist. + if (const SVal *OldV = B.lookup(R)) { + if (const MemRegion *RV = OldV->getAsRegion()) + WorkList.push_back(RV); + } + + // Invalidate the binding. + DefinedOrUnknownSVal V = ValMgr.getConjuredSymbolVal(R, Ex, T, Count); + assert(SymbolManager::canSymbolicate(T) || V.isUnknown()); + B = RBFactory.Add(B, R, V); } - SVal V = ValMgr.getConjuredSymbolVal(E, T, Count); - assert(SymbolManager::canSymbolicate(T) || V.isUnknown()); - return Bind(state, ValMgr.makeLoc(TR), V); + // Create a new state with the updated bindings. + return state->makeWithStore(B.getRoot())->set<RegionDefaultValue>(DVM); } //===----------------------------------------------------------------------===// diff --git a/lib/Analysis/ValueManager.cpp b/lib/Analysis/ValueManager.cpp index 9c3dbdd24e..fe670e79b3 100644 --- a/lib/Analysis/ValueManager.cpp +++ b/lib/Analysis/ValueManager.cpp @@ -88,13 +88,15 @@ DefinedOrUnknownSVal ValueManager::getRegionValueSymbolVal(const MemRegion* R, return nonloc::SymbolVal(sym); } -DefinedOrUnknownSVal ValueManager::getConjuredSymbolVal(const Expr *E, unsigned Count) { +DefinedOrUnknownSVal ValueManager::getConjuredSymbolVal(const void *SymbolTag, + const Expr *E, + unsigned Count) { QualType T = E->getType(); if (!SymbolManager::canSymbolicate(T)) return UnknownVal(); - SymbolRef sym = SymMgr.getConjuredSymbol(E, Count); + SymbolRef sym = SymMgr.getConjuredSymbol(E, Count, SymbolTag); if (Loc::IsLocType(T)) return loc::MemRegionVal(MemMgr.getSymbolicRegion(sym)); @@ -102,14 +104,15 @@ DefinedOrUnknownSVal ValueManager::getConjuredSymbolVal(const Expr *E, unsigned return nonloc::SymbolVal(sym); } -DefinedOrUnknownSVal ValueManager::getConjuredSymbolVal(const Expr *E, +DefinedOrUnknownSVal ValueManager::getConjuredSymbolVal(const void *SymbolTag, + const Expr *E, QualType T, unsigned Count) { if (!SymbolManager::canSymbolicate(T)) return UnknownVal(); - SymbolRef sym = SymMgr.getConjuredSymbol(E, T, Count); + SymbolRef sym = SymMgr.getConjuredSymbol(E, T, Count, SymbolTag); if (Loc::IsLocType(T)) return loc::MemRegionVal(MemMgr.getSymbolicRegion(sym)); diff --git a/test/Analysis/misc-ps-region-store.m b/test/Analysis/misc-ps-region-store.m index dd1e6455f0..76084d5c9e 100644 --- a/test/Analysis/misc-ps-region-store.m +++ b/test/Analysis/misc-ps-region-store.m @@ -237,3 +237,15 @@ void rdar_7249327(unsigned int A[2*32]) { x += *b++; // no-warning } +// <rdar://problem/6914474> - Check that 'x' is invalidated because its +// address is passed in as a value to a struct. +struct doodad_6914474 { int *v; }; +extern void prod_6914474(struct doodad_6914474 *d); +int rdar_6914474(void) { + int x; + struct doodad_6914474 d; + d.v = &x; + prod_6914474(&d); + return x; // no-warning +} + |