blob: ca78faf34911ccbcef1d4e44fe2ead237d8c2836 [file] [log] [blame]
Ted Kremenekaed9b6a2008-02-28 10:21:43 +00001//= ValueState*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//
Gabor Greif843e9342008-03-06 10:40:09 +000010// This file defines SymbolID, ExprBindKey, and ValueState*
Ted Kremenek9153f732008-02-05 07:17:49 +000011//
12//===----------------------------------------------------------------------===//
13
Ted Kremenek0f5f0592008-02-27 06:07:00 +000014#include "clang/Analysis/PathSensitive/ValueState.h"
Ted Kremenek90e14812008-02-14 23:25:54 +000015#include "llvm/ADT/SmallSet.h"
Ted Kremenekf66ea2cd2008-02-04 21:59:22 +000016
17using namespace clang;
18
Ted Kremenek862d5bb2008-02-06 00:54:14 +000019bool ValueState::isNotEqual(SymbolID sym, const llvm::APSInt& V) const {
Ted Kremenekaa1c4e52008-02-21 18:02:17 +000020
21 // Retrieve the NE-set associated with the given symbol.
Ted Kremeneke8fdc832008-07-07 16:21:19 +000022 const ConstNotEqTy::data_type* T = ConstNotEq.lookup(sym);
Ted Kremenekaa1c4e52008-02-21 18:02:17 +000023
24 // See if V is present in the NE-set.
Ted Kremeneke8fdc832008-07-07 16:21:19 +000025 return T ? T->contains(&V) : false;
Ted Kremenek862d5bb2008-02-06 00:54:14 +000026}
27
28const llvm::APSInt* ValueState::getSymVal(SymbolID sym) const {
Ted Kremeneke8fdc832008-07-07 16:21:19 +000029 ConstEqTy::data_type* T = ConstEq.lookup(sym);
30 return T ? *T : NULL;
Ted Kremenek862d5bb2008-02-06 00:54:14 +000031}
32
Ted Kremenek4323a572008-07-10 22:03:41 +000033const ValueState*
34ValueStateManager::RemoveDeadBindings(const ValueState* St, Stmt* Loc,
Ted Kremenek77d7ef82008-04-24 18:31:42 +000035 const LiveVariables& Liveness,
Ted Kremenekf59bf482008-07-17 18:38:48 +000036 DeadSymbolsTy& DSymbols) {
Ted Kremenekb87d9092008-02-08 19:17:19 +000037
38 // This code essentially performs a "mark-and-sweep" of the VariableBindings.
39 // The roots are any Block-level exprs and Decls that our liveness algorithm
40 // tells us are live. We then see what Decls they may reference, and keep
41 // those around. This code more than likely can be made faster, and the
42 // frequency of which this method is called should be experimented with
Ted Kremenekf59bf482008-07-17 18:38:48 +000043 // for optimum performance.
44 DRoots.clear();
45 StoreManager::LiveSymbolsTy LSymbols;
Ted Kremeneke7d22112008-02-11 19:21:59 +000046
Ted Kremenekaed9b6a2008-02-28 10:21:43 +000047 ValueState NewSt = *St;
Ted Kremenekf59bf482008-07-17 18:38:48 +000048
49 // FIXME: Put this in environment.
50 // Clean up the environment.
Ted Kremeneke7d22112008-02-11 19:21:59 +000051
52 // Drop bindings for subexpressions.
Ted Kremenek8133a262008-07-08 21:46:56 +000053 NewSt.Env = EnvMgr.RemoveSubExprBindings(NewSt.Env);
Ted Kremeneke7d22112008-02-11 19:21:59 +000054
55 // Iterate over the block-expr bindings.
Ted Kremenekaa1c4e52008-02-21 18:02:17 +000056
Ted Kremenekaed9b6a2008-02-28 10:21:43 +000057 for (ValueState::beb_iterator I = St->beb_begin(), E = St->beb_end();
Ted Kremenekaa1c4e52008-02-21 18:02:17 +000058 I!=E ; ++I) {
Ted Kremeneke7d22112008-02-11 19:21:59 +000059 Expr* BlkExpr = I.getKey();
Ted Kremenekb87d9092008-02-08 19:17:19 +000060
Ted Kremeneke7d22112008-02-11 19:21:59 +000061 if (Liveness.isLive(Loc, BlkExpr)) {
Ted Kremenekaa1c4e52008-02-21 18:02:17 +000062 RVal X = I.getData();
Ted Kremenek90e14812008-02-14 23:25:54 +000063
64 if (isa<lval::DeclVal>(X)) {
65 lval::DeclVal LV = cast<lval::DeclVal>(X);
Ted Kremenekf59bf482008-07-17 18:38:48 +000066 DRoots.push_back(LV.getDecl());
Ted Kremenekb87d9092008-02-08 19:17:19 +000067 }
Ted Kremenek90e14812008-02-14 23:25:54 +000068
Ted Kremenekaa1c4e52008-02-21 18:02:17 +000069 for (RVal::symbol_iterator SI = X.symbol_begin(), SE = X.symbol_end();
70 SI != SE; ++SI) {
Ted Kremenekf59bf482008-07-17 18:38:48 +000071 LSymbols.insert(*SI);
Ted Kremenekaa1c4e52008-02-21 18:02:17 +000072 }
Ted Kremenekb87d9092008-02-08 19:17:19 +000073 }
Ted Kremenek05a23782008-02-26 19:05:15 +000074 else {
75 RVal X = I.getData();
76
Ted Kremenek4a4e5242008-02-28 09:25:22 +000077 if (X.isUndef() && cast<UndefinedVal>(X).getData())
Ted Kremenek05a23782008-02-26 19:05:15 +000078 continue;
79
Ted Kremenek8133a262008-07-08 21:46:56 +000080 NewSt.Env = EnvMgr.RemoveBlkExpr(NewSt.Env, BlkExpr);
Ted Kremenek05a23782008-02-26 19:05:15 +000081 }
Ted Kremenekb87d9092008-02-08 19:17:19 +000082 }
Ted Kremenek016f52f2008-02-08 21:10:02 +000083
Ted Kremenekf59bf482008-07-17 18:38:48 +000084 // Clean up the store.
85 DSymbols.clear();
86 NewSt.St = StMgr->RemoveDeadBindings(St->getStore(), Loc, Liveness, DRoots,
87 LSymbols, DSymbols);
Ted Kremenekb87d9092008-02-08 19:17:19 +000088
Ted Kremenekf59bf482008-07-17 18:38:48 +000089 // Remove the dead symbols from the symbol tracker.
Ted Kremenek77d7ef82008-04-24 18:31:42 +000090 for (ValueState::ce_iterator I = St->ce_begin(), E=St->ce_end(); I!=E; ++I) {
91
92 SymbolID sym = I.getKey();
93
Ted Kremenekf59bf482008-07-17 18:38:48 +000094 if (!LSymbols.count(sym)) {
95 DSymbols.insert(sym);
Ted Kremenek77d7ef82008-04-24 18:31:42 +000096 NewSt.ConstEq = CEFactory.Remove(NewSt.ConstEq, sym);
97 }
98 }
99
100 for (ValueState::cne_iterator I = St->cne_begin(), E=St->cne_end(); I!=E;++I){
101
102 SymbolID sym = I.getKey();
103
Ted Kremenekf59bf482008-07-17 18:38:48 +0000104 if (!LSymbols.count(sym)) {
105 DSymbols.insert(sym);
Ted Kremenek77d7ef82008-04-24 18:31:42 +0000106 NewSt.ConstNotEq = CNEFactory.Remove(NewSt.ConstNotEq, sym);
107 }
108 }
Ted Kremenek90e14812008-02-14 23:25:54 +0000109
Ted Kremeneke7d22112008-02-11 19:21:59 +0000110 return getPersistentState(NewSt);
Ted Kremenekb87d9092008-02-08 19:17:19 +0000111}
Ted Kremenek862d5bb2008-02-06 00:54:14 +0000112
Ted Kremenek4323a572008-07-10 22:03:41 +0000113const ValueState* ValueStateManager::SetRVal(const ValueState* St, LVal LV,
114 RVal V) {
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000115
Ted Kremenek4323a572008-07-10 22:03:41 +0000116 Store OldStore = St->getStore();
117 Store NewStore = StMgr->SetRVal(OldStore, LV, V);
Ted Kremenek3271f8d2008-02-07 04:16:04 +0000118
Ted Kremenek4323a572008-07-10 22:03:41 +0000119 if (NewStore == OldStore)
120 return St;
Ted Kremenek692416c2008-02-18 22:57:02 +0000121
Ted Kremenek4323a572008-07-10 22:03:41 +0000122 ValueState NewSt = *St;
123 NewSt.St = NewStore;
124 return getPersistentState(NewSt);
Ted Kremenekf66ea2cd2008-02-04 21:59:22 +0000125}
126
Ted Kremenek4323a572008-07-10 22:03:41 +0000127const ValueState* ValueStateManager::Unbind(const ValueState* St, LVal LV) {
128 Store OldStore = St->getStore();
129 Store NewStore = StMgr->Remove(OldStore, LV);
130
131 if (NewStore == OldStore)
132 return St;
133
134 ValueState NewSt = *St;
135 NewSt.St = NewStore;
136 return getPersistentState(NewSt);
137}
138
139
140const ValueState* ValueStateManager::AddNE(const ValueState* St, SymbolID sym,
141 const llvm::APSInt& V) {
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000142
Ted Kremenek862d5bb2008-02-06 00:54:14 +0000143 // First, retrieve the NE-set associated with the given symbol.
Ted Kremeneke8fdc832008-07-07 16:21:19 +0000144 ValueState::ConstNotEqTy::data_type* T = St->ConstNotEq.lookup(sym);
145 ValueState::IntSetTy S = T ? *T : ISetFactory.GetEmptySet();
Ted Kremenek862d5bb2008-02-06 00:54:14 +0000146
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000147 // Now add V to the NE set.
Ted Kremenek862d5bb2008-02-06 00:54:14 +0000148 S = ISetFactory.Add(S, &V);
149
150 // Create a new state with the old binding replaced.
Ted Kremenekaed9b6a2008-02-28 10:21:43 +0000151 ValueState NewSt = *St;
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000152 NewSt.ConstNotEq = CNEFactory.Add(NewSt.ConstNotEq, sym, S);
Ted Kremenek862d5bb2008-02-06 00:54:14 +0000153
154 // Get the persistent copy.
Ted Kremeneke7d22112008-02-11 19:21:59 +0000155 return getPersistentState(NewSt);
Ted Kremenek862d5bb2008-02-06 00:54:14 +0000156}
157
Ted Kremenek4323a572008-07-10 22:03:41 +0000158const ValueState* ValueStateManager::AddEQ(const ValueState* St, SymbolID sym,
159 const llvm::APSInt& V) {
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000160
Ted Kremenek862d5bb2008-02-06 00:54:14 +0000161 // Create a new state with the old binding replaced.
Ted Kremenekaed9b6a2008-02-28 10:21:43 +0000162 ValueState NewSt = *St;
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000163 NewSt.ConstEq = CEFactory.Add(NewSt.ConstEq, sym, &V);
Ted Kremenek862d5bb2008-02-06 00:54:14 +0000164
165 // Get the persistent copy.
Ted Kremeneke7d22112008-02-11 19:21:59 +0000166 return getPersistentState(NewSt);
Ted Kremenek862d5bb2008-02-06 00:54:14 +0000167}
168
Ted Kremenek4323a572008-07-10 22:03:41 +0000169const ValueState* ValueStateManager::getInitialState() {
Ted Kremenek5a7b3822008-02-26 23:37:01 +0000170
Ted Kremenek8133a262008-07-08 21:46:56 +0000171 ValueState StateImpl(EnvMgr.getInitialEnvironment(),
Ted Kremenek4323a572008-07-10 22:03:41 +0000172 StMgr->getInitialStore(),
Ted Kremenek8133a262008-07-08 21:46:56 +0000173 CNEFactory.GetEmptyMap(),
174 CEFactory.GetEmptyMap());
Ted Kremenek9153f732008-02-05 07:17:49 +0000175
176 return getPersistentState(StateImpl);
177}
178
Ted Kremenek4323a572008-07-10 22:03:41 +0000179const ValueState* ValueStateManager::getPersistentState(ValueState& State) {
Ted Kremenek9153f732008-02-05 07:17:49 +0000180
181 llvm::FoldingSetNodeID ID;
182 State.Profile(ID);
Ted Kremeneke7d22112008-02-11 19:21:59 +0000183 void* InsertPos;
Ted Kremenek9153f732008-02-05 07:17:49 +0000184
Ted Kremenekaed9b6a2008-02-28 10:21:43 +0000185 if (ValueState* I = StateSet.FindNodeOrInsertPos(ID, InsertPos))
Ted Kremenek9153f732008-02-05 07:17:49 +0000186 return I;
187
Ted Kremenekaed9b6a2008-02-28 10:21:43 +0000188 ValueState* I = (ValueState*) Alloc.Allocate<ValueState>();
189 new (I) ValueState(State);
Ted Kremenek9153f732008-02-05 07:17:49 +0000190 StateSet.InsertNode(I, InsertPos);
191 return I;
192}
Ted Kremeneke7d22112008-02-11 19:21:59 +0000193
Ted Kremenek461f9772008-03-11 18:57:24 +0000194void ValueState::printDOT(std::ostream& Out, CheckerStatePrinter* P) const {
195 print(Out, P, "\\l", "\\|");
Ted Kremenek59894f92008-03-04 18:30:35 +0000196}
197
Ted Kremenek461f9772008-03-11 18:57:24 +0000198void ValueState::printStdErr(CheckerStatePrinter* P) const {
199 print(*llvm::cerr, P);
200}
201
202void ValueState::print(std::ostream& Out, CheckerStatePrinter* P,
203 const char* nl, const char* sep) const {
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000204
Ted Kremeneke7d22112008-02-11 19:21:59 +0000205 // Print Variable Bindings
Ted Kremenek59894f92008-03-04 18:30:35 +0000206 Out << "Variables:" << nl;
Ted Kremeneke7d22112008-02-11 19:21:59 +0000207
208 bool isFirst = true;
209
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000210 for (vb_iterator I = vb_begin(), E = vb_end(); I != E; ++I) {
Ted Kremeneke7d22112008-02-11 19:21:59 +0000211
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000212 if (isFirst) isFirst = false;
Ted Kremenek59894f92008-03-04 18:30:35 +0000213 else Out << nl;
Ted Kremeneke7d22112008-02-11 19:21:59 +0000214
215 Out << ' ' << I.getKey()->getName() << " : ";
216 I.getData().print(Out);
217 }
218
219 // Print Subexpression bindings.
220
221 isFirst = true;
222
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000223 for (seb_iterator I = seb_begin(), E = seb_end(); I != E; ++I) {
Ted Kremeneke7d22112008-02-11 19:21:59 +0000224
225 if (isFirst) {
Ted Kremenek59894f92008-03-04 18:30:35 +0000226 Out << nl << nl << "Sub-Expressions:" << nl;
Ted Kremeneke7d22112008-02-11 19:21:59 +0000227 isFirst = false;
228 }
Ted Kremenek59894f92008-03-04 18:30:35 +0000229 else { Out << nl; }
Ted Kremeneke7d22112008-02-11 19:21:59 +0000230
231 Out << " (" << (void*) I.getKey() << ") ";
232 I.getKey()->printPretty(Out);
233 Out << " : ";
234 I.getData().print(Out);
235 }
236
237 // Print block-expression bindings.
238
239 isFirst = true;
240
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000241 for (beb_iterator I = beb_begin(), E = beb_end(); I != E; ++I) {
Ted Kremeneke7d22112008-02-11 19:21:59 +0000242
243 if (isFirst) {
Ted Kremenek59894f92008-03-04 18:30:35 +0000244 Out << nl << nl << "Block-level Expressions:" << nl;
Ted Kremeneke7d22112008-02-11 19:21:59 +0000245 isFirst = false;
246 }
Ted Kremenek59894f92008-03-04 18:30:35 +0000247 else { Out << nl; }
Ted Kremeneke7d22112008-02-11 19:21:59 +0000248
249 Out << " (" << (void*) I.getKey() << ") ";
250 I.getKey()->printPretty(Out);
251 Out << " : ";
252 I.getData().print(Out);
253 }
254
255 // Print equality constraints.
256
Ted Kremenekaed9b6a2008-02-28 10:21:43 +0000257 if (!ConstEq.isEmpty()) {
Ted Kremeneke7d22112008-02-11 19:21:59 +0000258
Ted Kremenek59894f92008-03-04 18:30:35 +0000259 Out << nl << sep << "'==' constraints:";
Ted Kremeneke7d22112008-02-11 19:21:59 +0000260
Ted Kremenekaed9b6a2008-02-28 10:21:43 +0000261 for (ConstEqTy::iterator I = ConstEq.begin(),
262 E = ConstEq.end(); I!=E; ++I) {
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000263
Ted Kremenek59894f92008-03-04 18:30:35 +0000264 Out << nl << " $" << I.getKey()
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000265 << " : " << I.getData()->toString();
266 }
Ted Kremeneke7d22112008-02-11 19:21:59 +0000267 }
Ted Kremeneke7d22112008-02-11 19:21:59 +0000268
269 // Print != constraints.
270
Ted Kremenekaed9b6a2008-02-28 10:21:43 +0000271 if (!ConstNotEq.isEmpty()) {
Ted Kremeneke7d22112008-02-11 19:21:59 +0000272
Ted Kremenek59894f92008-03-04 18:30:35 +0000273 Out << nl << sep << "'!=' constraints:";
Ted Kremeneke7d22112008-02-11 19:21:59 +0000274
Ted Kremenekaed9b6a2008-02-28 10:21:43 +0000275 for (ConstNotEqTy::iterator I = ConstNotEq.begin(),
276 EI = ConstNotEq.end(); I != EI; ++I) {
Ted Kremeneke7d22112008-02-11 19:21:59 +0000277
Ted Kremenek59894f92008-03-04 18:30:35 +0000278 Out << nl << " $" << I.getKey() << " : ";
Ted Kremeneke7d22112008-02-11 19:21:59 +0000279 isFirst = true;
280
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000281 IntSetTy::iterator J = I.getData().begin(), EJ = I.getData().end();
Ted Kremeneke7d22112008-02-11 19:21:59 +0000282
283 for ( ; J != EJ; ++J) {
284 if (isFirst) isFirst = false;
285 else Out << ", ";
286
287 Out << (*J)->toString();
288 }
289 }
290 }
Ted Kremenek461f9772008-03-11 18:57:24 +0000291
292 // Print checker-specific data.
293
294 if (P && CheckerState)
295 P->PrintCheckerState(Out, CheckerState, nl, sep);
Ted Kremeneke7d22112008-02-11 19:21:59 +0000296}