1 //== BasicStore.cpp - Basic map from Locations to Values --------*- C++ -*--==//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file defined the BasicStore and BasicStoreManager classes.
12 //===----------------------------------------------------------------------===//
14 #include "clang/AST/DeclCXX.h"
15 #include "clang/AST/ExprObjC.h"
16 #include "clang/Analysis/Analyses/LiveVariables.h"
17 #include "clang/Analysis/AnalysisContext.h"
18 #include "clang/GR/PathSensitive/GRState.h"
19 #include "llvm/ADT/ImmutableMap.h"
21 using namespace clang
;
23 typedef llvm::ImmutableMap
<const MemRegion
*,SVal
> BindingsTy
;
27 class BasicStoreSubRegionMap
: public SubRegionMap
{
29 BasicStoreSubRegionMap() {}
31 bool iterSubRegions(const MemRegion
* R
, Visitor
& V
) const {
32 return true; // Do nothing. No subregions.
36 class BasicStoreManager
: public StoreManager
{
37 BindingsTy::Factory VBFactory
;
39 BasicStoreManager(GRStateManager
& mgr
)
40 : StoreManager(mgr
), VBFactory(mgr
.getAllocator()) {}
42 ~BasicStoreManager() {}
44 SubRegionMap
*getSubRegionMap(Store store
) {
45 return new BasicStoreSubRegionMap();
48 SVal
Retrieve(Store store
, Loc loc
, QualType T
= QualType());
50 Store
InvalidateRegion(Store store
, const MemRegion
*R
, const Expr
*E
,
51 unsigned Count
, InvalidatedSymbols
*IS
);
53 Store
InvalidateRegions(Store store
, const MemRegion
* const *Begin
,
54 const MemRegion
* const *End
, const Expr
*E
,
55 unsigned Count
, InvalidatedSymbols
*IS
,
56 bool invalidateGlobals
, InvalidatedRegions
*Regions
);
58 Store
scanForIvars(Stmt
*B
, const Decl
* SelfDecl
,
59 const MemRegion
*SelfRegion
, Store St
);
61 Store
Bind(Store St
, Loc loc
, SVal V
);
62 Store
Remove(Store St
, Loc loc
);
63 Store
getInitialStore(const LocationContext
*InitLoc
);
65 Store
BindCompoundLiteral(Store store
, const CompoundLiteralExpr
*,
66 const LocationContext
*, SVal val
) {
70 /// ArrayToPointer - Used by GRExprEngine::VistCast to handle implicit
71 /// conversions between arrays and pointers.
72 SVal
ArrayToPointer(Loc Array
) { return Array
; }
74 /// RemoveDeadBindings - Scans a BasicStore of 'state' for dead values.
75 /// It updatees the GRState object in place with the values removed.
76 Store
RemoveDeadBindings(Store store
, const StackFrameContext
*LCtx
,
77 SymbolReaper
& SymReaper
,
78 llvm::SmallVectorImpl
<const MemRegion
*>& RegionRoots
);
80 void iterBindings(Store store
, BindingsHandler
& f
);
82 Store
BindDecl(Store store
, const VarRegion
*VR
, SVal InitVal
) {
83 return BindDeclInternal(store
, VR
, &InitVal
);
86 Store
BindDeclWithNoInit(Store store
, const VarRegion
*VR
) {
87 return BindDeclInternal(store
, VR
, 0);
90 Store
BindDeclInternal(Store store
, const VarRegion
*VR
, SVal
*InitVal
);
92 static inline BindingsTy
GetBindings(Store store
) {
93 return BindingsTy(static_cast<const BindingsTy::TreeTy
*>(store
));
96 void print(Store store
, llvm::raw_ostream
& Out
, const char* nl
,
100 SVal
LazyRetrieve(Store store
, const TypedRegion
*R
);
103 } // end anonymous namespace
106 StoreManager
* clang::CreateBasicStoreManager(GRStateManager
& StMgr
) {
107 return new BasicStoreManager(StMgr
);
110 static bool isHigherOrderRawPtr(QualType T
, ASTContext
&C
) {
111 bool foundPointer
= false;
113 const PointerType
*PT
= T
->getAs
<PointerType
>();
118 // intptr_t* or intptr_t**, etc?
119 if (T
->isIntegerType() && C
.getTypeSize(T
) == C
.getTypeSize(C
.VoidPtrTy
))
122 QualType X
= C
.getCanonicalType(T
).getUnqualifiedType();
123 return X
== C
.VoidTy
;
127 T
= PT
->getPointeeType();
131 SVal
BasicStoreManager::LazyRetrieve(Store store
, const TypedRegion
*R
) {
132 const VarRegion
*VR
= dyn_cast
<VarRegion
>(R
);
136 const VarDecl
*VD
= VR
->getDecl();
137 QualType T
= VD
->getType();
139 // Only handle simple types that we can symbolicate.
140 if (!SymbolManager::canSymbolicate(T
) || !T
->isScalarType())
143 // Globals and parameters start with symbolic values.
144 // Local variables initially are undefined.
146 // Non-static globals may have had their values reset by InvalidateRegions.
147 const MemSpaceRegion
*MS
= VR
->getMemorySpace();
148 if (isa
<NonStaticGlobalSpaceRegion
>(MS
)) {
149 BindingsTy B
= GetBindings(store
);
150 // FIXME: Copy-and-pasted from RegionStore.cpp.
151 if (BindingsTy::data_type
*Val
= B
.lookup(MS
)) {
152 if (SymbolRef parentSym
= Val
->getAsSymbol())
153 return svalBuilder
.getDerivedRegionValueSymbolVal(parentSym
, R
);
155 if (Val
->isZeroConstant())
156 return svalBuilder
.makeZeroVal(T
);
158 if (Val
->isUnknownOrUndef())
161 assert(0 && "Unknown default value.");
165 if (VR
->hasGlobalsOrParametersStorage() ||
166 isa
<UnknownSpaceRegion
>(VR
->getMemorySpace()))
167 return svalBuilder
.getRegionValueSymbolVal(R
);
169 return UndefinedVal();
172 SVal
BasicStoreManager::Retrieve(Store store
, Loc loc
, QualType T
) {
173 if (isa
<UnknownVal
>(loc
))
176 assert(!isa
<UndefinedVal
>(loc
));
178 switch (loc
.getSubKind()) {
180 case loc::MemRegionKind
: {
181 const MemRegion
* R
= cast
<loc::MemRegionVal
>(loc
).getRegion();
183 if (!(isa
<VarRegion
>(R
) || isa
<ObjCIvarRegion
>(R
) ||
184 isa
<CXXThisRegion
>(R
)))
187 BindingsTy B
= GetBindings(store
);
188 BindingsTy::data_type
*Val
= B
.lookup(R
);
189 const TypedRegion
*TR
= cast
<TypedRegion
>(R
);
192 return CastRetrievedVal(*Val
, TR
, T
);
194 SVal V
= LazyRetrieve(store
, TR
);
195 return V
.isUnknownOrUndef() ? V
: CastRetrievedVal(V
, TR
, T
);
198 case loc::ConcreteIntKind
:
199 // Support direct accesses to memory. It's up to individual checkers
204 assert (false && "Invalid Loc.");
211 Store
BasicStoreManager::Bind(Store store
, Loc loc
, SVal V
) {
212 if (isa
<loc::ConcreteInt
>(loc
))
215 const MemRegion
* R
= cast
<loc::MemRegionVal
>(loc
).getRegion();
217 // Special case: a default symbol assigned to the NonStaticGlobalsSpaceRegion
218 // that is used to derive other symbols.
219 if (isa
<NonStaticGlobalSpaceRegion
>(R
)) {
220 BindingsTy B
= GetBindings(store
);
221 return VBFactory
.add(B
, R
, V
).getRoot();
224 // Special case: handle store of pointer values (Loc) to pointers via
225 // a cast to intXX_t*, void*, etc. This is needed to handle
226 // OSCompareAndSwap32Barrier/OSCompareAndSwap64Barrier.
227 if (isa
<Loc
>(V
) || isa
<nonloc::LocAsInteger
>(V
))
228 if (const ElementRegion
*ER
= dyn_cast
<ElementRegion
>(R
)) {
229 // FIXME: Should check for index 0.
230 QualType T
= ER
->getLocationType();
232 if (isHigherOrderRawPtr(T
, Ctx
))
233 R
= ER
->getSuperRegion();
236 if (!(isa
<VarRegion
>(R
) || isa
<ObjCIvarRegion
>(R
) || isa
<CXXThisRegion
>(R
)))
239 const TypedRegion
*TyR
= cast
<TypedRegion
>(R
);
241 // Do not bind to arrays. We need to explicitly check for this so that
242 // we do not encounter any weirdness of trying to load/store from arrays.
243 if (TyR
->isBoundable() && TyR
->getValueType()->isArrayType())
246 if (nonloc::LocAsInteger
*X
= dyn_cast
<nonloc::LocAsInteger
>(&V
)) {
247 // Only convert 'V' to a location iff the underlying region type
248 // is a location as well.
249 // FIXME: We are allowing a store of an arbitrary location to
250 // a pointer. We may wish to flag a type error here if the types
251 // are incompatible. This may also cause lots of breakage
252 // elsewhere. Food for thought.
253 if (TyR
->isBoundable() && Loc::IsLocType(TyR
->getValueType()))
257 BindingsTy B
= GetBindings(store
);
259 ? VBFactory
.remove(B
, R
).getRoot()
260 : VBFactory
.add(B
, R
, V
).getRoot();
263 Store
BasicStoreManager::Remove(Store store
, Loc loc
) {
264 switch (loc
.getSubKind()) {
265 case loc::MemRegionKind
: {
266 const MemRegion
* R
= cast
<loc::MemRegionVal
>(loc
).getRegion();
268 if (!(isa
<VarRegion
>(R
) || isa
<ObjCIvarRegion
>(R
) ||
269 isa
<CXXThisRegion
>(R
)))
272 return VBFactory
.remove(GetBindings(store
), R
).getRoot();
275 assert ("Remove for given Loc type not yet implemented.");
280 Store
BasicStoreManager::RemoveDeadBindings(Store store
,
281 const StackFrameContext
*LCtx
,
282 SymbolReaper
& SymReaper
,
283 llvm::SmallVectorImpl
<const MemRegion
*>& RegionRoots
)
285 BindingsTy B
= GetBindings(store
);
286 typedef SVal::symbol_iterator symbol_iterator
;
288 // Iterate over the variable bindings.
289 for (BindingsTy::iterator I
=B
.begin(), E
=B
.end(); I
!=E
; ++I
) {
290 if (const VarRegion
*VR
= dyn_cast
<VarRegion
>(I
.getKey())) {
291 if (SymReaper
.isLive(VR
))
292 RegionRoots
.push_back(VR
);
296 else if (isa
<ObjCIvarRegion
>(I
.getKey()) ||
297 isa
<NonStaticGlobalSpaceRegion
>(I
.getKey()) ||
298 isa
<CXXThisRegion
>(I
.getKey()))
299 RegionRoots
.push_back(I
.getKey());
303 // Mark the bindings in the data as live.
304 SVal X
= I
.getData();
305 for (symbol_iterator SI
=X
.symbol_begin(), SE
=X
.symbol_end(); SI
!=SE
; ++SI
)
306 SymReaper
.markLive(*SI
);
309 // Scan for live variables and live symbols.
310 llvm::SmallPtrSet
<const MemRegion
*, 10> Marked
;
312 while (!RegionRoots
.empty()) {
313 const MemRegion
* MR
= RegionRoots
.back();
314 RegionRoots
.pop_back();
317 if (const SymbolicRegion
* SymR
= dyn_cast
<SymbolicRegion
>(MR
)) {
318 SymReaper
.markLive(SymR
->getSymbol());
321 else if (isa
<VarRegion
>(MR
) || isa
<ObjCIvarRegion
>(MR
) ||
322 isa
<NonStaticGlobalSpaceRegion
>(MR
) || isa
<CXXThisRegion
>(MR
)) {
323 if (Marked
.count(MR
))
327 SVal X
= Retrieve(store
, loc::MemRegionVal(MR
));
329 // FIXME: We need to handle symbols nested in region definitions.
330 for (symbol_iterator SI
=X
.symbol_begin(),SE
=X
.symbol_end();SI
!=SE
;++SI
)
331 SymReaper
.markLive(*SI
);
333 if (!isa
<loc::MemRegionVal
>(X
))
336 const loc::MemRegionVal
& LVD
= cast
<loc::MemRegionVal
>(X
);
337 RegionRoots
.push_back(LVD
.getRegion());
340 else if (const SubRegion
* R
= dyn_cast
<SubRegion
>(MR
))
341 MR
= R
->getSuperRegion();
347 // Remove dead variable bindings.
348 for (BindingsTy::iterator I
=B
.begin(), E
=B
.end(); I
!=E
; ++I
) {
349 const MemRegion
* R
= I
.getKey();
351 if (!Marked
.count(R
)) {
352 store
= Remove(store
, svalBuilder
.makeLoc(R
));
353 SVal X
= I
.getData();
355 for (symbol_iterator SI
=X
.symbol_begin(), SE
=X
.symbol_end(); SI
!=SE
; ++SI
)
356 SymReaper
.maybeDead(*SI
);
363 Store
BasicStoreManager::scanForIvars(Stmt
*B
, const Decl
* SelfDecl
,
364 const MemRegion
*SelfRegion
, Store St
) {
365 for (Stmt::child_iterator CI
=B
->child_begin(), CE
=B
->child_end();
371 // Check if the statement is an ivar reference. We only
372 // care about self.ivar.
373 if (ObjCIvarRefExpr
*IV
= dyn_cast
<ObjCIvarRefExpr
>(*CI
)) {
374 const Expr
*Base
= IV
->getBase()->IgnoreParenCasts();
375 if (const DeclRefExpr
*DR
= dyn_cast
<DeclRefExpr
>(Base
)) {
376 if (DR
->getDecl() == SelfDecl
) {
377 const ObjCIvarRegion
*IVR
= MRMgr
.getObjCIvarRegion(IV
->getDecl(),
379 SVal X
= svalBuilder
.getRegionValueSymbolVal(IVR
);
380 St
= Bind(St
, svalBuilder
.makeLoc(IVR
), X
);
385 St
= scanForIvars(*CI
, SelfDecl
, SelfRegion
, St
);
391 Store
BasicStoreManager::getInitialStore(const LocationContext
*InitLoc
) {
392 // The LiveVariables information already has a compilation of all VarDecls
393 // used in the function. Iterate through this set, and "symbolicate"
394 // any VarDecl whose value originally comes from outside the function.
395 typedef LiveVariables::AnalysisDataTy LVDataTy
;
396 LVDataTy
& D
= InitLoc
->getLiveVariables()->getAnalysisData();
397 Store St
= VBFactory
.getEmptyMap().getRoot();
399 for (LVDataTy::decl_iterator I
=D
.begin_decl(), E
=D
.end_decl(); I
!= E
; ++I
) {
400 const NamedDecl
* ND
= I
->first
;
402 // Handle implicit parameters.
403 if (const ImplicitParamDecl
* PD
= dyn_cast
<ImplicitParamDecl
>(ND
)) {
404 const Decl
& CD
= *InitLoc
->getDecl();
405 if (const ObjCMethodDecl
* MD
= dyn_cast
<ObjCMethodDecl
>(&CD
)) {
406 if (MD
->getSelfDecl() == PD
) {
407 // FIXME: Add type constraints (when they become available) to
408 // SelfRegion? (i.e., it implements MD->getClassInterface()).
409 const VarRegion
*VR
= MRMgr
.getVarRegion(PD
, InitLoc
);
410 const MemRegion
*SelfRegion
=
411 svalBuilder
.getRegionValueSymbolVal(VR
).getAsRegion();
413 St
= Bind(St
, svalBuilder
.makeLoc(VR
), loc::MemRegionVal(SelfRegion
));
414 // Scan the method for ivar references. While this requires an
415 // entire AST scan, the cost should not be high in practice.
416 St
= scanForIvars(MD
->getBody(), PD
, SelfRegion
, St
);
422 if (const CXXMethodDecl
*MD
= dyn_cast
<CXXMethodDecl
>(InitLoc
->getDecl())) {
423 // For C++ methods add symbolic region for 'this' in initial stack frame.
424 QualType ThisT
= MD
->getThisType(StateMgr
.getContext());
425 MemRegionManager
&RegMgr
= svalBuilder
.getRegionManager();
426 const CXXThisRegion
*ThisR
= RegMgr
.getCXXThisRegion(ThisT
, InitLoc
);
427 SVal ThisV
= svalBuilder
.getRegionValueSymbolVal(ThisR
);
428 St
= Bind(St
, svalBuilder
.makeLoc(ThisR
), ThisV
);
434 Store
BasicStoreManager::BindDeclInternal(Store store
, const VarRegion
* VR
,
437 BasicValueFactory
& BasicVals
= StateMgr
.getBasicVals();
438 const VarDecl
*VD
= VR
->getDecl();
440 // BasicStore does not model arrays and structs.
441 if (VD
->getType()->isArrayType() || VD
->getType()->isStructureOrClassType())
444 if (VD
->hasGlobalStorage()) {
445 // Handle variables with global storage: extern, static, PrivateExtern.
447 // FIXME:: static variables may have an initializer, but the second time a
448 // function is called those values may not be current. Currently, a function
449 // will not be called more than once.
451 // Static global variables should not be visited here.
452 assert(!(VD
->getStorageClass() == SC_Static
&&
453 VD
->isFileVarDecl()));
455 // Process static variables.
456 if (VD
->getStorageClass() == SC_Static
) {
457 // C99: 6.7.8 Initialization
458 // If an object that has static storage duration is not initialized
460 // —if it has pointer type, it is initialized to a null pointer;
461 // —if it has arithmetic type, it is initialized to (positive or
464 QualType T
= VD
->getType();
465 if (Loc::IsLocType(T
))
466 store
= Bind(store
, loc::MemRegionVal(VR
),
467 loc::ConcreteInt(BasicVals
.getValue(0, T
)));
468 else if (T
->isIntegerType() && T
->isScalarType())
469 store
= Bind(store
, loc::MemRegionVal(VR
),
470 nonloc::ConcreteInt(BasicVals
.getValue(0, T
)));
472 store
= Bind(store
, loc::MemRegionVal(VR
), *InitVal
);
476 // Process local scalar variables.
477 QualType T
= VD
->getType();
478 // BasicStore only supports scalars.
479 if ((T
->isScalarType() || T
->isReferenceType()) &&
480 svalBuilder
.getSymbolManager().canSymbolicate(T
)) {
481 SVal V
= InitVal
? *InitVal
: UndefinedVal();
482 store
= Bind(store
, loc::MemRegionVal(VR
), V
);
489 void BasicStoreManager::print(Store store
, llvm::raw_ostream
& Out
,
490 const char* nl
, const char *sep
) {
492 BindingsTy B
= GetBindings(store
);
493 Out
<< "Variables:" << nl
;
497 for (BindingsTy::iterator I
=B
.begin(), E
=B
.end(); I
!= E
; ++I
) {
503 Out
<< ' ' << I
.getKey() << " : " << I
.getData();
508 void BasicStoreManager::iterBindings(Store store
, BindingsHandler
& f
) {
509 BindingsTy B
= GetBindings(store
);
511 for (BindingsTy::iterator I
=B
.begin(), E
=B
.end(); I
!= E
; ++I
)
512 if (!f
.HandleBinding(*this, store
, I
.getKey(), I
.getData()))
517 StoreManager::BindingsHandler::~BindingsHandler() {}
519 //===----------------------------------------------------------------------===//
520 // Binding invalidation.
521 //===----------------------------------------------------------------------===//
524 Store
BasicStoreManager::InvalidateRegions(Store store
,
525 const MemRegion
* const *I
,
526 const MemRegion
* const *End
,
527 const Expr
*E
, unsigned Count
,
528 InvalidatedSymbols
*IS
,
529 bool invalidateGlobals
,
530 InvalidatedRegions
*Regions
) {
531 if (invalidateGlobals
) {
532 BindingsTy B
= GetBindings(store
);
533 for (BindingsTy::iterator I
=B
.begin(), End
=B
.end(); I
!= End
; ++I
) {
534 const MemRegion
*R
= I
.getKey();
535 if (isa
<NonStaticGlobalSpaceRegion
>(R
->getMemorySpace()))
536 store
= InvalidateRegion(store
, R
, E
, Count
, IS
);
540 for ( ; I
!= End
; ++I
) {
541 const MemRegion
*R
= *I
;
542 // Don't invalidate globals twice.
543 if (invalidateGlobals
) {
544 if (isa
<NonStaticGlobalSpaceRegion
>(R
->getMemorySpace()))
547 store
= InvalidateRegion(store
, *I
, E
, Count
, IS
);
549 Regions
->push_back(R
);
552 // FIXME: This is copy-and-paste from RegionStore.cpp.
553 if (invalidateGlobals
) {
554 // Bind the non-static globals memory space to a new symbol that we will
555 // use to derive the bindings for all non-static globals.
556 const GlobalsSpaceRegion
*GS
= MRMgr
.getGlobalsRegion();
558 svalBuilder
.getConjuredSymbolVal(/* SymbolTag = */ (void*) GS
, E
,
559 /* symbol type, doesn't matter */ Ctx
.IntTy
,
562 store
= Bind(store
, loc::MemRegionVal(GS
), V
);
564 Regions
->push_back(GS
);
571 Store
BasicStoreManager::InvalidateRegion(Store store
,
575 InvalidatedSymbols
*IS
) {
578 if (!(isa
<VarRegion
>(R
) || isa
<ObjCIvarRegion
>(R
)))
582 BindingsTy B
= GetBindings(store
);
583 if (BindingsTy::data_type
*Val
= B
.lookup(R
)) {
584 if (SymbolRef Sym
= Val
->getAsSymbol())
589 QualType T
= cast
<TypedRegion
>(R
)->getValueType();
590 SVal V
= svalBuilder
.getConjuredSymbolVal(R
, E
, T
, Count
);
591 return Bind(store
, loc::MemRegionVal(R
), V
);