blob: f431d1e441720cb67ce1d49a0c6c4acc11706311 [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 {
Ted Kremeneka90ccfe2008-01-31 19:34:24 +000058 return reinterpret_cast<void*>(Raw & ~Mask);
59 }
60
Ted Kremenek9153f732008-02-05 07:17:49 +000061 VarBindKey(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 Kremenek9153f732008-02-05 07:17:49 +000066 VarBindKey(Stmt* S, bool isBlkExpr = false)
Ted Kremeneka90ccfe2008-01-31 19:34:24 +000067 : Raw(reinterpret_cast<uintptr_t>(S) | (isBlkExpr ? IsBlkExpr : IsSubExpr)){
68 assert(S && "Tracked statement cannot be NULL.");
69 }
70
Ted Kremeneka90ccfe2008-01-31 19:34:24 +000071 bool isSubExpr() const { return getKind() == IsSubExpr; }
72 bool isBlkExpr() const { return getKind() == IsBlkExpr; }
73 bool isDecl() const { return getKind() == IsDecl; }
74 bool isStmt() const { return getKind() <= IsBlkExpr; }
75
76 inline void Profile(llvm::FoldingSetNodeID& ID) const {
Ted Kremenek071679d2008-02-08 19:08:13 +000077 ID.AddPointer(getPtr());
Ted Kremeneka90ccfe2008-01-31 19:34:24 +000078 }
79
Ted Kremenek9153f732008-02-05 07:17:49 +000080 inline bool operator==(const VarBindKey& X) const {
Ted Kremenek071679d2008-02-08 19:08:13 +000081 return getPtr() == X.getPtr();
Ted Kremeneka90ccfe2008-01-31 19:34:24 +000082 }
83
Ted Kremenek9153f732008-02-05 07:17:49 +000084 inline bool operator!=(const VarBindKey& X) const {
Ted Kremeneka90ccfe2008-01-31 19:34:24 +000085 return !operator==(X);
86 }
87
Ted Kremenek9153f732008-02-05 07:17:49 +000088 inline bool operator<(const VarBindKey& X) const {
Ted Kremeneka90ccfe2008-01-31 19:34:24 +000089 return getPtr() < X.getPtr();
90 }
91};
92
93//===----------------------------------------------------------------------===//
94// ValueState - An ImmutableMap type Stmt*/Decl*/Symbols to RValues.
95//===----------------------------------------------------------------------===//
96
Ted Kremenek9153f732008-02-05 07:17:49 +000097namespace vstate {
Ted Kremenek174aea42008-02-05 18:51:06 +000098 typedef llvm::ImmutableSet<llvm::APSInt*> IntSetTy;
99
Ted Kremenek53c641a2008-02-08 03:02:48 +0000100 typedef llvm::ImmutableMap<VarBindKey,RValue> VarBindingsTy;
Ted Kremenek862d5bb2008-02-06 00:54:14 +0000101 typedef llvm::ImmutableMap<SymbolID,IntSetTy> ConstantNotEqTy;
102 typedef llvm::ImmutableMap<SymbolID,const llvm::APSInt*> ConstantEqTy;
Ted Kremenek9153f732008-02-05 07:17:49 +0000103}
Ted Kremenek6f886bd2008-02-05 18:24:17 +0000104
105/// ValueStateImpl - This class encapsulates the actual data values for
106/// for a "state" in our symbolic value tracking. It is intended to be
107/// used as a functional object; that is once it is created and made
108/// "persistent" in a FoldingSet its values will never change.
Ted Kremeneka40ba022008-02-06 02:50:36 +0000109class ValueStateImpl : public llvm::FoldingSetNode {
110private:
111 void operator=(const ValueStateImpl& R) const;
112
113public:
Ted Kremenek53c641a2008-02-08 03:02:48 +0000114 vstate::VarBindingsTy VarBindings;
Ted Kremenek174aea42008-02-05 18:51:06 +0000115 vstate::ConstantNotEqTy ConstantNotEq;
Ted Kremenek862d5bb2008-02-06 00:54:14 +0000116 vstate::ConstantEqTy ConstantEq;
Ted Kremenek9153f732008-02-05 07:17:49 +0000117
Ted Kremenek174aea42008-02-05 18:51:06 +0000118 /// This ctor is used when creating the first ValueStateImpl object.
Ted Kremenek53c641a2008-02-08 03:02:48 +0000119 ValueStateImpl(vstate::VarBindingsTy VB,
Ted Kremenek862d5bb2008-02-06 00:54:14 +0000120 vstate::ConstantNotEqTy CNE,
121 vstate::ConstantEqTy CE)
Ted Kremenek53c641a2008-02-08 03:02:48 +0000122 : VarBindings(VB), ConstantNotEq(CNE), ConstantEq(CE) {}
Ted Kremenek9153f732008-02-05 07:17:49 +0000123
Ted Kremenek174aea42008-02-05 18:51:06 +0000124 /// Copy ctor - We must explicitly define this or else the "Next" ptr
125 /// in FoldingSetNode will also get copied.
Ted Kremenek9153f732008-02-05 07:17:49 +0000126 ValueStateImpl(const ValueStateImpl& RHS)
Ted Kremenek6f886bd2008-02-05 18:24:17 +0000127 : llvm::FoldingSetNode(),
Ted Kremenek53c641a2008-02-08 03:02:48 +0000128 VarBindings(RHS.VarBindings),
Ted Kremenek862d5bb2008-02-06 00:54:14 +0000129 ConstantNotEq(RHS.ConstantNotEq),
130 ConstantEq(RHS.ConstantEq) {}
Ted Kremenek9153f732008-02-05 07:17:49 +0000131
Ted Kremeneka40ba022008-02-06 02:50:36 +0000132
133
Ted Kremenek174aea42008-02-05 18:51:06 +0000134 /// Profile - Profile the contents of a ValueStateImpl object for use
135 /// in a FoldingSet.
Ted Kremenek9153f732008-02-05 07:17:49 +0000136 static void Profile(llvm::FoldingSetNodeID& ID, const ValueStateImpl& V) {
Ted Kremenek53c641a2008-02-08 03:02:48 +0000137 V.VarBindings.Profile(ID);
Ted Kremenek862d5bb2008-02-06 00:54:14 +0000138 V.ConstantNotEq.Profile(ID);
139 V.ConstantEq.Profile(ID);
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000140 }
Ted Kremenek174aea42008-02-05 18:51:06 +0000141
142 /// Profile - Used to profile the contents of this object for inclusion
143 /// in a FoldingSet.
Ted Kremenek9153f732008-02-05 07:17:49 +0000144 void Profile(llvm::FoldingSetNodeID& ID) const {
145 Profile(ID, *this);
146 }
147
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000148};
149
Ted Kremenek6f886bd2008-02-05 18:24:17 +0000150/// ValueState - This class represents a "state" in our symbolic value
151/// tracking. It is really just a "smart pointer", wrapping a pointer
152/// to ValueStateImpl object. Making this class a smart pointer means that its
153/// size is always the size of a pointer, which allows easy conversion to
154/// void* when being handled by GREngine. It also forces us to unique states;
155/// consequently, a ValueStateImpl* with a specific address will always refer
156/// to the unique state with those values.
Ted Kremeneka40ba022008-02-06 02:50:36 +0000157class ValueState {
Ted Kremenek9153f732008-02-05 07:17:49 +0000158 ValueStateImpl* Data;
159public:
Ted Kremeneked900212008-02-05 18:17:58 +0000160 ValueState(ValueStateImpl* D) : Data(D) {}
Ted Kremeneka40ba022008-02-06 02:50:36 +0000161 ValueState() : Data(0) {}
Ted Kremeneked900212008-02-05 18:17:58 +0000162
Ted Kremenekcba2e432008-02-05 19:35:18 +0000163 // Accessors.
Ted Kremeneked900212008-02-05 18:17:58 +0000164 ValueStateImpl* getImpl() const { return Data; }
Ted Kremenek174aea42008-02-05 18:51:06 +0000165
Ted Kremenekcba2e432008-02-05 19:35:18 +0000166 // Typedefs.
Ted Kremenek862d5bb2008-02-06 00:54:14 +0000167 typedef vstate::IntSetTy IntSetTy;
Ted Kremenek53c641a2008-02-08 03:02:48 +0000168 typedef vstate::VarBindingsTy VarBindingsTy;
Ted Kremenekcba2e432008-02-05 19:35:18 +0000169 typedef vstate::ConstantNotEqTy ConstantNotEqTy;
Ted Kremenek862d5bb2008-02-06 00:54:14 +0000170 typedef vstate::ConstantEqTy ConstantEqTy;
171
Ted Kremenekcba2e432008-02-05 19:35:18 +0000172 typedef llvm::SmallVector<ValueState,5> BufferTy;
Ted Kremenek174aea42008-02-05 18:51:06 +0000173
Ted Kremenek862d5bb2008-02-06 00:54:14 +0000174 // Queries.
175
176 bool isNotEqual(SymbolID sym, const llvm::APSInt& V) const;
177 const llvm::APSInt* getSymVal(SymbolID sym) const;
178
Ted Kremenek174aea42008-02-05 18:51:06 +0000179 // Iterators.
180
Ted Kremenek53c641a2008-02-08 03:02:48 +0000181 typedef VarBindingsTy::iterator vb_iterator;
182 vb_iterator begin() { return Data->VarBindings.begin(); }
183 vb_iterator end() { return Data->VarBindings.end(); }
Ted Kremenek9153f732008-02-05 07:17:49 +0000184
Ted Kremeneked900212008-02-05 18:17:58 +0000185 // Profiling and equality testing.
186
Ted Kremenek9153f732008-02-05 07:17:49 +0000187 bool operator==(const ValueState& RHS) const {
188 return Data == RHS.Data;
189 }
190
191 static void Profile(llvm::FoldingSetNodeID& ID, const ValueState& V) {
192 ID.AddPointer(V.getImpl());
193 }
194
195 void Profile(llvm::FoldingSetNodeID& ID) const {
196 Profile(ID, *this);
197 }
Ted Kremenek9153f732008-02-05 07:17:49 +0000198};
199
200template<> struct GRTrait<ValueState> {
201 static inline void* toPtr(ValueState St) {
202 return reinterpret_cast<void*>(St.getImpl());
203 }
204 static inline ValueState toState(void* P) {
205 return ValueState(static_cast<ValueStateImpl*>(P));
206 }
207};
208
Ted Kremeneke070a1d2008-02-04 21:59:01 +0000209
210class ValueStateManager {
211public:
212 typedef ValueState StateTy;
213
214private:
Ted Kremenek862d5bb2008-02-06 00:54:14 +0000215 ValueState::IntSetTy::Factory ISetFactory;
Ted Kremenek53c641a2008-02-08 03:02:48 +0000216 ValueState::VarBindingsTy::Factory VBFactory;
Ted Kremenek174aea42008-02-05 18:51:06 +0000217 ValueState::ConstantNotEqTy::Factory CNEFactory;
Ted Kremenek862d5bb2008-02-06 00:54:14 +0000218 ValueState::ConstantEqTy::Factory CEFactory;
Ted Kremenek174aea42008-02-05 18:51:06 +0000219
220 /// StateSet - FoldingSet containing all the states created for analyzing
221 /// a particular function. This is used to unique states.
Ted Kremenek9153f732008-02-05 07:17:49 +0000222 llvm::FoldingSet<ValueStateImpl> StateSet;
Ted Kremeneke070a1d2008-02-04 21:59:01 +0000223
224 /// ValueMgr - Object that manages the data for all created RValues.
225 ValueManager ValMgr;
Ted Kremenek9153f732008-02-05 07:17:49 +0000226
Ted Kremeneke070a1d2008-02-04 21:59:01 +0000227 /// SymMgr - Object that manages the symbol information.
228 SymbolManager SymMgr;
Ted Kremenek9153f732008-02-05 07:17:49 +0000229
230 /// Alloc - A BumpPtrAllocator to allocate states.
231 llvm::BumpPtrAllocator& Alloc;
232
233 StateTy getPersistentState(const ValueState& St);
Ted Kremeneke070a1d2008-02-04 21:59:01 +0000234
235public:
Ted Kremenek9153f732008-02-05 07:17:49 +0000236 ValueStateManager(ASTContext& Ctx, llvm::BumpPtrAllocator& alloc)
237 : ValMgr(Ctx, alloc), Alloc(alloc) {}
Ted Kremeneke070a1d2008-02-04 21:59:01 +0000238
Ted Kremenek9153f732008-02-05 07:17:49 +0000239 StateTy getInitialState();
Ted Kremeneke070a1d2008-02-04 21:59:01 +0000240
241 ValueManager& getValueManager() { return ValMgr; }
242 SymbolManager& getSymbolManager() { return SymMgr; }
243
Ted Kremenekb87d9092008-02-08 19:17:19 +0000244 StateTy RemoveDeadBindings(StateTy St, Stmt* Loc,
245 const LiveVariables& Liveness);
246
Ted Kremeneke070a1d2008-02-04 21:59:01 +0000247 StateTy SetValue(StateTy St, Stmt* S, bool isBlkExpr, const RValue& V);
248 StateTy SetValue(StateTy St, const LValue& LV, const RValue& V);
249
Ted Kremenekf233d482008-02-05 00:26:40 +0000250 RValue GetValue(const StateTy& St, Stmt* S, bool* hasVal = NULL);
Ted Kremenekb87d9092008-02-08 19:17:19 +0000251 RValue GetValue(const StateTy& St, const LValue& LV, QualType* T = NULL);
Ted Kremeneke070a1d2008-02-04 21:59:01 +0000252 LValue GetLValue(const StateTy& St, Stmt* S);
Ted Kremenekb87d9092008-02-08 19:17:19 +0000253
254
255
Ted Kremenek9153f732008-02-05 07:17:49 +0000256
257 StateTy Add(StateTy St, VarBindKey K, const RValue& V);
258 StateTy Remove(StateTy St, VarBindKey K);
259 StateTy getPersistentState(const ValueStateImpl& Impl);
Ted Kremenek862d5bb2008-02-06 00:54:14 +0000260
261 StateTy AddEQ(StateTy St, SymbolID sym, const llvm::APSInt& V);
262 StateTy AddNE(StateTy St, SymbolID sym, const llvm::APSInt& V);
Ted Kremeneke070a1d2008-02-04 21:59:01 +0000263};
264
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000265} // end clang namespace
266
267//==------------------------------------------------------------------------==//
Ted Kremenek9153f732008-02-05 07:17:49 +0000268// Casting machinery to get cast<> and dyn_cast<> working with VarBindKey.
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000269//==------------------------------------------------------------------------==//
270
271namespace llvm {
272
273 template<> inline bool
Ted Kremenek9153f732008-02-05 07:17:49 +0000274 isa<clang::ValueDecl,clang::VarBindKey>(const clang::VarBindKey& V) {
275 return V.getKind() == clang::VarBindKey::IsDecl;
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000276 }
277
278 template<> inline bool
Ted Kremenek9153f732008-02-05 07:17:49 +0000279 isa<clang::Stmt,clang::VarBindKey>(const clang::VarBindKey& V) {
280 return ((unsigned) V.getKind()) < clang::VarBindKey::IsDecl;
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000281 }
282
Ted Kremenek9153f732008-02-05 07:17:49 +0000283 template<> struct cast_retty_impl<clang::ValueDecl,clang::VarBindKey> {
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000284 typedef const clang::ValueDecl* ret_type;
285 };
286
Ted Kremenek9153f732008-02-05 07:17:49 +0000287 template<> struct cast_retty_impl<clang::Stmt,clang::VarBindKey> {
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000288 typedef const clang::Stmt* ret_type;
289 };
290
Ted Kremenek9153f732008-02-05 07:17:49 +0000291 template<> struct simplify_type<clang::VarBindKey> {
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000292 typedef void* SimpleType;
Ted Kremenek9153f732008-02-05 07:17:49 +0000293 static inline SimpleType getSimplifiedValue(const clang::VarBindKey &V) {
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000294 return V.getPtr();
295 }
296 };
297} // end llvm namespace
298
299#endif