blob: b5a5985c445dba1e532221713878b6250a46e0dd [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 Kremenek0eb0afa2008-02-04 21:59:22 +000036RValue ValueStateManager::GetValue(const StateTy& St, const LValue& LV) {
Ted Kremenek9b32cd02008-02-07 04:16:04 +000037 if (isa<InvalidValue>(LV))
38 return InvalidValue();
39
Ted Kremenek0eb0afa2008-02-04 21:59:22 +000040 switch (LV.getSubKind()) {
Ted Kremenek1b63a3b2008-02-05 21:52:21 +000041 case lval::DeclValKind: {
Ted Kremenek2d8dce32008-02-05 07:17:49 +000042 StateTy::VariableBindingsTy::TreeTy* T =
Ted Kremenek1b63a3b2008-02-05 21:52:21 +000043 St.getImpl()->VariableBindings.SlimFind(cast<lval::DeclVal>(LV).getDecl());
Ted Kremenek2d8dce32008-02-05 07:17:49 +000044
Ted Kremenek0eb0afa2008-02-04 21:59:22 +000045 return T ? T->getValue().second : InvalidValue();
46 }
47 default:
48 assert (false && "Invalid LValue.");
49 break;
50 }
51
52 return InvalidValue();
53}
54
Ted Kremenek13f31562008-02-06 00:54:14 +000055ValueStateManager::StateTy
56ValueStateManager::AddNE(StateTy St, SymbolID sym, const llvm::APSInt& V) {
57 // First, retrieve the NE-set associated with the given symbol.
58 ValueState::ConstantNotEqTy::TreeTy* T =
59 St.getImpl()->ConstantNotEq.SlimFind(sym);
60
61 ValueState::IntSetTy S = T ? T->getValue().second : ISetFactory.GetEmptySet();
62
63 // Now add V to the NE set.
64 S = ISetFactory.Add(S, &V);
65
66 // Create a new state with the old binding replaced.
67 ValueStateImpl NewStateImpl = *St.getImpl();
68 NewStateImpl.ConstantNotEq = CNEFactory.Add(NewStateImpl.ConstantNotEq,
69 sym, S);
70
71 // Get the persistent copy.
72 return getPersistentState(NewStateImpl);
73}
74
75ValueStateManager::StateTy
76ValueStateManager::AddEQ(StateTy St, SymbolID sym, const llvm::APSInt& V) {
77 // Create a new state with the old binding replaced.
78 ValueStateImpl NewStateImpl = *St.getImpl();
79 NewStateImpl.ConstantEq = CEFactory.Add(NewStateImpl.ConstantEq, sym, &V);
80
81 // Get the persistent copy.
82 return getPersistentState(NewStateImpl);
83}
84
Ted Kremenek1f0eb992008-02-05 00:26:40 +000085RValue ValueStateManager::GetValue(const StateTy& St, Stmt* S, bool* hasVal) {
Ted Kremenek0eb0afa2008-02-04 21:59:22 +000086 for (;;) {
87 switch (S->getStmtClass()) {
88
89 // ParenExprs are no-ops.
90
91 case Stmt::ParenExprClass:
92 S = cast<ParenExpr>(S)->getSubExpr();
93 continue;
94
95 // DeclRefExprs can either evaluate to an LValue or a Non-LValue
96 // (assuming an implicit "load") depending on the context. In this
97 // context we assume that we are retrieving the value contained
98 // within the referenced variables.
99
100 case Stmt::DeclRefExprClass:
Ted Kremenek1b63a3b2008-02-05 21:52:21 +0000101 return GetValue(St, lval::DeclVal(cast<DeclRefExpr>(S)->getDecl()));
Ted Kremenek0eb0afa2008-02-04 21:59:22 +0000102
103 // Integer literals evaluate to an RValue. Simply retrieve the
104 // RValue for the literal.
105
106 case Stmt::IntegerLiteralClass:
107 return NonLValue::GetValue(ValMgr, cast<IntegerLiteral>(S));
108
109 // Casts where the source and target type are the same
110 // are no-ops. We blast through these to get the descendant
111 // subexpression that has a value.
112
113 case Stmt::ImplicitCastExprClass: {
114 ImplicitCastExpr* C = cast<ImplicitCastExpr>(S);
115 if (C->getType() == C->getSubExpr()->getType()) {
116 S = C->getSubExpr();
117 continue;
118 }
119 break;
120 }
121
122 case Stmt::CastExprClass: {
123 CastExpr* C = cast<CastExpr>(S);
124 if (C->getType() == C->getSubExpr()->getType()) {
125 S = C->getSubExpr();
126 continue;
127 }
128 break;
129 }
130
131 // Handle all other Stmt* using a lookup.
132
133 default:
134 break;
135 };
136
137 break;
138 }
139
Ted Kremenek2d8dce32008-02-05 07:17:49 +0000140 StateTy::VariableBindingsTy::TreeTy* T =
141 St.getImpl()->VariableBindings.SlimFind(S);
Ted Kremenek0eb0afa2008-02-04 21:59:22 +0000142
Ted Kremenek1f0eb992008-02-05 00:26:40 +0000143 if (T) {
144 if (hasVal) *hasVal = true;
145 return T->getValue().second;
146 }
147 else {
148 if (hasVal) *hasVal = false;
149 return InvalidValue();
150 }
Ted Kremenek0eb0afa2008-02-04 21:59:22 +0000151}
152
153LValue ValueStateManager::GetLValue(const StateTy& St, Stmt* S) {
154
155 while (ParenExpr* P = dyn_cast<ParenExpr>(S))
156 S = P->getSubExpr();
157
158 if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(S))
Ted Kremenek1b63a3b2008-02-05 21:52:21 +0000159 return lval::DeclVal(DR->getDecl());
Ted Kremenek0eb0afa2008-02-04 21:59:22 +0000160
Ted Kremeneke1f38b62008-02-07 01:08:27 +0000161 if (UnaryOperator* U = dyn_cast<UnaryOperator>(S))
162 if (U->getOpcode() == UnaryOperator::Deref)
163 return cast<LValue>(GetValue(St, U->getSubExpr()));
164
Ted Kremenek0eb0afa2008-02-04 21:59:22 +0000165 return cast<LValue>(GetValue(St, S));
166}
167
168
169ValueStateManager::StateTy
170ValueStateManager::SetValue(StateTy St, Stmt* S, bool isBlkExpr,
171 const RValue& V) {
172
173 assert (S);
Ted Kremenek2d8dce32008-02-05 07:17:49 +0000174 return V.isValid() ? Add(St, VarBindKey(S, isBlkExpr), V) : St;
Ted Kremenek0eb0afa2008-02-04 21:59:22 +0000175}
176
177ValueStateManager::StateTy
178ValueStateManager::SetValue(StateTy St, const LValue& LV, const RValue& V) {
179
180 switch (LV.getSubKind()) {
Ted Kremenek1b63a3b2008-02-05 21:52:21 +0000181 case lval::DeclValKind:
182 return V.isValid() ? Add(St, cast<lval::DeclVal>(LV).getDecl(), V)
183 : Remove(St, cast<lval::DeclVal>(LV).getDecl());
Ted Kremenek0eb0afa2008-02-04 21:59:22 +0000184
185 default:
186 assert ("SetValue for given LValue type not yet implemented.");
187 return St;
188 }
189}
190
Ted Kremenek2d8dce32008-02-05 07:17:49 +0000191ValueStateManager::StateTy
192ValueStateManager::Remove(StateTy St, VarBindKey K) {
193
194 // Create a new state with the old binding removed.
195 ValueStateImpl NewStateImpl = *St.getImpl();
196 NewStateImpl.VariableBindings =
197 VBFactory.Remove(NewStateImpl.VariableBindings, K);
198
199 // Get the persistent copy.
200 return getPersistentState(NewStateImpl);
Ted Kremenek0eb0afa2008-02-04 21:59:22 +0000201}
Ted Kremenek2d8dce32008-02-05 07:17:49 +0000202
203ValueStateManager::StateTy
204ValueStateManager::Add(StateTy St, VarBindKey K, const RValue& V) {
Ted Kremenek0eb0afa2008-02-04 21:59:22 +0000205
Ted Kremenek2d8dce32008-02-05 07:17:49 +0000206 // Create a new state with the old binding removed.
207 ValueStateImpl NewStateImpl = *St.getImpl();
208 NewStateImpl.VariableBindings =
209 VBFactory.Add(NewStateImpl.VariableBindings, K, V);
210
211 // Get the persistent copy.
212 return getPersistentState(NewStateImpl);
213}
214
215
216ValueStateManager::StateTy
217ValueStateManager::getInitialState() {
218
219 // Create a state with empty variable bindings.
Ted Kremenek64220872008-02-05 18:51:06 +0000220 ValueStateImpl StateImpl(VBFactory.GetEmptyMap(),
Ted Kremenek13f31562008-02-06 00:54:14 +0000221 CNEFactory.GetEmptyMap(),
222 CEFactory.GetEmptyMap());
Ted Kremenek2d8dce32008-02-05 07:17:49 +0000223
224 return getPersistentState(StateImpl);
225}
226
227ValueStateManager::StateTy
228ValueStateManager::getPersistentState(const ValueStateImpl &State) {
229
230 llvm::FoldingSetNodeID ID;
231 State.Profile(ID);
232 void* InsertPos;
233
234 if (ValueStateImpl* I = StateSet.FindNodeOrInsertPos(ID, InsertPos))
235 return I;
236
Ted Kremenek9a4e8072008-02-06 02:45:20 +0000237 ValueStateImpl* I = (ValueStateImpl*) Alloc.Allocate<ValueStateImpl>();
Ted Kremenek2d8dce32008-02-05 07:17:49 +0000238 new (I) ValueStateImpl(State);
239 StateSet.InsertNode(I, InsertPos);
240 return I;
241}