blob: 1067531f5bbe637a9a3a6b191b4bfdea8163cbe4 [file] [log] [blame]
Ted Kremeneka90ccfe2008-01-31 19:34:24 +00001//== ValueState.h - 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//
Ted Kremenek9153f732008-02-05 07:17:49 +000010// This files defines SymbolID, VarBindKey, and ValueState.
Ted Kremeneka90ccfe2008-01-31 19:34:24 +000011//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_CLANG_ANALYSIS_VALUESTATE_H
15#define LLVM_CLANG_ANALYSIS_VALUESTATE_H
16
17// FIXME: Reduce the number of includes.
18
19#include "RValues.h"
20
21#include "clang/Analysis/PathSensitive/GREngine.h"
22#include "clang/AST/Expr.h"
23#include "clang/AST/Decl.h"
24#include "clang/AST/ASTContext.h"
25#include "clang/Analysis/Analyses/LiveVariables.h"
26
27#include "llvm/Support/Casting.h"
28#include "llvm/Support/DataTypes.h"
29#include "llvm/ADT/APSInt.h"
30#include "llvm/ADT/FoldingSet.h"
31#include "llvm/ADT/ImmutableMap.h"
32#include "llvm/ADT/SmallVector.h"
33#include "llvm/ADT/SmallPtrSet.h"
34#include "llvm/Support/Allocator.h"
35#include "llvm/Support/Compiler.h"
36#include "llvm/Support/Streams.h"
37
38#include <functional>
39
40namespace clang {
41
Ted Kremenek9153f732008-02-05 07:17:49 +000042/// VarBindKey - A variant smart pointer that wraps either a ValueDecl* or a
Ted Kremeneka90ccfe2008-01-31 19:34:24 +000043/// Stmt*. Use cast<> or dyn_cast<> to get actual pointer type
Ted Kremenek9153f732008-02-05 07:17:49 +000044class VarBindKey {
Ted Kremeneka90ccfe2008-01-31 19:34:24 +000045 uintptr_t Raw;
Ted Kremenek9153f732008-02-05 07:17:49 +000046 void operator=(const VarBindKey& RHS); // Do not implement.
Ted Kremeneka90ccfe2008-01-31 19:34:24 +000047
48public:
49 enum Kind { IsSubExpr=0x0, IsBlkExpr=0x1, IsDecl=0x2, // L-Value Bindings.
50 IsSymbol=0x3, // Symbol Bindings.
51 Mask=0x3 };
52
53 inline Kind getKind() const {
54 return (Kind) (Raw & Mask);
55 }
56
57 inline void* getPtr() const {
58 assert (getKind() != IsSymbol);
59 return reinterpret_cast<void*>(Raw & ~Mask);
60 }
61
62 inline SymbolID getSymbolID() const {
63 assert (getKind() == IsSymbol);
64 return Raw >> 2;
65 }
66
Ted Kremenek9153f732008-02-05 07:17:49 +000067 VarBindKey(const ValueDecl* VD)
Ted Kremeneka90ccfe2008-01-31 19:34:24 +000068 : Raw(reinterpret_cast<uintptr_t>(VD) | IsDecl) {
69 assert(VD && "ValueDecl cannot be NULL.");
70 }
71
Ted Kremenek9153f732008-02-05 07:17:49 +000072 VarBindKey(Stmt* S, bool isBlkExpr = false)
Ted Kremeneka90ccfe2008-01-31 19:34:24 +000073 : Raw(reinterpret_cast<uintptr_t>(S) | (isBlkExpr ? IsBlkExpr : IsSubExpr)){
74 assert(S && "Tracked statement cannot be NULL.");
75 }
76
Ted Kremenek9153f732008-02-05 07:17:49 +000077 VarBindKey(SymbolID V)
Ted Kremeneka90ccfe2008-01-31 19:34:24 +000078 : Raw((V << 2) | IsSymbol) {}
79
80 bool isSymbol() const { return getKind() == IsSymbol; }
81 bool isSubExpr() const { return getKind() == IsSubExpr; }
82 bool isBlkExpr() const { return getKind() == IsBlkExpr; }
83 bool isDecl() const { return getKind() == IsDecl; }
84 bool isStmt() const { return getKind() <= IsBlkExpr; }
85
86 inline void Profile(llvm::FoldingSetNodeID& ID) const {
87 ID.AddInteger(isSymbol() ? 1 : 0);
88
89 if (isSymbol())
90 ID.AddInteger(getSymbolID());
91 else
92 ID.AddPointer(getPtr());
93 }
94
Ted Kremenek9153f732008-02-05 07:17:49 +000095 inline bool operator==(const VarBindKey& X) const {
Ted Kremeneka90ccfe2008-01-31 19:34:24 +000096 return isSymbol() ? getSymbolID() == X.getSymbolID()
97 : getPtr() == X.getPtr();
98 }
99
Ted Kremenek9153f732008-02-05 07:17:49 +0000100 inline bool operator!=(const VarBindKey& X) const {
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000101 return !operator==(X);
102 }
103
Ted Kremenek9153f732008-02-05 07:17:49 +0000104 inline bool operator<(const VarBindKey& X) const {
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000105 if (isSymbol())
106 return X.isSymbol() ? getSymbolID() < X.getSymbolID() : false;
107
108 return getPtr() < X.getPtr();
109 }
110};
111
112//===----------------------------------------------------------------------===//
113// ValueState - An ImmutableMap type Stmt*/Decl*/Symbols to RValues.
114//===----------------------------------------------------------------------===//
115
Ted Kremenek9153f732008-02-05 07:17:49 +0000116namespace vstate {
Ted Kremenek174aea42008-02-05 18:51:06 +0000117 typedef llvm::ImmutableSet<llvm::APSInt*> IntSetTy;
118
Ted Kremenek862d5bb2008-02-06 00:54:14 +0000119 typedef llvm::ImmutableMap<VarBindKey,RValue> VariableBindingsTy;
120 typedef llvm::ImmutableMap<SymbolID,IntSetTy> ConstantNotEqTy;
121 typedef llvm::ImmutableMap<SymbolID,const llvm::APSInt*> ConstantEqTy;
Ted Kremenek9153f732008-02-05 07:17:49 +0000122}
Ted Kremenek6f886bd2008-02-05 18:24:17 +0000123
124/// ValueStateImpl - This class encapsulates the actual data values for
125/// for a "state" in our symbolic value tracking. It is intended to be
126/// used as a functional object; that is once it is created and made
127/// "persistent" in a FoldingSet its values will never change.
Ted Kremeneka40ba022008-02-06 02:50:36 +0000128class ValueStateImpl : public llvm::FoldingSetNode {
129private:
130 void operator=(const ValueStateImpl& R) const;
131
132public:
Ted Kremenek9153f732008-02-05 07:17:49 +0000133 vstate::VariableBindingsTy VariableBindings;
Ted Kremenek174aea42008-02-05 18:51:06 +0000134 vstate::ConstantNotEqTy ConstantNotEq;
Ted Kremenek862d5bb2008-02-06 00:54:14 +0000135 vstate::ConstantEqTy ConstantEq;
Ted Kremenek9153f732008-02-05 07:17:49 +0000136
Ted Kremenek174aea42008-02-05 18:51:06 +0000137 /// This ctor is used when creating the first ValueStateImpl object.
Ted Kremenek862d5bb2008-02-06 00:54:14 +0000138 ValueStateImpl(vstate::VariableBindingsTy VB,
139 vstate::ConstantNotEqTy CNE,
140 vstate::ConstantEqTy CE)
141 : VariableBindings(VB), ConstantNotEq(CNE), ConstantEq(CE) {}
Ted Kremenek9153f732008-02-05 07:17:49 +0000142
Ted Kremenek174aea42008-02-05 18:51:06 +0000143 /// Copy ctor - We must explicitly define this or else the "Next" ptr
144 /// in FoldingSetNode will also get copied.
Ted Kremenek9153f732008-02-05 07:17:49 +0000145 ValueStateImpl(const ValueStateImpl& RHS)
Ted Kremenek6f886bd2008-02-05 18:24:17 +0000146 : llvm::FoldingSetNode(),
Ted Kremenek174aea42008-02-05 18:51:06 +0000147 VariableBindings(RHS.VariableBindings),
Ted Kremenek862d5bb2008-02-06 00:54:14 +0000148 ConstantNotEq(RHS.ConstantNotEq),
149 ConstantEq(RHS.ConstantEq) {}
Ted Kremenek9153f732008-02-05 07:17:49 +0000150
Ted Kremeneka40ba022008-02-06 02:50:36 +0000151
152
Ted Kremenek174aea42008-02-05 18:51:06 +0000153 /// Profile - Profile the contents of a ValueStateImpl object for use
154 /// in a FoldingSet.
Ted Kremenek9153f732008-02-05 07:17:49 +0000155 static void Profile(llvm::FoldingSetNodeID& ID, const ValueStateImpl& V) {
156 V.VariableBindings.Profile(ID);
Ted Kremenek862d5bb2008-02-06 00:54:14 +0000157 V.ConstantNotEq.Profile(ID);
158 V.ConstantEq.Profile(ID);
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000159 }
Ted Kremenek174aea42008-02-05 18:51:06 +0000160
161 /// Profile - Used to profile the contents of this object for inclusion
162 /// in a FoldingSet.
Ted Kremenek9153f732008-02-05 07:17:49 +0000163 void Profile(llvm::FoldingSetNodeID& ID) const {
164 Profile(ID, *this);
165 }
166
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000167};
168
Ted Kremenek6f886bd2008-02-05 18:24:17 +0000169/// ValueState - This class represents a "state" in our symbolic value
170/// tracking. It is really just a "smart pointer", wrapping a pointer
171/// to ValueStateImpl object. Making this class a smart pointer means that its
172/// size is always the size of a pointer, which allows easy conversion to
173/// void* when being handled by GREngine. It also forces us to unique states;
174/// consequently, a ValueStateImpl* with a specific address will always refer
175/// to the unique state with those values.
Ted Kremeneka40ba022008-02-06 02:50:36 +0000176class ValueState {
Ted Kremenek9153f732008-02-05 07:17:49 +0000177 ValueStateImpl* Data;
178public:
Ted Kremeneked900212008-02-05 18:17:58 +0000179 ValueState(ValueStateImpl* D) : Data(D) {}
Ted Kremeneka40ba022008-02-06 02:50:36 +0000180 ValueState() : Data(0) {}
Ted Kremeneked900212008-02-05 18:17:58 +0000181
Ted Kremenekcba2e432008-02-05 19:35:18 +0000182 // Accessors.
Ted Kremeneked900212008-02-05 18:17:58 +0000183 ValueStateImpl* getImpl() const { return Data; }
Ted Kremenek174aea42008-02-05 18:51:06 +0000184
Ted Kremenekcba2e432008-02-05 19:35:18 +0000185 // Typedefs.
Ted Kremenek862d5bb2008-02-06 00:54:14 +0000186 typedef vstate::IntSetTy IntSetTy;
Ted Kremenekcba2e432008-02-05 19:35:18 +0000187 typedef vstate::VariableBindingsTy VariableBindingsTy;
188 typedef vstate::ConstantNotEqTy ConstantNotEqTy;
Ted Kremenek862d5bb2008-02-06 00:54:14 +0000189 typedef vstate::ConstantEqTy ConstantEqTy;
190
Ted Kremenekcba2e432008-02-05 19:35:18 +0000191 typedef llvm::SmallVector<ValueState,5> BufferTy;
Ted Kremenek174aea42008-02-05 18:51:06 +0000192
Ted Kremenek862d5bb2008-02-06 00:54:14 +0000193 // Queries.
194
195 bool isNotEqual(SymbolID sym, const llvm::APSInt& V) const;
196 const llvm::APSInt* getSymVal(SymbolID sym) const;
197
Ted Kremenek174aea42008-02-05 18:51:06 +0000198 // Iterators.
199
200 typedef VariableBindingsTy::iterator vb_iterator;
Ted Kremenekb80cbfe2008-02-05 18:19:15 +0000201 vb_iterator begin() { return Data->VariableBindings.begin(); }
202 vb_iterator end() { return Data->VariableBindings.end(); }
Ted Kremenek9153f732008-02-05 07:17:49 +0000203
Ted Kremeneked900212008-02-05 18:17:58 +0000204 // Profiling and equality testing.
205
Ted Kremenek9153f732008-02-05 07:17:49 +0000206 bool operator==(const ValueState& RHS) const {
207 return Data == RHS.Data;
208 }
209
210 static void Profile(llvm::FoldingSetNodeID& ID, const ValueState& V) {
211 ID.AddPointer(V.getImpl());
212 }
213
214 void Profile(llvm::FoldingSetNodeID& ID) const {
215 Profile(ID, *this);
216 }
Ted Kremenek9153f732008-02-05 07:17:49 +0000217};
218
219template<> struct GRTrait<ValueState> {
220 static inline void* toPtr(ValueState St) {
221 return reinterpret_cast<void*>(St.getImpl());
222 }
223 static inline ValueState toState(void* P) {
224 return ValueState(static_cast<ValueStateImpl*>(P));
225 }
226};
227
Ted Kremeneke070a1d2008-02-04 21:59:01 +0000228
229class ValueStateManager {
230public:
231 typedef ValueState StateTy;
232
233private:
Ted Kremenek862d5bb2008-02-06 00:54:14 +0000234 ValueState::IntSetTy::Factory ISetFactory;
Ted Kremenek9153f732008-02-05 07:17:49 +0000235 ValueState::VariableBindingsTy::Factory VBFactory;
Ted Kremenek174aea42008-02-05 18:51:06 +0000236 ValueState::ConstantNotEqTy::Factory CNEFactory;
Ted Kremenek862d5bb2008-02-06 00:54:14 +0000237 ValueState::ConstantEqTy::Factory CEFactory;
Ted Kremenek174aea42008-02-05 18:51:06 +0000238
239 /// StateSet - FoldingSet containing all the states created for analyzing
240 /// a particular function. This is used to unique states.
Ted Kremenek9153f732008-02-05 07:17:49 +0000241 llvm::FoldingSet<ValueStateImpl> StateSet;
Ted Kremeneke070a1d2008-02-04 21:59:01 +0000242
243 /// ValueMgr - Object that manages the data for all created RValues.
244 ValueManager ValMgr;
Ted Kremenek9153f732008-02-05 07:17:49 +0000245
Ted Kremeneke070a1d2008-02-04 21:59:01 +0000246 /// SymMgr - Object that manages the symbol information.
247 SymbolManager SymMgr;
Ted Kremenek9153f732008-02-05 07:17:49 +0000248
249 /// Alloc - A BumpPtrAllocator to allocate states.
250 llvm::BumpPtrAllocator& Alloc;
251
252 StateTy getPersistentState(const ValueState& St);
Ted Kremeneke070a1d2008-02-04 21:59:01 +0000253
254public:
Ted Kremenek9153f732008-02-05 07:17:49 +0000255 ValueStateManager(ASTContext& Ctx, llvm::BumpPtrAllocator& alloc)
256 : ValMgr(Ctx, alloc), Alloc(alloc) {}
Ted Kremeneke070a1d2008-02-04 21:59:01 +0000257
Ted Kremenek9153f732008-02-05 07:17:49 +0000258 StateTy getInitialState();
Ted Kremeneke070a1d2008-02-04 21:59:01 +0000259
260 ValueManager& getValueManager() { return ValMgr; }
261 SymbolManager& getSymbolManager() { return SymMgr; }
262
263 StateTy SetValue(StateTy St, Stmt* S, bool isBlkExpr, const RValue& V);
264 StateTy SetValue(StateTy St, const LValue& LV, const RValue& V);
265
Ted Kremenekf233d482008-02-05 00:26:40 +0000266 RValue GetValue(const StateTy& St, Stmt* S, bool* hasVal = NULL);
Ted Kremeneke070a1d2008-02-04 21:59:01 +0000267 RValue GetValue(const StateTy& St, const LValue& LV);
Ted Kremenekf233d482008-02-05 00:26:40 +0000268
Ted Kremeneke070a1d2008-02-04 21:59:01 +0000269 LValue GetLValue(const StateTy& St, Stmt* S);
Ted Kremenek9153f732008-02-05 07:17:49 +0000270
271 StateTy Add(StateTy St, VarBindKey K, const RValue& V);
272 StateTy Remove(StateTy St, VarBindKey K);
273 StateTy getPersistentState(const ValueStateImpl& Impl);
Ted Kremenek862d5bb2008-02-06 00:54:14 +0000274
275 StateTy AddEQ(StateTy St, SymbolID sym, const llvm::APSInt& V);
276 StateTy AddNE(StateTy St, SymbolID sym, const llvm::APSInt& V);
Ted Kremeneke070a1d2008-02-04 21:59:01 +0000277};
278
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000279} // end clang namespace
280
281//==------------------------------------------------------------------------==//
Ted Kremenek9153f732008-02-05 07:17:49 +0000282// Casting machinery to get cast<> and dyn_cast<> working with VarBindKey.
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000283//==------------------------------------------------------------------------==//
284
285namespace llvm {
286
287 template<> inline bool
Ted Kremenek9153f732008-02-05 07:17:49 +0000288 isa<clang::ValueDecl,clang::VarBindKey>(const clang::VarBindKey& V) {
289 return V.getKind() == clang::VarBindKey::IsDecl;
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000290 }
291
292 template<> inline bool
Ted Kremenek9153f732008-02-05 07:17:49 +0000293 isa<clang::Stmt,clang::VarBindKey>(const clang::VarBindKey& V) {
294 return ((unsigned) V.getKind()) < clang::VarBindKey::IsDecl;
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000295 }
296
Ted Kremenek9153f732008-02-05 07:17:49 +0000297 template<> struct cast_retty_impl<clang::ValueDecl,clang::VarBindKey> {
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000298 typedef const clang::ValueDecl* ret_type;
299 };
300
Ted Kremenek9153f732008-02-05 07:17:49 +0000301 template<> struct cast_retty_impl<clang::Stmt,clang::VarBindKey> {
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000302 typedef const clang::Stmt* ret_type;
303 };
304
Ted Kremenek9153f732008-02-05 07:17:49 +0000305 template<> struct simplify_type<clang::VarBindKey> {
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000306 typedef void* SimpleType;
Ted Kremenek9153f732008-02-05 07:17:49 +0000307 static inline SimpleType getSimplifiedValue(const clang::VarBindKey &V) {
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000308 return V.getPtr();
309 }
310 };
311} // end llvm namespace
312
313#endif