blob: 1e3730ff4b685d2e75e6ef1ac339e775c7c6b33d [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 Kremenekd70b62e2008-02-08 20:29:23 +000010// This files defines SymbolID, ExprBindKey, 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 Kremenekd70b62e2008-02-08 20:29:23 +000042/// ExprBindKey - 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 Kremenekd70b62e2008-02-08 20:29:23 +000044class ExprBindKey {
Ted Kremeneka90ccfe2008-01-31 19:34:24 +000045 uintptr_t Raw;
Ted Kremenekd70b62e2008-02-08 20:29:23 +000046 void operator=(const ExprBindKey& 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 {
Ted Kremeneka90ccfe2008-01-31 19:34:24 +000058 return reinterpret_cast<void*>(Raw & ~Mask);
59 }
60
Ted Kremenekd70b62e2008-02-08 20:29:23 +000061 ExprBindKey(const ValueDecl* VD)
Ted Kremeneka90ccfe2008-01-31 19:34:24 +000062 : Raw(reinterpret_cast<uintptr_t>(VD) | IsDecl) {
63 assert(VD && "ValueDecl cannot be NULL.");
64 }
65
Ted Kremenekd70b62e2008-02-08 20:29:23 +000066 ExprBindKey(Expr* E, bool isBlkExpr = false)
67 : Raw(reinterpret_cast<uintptr_t>(E) | (isBlkExpr ? IsBlkExpr : IsSubExpr)){
68 assert(E && "Tracked statement cannot be NULL.");
Ted Kremeneka90ccfe2008-01-31 19:34:24 +000069 }
70
Ted Kremeneka90ccfe2008-01-31 19:34:24 +000071 bool isSubExpr() const { return getKind() == IsSubExpr; }
72 bool isBlkExpr() const { return getKind() == IsBlkExpr; }
Ted Kremenekd70b62e2008-02-08 20:29:23 +000073
74
75
76
Ted Kremeneka90ccfe2008-01-31 19:34:24 +000077 bool isDecl() const { return getKind() == IsDecl; }
78 bool isStmt() const { return getKind() <= IsBlkExpr; }
79
80 inline void Profile(llvm::FoldingSetNodeID& ID) const {
Ted Kremenek071679d2008-02-08 19:08:13 +000081 ID.AddPointer(getPtr());
Ted Kremeneka90ccfe2008-01-31 19:34:24 +000082 }
83
Ted Kremenekd70b62e2008-02-08 20:29:23 +000084 inline bool operator==(const ExprBindKey& X) const {
Ted Kremenek071679d2008-02-08 19:08:13 +000085 return getPtr() == X.getPtr();
Ted Kremeneka90ccfe2008-01-31 19:34:24 +000086 }
87
Ted Kremenekd70b62e2008-02-08 20:29:23 +000088 inline bool operator!=(const ExprBindKey& X) const {
Ted Kremeneka90ccfe2008-01-31 19:34:24 +000089 return !operator==(X);
90 }
91
Ted Kremenekd70b62e2008-02-08 20:29:23 +000092 inline bool operator<(const ExprBindKey& X) const {
Ted Kremeneka90ccfe2008-01-31 19:34:24 +000093 return getPtr() < X.getPtr();
94 }
95};
96
97//===----------------------------------------------------------------------===//
98// ValueState - An ImmutableMap type Stmt*/Decl*/Symbols to RValues.
99//===----------------------------------------------------------------------===//
100
Ted Kremenek9153f732008-02-05 07:17:49 +0000101namespace vstate {
Ted Kremenek174aea42008-02-05 18:51:06 +0000102 typedef llvm::ImmutableSet<llvm::APSInt*> IntSetTy;
103
Ted Kremenekd70b62e2008-02-08 20:29:23 +0000104 typedef llvm::ImmutableMap<ExprBindKey,RValue> VarBindingsTy;
Ted Kremenek862d5bb2008-02-06 00:54:14 +0000105 typedef llvm::ImmutableMap<SymbolID,IntSetTy> ConstantNotEqTy;
106 typedef llvm::ImmutableMap<SymbolID,const llvm::APSInt*> ConstantEqTy;
Ted Kremenek9153f732008-02-05 07:17:49 +0000107}
Ted Kremenek6f886bd2008-02-05 18:24:17 +0000108
109/// ValueStateImpl - This class encapsulates the actual data values for
110/// for a "state" in our symbolic value tracking. It is intended to be
111/// used as a functional object; that is once it is created and made
112/// "persistent" in a FoldingSet its values will never change.
Ted Kremeneka40ba022008-02-06 02:50:36 +0000113class ValueStateImpl : public llvm::FoldingSetNode {
114private:
115 void operator=(const ValueStateImpl& R) const;
116
117public:
Ted Kremenek53c641a2008-02-08 03:02:48 +0000118 vstate::VarBindingsTy VarBindings;
Ted Kremenek174aea42008-02-05 18:51:06 +0000119 vstate::ConstantNotEqTy ConstantNotEq;
Ted Kremenek862d5bb2008-02-06 00:54:14 +0000120 vstate::ConstantEqTy ConstantEq;
Ted Kremenek9153f732008-02-05 07:17:49 +0000121
Ted Kremenek174aea42008-02-05 18:51:06 +0000122 /// This ctor is used when creating the first ValueStateImpl object.
Ted Kremenek53c641a2008-02-08 03:02:48 +0000123 ValueStateImpl(vstate::VarBindingsTy VB,
Ted Kremenek862d5bb2008-02-06 00:54:14 +0000124 vstate::ConstantNotEqTy CNE,
125 vstate::ConstantEqTy CE)
Ted Kremenek53c641a2008-02-08 03:02:48 +0000126 : VarBindings(VB), ConstantNotEq(CNE), ConstantEq(CE) {}
Ted Kremenek9153f732008-02-05 07:17:49 +0000127
Ted Kremenek174aea42008-02-05 18:51:06 +0000128 /// Copy ctor - We must explicitly define this or else the "Next" ptr
129 /// in FoldingSetNode will also get copied.
Ted Kremenek9153f732008-02-05 07:17:49 +0000130 ValueStateImpl(const ValueStateImpl& RHS)
Ted Kremenek6f886bd2008-02-05 18:24:17 +0000131 : llvm::FoldingSetNode(),
Ted Kremenek53c641a2008-02-08 03:02:48 +0000132 VarBindings(RHS.VarBindings),
Ted Kremenek862d5bb2008-02-06 00:54:14 +0000133 ConstantNotEq(RHS.ConstantNotEq),
134 ConstantEq(RHS.ConstantEq) {}
Ted Kremenek9153f732008-02-05 07:17:49 +0000135
Ted Kremeneka40ba022008-02-06 02:50:36 +0000136
137
Ted Kremenek174aea42008-02-05 18:51:06 +0000138 /// Profile - Profile the contents of a ValueStateImpl object for use
139 /// in a FoldingSet.
Ted Kremenek9153f732008-02-05 07:17:49 +0000140 static void Profile(llvm::FoldingSetNodeID& ID, const ValueStateImpl& V) {
Ted Kremenek53c641a2008-02-08 03:02:48 +0000141 V.VarBindings.Profile(ID);
Ted Kremenek862d5bb2008-02-06 00:54:14 +0000142 V.ConstantNotEq.Profile(ID);
143 V.ConstantEq.Profile(ID);
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000144 }
Ted Kremenek174aea42008-02-05 18:51:06 +0000145
146 /// Profile - Used to profile the contents of this object for inclusion
147 /// in a FoldingSet.
Ted Kremenek9153f732008-02-05 07:17:49 +0000148 void Profile(llvm::FoldingSetNodeID& ID) const {
149 Profile(ID, *this);
150 }
151
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000152};
153
Ted Kremenek6f886bd2008-02-05 18:24:17 +0000154/// ValueState - This class represents a "state" in our symbolic value
155/// tracking. It is really just a "smart pointer", wrapping a pointer
156/// to ValueStateImpl object. Making this class a smart pointer means that its
157/// size is always the size of a pointer, which allows easy conversion to
158/// void* when being handled by GREngine. It also forces us to unique states;
159/// consequently, a ValueStateImpl* with a specific address will always refer
160/// to the unique state with those values.
Ted Kremeneka40ba022008-02-06 02:50:36 +0000161class ValueState {
Ted Kremenek9153f732008-02-05 07:17:49 +0000162 ValueStateImpl* Data;
163public:
Ted Kremeneked900212008-02-05 18:17:58 +0000164 ValueState(ValueStateImpl* D) : Data(D) {}
Ted Kremeneka40ba022008-02-06 02:50:36 +0000165 ValueState() : Data(0) {}
Ted Kremeneked900212008-02-05 18:17:58 +0000166
Ted Kremenekcba2e432008-02-05 19:35:18 +0000167 // Accessors.
Ted Kremeneked900212008-02-05 18:17:58 +0000168 ValueStateImpl* getImpl() const { return Data; }
Ted Kremenek174aea42008-02-05 18:51:06 +0000169
Ted Kremenekcba2e432008-02-05 19:35:18 +0000170 // Typedefs.
Ted Kremenek862d5bb2008-02-06 00:54:14 +0000171 typedef vstate::IntSetTy IntSetTy;
Ted Kremenek53c641a2008-02-08 03:02:48 +0000172 typedef vstate::VarBindingsTy VarBindingsTy;
Ted Kremenekcba2e432008-02-05 19:35:18 +0000173 typedef vstate::ConstantNotEqTy ConstantNotEqTy;
Ted Kremenek862d5bb2008-02-06 00:54:14 +0000174 typedef vstate::ConstantEqTy ConstantEqTy;
175
Ted Kremenekcba2e432008-02-05 19:35:18 +0000176 typedef llvm::SmallVector<ValueState,5> BufferTy;
Ted Kremenek174aea42008-02-05 18:51:06 +0000177
Ted Kremenek862d5bb2008-02-06 00:54:14 +0000178 // Queries.
179
180 bool isNotEqual(SymbolID sym, const llvm::APSInt& V) const;
181 const llvm::APSInt* getSymVal(SymbolID sym) const;
182
Ted Kremenek174aea42008-02-05 18:51:06 +0000183 // Iterators.
184
Ted Kremenek53c641a2008-02-08 03:02:48 +0000185 typedef VarBindingsTy::iterator vb_iterator;
186 vb_iterator begin() { return Data->VarBindings.begin(); }
187 vb_iterator end() { return Data->VarBindings.end(); }
Ted Kremenek9153f732008-02-05 07:17:49 +0000188
Ted Kremeneked900212008-02-05 18:17:58 +0000189 // Profiling and equality testing.
190
Ted Kremenek9153f732008-02-05 07:17:49 +0000191 bool operator==(const ValueState& RHS) const {
192 return Data == RHS.Data;
193 }
194
195 static void Profile(llvm::FoldingSetNodeID& ID, const ValueState& V) {
196 ID.AddPointer(V.getImpl());
197 }
198
199 void Profile(llvm::FoldingSetNodeID& ID) const {
200 Profile(ID, *this);
201 }
Ted Kremenek9153f732008-02-05 07:17:49 +0000202};
203
204template<> struct GRTrait<ValueState> {
205 static inline void* toPtr(ValueState St) {
206 return reinterpret_cast<void*>(St.getImpl());
207 }
208 static inline ValueState toState(void* P) {
209 return ValueState(static_cast<ValueStateImpl*>(P));
210 }
211};
212
Ted Kremeneke070a1d2008-02-04 21:59:01 +0000213
214class ValueStateManager {
215public:
216 typedef ValueState StateTy;
217
218private:
Ted Kremenek862d5bb2008-02-06 00:54:14 +0000219 ValueState::IntSetTy::Factory ISetFactory;
Ted Kremenek53c641a2008-02-08 03:02:48 +0000220 ValueState::VarBindingsTy::Factory VBFactory;
Ted Kremenek174aea42008-02-05 18:51:06 +0000221 ValueState::ConstantNotEqTy::Factory CNEFactory;
Ted Kremenek862d5bb2008-02-06 00:54:14 +0000222 ValueState::ConstantEqTy::Factory CEFactory;
Ted Kremenek174aea42008-02-05 18:51:06 +0000223
224 /// StateSet - FoldingSet containing all the states created for analyzing
225 /// a particular function. This is used to unique states.
Ted Kremenek9153f732008-02-05 07:17:49 +0000226 llvm::FoldingSet<ValueStateImpl> StateSet;
Ted Kremeneke070a1d2008-02-04 21:59:01 +0000227
228 /// ValueMgr - Object that manages the data for all created RValues.
229 ValueManager ValMgr;
Ted Kremenek9153f732008-02-05 07:17:49 +0000230
Ted Kremeneke070a1d2008-02-04 21:59:01 +0000231 /// SymMgr - Object that manages the symbol information.
232 SymbolManager SymMgr;
Ted Kremenek9153f732008-02-05 07:17:49 +0000233
234 /// Alloc - A BumpPtrAllocator to allocate states.
235 llvm::BumpPtrAllocator& Alloc;
236
237 StateTy getPersistentState(const ValueState& St);
Ted Kremeneke070a1d2008-02-04 21:59:01 +0000238
239public:
Ted Kremenek9153f732008-02-05 07:17:49 +0000240 ValueStateManager(ASTContext& Ctx, llvm::BumpPtrAllocator& alloc)
241 : ValMgr(Ctx, alloc), Alloc(alloc) {}
Ted Kremeneke070a1d2008-02-04 21:59:01 +0000242
Ted Kremenek9153f732008-02-05 07:17:49 +0000243 StateTy getInitialState();
Ted Kremeneke070a1d2008-02-04 21:59:01 +0000244
245 ValueManager& getValueManager() { return ValMgr; }
246 SymbolManager& getSymbolManager() { return SymMgr; }
247
Ted Kremenekb87d9092008-02-08 19:17:19 +0000248 StateTy RemoveDeadBindings(StateTy St, Stmt* Loc,
249 const LiveVariables& Liveness);
250
Ted Kremenekd70b62e2008-02-08 20:29:23 +0000251 StateTy SetValue(StateTy St, Expr* S, bool isBlkExpr, const RValue& V);
Ted Kremeneke070a1d2008-02-04 21:59:01 +0000252 StateTy SetValue(StateTy St, const LValue& LV, const RValue& V);
253
Ted Kremenekd70b62e2008-02-08 20:29:23 +0000254 RValue GetValue(const StateTy& St, Expr* S, bool* hasVal = NULL);
Ted Kremenekb87d9092008-02-08 19:17:19 +0000255 RValue GetValue(const StateTy& St, const LValue& LV, QualType* T = NULL);
Ted Kremenekd70b62e2008-02-08 20:29:23 +0000256 LValue GetLValue(const StateTy& St, Expr* S);
Ted Kremenekb87d9092008-02-08 19:17:19 +0000257
258
259
Ted Kremenek9153f732008-02-05 07:17:49 +0000260
Ted Kremenekd70b62e2008-02-08 20:29:23 +0000261 StateTy Add(StateTy St, ExprBindKey K, const RValue& V);
262 StateTy Remove(StateTy St, ExprBindKey K);
Ted Kremenek9153f732008-02-05 07:17:49 +0000263 StateTy getPersistentState(const ValueStateImpl& Impl);
Ted Kremenek862d5bb2008-02-06 00:54:14 +0000264
265 StateTy AddEQ(StateTy St, SymbolID sym, const llvm::APSInt& V);
266 StateTy AddNE(StateTy St, SymbolID sym, const llvm::APSInt& V);
Ted Kremeneke070a1d2008-02-04 21:59:01 +0000267};
268
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000269} // end clang namespace
270
271//==------------------------------------------------------------------------==//
Ted Kremenekd70b62e2008-02-08 20:29:23 +0000272// Casting machinery to get cast<> and dyn_cast<> working with ExprBindKey.
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000273//==------------------------------------------------------------------------==//
274
275namespace llvm {
276
277 template<> inline bool
Ted Kremenekd70b62e2008-02-08 20:29:23 +0000278 isa<clang::ValueDecl,clang::ExprBindKey>(const clang::ExprBindKey& V) {
279 return V.getKind() == clang::ExprBindKey::IsDecl;
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000280 }
281
282 template<> inline bool
Ted Kremenekd70b62e2008-02-08 20:29:23 +0000283 isa<clang::Stmt,clang::ExprBindKey>(const clang::ExprBindKey& V) {
284 return ((unsigned) V.getKind()) < clang::ExprBindKey::IsDecl;
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000285 }
286
Ted Kremenekd70b62e2008-02-08 20:29:23 +0000287 template<> struct cast_retty_impl<clang::ValueDecl,clang::ExprBindKey> {
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000288 typedef const clang::ValueDecl* ret_type;
289 };
290
Ted Kremenekd70b62e2008-02-08 20:29:23 +0000291 template<> struct cast_retty_impl<clang::Stmt,clang::ExprBindKey> {
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000292 typedef const clang::Stmt* ret_type;
293 };
294
Ted Kremenekd70b62e2008-02-08 20:29:23 +0000295 template<> struct simplify_type<clang::ExprBindKey> {
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000296 typedef void* SimpleType;
Ted Kremenekd70b62e2008-02-08 20:29:23 +0000297 static inline SimpleType getSimplifiedValue(const clang::ExprBindKey &V) {
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000298 return V.getPtr();
299 }
300 };
301} // end llvm namespace
302
303#endif