blob: 5522600d84913bf3309fea3a8c5b906c20cb1a84 [file] [log] [blame]
Ted Kremenek4adc81e2008-08-13 04:27:00 +00001//= GRState*cpp - Path-Sens. "State" for tracking valuues -----*- C++ -*--=//
Ted Kremenek9153f732008-02-05 07:17:49 +00002//
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//
Ted Kremenek4adc81e2008-08-13 04:27:00 +000010// This file defines SymbolID, ExprBindKey, and GRState*
Ted Kremenek9153f732008-02-05 07:17:49 +000011//
12//===----------------------------------------------------------------------===//
13
Ted Kremenek4adc81e2008-08-13 04:27:00 +000014#include "clang/Analysis/PathSensitive/GRState.h"
Ted Kremenek90e14812008-02-14 23:25:54 +000015#include "llvm/ADT/SmallSet.h"
Ted Kremenek729a9a22008-07-17 23:15:45 +000016#include "clang/Analysis/PathSensitive/GRTransferFuncs.h"
Ted Kremenekf66ea2cd2008-02-04 21:59:22 +000017
18using namespace clang;
19
Ted Kremenek1c72ef02008-08-16 00:49:49 +000020GRStateManager::~GRStateManager() {
21 for (std::vector<GRState::Printer*>::iterator I=Printers.begin(),
22 E=Printers.end(); I!=E; ++I)
23 delete *I;
24
25 for (GDMContextsTy::iterator I=GDMContexts.begin(), E=GDMContexts.end();
26 I!=E; ++I)
27 I->second.second(I->second.first);
28}
29
30//===----------------------------------------------------------------------===//
31// Basic symbolic analysis. This will eventually be refactored into a
32// separate component.
33//===----------------------------------------------------------------------===//
34
35typedef llvm::ImmutableMap<SymbolID,GRState::IntSetTy> ConstNotEqTy;
36
37static int ConstNotEqTyIndex = 0;
38
39namespace clang {
40 template<> struct GRStateTrait<ConstNotEqTy> {
41 typedef ConstNotEqTy data_type;
42 typedef ConstNotEqTy::Factory& context_type;
43 typedef SymbolID key_type;
44 typedef GRState::IntSetTy value_type;
45 typedef const GRState::IntSetTy* lookup_type;
46
47 static data_type MakeData(void* const* p) {
48 return p ? ConstNotEqTy((ConstNotEqTy::TreeTy*) *p) : ConstNotEqTy(0);
49 }
50 static void* MakeVoidPtr(ConstNotEqTy B) {
51 return B.getRoot();
52 }
53 static void* GDMIndex() {
54 return &ConstNotEqTyIndex;
55 }
56 static lookup_type Lookup(ConstNotEqTy B, SymbolID K) {
57 return B.lookup(K);
58 }
59 static data_type Set(data_type B, key_type K, value_type E,context_type F){
60 return F.Add(B, K, E);
61 }
62
63 static data_type Remove(ConstNotEqTy B, SymbolID K, context_type F) {
64 return F.Remove(B, K);
65 }
66
67 static context_type MakeContext(void* p) {
68 return *((ConstNotEqTy::Factory*) p);
69 }
70
71 static void* CreateContext(llvm::BumpPtrAllocator& Alloc) {
72 return new ConstNotEqTy::Factory(Alloc);
73 }
74
75 static void DeleteContext(void* Ctx) {
76 delete (ConstNotEqTy::Factory*) Ctx;
77 }
78 };
79}
80
Ted Kremenek4adc81e2008-08-13 04:27:00 +000081bool GRState::isNotEqual(SymbolID sym, const llvm::APSInt& V) const {
Ted Kremenekaa1c4e52008-02-21 18:02:17 +000082
83 // Retrieve the NE-set associated with the given symbol.
Ted Kremenek1c72ef02008-08-16 00:49:49 +000084 const ConstNotEqTy::data_type* T = get<ConstNotEqTy>(sym);
Ted Kremenekaa1c4e52008-02-21 18:02:17 +000085
86 // See if V is present in the NE-set.
Ted Kremeneke8fdc832008-07-07 16:21:19 +000087 return T ? T->contains(&V) : false;
Ted Kremenek862d5bb2008-02-06 00:54:14 +000088}
89
Ted Kremenek4adc81e2008-08-13 04:27:00 +000090bool GRState::isEqual(SymbolID sym, const llvm::APSInt& V) const {
Ted Kremenek584def72008-07-22 00:46:16 +000091
92 // Retrieve the EQ-set associated with the given symbol.
93 const ConstEqTy::data_type* T = ConstEq.lookup(sym);
94
95 // See if V is present in the EQ-set.
96 return T ? **T == V : false;
97}
98
Ted Kremenek4adc81e2008-08-13 04:27:00 +000099const llvm::APSInt* GRState::getSymVal(SymbolID sym) const {
Ted Kremeneke8fdc832008-07-07 16:21:19 +0000100 ConstEqTy::data_type* T = ConstEq.lookup(sym);
101 return T ? *T : NULL;
Ted Kremenek862d5bb2008-02-06 00:54:14 +0000102}
103
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000104const GRState*
105GRStateManager::RemoveDeadBindings(const GRState* St, Stmt* Loc,
Ted Kremenek1c72ef02008-08-16 00:49:49 +0000106 const LiveVariables& Liveness,
107 DeadSymbolsTy& DSymbols) {
Ted Kremenekb87d9092008-02-08 19:17:19 +0000108
109 // This code essentially performs a "mark-and-sweep" of the VariableBindings.
110 // The roots are any Block-level exprs and Decls that our liveness algorithm
111 // tells us are live. We then see what Decls they may reference, and keep
112 // those around. This code more than likely can be made faster, and the
113 // frequency of which this method is called should be experimented with
Ted Kremenekf59bf482008-07-17 18:38:48 +0000114 // for optimum performance.
115 DRoots.clear();
116 StoreManager::LiveSymbolsTy LSymbols;
Ted Kremeneke7d22112008-02-11 19:21:59 +0000117
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000118 GRState NewSt = *St;
Ted Kremenekf59bf482008-07-17 18:38:48 +0000119
120 // FIXME: Put this in environment.
121 // Clean up the environment.
Ted Kremeneke7d22112008-02-11 19:21:59 +0000122
123 // Drop bindings for subexpressions.
Ted Kremenek8133a262008-07-08 21:46:56 +0000124 NewSt.Env = EnvMgr.RemoveSubExprBindings(NewSt.Env);
Ted Kremeneke7d22112008-02-11 19:21:59 +0000125
126 // Iterate over the block-expr bindings.
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000127
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000128 for (GRState::beb_iterator I = St->beb_begin(), E = St->beb_end();
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000129 I!=E ; ++I) {
Ted Kremeneke7d22112008-02-11 19:21:59 +0000130 Expr* BlkExpr = I.getKey();
Ted Kremenekb87d9092008-02-08 19:17:19 +0000131
Ted Kremeneke7d22112008-02-11 19:21:59 +0000132 if (Liveness.isLive(Loc, BlkExpr)) {
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000133 RVal X = I.getData();
Ted Kremenek90e14812008-02-14 23:25:54 +0000134
135 if (isa<lval::DeclVal>(X)) {
136 lval::DeclVal LV = cast<lval::DeclVal>(X);
Ted Kremenekf59bf482008-07-17 18:38:48 +0000137 DRoots.push_back(LV.getDecl());
Ted Kremenekb87d9092008-02-08 19:17:19 +0000138 }
Ted Kremenek90e14812008-02-14 23:25:54 +0000139
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000140 for (RVal::symbol_iterator SI = X.symbol_begin(), SE = X.symbol_end();
141 SI != SE; ++SI) {
Ted Kremenekf59bf482008-07-17 18:38:48 +0000142 LSymbols.insert(*SI);
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000143 }
Ted Kremenekb87d9092008-02-08 19:17:19 +0000144 }
Ted Kremenek05a23782008-02-26 19:05:15 +0000145 else {
146 RVal X = I.getData();
147
Ted Kremenek4a4e5242008-02-28 09:25:22 +0000148 if (X.isUndef() && cast<UndefinedVal>(X).getData())
Ted Kremenek05a23782008-02-26 19:05:15 +0000149 continue;
150
Ted Kremenek8133a262008-07-08 21:46:56 +0000151 NewSt.Env = EnvMgr.RemoveBlkExpr(NewSt.Env, BlkExpr);
Ted Kremenek05a23782008-02-26 19:05:15 +0000152 }
Ted Kremenekb87d9092008-02-08 19:17:19 +0000153 }
Ted Kremenek016f52f2008-02-08 21:10:02 +0000154
Ted Kremenekf59bf482008-07-17 18:38:48 +0000155 // Clean up the store.
156 DSymbols.clear();
157 NewSt.St = StMgr->RemoveDeadBindings(St->getStore(), Loc, Liveness, DRoots,
158 LSymbols, DSymbols);
Ted Kremenekb87d9092008-02-08 19:17:19 +0000159
Ted Kremenekf59bf482008-07-17 18:38:48 +0000160 // Remove the dead symbols from the symbol tracker.
Ted Kremenek1c72ef02008-08-16 00:49:49 +0000161 // FIXME: Refactor into something else that manages symbol values.
162 for (GRState::ConstEqTy::iterator I = St->ConstEq.begin(),
163 E=St->ConstEq.end(); I!=E; ++I) {
Ted Kremenek77d7ef82008-04-24 18:31:42 +0000164
165 SymbolID sym = I.getKey();
166
Ted Kremenekf59bf482008-07-17 18:38:48 +0000167 if (!LSymbols.count(sym)) {
168 DSymbols.insert(sym);
Ted Kremenek77d7ef82008-04-24 18:31:42 +0000169 NewSt.ConstEq = CEFactory.Remove(NewSt.ConstEq, sym);
170 }
171 }
172
Ted Kremenek1c72ef02008-08-16 00:49:49 +0000173 GRStateRef state(getPersistentState(NewSt), *this);
174 ConstNotEqTy CNE = state.get<ConstNotEqTy>();
175 ConstNotEqTy::Factory& CNEFactory = state.get_context<ConstNotEqTy>();
176
177 for (ConstNotEqTy::iterator I = CNE.begin(), E = CNE.end(); I != E; ++I) {
178 SymbolID sym = I.getKey();
Ted Kremenekf59bf482008-07-17 18:38:48 +0000179 if (!LSymbols.count(sym)) {
180 DSymbols.insert(sym);
Ted Kremenek1c72ef02008-08-16 00:49:49 +0000181 CNE = CNEFactory.Remove(CNE, sym);
Ted Kremenek77d7ef82008-04-24 18:31:42 +0000182 }
183 }
Ted Kremenek90e14812008-02-14 23:25:54 +0000184
Ted Kremenek1c72ef02008-08-16 00:49:49 +0000185 return state.set<ConstNotEqTy>(CNE);
Ted Kremenekb87d9092008-02-08 19:17:19 +0000186}
Ted Kremenek862d5bb2008-02-06 00:54:14 +0000187
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000188const GRState* GRStateManager::SetRVal(const GRState* St, LVal LV,
Ted Kremenek4323a572008-07-10 22:03:41 +0000189 RVal V) {
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000190
Ted Kremenek4323a572008-07-10 22:03:41 +0000191 Store OldStore = St->getStore();
192 Store NewStore = StMgr->SetRVal(OldStore, LV, V);
Ted Kremenek3271f8d2008-02-07 04:16:04 +0000193
Ted Kremenek4323a572008-07-10 22:03:41 +0000194 if (NewStore == OldStore)
195 return St;
Ted Kremenek692416c2008-02-18 22:57:02 +0000196
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000197 GRState NewSt = *St;
Ted Kremenek4323a572008-07-10 22:03:41 +0000198 NewSt.St = NewStore;
199 return getPersistentState(NewSt);
Ted Kremenekf66ea2cd2008-02-04 21:59:22 +0000200}
201
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000202const GRState* GRStateManager::Unbind(const GRState* St, LVal LV) {
Ted Kremenek4323a572008-07-10 22:03:41 +0000203 Store OldStore = St->getStore();
204 Store NewStore = StMgr->Remove(OldStore, LV);
205
206 if (NewStore == OldStore)
207 return St;
208
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000209 GRState NewSt = *St;
Ted Kremenek4323a572008-07-10 22:03:41 +0000210 NewSt.St = NewStore;
211 return getPersistentState(NewSt);
212}
213
214
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000215const GRState* GRStateManager::AddNE(const GRState* St, SymbolID sym,
Ted Kremenek1c72ef02008-08-16 00:49:49 +0000216 const llvm::APSInt& V) {
217
218 GRStateRef state(St, *this);
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000219
Ted Kremenek862d5bb2008-02-06 00:54:14 +0000220 // First, retrieve the NE-set associated with the given symbol.
Ted Kremenek1c72ef02008-08-16 00:49:49 +0000221 ConstNotEqTy::data_type* T = state.get<ConstNotEqTy>(sym);
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000222 GRState::IntSetTy S = T ? *T : ISetFactory.GetEmptySet();
Ted Kremenek862d5bb2008-02-06 00:54:14 +0000223
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000224 // Now add V to the NE set.
Ted Kremenek862d5bb2008-02-06 00:54:14 +0000225 S = ISetFactory.Add(S, &V);
226
227 // Create a new state with the old binding replaced.
Ted Kremenek1c72ef02008-08-16 00:49:49 +0000228 return state.set<ConstNotEqTy>(sym, S);
Ted Kremenek862d5bb2008-02-06 00:54:14 +0000229}
230
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000231const GRState* GRStateManager::AddEQ(const GRState* St, SymbolID sym,
Ted Kremenek4323a572008-07-10 22:03:41 +0000232 const llvm::APSInt& V) {
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000233
Ted Kremenek862d5bb2008-02-06 00:54:14 +0000234 // Create a new state with the old binding replaced.
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000235 GRState NewSt = *St;
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000236 NewSt.ConstEq = CEFactory.Add(NewSt.ConstEq, sym, &V);
Ted Kremenek862d5bb2008-02-06 00:54:14 +0000237
238 // Get the persistent copy.
Ted Kremeneke7d22112008-02-11 19:21:59 +0000239 return getPersistentState(NewSt);
Ted Kremenek862d5bb2008-02-06 00:54:14 +0000240}
241
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000242const GRState* GRStateManager::getInitialState() {
Ted Kremenek5a7b3822008-02-26 23:37:01 +0000243
Ted Kremenek72cd17f2008-08-14 21:16:54 +0000244 GRState StateImpl(EnvMgr.getInitialEnvironment(), StMgr->getInitialStore(),
Ted Kremenek1c72ef02008-08-16 00:49:49 +0000245 GDMFactory.GetEmptyMap(),
Ted Kremenek72cd17f2008-08-14 21:16:54 +0000246 CEFactory.GetEmptyMap());
Ted Kremenek9153f732008-02-05 07:17:49 +0000247
248 return getPersistentState(StateImpl);
249}
250
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000251const GRState* GRStateManager::getPersistentState(GRState& State) {
Ted Kremenek9153f732008-02-05 07:17:49 +0000252
253 llvm::FoldingSetNodeID ID;
254 State.Profile(ID);
Ted Kremeneke7d22112008-02-11 19:21:59 +0000255 void* InsertPos;
Ted Kremenek9153f732008-02-05 07:17:49 +0000256
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000257 if (GRState* I = StateSet.FindNodeOrInsertPos(ID, InsertPos))
Ted Kremenek9153f732008-02-05 07:17:49 +0000258 return I;
259
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000260 GRState* I = (GRState*) Alloc.Allocate<GRState>();
261 new (I) GRState(State);
Ted Kremenek9153f732008-02-05 07:17:49 +0000262 StateSet.InsertNode(I, InsertPos);
263 return I;
264}
Ted Kremeneke7d22112008-02-11 19:21:59 +0000265
Ted Kremenek59894f92008-03-04 18:30:35 +0000266
Ted Kremenek1c72ef02008-08-16 00:49:49 +0000267//===----------------------------------------------------------------------===//
268// State pretty-printing.
269//===----------------------------------------------------------------------===//
Ted Kremenek461f9772008-03-11 18:57:24 +0000270
Ted Kremenekae6814e2008-08-13 21:24:49 +0000271void GRState::print(std::ostream& Out, Printer** Beg, Printer** End,
272 const char* nl, const char* sep) const {
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000273
Ted Kremeneke7d22112008-02-11 19:21:59 +0000274 // Print Variable Bindings
Ted Kremenek59894f92008-03-04 18:30:35 +0000275 Out << "Variables:" << nl;
Ted Kremeneke7d22112008-02-11 19:21:59 +0000276
277 bool isFirst = true;
278
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000279 for (vb_iterator I = vb_begin(), E = vb_end(); I != E; ++I) {
Ted Kremeneke7d22112008-02-11 19:21:59 +0000280
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000281 if (isFirst) isFirst = false;
Ted Kremenek59894f92008-03-04 18:30:35 +0000282 else Out << nl;
Ted Kremeneke7d22112008-02-11 19:21:59 +0000283
284 Out << ' ' << I.getKey()->getName() << " : ";
285 I.getData().print(Out);
286 }
287
288 // Print Subexpression bindings.
289
290 isFirst = true;
291
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000292 for (seb_iterator I = seb_begin(), E = seb_end(); I != E; ++I) {
Ted Kremeneke7d22112008-02-11 19:21:59 +0000293
294 if (isFirst) {
Ted Kremenek59894f92008-03-04 18:30:35 +0000295 Out << nl << nl << "Sub-Expressions:" << nl;
Ted Kremeneke7d22112008-02-11 19:21:59 +0000296 isFirst = false;
297 }
Ted Kremenek59894f92008-03-04 18:30:35 +0000298 else { Out << nl; }
Ted Kremeneke7d22112008-02-11 19:21:59 +0000299
300 Out << " (" << (void*) I.getKey() << ") ";
301 I.getKey()->printPretty(Out);
302 Out << " : ";
303 I.getData().print(Out);
304 }
305
306 // Print block-expression bindings.
307
308 isFirst = true;
309
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000310 for (beb_iterator I = beb_begin(), E = beb_end(); I != E; ++I) {
Ted Kremeneke7d22112008-02-11 19:21:59 +0000311
312 if (isFirst) {
Ted Kremenek59894f92008-03-04 18:30:35 +0000313 Out << nl << nl << "Block-level Expressions:" << nl;
Ted Kremeneke7d22112008-02-11 19:21:59 +0000314 isFirst = false;
315 }
Ted Kremenek59894f92008-03-04 18:30:35 +0000316 else { Out << nl; }
Ted Kremeneke7d22112008-02-11 19:21:59 +0000317
318 Out << " (" << (void*) I.getKey() << ") ";
319 I.getKey()->printPretty(Out);
320 Out << " : ";
321 I.getData().print(Out);
322 }
323
324 // Print equality constraints.
Ted Kremenekae6814e2008-08-13 21:24:49 +0000325 // FIXME: Make just another printer do this.
Ted Kremeneke7d22112008-02-11 19:21:59 +0000326
Ted Kremenekaed9b6a2008-02-28 10:21:43 +0000327 if (!ConstEq.isEmpty()) {
Ted Kremeneke7d22112008-02-11 19:21:59 +0000328
Ted Kremenek59894f92008-03-04 18:30:35 +0000329 Out << nl << sep << "'==' constraints:";
Ted Kremeneke7d22112008-02-11 19:21:59 +0000330
Ted Kremenekaed9b6a2008-02-28 10:21:43 +0000331 for (ConstEqTy::iterator I = ConstEq.begin(),
332 E = ConstEq.end(); I!=E; ++I) {
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000333
Ted Kremenek59894f92008-03-04 18:30:35 +0000334 Out << nl << " $" << I.getKey()
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000335 << " : " << I.getData()->toString();
336 }
Ted Kremeneke7d22112008-02-11 19:21:59 +0000337 }
Ted Kremeneke7d22112008-02-11 19:21:59 +0000338
339 // Print != constraints.
Ted Kremenekae6814e2008-08-13 21:24:49 +0000340 // FIXME: Make just another printer do this.
Ted Kremenek1c72ef02008-08-16 00:49:49 +0000341
342 ConstNotEqTy CNE = get<ConstNotEqTy>();
343
344 if (!CNE.isEmpty()) {
Ted Kremeneke7d22112008-02-11 19:21:59 +0000345
Ted Kremenek59894f92008-03-04 18:30:35 +0000346 Out << nl << sep << "'!=' constraints:";
Ted Kremeneke7d22112008-02-11 19:21:59 +0000347
Ted Kremenek1c72ef02008-08-16 00:49:49 +0000348 for (ConstNotEqTy::iterator I = CNE.begin(), EI = CNE.end(); I!=EI; ++I) {
Ted Kremenek59894f92008-03-04 18:30:35 +0000349 Out << nl << " $" << I.getKey() << " : ";
Ted Kremeneke7d22112008-02-11 19:21:59 +0000350 isFirst = true;
351
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000352 IntSetTy::iterator J = I.getData().begin(), EJ = I.getData().end();
Ted Kremeneke7d22112008-02-11 19:21:59 +0000353
354 for ( ; J != EJ; ++J) {
355 if (isFirst) isFirst = false;
356 else Out << ", ";
357
358 Out << (*J)->toString();
359 }
360 }
361 }
Ted Kremenek461f9772008-03-11 18:57:24 +0000362
Ted Kremenekae6814e2008-08-13 21:24:49 +0000363 // Print checker-specific data.
364 for ( ; Beg != End ; ++Beg) (*Beg)->Print(Out, this, nl, sep);
Ted Kremeneke7d22112008-02-11 19:21:59 +0000365}
Ted Kremenek729a9a22008-07-17 23:15:45 +0000366
Ted Kremenek1c72ef02008-08-16 00:49:49 +0000367void GRStateRef::printDOT(std::ostream& Out) const {
368 print(Out, "\\l", "\\|");
369}
370
371void GRStateRef::printStdErr() const {
372 print(*llvm::cerr);
373}
374
375void GRStateRef::print(std::ostream& Out, const char* nl, const char* sep)const{
376 GRState::Printer **beg = Mgr->Printers.empty() ? 0 : &Mgr->Printers[0];
377 GRState::Printer **end = !beg ? 0 : beg + Mgr->Printers.size();
378 St->print(Out, beg, end, nl, sep);
379}
380
Ted Kremenek72cd17f2008-08-14 21:16:54 +0000381//===----------------------------------------------------------------------===//
382// Generic Data Map.
383//===----------------------------------------------------------------------===//
384
385void* const* GRState::FindGDM(void* K) const {
386 return GDM.lookup(K);
387}
388
Ted Kremenek1c72ef02008-08-16 00:49:49 +0000389void*
390GRStateManager::FindGDMContext(void* K,
391 void* (*CreateContext)(llvm::BumpPtrAllocator&),
392 void (*DeleteContext)(void*)) {
393
394 std::pair<void*, void (*)(void*)>& p = GDMContexts[K];
395 if (!p.first) {
396 p.first = CreateContext(Alloc);
397 p.second = DeleteContext;
398 }
399
400 return p.first;
401}
402
Ted Kremenek72cd17f2008-08-14 21:16:54 +0000403const GRState* GRStateManager::addGDM(const GRState* St, void* Key, void* Data){
404 GRState::GenericDataMap M1 = St->getGDM();
405 GRState::GenericDataMap M2 = GDMFactory.Add(M1, Key, Data);
406
407 if (M1 == M2)
408 return St;
409
410 GRState NewSt = *St;
411 NewSt.GDM = M2;
412 return getPersistentState(NewSt);
413}
Ted Kremenek584def72008-07-22 00:46:16 +0000414
415//===----------------------------------------------------------------------===//
416// Queries.
417//===----------------------------------------------------------------------===//
418
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000419bool GRStateManager::isEqual(const GRState* state, Expr* Ex,
Ted Kremenek1c72ef02008-08-16 00:49:49 +0000420 const llvm::APSInt& Y) {
421
Ted Kremenek584def72008-07-22 00:46:16 +0000422 RVal V = GetRVal(state, Ex);
423
424 if (lval::ConcreteInt* X = dyn_cast<lval::ConcreteInt>(&V))
425 return X->getValue() == Y;
426
427 if (nonlval::ConcreteInt* X = dyn_cast<nonlval::ConcreteInt>(&V))
428 return X->getValue() == Y;
429
430 if (nonlval::SymbolVal* X = dyn_cast<nonlval::SymbolVal>(&V))
431 return state->isEqual(X->getSymbol(), Y);
432
433 if (lval::SymbolVal* X = dyn_cast<lval::SymbolVal>(&V))
434 return state->isEqual(X->getSymbol(), Y);
435
436 return false;
437}
438
Ted Kremenek1c72ef02008-08-16 00:49:49 +0000439bool GRStateManager::isEqual(const GRState* state, Expr* Ex, uint64_t x) {
Ted Kremenek584def72008-07-22 00:46:16 +0000440 return isEqual(state, Ex, BasicVals.getValue(x, Ex->getType()));
441}
442
Ted Kremenek729a9a22008-07-17 23:15:45 +0000443//===----------------------------------------------------------------------===//
444// "Assume" logic.
445//===----------------------------------------------------------------------===//
446
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000447const GRState* GRStateManager::Assume(const GRState* St, LVal Cond,
Ted Kremenek729a9a22008-07-17 23:15:45 +0000448 bool Assumption, bool& isFeasible) {
449
450 St = AssumeAux(St, Cond, Assumption, isFeasible);
451
452 return isFeasible ? TF->EvalAssume(*this, St, Cond, Assumption, isFeasible)
453 : St;
454}
455
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000456const GRState* GRStateManager::AssumeAux(const GRState* St, LVal Cond,
Ted Kremenek729a9a22008-07-17 23:15:45 +0000457 bool Assumption, bool& isFeasible) {
458
459 switch (Cond.getSubKind()) {
460 default:
461 assert (false && "'Assume' not implemented for this LVal.");
462 return St;
463
464 case lval::SymbolValKind:
465 if (Assumption)
466 return AssumeSymNE(St, cast<lval::SymbolVal>(Cond).getSymbol(),
467 BasicVals.getZeroWithPtrWidth(), isFeasible);
468 else
469 return AssumeSymEQ(St, cast<lval::SymbolVal>(Cond).getSymbol(),
470 BasicVals.getZeroWithPtrWidth(), isFeasible);
471
Ted Kremenek729a9a22008-07-17 23:15:45 +0000472 case lval::DeclValKind:
473 case lval::FuncValKind:
474 case lval::GotoLabelKind:
475 case lval::StringLiteralValKind:
476 isFeasible = Assumption;
477 return St;
478
479 case lval::FieldOffsetKind:
480 return AssumeAux(St, cast<lval::FieldOffset>(Cond).getBase(),
481 Assumption, isFeasible);
482
483 case lval::ArrayOffsetKind:
484 return AssumeAux(St, cast<lval::ArrayOffset>(Cond).getBase(),
485 Assumption, isFeasible);
486
487 case lval::ConcreteIntKind: {
488 bool b = cast<lval::ConcreteInt>(Cond).getValue() != 0;
489 isFeasible = b ? Assumption : !Assumption;
490 return St;
491 }
492 }
493}
494
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000495const GRState* GRStateManager::Assume(const GRState* St, NonLVal Cond,
Ted Kremenek729a9a22008-07-17 23:15:45 +0000496 bool Assumption, bool& isFeasible) {
497
498 St = AssumeAux(St, Cond, Assumption, isFeasible);
499
500 return isFeasible ? TF->EvalAssume(*this, St, Cond, Assumption, isFeasible)
501 : St;
502}
503
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000504const GRState* GRStateManager::AssumeAux(const GRState* St, NonLVal Cond,
Ted Kremenek729a9a22008-07-17 23:15:45 +0000505 bool Assumption, bool& isFeasible) {
506 switch (Cond.getSubKind()) {
507 default:
508 assert (false && "'Assume' not implemented for this NonLVal.");
509 return St;
510
511
512 case nonlval::SymbolValKind: {
513 nonlval::SymbolVal& SV = cast<nonlval::SymbolVal>(Cond);
514 SymbolID sym = SV.getSymbol();
515
516 if (Assumption)
517 return AssumeSymNE(St, sym, BasicVals.getValue(0, SymMgr.getType(sym)),
518 isFeasible);
519 else
520 return AssumeSymEQ(St, sym, BasicVals.getValue(0, SymMgr.getType(sym)),
521 isFeasible);
522 }
523
524 case nonlval::SymIntConstraintValKind:
525 return
526 AssumeSymInt(St, Assumption,
527 cast<nonlval::SymIntConstraintVal>(Cond).getConstraint(),
528 isFeasible);
529
530 case nonlval::ConcreteIntKind: {
531 bool b = cast<nonlval::ConcreteInt>(Cond).getValue() != 0;
532 isFeasible = b ? Assumption : !Assumption;
533 return St;
534 }
535
536 case nonlval::LValAsIntegerKind: {
537 return AssumeAux(St, cast<nonlval::LValAsInteger>(Cond).getLVal(),
538 Assumption, isFeasible);
539 }
540 }
541}
542
Ted Kremenek729a9a22008-07-17 23:15:45 +0000543
Ted Kremenek729a9a22008-07-17 23:15:45 +0000544
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000545const GRState* GRStateManager::AssumeSymInt(const GRState* St,
Ted Kremenek729a9a22008-07-17 23:15:45 +0000546 bool Assumption,
547 const SymIntConstraint& C,
548 bool& isFeasible) {
549
550 switch (C.getOpcode()) {
551 default:
552 // No logic yet for other operators.
553 isFeasible = true;
554 return St;
555
556 case BinaryOperator::EQ:
557 if (Assumption)
558 return AssumeSymEQ(St, C.getSymbol(), C.getInt(), isFeasible);
559 else
560 return AssumeSymNE(St, C.getSymbol(), C.getInt(), isFeasible);
561
562 case BinaryOperator::NE:
563 if (Assumption)
564 return AssumeSymNE(St, C.getSymbol(), C.getInt(), isFeasible);
565 else
566 return AssumeSymEQ(St, C.getSymbol(), C.getInt(), isFeasible);
Ted Kremenek2619be02008-08-07 22:30:22 +0000567
568 case BinaryOperator::GE:
569 if (Assumption)
570 return AssumeSymGE(St, C.getSymbol(), C.getInt(), isFeasible);
571 else
572 return AssumeSymLT(St, C.getSymbol(), C.getInt(), isFeasible);
573
574 case BinaryOperator::LE:
575 if (Assumption)
576 return AssumeSymLE(St, C.getSymbol(), C.getInt(), isFeasible);
577 else
578 return AssumeSymGT(St, C.getSymbol(), C.getInt(), isFeasible);
Ted Kremenek729a9a22008-07-17 23:15:45 +0000579 }
580}
Ted Kremenek2619be02008-08-07 22:30:22 +0000581
582//===----------------------------------------------------------------------===//
583// FIXME: This should go into a plug-in constraint engine.
584//===----------------------------------------------------------------------===//
585
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000586const GRState*
587GRStateManager::AssumeSymNE(const GRState* St, SymbolID sym,
Ted Kremenek2619be02008-08-07 22:30:22 +0000588 const llvm::APSInt& V, bool& isFeasible) {
589
590 // First, determine if sym == X, where X != V.
591 if (const llvm::APSInt* X = St->getSymVal(sym)) {
592 isFeasible = *X != V;
593 return St;
594 }
595
596 // Second, determine if sym != V.
597 if (St->isNotEqual(sym, V)) {
598 isFeasible = true;
599 return St;
600 }
601
602 // If we reach here, sym is not a constant and we don't know if it is != V.
603 // Make that assumption.
604
605 isFeasible = true;
606 return AddNE(St, sym, V);
607}
608
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000609const GRState*
610GRStateManager::AssumeSymEQ(const GRState* St, SymbolID sym,
Ted Kremenek2619be02008-08-07 22:30:22 +0000611 const llvm::APSInt& V, bool& isFeasible) {
612
613 // First, determine if sym == X, where X != V.
614 if (const llvm::APSInt* X = St->getSymVal(sym)) {
615 isFeasible = *X == V;
616 return St;
617 }
618
619 // Second, determine if sym != V.
620 if (St->isNotEqual(sym, V)) {
621 isFeasible = false;
622 return St;
623 }
624
625 // If we reach here, sym is not a constant and we don't know if it is == V.
626 // Make that assumption.
627
628 isFeasible = true;
629 return AddEQ(St, sym, V);
630}
631
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000632const GRState*
633GRStateManager::AssumeSymLT(const GRState* St, SymbolID sym,
Ted Kremenek2619be02008-08-07 22:30:22 +0000634 const llvm::APSInt& V, bool& isFeasible) {
635
636 // FIXME: For now have assuming x < y be the same as assuming sym != V;
637 return AssumeSymNE(St, sym, V, isFeasible);
638}
639
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000640const GRState*
641GRStateManager::AssumeSymGT(const GRState* St, SymbolID sym,
Ted Kremenek2619be02008-08-07 22:30:22 +0000642 const llvm::APSInt& V, bool& isFeasible) {
643
644 // FIXME: For now have assuming x > y be the same as assuming sym != V;
645 return AssumeSymNE(St, sym, V, isFeasible);
646}
647
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000648const GRState*
649GRStateManager::AssumeSymGE(const GRState* St, SymbolID sym,
Ted Kremenek2619be02008-08-07 22:30:22 +0000650 const llvm::APSInt& V, bool& isFeasible) {
651
652 // FIXME: Primitive logic for now. Only reject a path if the value of
653 // sym is a constant X and !(X >= V).
654
655 if (const llvm::APSInt* X = St->getSymVal(sym)) {
656 isFeasible = *X >= V;
657 return St;
658 }
659
660 isFeasible = true;
661 return St;
662}
663
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000664const GRState*
665GRStateManager::AssumeSymLE(const GRState* St, SymbolID sym,
Ted Kremenek2619be02008-08-07 22:30:22 +0000666 const llvm::APSInt& V, bool& isFeasible) {
667
668 // FIXME: Primitive logic for now. Only reject a path if the value of
669 // sym is a constant X and !(X <= V).
670
671 if (const llvm::APSInt* X = St->getSymVal(sym)) {
672 isFeasible = *X <= V;
673 return St;
674 }
675
676 isFeasible = true;
677 return St;
678}
679