blob: 2166a8699ff953dcb925f1490ff2da2a7a7bceab [file] [log] [blame]
Ted Kremenek9153f732008-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 Kremenekf66ea2cd2008-02-04 21:59:22 +000014#include "ValueState.h"
15
16using namespace clang;
17
18RValue ValueStateManager::GetValue(const StateTy& St, const LValue& LV) {
19 switch (LV.getSubKind()) {
20 case LValueDeclKind: {
Ted Kremenek9153f732008-02-05 07:17:49 +000021 StateTy::VariableBindingsTy::TreeTy* T =
22 St.getImpl()->VariableBindings.SlimFind(cast<LValueDecl>(LV).getDecl());
23
Ted Kremenekf66ea2cd2008-02-04 21:59:22 +000024 return T ? T->getValue().second : InvalidValue();
25 }
26 default:
27 assert (false && "Invalid LValue.");
28 break;
29 }
30
31 return InvalidValue();
32}
33
Ted Kremenekf233d482008-02-05 00:26:40 +000034RValue ValueStateManager::GetValue(const StateTy& St, Stmt* S, bool* hasVal) {
Ted Kremenekf66ea2cd2008-02-04 21:59:22 +000035 for (;;) {
36 switch (S->getStmtClass()) {
37
38 // ParenExprs are no-ops.
39
40 case Stmt::ParenExprClass:
41 S = cast<ParenExpr>(S)->getSubExpr();
42 continue;
43
44 // DeclRefExprs can either evaluate to an LValue or a Non-LValue
45 // (assuming an implicit "load") depending on the context. In this
46 // context we assume that we are retrieving the value contained
47 // within the referenced variables.
48
49 case Stmt::DeclRefExprClass:
50 return GetValue(St, LValueDecl(cast<DeclRefExpr>(S)->getDecl()));
51
52 // Integer literals evaluate to an RValue. Simply retrieve the
53 // RValue for the literal.
54
55 case Stmt::IntegerLiteralClass:
56 return NonLValue::GetValue(ValMgr, cast<IntegerLiteral>(S));
57
58 // Casts where the source and target type are the same
59 // are no-ops. We blast through these to get the descendant
60 // subexpression that has a value.
61
62 case Stmt::ImplicitCastExprClass: {
63 ImplicitCastExpr* C = cast<ImplicitCastExpr>(S);
64 if (C->getType() == C->getSubExpr()->getType()) {
65 S = C->getSubExpr();
66 continue;
67 }
68 break;
69 }
70
71 case Stmt::CastExprClass: {
72 CastExpr* C = cast<CastExpr>(S);
73 if (C->getType() == C->getSubExpr()->getType()) {
74 S = C->getSubExpr();
75 continue;
76 }
77 break;
78 }
79
80 // Handle all other Stmt* using a lookup.
81
82 default:
83 break;
84 };
85
86 break;
87 }
88
Ted Kremenek9153f732008-02-05 07:17:49 +000089 StateTy::VariableBindingsTy::TreeTy* T =
90 St.getImpl()->VariableBindings.SlimFind(S);
Ted Kremenekf66ea2cd2008-02-04 21:59:22 +000091
Ted Kremenekf233d482008-02-05 00:26:40 +000092 if (T) {
93 if (hasVal) *hasVal = true;
94 return T->getValue().second;
95 }
96 else {
97 if (hasVal) *hasVal = false;
98 return InvalidValue();
99 }
Ted Kremenekf66ea2cd2008-02-04 21:59:22 +0000100}
101
102LValue ValueStateManager::GetLValue(const StateTy& St, Stmt* S) {
103
104 while (ParenExpr* P = dyn_cast<ParenExpr>(S))
105 S = P->getSubExpr();
106
107 if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(S))
108 return LValueDecl(DR->getDecl());
109
110 return cast<LValue>(GetValue(St, S));
111}
112
113
114ValueStateManager::StateTy
115ValueStateManager::SetValue(StateTy St, Stmt* S, bool isBlkExpr,
116 const RValue& V) {
117
118 assert (S);
Ted Kremenek9153f732008-02-05 07:17:49 +0000119 return V.isValid() ? Add(St, VarBindKey(S, isBlkExpr), V) : St;
Ted Kremenekf66ea2cd2008-02-04 21:59:22 +0000120}
121
122ValueStateManager::StateTy
123ValueStateManager::SetValue(StateTy St, const LValue& LV, const RValue& V) {
124
125 switch (LV.getSubKind()) {
126 case LValueDeclKind:
Ted Kremenek9153f732008-02-05 07:17:49 +0000127 return V.isValid() ? Add(St, cast<LValueDecl>(LV).getDecl(), V)
128 : Remove(St, cast<LValueDecl>(LV).getDecl());
Ted Kremenekf66ea2cd2008-02-04 21:59:22 +0000129
130 default:
131 assert ("SetValue for given LValue type not yet implemented.");
132 return St;
133 }
134}
135
Ted Kremenek9153f732008-02-05 07:17:49 +0000136ValueStateManager::StateTy
137ValueStateManager::Remove(StateTy St, VarBindKey K) {
138
139 // Create a new state with the old binding removed.
140 ValueStateImpl NewStateImpl = *St.getImpl();
141 NewStateImpl.VariableBindings =
142 VBFactory.Remove(NewStateImpl.VariableBindings, K);
143
144 // Get the persistent copy.
145 return getPersistentState(NewStateImpl);
Ted Kremenekf66ea2cd2008-02-04 21:59:22 +0000146}
Ted Kremenek9153f732008-02-05 07:17:49 +0000147
148ValueStateManager::StateTy
149ValueStateManager::Add(StateTy St, VarBindKey K, const RValue& V) {
Ted Kremenekf66ea2cd2008-02-04 21:59:22 +0000150
Ted Kremenek9153f732008-02-05 07:17:49 +0000151 // Create a new state with the old binding removed.
152 ValueStateImpl NewStateImpl = *St.getImpl();
153 NewStateImpl.VariableBindings =
154 VBFactory.Add(NewStateImpl.VariableBindings, K, V);
155
156 // Get the persistent copy.
157 return getPersistentState(NewStateImpl);
158}
159
160
161ValueStateManager::StateTy
162ValueStateManager::getInitialState() {
163
164 // Create a state with empty variable bindings.
165 ValueStateImpl StateImpl(VBFactory.GetEmptyMap());
166
167 return getPersistentState(StateImpl);
168}
169
170ValueStateManager::StateTy
171ValueStateManager::getPersistentState(const ValueStateImpl &State) {
172
173 llvm::FoldingSetNodeID ID;
174 State.Profile(ID);
175 void* InsertPos;
176
177 if (ValueStateImpl* I = StateSet.FindNodeOrInsertPos(ID, InsertPos))
178 return I;
179
180 ValueStateImpl* I = (ValueStateImpl*) Alloc.Allocate<ValueState>();
181 new (I) ValueStateImpl(State);
182 StateSet.InsertNode(I, InsertPos);
183 return I;
184}