blob: 3d7a2e6bef25ddfd24b5945829b1743b0e3147b5 [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 +000042class ExprBindKey {
Ted Kremeneka90ccfe2008-01-31 19:34:24 +000043 uintptr_t Raw;
Ted Kremenekd70b62e2008-02-08 20:29:23 +000044 void operator=(const ExprBindKey& RHS); // Do not implement.
Ted Kremeneka90ccfe2008-01-31 19:34:24 +000045
Ted Kremeneka90ccfe2008-01-31 19:34:24 +000046 inline void* getPtr() const {
Ted Kremeneka90ccfe2008-01-31 19:34:24 +000047 return reinterpret_cast<void*>(Raw & ~Mask);
48 }
49
Ted Kremenek016f52f2008-02-08 21:10:02 +000050public:
51 enum Kind { IsSubExpr=0x0, IsBlkExpr=0x1, Mask=0x1 };
Ted Kremeneka90ccfe2008-01-31 19:34:24 +000052
Ted Kremenek016f52f2008-02-08 21:10:02 +000053 inline Kind getKind() const {
54 return (Kind) (Raw & Mask);
55 }
56
57 inline Expr* getExpr() const {
58 return (Expr*) getPtr();
59 }
60
Ted Kremenekd70b62e2008-02-08 20:29:23 +000061 ExprBindKey(Expr* E, bool isBlkExpr = false)
62 : Raw(reinterpret_cast<uintptr_t>(E) | (isBlkExpr ? IsBlkExpr : IsSubExpr)){
63 assert(E && "Tracked statement cannot be NULL.");
Ted Kremeneka90ccfe2008-01-31 19:34:24 +000064 }
65
Ted Kremeneka90ccfe2008-01-31 19:34:24 +000066 bool isSubExpr() const { return getKind() == IsSubExpr; }
67 bool isBlkExpr() const { return getKind() == IsBlkExpr; }
Ted Kremenekd70b62e2008-02-08 20:29:23 +000068
Ted Kremeneka90ccfe2008-01-31 19:34:24 +000069 inline void Profile(llvm::FoldingSetNodeID& ID) const {
Ted Kremenek071679d2008-02-08 19:08:13 +000070 ID.AddPointer(getPtr());
Ted Kremeneka90ccfe2008-01-31 19:34:24 +000071 }
72
Ted Kremenekd70b62e2008-02-08 20:29:23 +000073 inline bool operator==(const ExprBindKey& X) const {
Ted Kremenek071679d2008-02-08 19:08:13 +000074 return getPtr() == X.getPtr();
Ted Kremeneka90ccfe2008-01-31 19:34:24 +000075 }
76
Ted Kremenekd70b62e2008-02-08 20:29:23 +000077 inline bool operator!=(const ExprBindKey& X) const {
Ted Kremeneka90ccfe2008-01-31 19:34:24 +000078 return !operator==(X);
79 }
80
Ted Kremenekd70b62e2008-02-08 20:29:23 +000081 inline bool operator<(const ExprBindKey& X) const {
Ted Kremeneka90ccfe2008-01-31 19:34:24 +000082 return getPtr() < X.getPtr();
83 }
84};
85
86//===----------------------------------------------------------------------===//
87// ValueState - An ImmutableMap type Stmt*/Decl*/Symbols to RValues.
88//===----------------------------------------------------------------------===//
89
Ted Kremenek9153f732008-02-05 07:17:49 +000090namespace vstate {
Ted Kremenek174aea42008-02-05 18:51:06 +000091 typedef llvm::ImmutableSet<llvm::APSInt*> IntSetTy;
92
Ted Kremenek016f52f2008-02-08 21:10:02 +000093 typedef llvm::ImmutableMap<ExprBindKey,RValue> ExprBindingsTy;
94 typedef llvm::ImmutableMap<VarDecl*,RValue> VarBindingsTy;
Ted Kremenek862d5bb2008-02-06 00:54:14 +000095 typedef llvm::ImmutableMap<SymbolID,IntSetTy> ConstantNotEqTy;
96 typedef llvm::ImmutableMap<SymbolID,const llvm::APSInt*> ConstantEqTy;
Ted Kremenek9153f732008-02-05 07:17:49 +000097}
Ted Kremenek6f886bd2008-02-05 18:24:17 +000098
99/// ValueStateImpl - This class encapsulates the actual data values for
100/// for a "state" in our symbolic value tracking. It is intended to be
101/// used as a functional object; that is once it is created and made
102/// "persistent" in a FoldingSet its values will never change.
Ted Kremeneka40ba022008-02-06 02:50:36 +0000103class ValueStateImpl : public llvm::FoldingSetNode {
104private:
105 void operator=(const ValueStateImpl& R) const;
106
107public:
Ted Kremenek016f52f2008-02-08 21:10:02 +0000108 vstate::ExprBindingsTy ExprBindings;
Ted Kremenek53c641a2008-02-08 03:02:48 +0000109 vstate::VarBindingsTy VarBindings;
Ted Kremenek174aea42008-02-05 18:51:06 +0000110 vstate::ConstantNotEqTy ConstantNotEq;
Ted Kremenek862d5bb2008-02-06 00:54:14 +0000111 vstate::ConstantEqTy ConstantEq;
Ted Kremenek9153f732008-02-05 07:17:49 +0000112
Ted Kremenek174aea42008-02-05 18:51:06 +0000113 /// This ctor is used when creating the first ValueStateImpl object.
Ted Kremenek016f52f2008-02-08 21:10:02 +0000114 ValueStateImpl(vstate::ExprBindingsTy EB,
115 vstate::VarBindingsTy VB,
Ted Kremenek862d5bb2008-02-06 00:54:14 +0000116 vstate::ConstantNotEqTy CNE,
117 vstate::ConstantEqTy CE)
Ted Kremenek016f52f2008-02-08 21:10:02 +0000118 : ExprBindings(EB), VarBindings(VB), ConstantNotEq(CNE), ConstantEq(CE) {}
Ted Kremenek9153f732008-02-05 07:17:49 +0000119
Ted Kremenek174aea42008-02-05 18:51:06 +0000120 /// Copy ctor - We must explicitly define this or else the "Next" ptr
121 /// in FoldingSetNode will also get copied.
Ted Kremenek9153f732008-02-05 07:17:49 +0000122 ValueStateImpl(const ValueStateImpl& RHS)
Ted Kremenek6f886bd2008-02-05 18:24:17 +0000123 : llvm::FoldingSetNode(),
Ted Kremenek016f52f2008-02-08 21:10:02 +0000124 ExprBindings(RHS.ExprBindings),
Ted Kremenek53c641a2008-02-08 03:02:48 +0000125 VarBindings(RHS.VarBindings),
Ted Kremenek862d5bb2008-02-06 00:54:14 +0000126 ConstantNotEq(RHS.ConstantNotEq),
127 ConstantEq(RHS.ConstantEq) {}
Ted Kremenek9153f732008-02-05 07:17:49 +0000128
Ted Kremeneka40ba022008-02-06 02:50:36 +0000129
130
Ted Kremenek174aea42008-02-05 18:51:06 +0000131 /// Profile - Profile the contents of a ValueStateImpl object for use
132 /// in a FoldingSet.
Ted Kremenek9153f732008-02-05 07:17:49 +0000133 static void Profile(llvm::FoldingSetNodeID& ID, const ValueStateImpl& V) {
Ted Kremenek016f52f2008-02-08 21:10:02 +0000134 V.ExprBindings.Profile(ID);
Ted Kremenek53c641a2008-02-08 03:02:48 +0000135 V.VarBindings.Profile(ID);
Ted Kremenek862d5bb2008-02-06 00:54:14 +0000136 V.ConstantNotEq.Profile(ID);
137 V.ConstantEq.Profile(ID);
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000138 }
Ted Kremenek174aea42008-02-05 18:51:06 +0000139
140 /// Profile - Used to profile the contents of this object for inclusion
141 /// in a FoldingSet.
Ted Kremenek9153f732008-02-05 07:17:49 +0000142 void Profile(llvm::FoldingSetNodeID& ID) const {
143 Profile(ID, *this);
144 }
145
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000146};
147
Ted Kremenek6f886bd2008-02-05 18:24:17 +0000148/// ValueState - This class represents a "state" in our symbolic value
149/// tracking. It is really just a "smart pointer", wrapping a pointer
150/// to ValueStateImpl object. Making this class a smart pointer means that its
151/// size is always the size of a pointer, which allows easy conversion to
152/// void* when being handled by GREngine. It also forces us to unique states;
153/// consequently, a ValueStateImpl* with a specific address will always refer
154/// to the unique state with those values.
Ted Kremeneka40ba022008-02-06 02:50:36 +0000155class ValueState {
Ted Kremenek9153f732008-02-05 07:17:49 +0000156 ValueStateImpl* Data;
157public:
Ted Kremeneked900212008-02-05 18:17:58 +0000158 ValueState(ValueStateImpl* D) : Data(D) {}
Ted Kremeneka40ba022008-02-06 02:50:36 +0000159 ValueState() : Data(0) {}
Ted Kremeneked900212008-02-05 18:17:58 +0000160
Ted Kremenekcba2e432008-02-05 19:35:18 +0000161 // Accessors.
Ted Kremeneked900212008-02-05 18:17:58 +0000162 ValueStateImpl* getImpl() const { return Data; }
Ted Kremenek174aea42008-02-05 18:51:06 +0000163
Ted Kremenekcba2e432008-02-05 19:35:18 +0000164 // Typedefs.
Ted Kremenek862d5bb2008-02-06 00:54:14 +0000165 typedef vstate::IntSetTy IntSetTy;
Ted Kremenek016f52f2008-02-08 21:10:02 +0000166 typedef vstate::ExprBindingsTy ExprBindingsTy;
167 typedef vstate::VarBindingsTy VarBindingsTy;
Ted Kremenekcba2e432008-02-05 19:35:18 +0000168 typedef vstate::ConstantNotEqTy ConstantNotEqTy;
Ted Kremenek862d5bb2008-02-06 00:54:14 +0000169 typedef vstate::ConstantEqTy ConstantEqTy;
170
Ted Kremenekcba2e432008-02-05 19:35:18 +0000171 typedef llvm::SmallVector<ValueState,5> BufferTy;
Ted Kremenek174aea42008-02-05 18:51:06 +0000172
Ted Kremenek862d5bb2008-02-06 00:54:14 +0000173 // Queries.
174
175 bool isNotEqual(SymbolID sym, const llvm::APSInt& V) const;
176 const llvm::APSInt* getSymVal(SymbolID sym) const;
177
Ted Kremenek174aea42008-02-05 18:51:06 +0000178 // Iterators.
179
Ted Kremenek53c641a2008-02-08 03:02:48 +0000180 typedef VarBindingsTy::iterator vb_iterator;
Ted Kremenek016f52f2008-02-08 21:10:02 +0000181 vb_iterator vb_begin() { return Data->VarBindings.begin(); }
182 vb_iterator vb_end() { return Data->VarBindings.end(); }
183
184 typedef ExprBindingsTy::iterator eb_iterator;
185 eb_iterator eb_begin() { return Data->ExprBindings.begin(); }
186 eb_iterator eb_end() { return Data->ExprBindings.end(); }
Ted Kremenek9153f732008-02-05 07:17:49 +0000187
Ted Kremeneked900212008-02-05 18:17:58 +0000188 // Profiling and equality testing.
189
Ted Kremenek9153f732008-02-05 07:17:49 +0000190 bool operator==(const ValueState& RHS) const {
191 return Data == RHS.Data;
192 }
193
194 static void Profile(llvm::FoldingSetNodeID& ID, const ValueState& V) {
195 ID.AddPointer(V.getImpl());
196 }
197
198 void Profile(llvm::FoldingSetNodeID& ID) const {
199 Profile(ID, *this);
200 }
Ted Kremenek9153f732008-02-05 07:17:49 +0000201};
202
203template<> struct GRTrait<ValueState> {
204 static inline void* toPtr(ValueState St) {
205 return reinterpret_cast<void*>(St.getImpl());
206 }
207 static inline ValueState toState(void* P) {
208 return ValueState(static_cast<ValueStateImpl*>(P));
209 }
210};
211
Ted Kremeneke070a1d2008-02-04 21:59:01 +0000212
213class ValueStateManager {
214public:
215 typedef ValueState StateTy;
216
217private:
Ted Kremenek862d5bb2008-02-06 00:54:14 +0000218 ValueState::IntSetTy::Factory ISetFactory;
Ted Kremenek016f52f2008-02-08 21:10:02 +0000219 ValueState::ExprBindingsTy::Factory EXFactory;
220 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
Ted Kremenekd70b62e2008-02-08 20:29:23 +0000258 StateTy Add(StateTy St, ExprBindKey K, const RValue& V);
259 StateTy Remove(StateTy St, ExprBindKey K);
Ted Kremenek016f52f2008-02-08 21:10:02 +0000260
261 StateTy Add(StateTy St, VarDecl* D, const RValue& V);
262 StateTy Remove(StateTy St, VarDecl* D);
263
Ted Kremenek9153f732008-02-05 07:17:49 +0000264 StateTy getPersistentState(const ValueStateImpl& Impl);
Ted Kremenek862d5bb2008-02-06 00:54:14 +0000265
266 StateTy AddEQ(StateTy St, SymbolID sym, const llvm::APSInt& V);
267 StateTy AddNE(StateTy St, SymbolID sym, const llvm::APSInt& V);
Ted Kremeneke070a1d2008-02-04 21:59:01 +0000268};
269
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000270} // end clang namespace
271
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000272#endif