blob: 905370720b9120315b9800953c01c5407fffd48c [file] [log] [blame]
Zhongxing Xu17892752008-10-08 02:50:44 +00001//== RegionStore.cpp - Field-sensitive store model --------------*- C++ -*--==//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file defines a basic region store model. In this model, we do have field
11// sensitivity. But we assume nothing about the heap shape. So recursive data
12// structures are largely ignored. Basically we do 1-limiting analysis.
13// Parameter pointers are assumed with no aliasing. Pointee objects of
14// parameters are created lazily.
15//
16//===----------------------------------------------------------------------===//
17#include "clang/Analysis/PathSensitive/MemRegion.h"
18#include "clang/Analysis/PathSensitive/GRState.h"
19#include "clang/Analysis/Analyses/LiveVariables.h"
20
21#include "llvm/ADT/ImmutableMap.h"
22#include "llvm/Support/Compiler.h"
23
24using namespace clang;
25
Zhongxing Xu1c96b242008-10-17 05:57:07 +000026typedef llvm::ImmutableMap<const MemRegion*, SVal> RegionBindingsTy;
Zhongxing Xu17892752008-10-08 02:50:44 +000027
28namespace {
29
30class VISIBILITY_HIDDEN RegionStoreManager : public StoreManager {
31 RegionBindingsTy::Factory RBFactory;
32 GRStateManager& StateMgr;
33 MemRegionManager MRMgr;
34
35public:
36 RegionStoreManager(GRStateManager& mgr)
37 : StateMgr(mgr), MRMgr(StateMgr.getAllocator()) {}
38
39 virtual ~RegionStoreManager() {}
40
Zhongxing Xu53bcdd42008-10-21 05:29:26 +000041 SVal GetSVal(Store S, Loc L, QualType T);
Zhongxing Xu1c96b242008-10-17 05:57:07 +000042 Store SetSVal(Store St, Loc LV, SVal V);
Zhongxing Xu17892752008-10-08 02:50:44 +000043
44 Store getInitialStore();
45
Zhongxing Xu53bcdd42008-10-21 05:29:26 +000046 Store AddDecl(Store store, const VarDecl* VD, Expr* Ex, SVal InitVal,
47 unsigned Count);
48
49 Loc getVarLoc(const VarDecl* VD) {
50 return loc::MemRegionVal(MRMgr.getVarRegion(VD));
51 }
52
53 Loc getElementLoc(const VarDecl* VD, SVal Idx);
54
Zhongxing Xu17892752008-10-08 02:50:44 +000055 static inline RegionBindingsTy GetRegionBindings(Store store) {
56 return RegionBindingsTy(static_cast<const RegionBindingsTy::TreeTy*>(store));
57 }
58};
59
60} // end anonymous namespace
61
Zhongxing Xu53bcdd42008-10-21 05:29:26 +000062Loc RegionStoreManager::getElementLoc(const VarDecl* VD, SVal Idx) {
63 MemRegion* R = MRMgr.getVarRegion(VD);
64 ElementRegion* ER = MRMgr.getElementRegion(Idx, R);
65 return loc::MemRegionVal(ER);
66}
67
68SVal RegionStoreManager::GetSVal(Store S, Loc L, QualType T) {
69 assert(!isa<UnknownVal>(L) && "location unknown");
70 assert(!isa<UndefinedVal>(L) && "location undefined");
71
72 switch (L.getSubKind()) {
73 case loc::MemRegionKind: {
74 const MemRegion* R = cast<loc::MemRegionVal>(L).getRegion();
75 assert(R && "bad region");
76
77 RegionBindingsTy B(static_cast<const RegionBindingsTy::TreeTy*>(S));
78 RegionBindingsTy::data_type* V = B.lookup(R);
79 return V ? *V : UnknownVal();
80 }
81
82 case loc::SymbolValKind:
83 return UnknownVal();
84
85 case loc::ConcreteIntKind:
86 return UndefinedVal(); // As in BasicStoreManager.
87
88 case loc::FuncValKind:
89 return L;
90
91 case loc::StringLiteralValKind:
92 return UnknownVal();
93
94 default:
95 assert(false && "Invalid Location");
96 break;
97 }
98}
99
Zhongxing Xu1c96b242008-10-17 05:57:07 +0000100Store RegionStoreManager::SetSVal(Store store, Loc LV, SVal V) {
101 assert(LV.getSubKind() == loc::MemRegionKind);
Zhongxing Xu17892752008-10-08 02:50:44 +0000102
Ted Kremenek993f1c72008-10-17 20:28:54 +0000103 const MemRegion* R = cast<loc::MemRegionVal>(LV).getRegion();
Zhongxing Xu17892752008-10-08 02:50:44 +0000104
105 if (!R)
106 return store;
107
108 RegionBindingsTy B = GetRegionBindings(store);
109 return V.isUnknown()
110 ? RBFactory.Remove(B, R).getRoot()
111 : RBFactory.Add(B, R, V).getRoot();
112}
113
114Store RegionStoreManager::getInitialStore() {
115 typedef LiveVariables::AnalysisDataTy LVDataTy;
116 LVDataTy& D = StateMgr.getLiveVariables().getAnalysisData();
117
118 Store St = RBFactory.GetEmptyMap().getRoot();
119
120 for (LVDataTy::decl_iterator I=D.begin_decl(), E=D.end_decl(); I != E; ++I) {
121 ScopedDecl* SD = const_cast<ScopedDecl*>(I->first);
122
123 if (VarDecl* VD = dyn_cast<VarDecl>(SD)) {
124 // Punt on static variables for now.
125 if (VD->getStorageClass() == VarDecl::Static)
126 continue;
127
128 QualType T = VD->getType();
129 // Only handle pointers and integers for now.
Zhongxing Xu1c96b242008-10-17 05:57:07 +0000130 if (Loc::IsLocType(T) || T->isIntegerType()) {
Zhongxing Xu17892752008-10-08 02:50:44 +0000131 // Initialize globals and parameters to symbolic values.
132 // Initialize local variables to undefined.
Zhongxing Xu1c96b242008-10-17 05:57:07 +0000133 SVal X = (VD->hasGlobalStorage() || isa<ParmVarDecl>(VD) ||
Zhongxing Xu17892752008-10-08 02:50:44 +0000134 isa<ImplicitParamDecl>(VD))
Zhongxing Xu1c96b242008-10-17 05:57:07 +0000135 ? SVal::GetSymbolValue(StateMgr.getSymbolManager(), VD)
Zhongxing Xu17892752008-10-08 02:50:44 +0000136 : UndefinedVal();
137
Zhongxing Xu53bcdd42008-10-21 05:29:26 +0000138 St = SetSVal(St, getVarLoc(VD), X);
Zhongxing Xu17892752008-10-08 02:50:44 +0000139 }
140 }
141 }
142 return St;
143}
Zhongxing Xu53bcdd42008-10-21 05:29:26 +0000144
145Store RegionStoreManager::AddDecl(Store store,
146 const VarDecl* VD, Expr* Ex,
147 SVal InitVal, unsigned Count) {
148 BasicValueFactory& BasicVals = StateMgr.getBasicVals();
149 SymbolManager& SymMgr = StateMgr.getSymbolManager();
150
151 if (VD->hasGlobalStorage()) {
152 // Static global variables should not be visited here.
153 assert(!(VD->getStorageClass() == VarDecl::Static &&
154 VD->isFileVarDecl()));
155 // Process static variables.
156 if (VD->getStorageClass() == VarDecl::Static) {
157 if (!Ex) {
158 // Only handle pointer and integer static variables.
159
160 QualType T = VD->getType();
161
162 if (Loc::IsLocType(T))
163 store = SetSVal(store, getVarLoc(VD),
164 loc::ConcreteInt(BasicVals.getValue(0, T)));
165
166 else if (T->isIntegerType())
167 store = SetSVal(store, getVarLoc(VD),
168 loc::ConcreteInt(BasicVals.getValue(0, T)));
169 else
170 assert("ignore other types of variables");
171 } else {
172 store = SetSVal(store, getVarLoc(VD), InitVal);
173 }
174 }
175 } else {
176 // Process local variables.
177
178 QualType T = VD->getType();
179
180 if (Loc::IsLocType(T) || T->isIntegerType()) {
181 SVal V = Ex ? InitVal : UndefinedVal();
182 if (Ex && InitVal.isUnknown()) {
183 // "Conjured" symbols.
184 SymbolID Sym = SymMgr.getConjuredSymbol(Ex, Count);
185 V = Loc::IsLocType(Ex->getType())
186 ? cast<SVal>(loc::SymbolVal(Sym))
187 : cast<SVal>(nonloc::SymbolVal(Sym));
188 }
189 store = SetSVal(store, getVarLoc(VD), V);
190
191 } else if (T->isArrayType()) {
192 // Only handle constant size array.
193 if (ConstantArrayType* CAT=dyn_cast<ConstantArrayType>(T.getTypePtr())) {
194
195 llvm::APInt Size = CAT->getSize();
196
197 for (llvm::APInt i = llvm::APInt::getNullValue(Size.getBitWidth());
198 i != Size; ++i) {
199 nonloc::ConcreteInt Idx(BasicVals.getValue(llvm::APSInt(i)));
200 store = SetSVal(store, getElementLoc(VD, Idx), UndefinedVal());
201 }
202 }
203 } else if (T->isStructureType()) {
204 // FIXME: Implement struct initialization.
205 }
206 }
207 return store;
208}
209