blob: d191623dd89a5843723883ad408c4fbad0f8ed95 [file] [log] [blame]
Ted Kremenek2d8dce32008-02-05 07:17:49 +00001//= ValueState.cpp - Path-Sens. "State" for tracking valuues -----*- 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 files defines SymbolID, VarBindKey, and ValueState.
11//
12//===----------------------------------------------------------------------===//
13
Ted Kremenek0eb0afa2008-02-04 21:59:22 +000014#include "ValueState.h"
15
16using namespace clang;
17
Ted Kremenek13f31562008-02-06 00:54:14 +000018bool ValueState::isNotEqual(SymbolID sym, const llvm::APSInt& V) const {
19 // First, retrieve the NE-set associated with the given symbol.
20 ConstantNotEqTy::TreeTy* T = Data->ConstantNotEq.SlimFind(sym);
21
22 if (!T)
23 return false;
24
25 // Second, see if V is present in the NE-set.
26 return T->getValue().second.contains(&V);
27}
28
29const llvm::APSInt* ValueState::getSymVal(SymbolID sym) const {
30 ConstantEqTy::TreeTy* T = Data->ConstantEq.SlimFind(sym);
31 return T ? T->getValue().second : NULL;
32}
33
34
35
Ted Kremenek80d52d02008-02-07 05:48:01 +000036RValue ValueStateManager::GetValue(const StateTy& St, const LValue& LV,
37 QualType* T) {
Ted Kremenekadec14b2008-02-08 02:57:34 +000038 if (isa<UnknownVal>(LV))
39 return UnknownVal();
Ted Kremenek9b32cd02008-02-07 04:16:04 +000040
Ted Kremenek0eb0afa2008-02-04 21:59:22 +000041 switch (LV.getSubKind()) {
Ted Kremenek1b63a3b2008-02-05 21:52:21 +000042 case lval::DeclValKind: {
Ted Kremenek0428e022008-02-08 03:02:48 +000043 StateTy::VarBindingsTy::TreeTy* T =
44 St.getImpl()->VarBindings.SlimFind(cast<lval::DeclVal>(LV).getDecl());
Ted Kremenek2d8dce32008-02-05 07:17:49 +000045
Ted Kremenekadec14b2008-02-08 02:57:34 +000046 return T ? T->getValue().second : UnknownVal();
Ted Kremenek0eb0afa2008-02-04 21:59:22 +000047 }
Ted Kremenek80d52d02008-02-07 05:48:01 +000048
49 // FIXME: We should bind how far a "ContentsOf" will go...
50
51 case lval::SymbolValKind: {
52 const lval::SymbolVal& SV = cast<lval::SymbolVal>(LV);
53 assert (T);
54
55 if (T->getTypePtr()->isPointerType())
56 return lval::SymbolVal(SymMgr.getContentsOfSymbol(SV.getSymbol()));
57 else
58 return nonlval::SymbolVal(SymMgr.getContentsOfSymbol(SV.getSymbol()));
59 }
60
Ted Kremenek0eb0afa2008-02-04 21:59:22 +000061 default:
62 assert (false && "Invalid LValue.");
63 break;
64 }
65
Ted Kremenekadec14b2008-02-08 02:57:34 +000066 return UnknownVal();
Ted Kremenek0eb0afa2008-02-04 21:59:22 +000067}
68
Ted Kremenek13f31562008-02-06 00:54:14 +000069ValueStateManager::StateTy
70ValueStateManager::AddNE(StateTy St, SymbolID sym, const llvm::APSInt& V) {
71 // First, retrieve the NE-set associated with the given symbol.
72 ValueState::ConstantNotEqTy::TreeTy* T =
73 St.getImpl()->ConstantNotEq.SlimFind(sym);
74
75 ValueState::IntSetTy S = T ? T->getValue().second : ISetFactory.GetEmptySet();
76
77 // Now add V to the NE set.
78 S = ISetFactory.Add(S, &V);
79
80 // Create a new state with the old binding replaced.
81 ValueStateImpl NewStateImpl = *St.getImpl();
82 NewStateImpl.ConstantNotEq = CNEFactory.Add(NewStateImpl.ConstantNotEq,
83 sym, S);
84
85 // Get the persistent copy.
86 return getPersistentState(NewStateImpl);
87}
88
89ValueStateManager::StateTy
90ValueStateManager::AddEQ(StateTy St, SymbolID sym, const llvm::APSInt& V) {
91 // Create a new state with the old binding replaced.
92 ValueStateImpl NewStateImpl = *St.getImpl();
93 NewStateImpl.ConstantEq = CEFactory.Add(NewStateImpl.ConstantEq, sym, &V);
94
95 // Get the persistent copy.
96 return getPersistentState(NewStateImpl);
97}
98
Ted Kremenek1f0eb992008-02-05 00:26:40 +000099RValue ValueStateManager::GetValue(const StateTy& St, Stmt* S, bool* hasVal) {
Ted Kremenek0eb0afa2008-02-04 21:59:22 +0000100 for (;;) {
101 switch (S->getStmtClass()) {
102
103 // ParenExprs are no-ops.
104
105 case Stmt::ParenExprClass:
106 S = cast<ParenExpr>(S)->getSubExpr();
107 continue;
108
109 // DeclRefExprs can either evaluate to an LValue or a Non-LValue
110 // (assuming an implicit "load") depending on the context. In this
111 // context we assume that we are retrieving the value contained
112 // within the referenced variables.
113
114 case Stmt::DeclRefExprClass:
Ted Kremenek1b63a3b2008-02-05 21:52:21 +0000115 return GetValue(St, lval::DeclVal(cast<DeclRefExpr>(S)->getDecl()));
Ted Kremenek0eb0afa2008-02-04 21:59:22 +0000116
117 // Integer literals evaluate to an RValue. Simply retrieve the
118 // RValue for the literal.
119
120 case Stmt::IntegerLiteralClass:
121 return NonLValue::GetValue(ValMgr, cast<IntegerLiteral>(S));
122
123 // Casts where the source and target type are the same
124 // are no-ops. We blast through these to get the descendant
125 // subexpression that has a value.
126
127 case Stmt::ImplicitCastExprClass: {
128 ImplicitCastExpr* C = cast<ImplicitCastExpr>(S);
129 if (C->getType() == C->getSubExpr()->getType()) {
130 S = C->getSubExpr();
131 continue;
132 }
133 break;
134 }
135
136 case Stmt::CastExprClass: {
137 CastExpr* C = cast<CastExpr>(S);
138 if (C->getType() == C->getSubExpr()->getType()) {
139 S = C->getSubExpr();
140 continue;
141 }
142 break;
143 }
144
145 // Handle all other Stmt* using a lookup.
146
147 default:
148 break;
149 };
150
151 break;
152 }
153
Ted Kremenek0428e022008-02-08 03:02:48 +0000154 StateTy::VarBindingsTy::TreeTy* T =
155 St.getImpl()->VarBindings.SlimFind(S);
Ted Kremenek0eb0afa2008-02-04 21:59:22 +0000156
Ted Kremenek1f0eb992008-02-05 00:26:40 +0000157 if (T) {
158 if (hasVal) *hasVal = true;
159 return T->getValue().second;
160 }
161 else {
162 if (hasVal) *hasVal = false;
Ted Kremenekadec14b2008-02-08 02:57:34 +0000163 return UnknownVal();
Ted Kremenek1f0eb992008-02-05 00:26:40 +0000164 }
Ted Kremenek0eb0afa2008-02-04 21:59:22 +0000165}
166
167LValue ValueStateManager::GetLValue(const StateTy& St, Stmt* S) {
168
169 while (ParenExpr* P = dyn_cast<ParenExpr>(S))
170 S = P->getSubExpr();
171
172 if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(S))
Ted Kremenek1b63a3b2008-02-05 21:52:21 +0000173 return lval::DeclVal(DR->getDecl());
Ted Kremenek0eb0afa2008-02-04 21:59:22 +0000174
Ted Kremeneke1f38b62008-02-07 01:08:27 +0000175 if (UnaryOperator* U = dyn_cast<UnaryOperator>(S))
176 if (U->getOpcode() == UnaryOperator::Deref)
177 return cast<LValue>(GetValue(St, U->getSubExpr()));
178
Ted Kremenek0eb0afa2008-02-04 21:59:22 +0000179 return cast<LValue>(GetValue(St, S));
180}
181
182
183ValueStateManager::StateTy
184ValueStateManager::SetValue(StateTy St, Stmt* S, bool isBlkExpr,
185 const RValue& V) {
186
187 assert (S);
Ted Kremenekadec14b2008-02-08 02:57:34 +0000188 return V.isKnown() ? Add(St, VarBindKey(S, isBlkExpr), V) : St;
Ted Kremenek0eb0afa2008-02-04 21:59:22 +0000189}
190
191ValueStateManager::StateTy
192ValueStateManager::SetValue(StateTy St, const LValue& LV, const RValue& V) {
193
194 switch (LV.getSubKind()) {
Ted Kremenek1b63a3b2008-02-05 21:52:21 +0000195 case lval::DeclValKind:
Ted Kremenekadec14b2008-02-08 02:57:34 +0000196 return V.isKnown() ? Add(St, cast<lval::DeclVal>(LV).getDecl(), V)
Ted Kremenek1b63a3b2008-02-05 21:52:21 +0000197 : Remove(St, cast<lval::DeclVal>(LV).getDecl());
Ted Kremenek0eb0afa2008-02-04 21:59:22 +0000198
199 default:
200 assert ("SetValue for given LValue type not yet implemented.");
201 return St;
202 }
203}
204
Ted Kremenek2d8dce32008-02-05 07:17:49 +0000205ValueStateManager::StateTy
206ValueStateManager::Remove(StateTy St, VarBindKey K) {
207
208 // Create a new state with the old binding removed.
209 ValueStateImpl NewStateImpl = *St.getImpl();
Ted Kremenek0428e022008-02-08 03:02:48 +0000210 NewStateImpl.VarBindings =
211 VBFactory.Remove(NewStateImpl.VarBindings, K);
Ted Kremenek2d8dce32008-02-05 07:17:49 +0000212
213 // Get the persistent copy.
214 return getPersistentState(NewStateImpl);
Ted Kremenek0eb0afa2008-02-04 21:59:22 +0000215}
Ted Kremenek2d8dce32008-02-05 07:17:49 +0000216
217ValueStateManager::StateTy
218ValueStateManager::Add(StateTy St, VarBindKey K, const RValue& V) {
Ted Kremenek0eb0afa2008-02-04 21:59:22 +0000219
Ted Kremenek2d8dce32008-02-05 07:17:49 +0000220 // Create a new state with the old binding removed.
221 ValueStateImpl NewStateImpl = *St.getImpl();
Ted Kremenek0428e022008-02-08 03:02:48 +0000222 NewStateImpl.VarBindings =
223 VBFactory.Add(NewStateImpl.VarBindings, K, V);
Ted Kremenek2d8dce32008-02-05 07:17:49 +0000224
225 // Get the persistent copy.
226 return getPersistentState(NewStateImpl);
227}
228
229
230ValueStateManager::StateTy
231ValueStateManager::getInitialState() {
232
233 // Create a state with empty variable bindings.
Ted Kremenek64220872008-02-05 18:51:06 +0000234 ValueStateImpl StateImpl(VBFactory.GetEmptyMap(),
Ted Kremenek13f31562008-02-06 00:54:14 +0000235 CNEFactory.GetEmptyMap(),
236 CEFactory.GetEmptyMap());
Ted Kremenek2d8dce32008-02-05 07:17:49 +0000237
238 return getPersistentState(StateImpl);
239}
240
241ValueStateManager::StateTy
242ValueStateManager::getPersistentState(const ValueStateImpl &State) {
243
244 llvm::FoldingSetNodeID ID;
245 State.Profile(ID);
246 void* InsertPos;
247
248 if (ValueStateImpl* I = StateSet.FindNodeOrInsertPos(ID, InsertPos))
249 return I;
250
Ted Kremenek9a4e8072008-02-06 02:45:20 +0000251 ValueStateImpl* I = (ValueStateImpl*) Alloc.Allocate<ValueStateImpl>();
Ted Kremenek2d8dce32008-02-05 07:17:49 +0000252 new (I) ValueStateImpl(State);
253 StateSet.InsertNode(I, InsertPos);
254 return I;
255}