blob: 424b832258e7f46044da986ad257c2658fdbe2a3 [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
Ted Kremenekcc409b72008-02-14 17:30:51 +000019#include "clang/Analysis/PathSensitive/RValues.h"
Ted Kremenek4d4dd852008-02-13 17:41:41 +000020#include "clang/Analysis/PathSensitive/GRCoreEngine.h"
Ted Kremeneka90ccfe2008-01-31 19:34:24 +000021#include "clang/AST/Expr.h"
22#include "clang/AST/Decl.h"
23#include "clang/AST/ASTContext.h"
24#include "clang/Analysis/Analyses/LiveVariables.h"
25
26#include "llvm/Support/Casting.h"
27#include "llvm/Support/DataTypes.h"
28#include "llvm/ADT/APSInt.h"
29#include "llvm/ADT/FoldingSet.h"
30#include "llvm/ADT/ImmutableMap.h"
31#include "llvm/ADT/SmallVector.h"
32#include "llvm/ADT/SmallPtrSet.h"
33#include "llvm/Support/Allocator.h"
34#include "llvm/Support/Compiler.h"
35#include "llvm/Support/Streams.h"
36
37#include <functional>
38
Ted Kremeneke7d22112008-02-11 19:21:59 +000039namespace clang {
Ted Kremeneka90ccfe2008-01-31 19:34:24 +000040
41//===----------------------------------------------------------------------===//
Ted Kremenekaa1c4e52008-02-21 18:02:17 +000042// ValueState - An ImmutableMap type Stmt*/Decl*/Symbols to RVals.
Ted Kremeneka90ccfe2008-01-31 19:34:24 +000043//===----------------------------------------------------------------------===//
44
Ted Kremenek9153f732008-02-05 07:17:49 +000045namespace vstate {
Ted Kremenek174aea42008-02-05 18:51:06 +000046 typedef llvm::ImmutableSet<llvm::APSInt*> IntSetTy;
47
Ted Kremenekaa1c4e52008-02-21 18:02:17 +000048 typedef llvm::ImmutableMap<Expr*,RVal> ExprBindingsTy;
49 typedef llvm::ImmutableMap<VarDecl*,RVal> VarBindingsTy;
50 typedef llvm::ImmutableMap<SymbolID,IntSetTy> ConstNotEqTy;
51 typedef llvm::ImmutableMap<SymbolID,const llvm::APSInt*> ConstEqTy;
Ted Kremenek9153f732008-02-05 07:17:49 +000052}
Ted Kremenek6f886bd2008-02-05 18:24:17 +000053
54/// ValueStateImpl - This class encapsulates the actual data values for
55/// for a "state" in our symbolic value tracking. It is intended to be
56/// used as a functional object; that is once it is created and made
57/// "persistent" in a FoldingSet its values will never change.
Ted Kremeneka40ba022008-02-06 02:50:36 +000058class ValueStateImpl : public llvm::FoldingSetNode {
59private:
60 void operator=(const ValueStateImpl& R) const;
61
62public:
Ted Kremeneke7d22112008-02-11 19:21:59 +000063 vstate::ExprBindingsTy SubExprBindings;
64 vstate::ExprBindingsTy BlockExprBindings;
Ted Kremenek53c641a2008-02-08 03:02:48 +000065 vstate::VarBindingsTy VarBindings;
Ted Kremenekaa1c4e52008-02-21 18:02:17 +000066 vstate::ConstNotEqTy ConstNotEq;
67 vstate::ConstEqTy ConstEq;
Ted Kremenek9153f732008-02-05 07:17:49 +000068
Ted Kremenek174aea42008-02-05 18:51:06 +000069 /// This ctor is used when creating the first ValueStateImpl object.
Ted Kremenekaa1c4e52008-02-21 18:02:17 +000070 ValueStateImpl(vstate::ExprBindingsTy EB, vstate::VarBindingsTy VB,
71 vstate::ConstNotEqTy CNE, vstate::ConstEqTy CE)
Ted Kremeneke7d22112008-02-11 19:21:59 +000072 : SubExprBindings(EB),
73 BlockExprBindings(EB),
74 VarBindings(VB),
Ted Kremenekaa1c4e52008-02-21 18:02:17 +000075 ConstNotEq(CNE),
76 ConstEq(CE) {}
Ted Kremenek9153f732008-02-05 07:17:49 +000077
Ted Kremenek174aea42008-02-05 18:51:06 +000078 /// Copy ctor - We must explicitly define this or else the "Next" ptr
79 /// in FoldingSetNode will also get copied.
Ted Kremenek9153f732008-02-05 07:17:49 +000080 ValueStateImpl(const ValueStateImpl& RHS)
Ted Kremenek6f886bd2008-02-05 18:24:17 +000081 : llvm::FoldingSetNode(),
Ted Kremeneke7d22112008-02-11 19:21:59 +000082 SubExprBindings(RHS.SubExprBindings),
83 BlockExprBindings(RHS.BlockExprBindings),
Ted Kremenek53c641a2008-02-08 03:02:48 +000084 VarBindings(RHS.VarBindings),
Ted Kremenekaa1c4e52008-02-21 18:02:17 +000085 ConstNotEq(RHS.ConstNotEq),
86 ConstEq(RHS.ConstEq) {}
Ted Kremeneka40ba022008-02-06 02:50:36 +000087
Ted Kremenek174aea42008-02-05 18:51:06 +000088 /// Profile - Profile the contents of a ValueStateImpl object for use
89 /// in a FoldingSet.
Ted Kremenek9153f732008-02-05 07:17:49 +000090 static void Profile(llvm::FoldingSetNodeID& ID, const ValueStateImpl& V) {
Ted Kremeneke7d22112008-02-11 19:21:59 +000091 V.SubExprBindings.Profile(ID);
92 V.BlockExprBindings.Profile(ID);
Ted Kremenek53c641a2008-02-08 03:02:48 +000093 V.VarBindings.Profile(ID);
Ted Kremenekaa1c4e52008-02-21 18:02:17 +000094 V.ConstNotEq.Profile(ID);
95 V.ConstEq.Profile(ID);
Ted Kremeneka90ccfe2008-01-31 19:34:24 +000096 }
Ted Kremenek174aea42008-02-05 18:51:06 +000097
98 /// Profile - Used to profile the contents of this object for inclusion
99 /// in a FoldingSet.
Ted Kremenek9153f732008-02-05 07:17:49 +0000100 void Profile(llvm::FoldingSetNodeID& ID) const {
101 Profile(ID, *this);
102 }
103
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000104};
105
Ted Kremenek6f886bd2008-02-05 18:24:17 +0000106/// ValueState - This class represents a "state" in our symbolic value
107/// tracking. It is really just a "smart pointer", wrapping a pointer
108/// to ValueStateImpl object. Making this class a smart pointer means that its
109/// size is always the size of a pointer, which allows easy conversion to
Ted Kremenek4d4dd852008-02-13 17:41:41 +0000110/// void* when being handled by GRCoreEngine. It also forces us to unique states;
Ted Kremenek6f886bd2008-02-05 18:24:17 +0000111/// consequently, a ValueStateImpl* with a specific address will always refer
112/// to the unique state with those values.
Ted Kremeneka40ba022008-02-06 02:50:36 +0000113class ValueState {
Ted Kremenek9153f732008-02-05 07:17:49 +0000114 ValueStateImpl* Data;
115public:
Ted Kremeneked900212008-02-05 18:17:58 +0000116 ValueState(ValueStateImpl* D) : Data(D) {}
Ted Kremeneka40ba022008-02-06 02:50:36 +0000117 ValueState() : Data(0) {}
Ted Kremeneked900212008-02-05 18:17:58 +0000118
Ted Kremenekcba2e432008-02-05 19:35:18 +0000119 // Accessors.
Ted Kremeneked900212008-02-05 18:17:58 +0000120 ValueStateImpl* getImpl() const { return Data; }
Ted Kremeneke7d22112008-02-11 19:21:59 +0000121 ValueStateImpl& operator*() { return *Data; }
122 ValueStateImpl* operator->() { return Data; }
Ted Kremenek174aea42008-02-05 18:51:06 +0000123
Ted Kremenekcba2e432008-02-05 19:35:18 +0000124 // Typedefs.
Ted Kremenek862d5bb2008-02-06 00:54:14 +0000125 typedef vstate::IntSetTy IntSetTy;
Ted Kremenek016f52f2008-02-08 21:10:02 +0000126 typedef vstate::ExprBindingsTy ExprBindingsTy;
127 typedef vstate::VarBindingsTy VarBindingsTy;
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000128 typedef vstate::ConstNotEqTy ConstNotEqTy;
129 typedef vstate::ConstEqTy ConstEqTy;
Ted Kremenek862d5bb2008-02-06 00:54:14 +0000130
Ted Kremenekcba2e432008-02-05 19:35:18 +0000131 typedef llvm::SmallVector<ValueState,5> BufferTy;
Ted Kremenek174aea42008-02-05 18:51:06 +0000132
Ted Kremenek862d5bb2008-02-06 00:54:14 +0000133 // Queries.
134
135 bool isNotEqual(SymbolID sym, const llvm::APSInt& V) const;
136 const llvm::APSInt* getSymVal(SymbolID sym) const;
137
Ted Kremenek174aea42008-02-05 18:51:06 +0000138 // Iterators.
139
Ted Kremeneke7d22112008-02-11 19:21:59 +0000140 typedef VarBindingsTy::iterator vb_iterator;
141 vb_iterator vb_begin() const { return Data->VarBindings.begin(); }
142 vb_iterator vb_end() const { return Data->VarBindings.end(); }
143
144 typedef ExprBindingsTy::iterator seb_iterator;
145 seb_iterator seb_begin() const { return Data->SubExprBindings.begin(); }
146 seb_iterator seb_end() const { return Data->SubExprBindings.end(); }
Ted Kremenek016f52f2008-02-08 21:10:02 +0000147
Ted Kremeneke7d22112008-02-11 19:21:59 +0000148 typedef ExprBindingsTy::iterator beb_iterator;
149 beb_iterator beb_begin() const { return Data->BlockExprBindings.begin(); }
150 beb_iterator beb_end() const { return Data->BlockExprBindings.end(); }
Ted Kremenek9153f732008-02-05 07:17:49 +0000151
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000152 typedef ConstNotEqTy::iterator cne_iterator;
153 cne_iterator cne_begin() const { return Data->ConstNotEq.begin(); }
154 cne_iterator cne_end() const { return Data->ConstNotEq.end(); }
Ted Kremenek90e14812008-02-14 23:25:54 +0000155
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000156 typedef ConstEqTy::iterator ce_iterator;
157 ce_iterator ce_begin() const { return Data->ConstEq.begin(); }
158 ce_iterator ce_end() const { return Data->ConstEq.end(); }
Ted Kremenek90e14812008-02-14 23:25:54 +0000159
Ted Kremeneked900212008-02-05 18:17:58 +0000160 // Profiling and equality testing.
161
Ted Kremenek9153f732008-02-05 07:17:49 +0000162 bool operator==(const ValueState& RHS) const {
163 return Data == RHS.Data;
164 }
165
166 static void Profile(llvm::FoldingSetNodeID& ID, const ValueState& V) {
167 ID.AddPointer(V.getImpl());
168 }
169
170 void Profile(llvm::FoldingSetNodeID& ID) const {
171 Profile(ID, *this);
172 }
Ted Kremeneke7d22112008-02-11 19:21:59 +0000173
174 void printDOT(std::ostream& Out) const;
175 void print(std::ostream& Out) const;
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000176 void printStdErr() const { print(*llvm::cerr); }
Ted Kremeneke7d22112008-02-11 19:21:59 +0000177
Ted Kremenek9153f732008-02-05 07:17:49 +0000178};
179
180template<> struct GRTrait<ValueState> {
181 static inline void* toPtr(ValueState St) {
182 return reinterpret_cast<void*>(St.getImpl());
183 }
184 static inline ValueState toState(void* P) {
185 return ValueState(static_cast<ValueStateImpl*>(P));
186 }
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000187};
Ted Kremeneke070a1d2008-02-04 21:59:01 +0000188
189class ValueStateManager {
190public:
191 typedef ValueState StateTy;
192
193private:
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000194 ValueState::IntSetTy::Factory ISetFactory;
195 ValueState::ExprBindingsTy::Factory EXFactory;
196 ValueState::VarBindingsTy::Factory VBFactory;
197 ValueState::ConstNotEqTy::Factory CNEFactory;
198 ValueState::ConstEqTy::Factory CEFactory;
Ted Kremenek174aea42008-02-05 18:51:06 +0000199
200 /// StateSet - FoldingSet containing all the states created for analyzing
201 /// a particular function. This is used to unique states.
Ted Kremenek9153f732008-02-05 07:17:49 +0000202 llvm::FoldingSet<ValueStateImpl> StateSet;
Ted Kremeneke070a1d2008-02-04 21:59:01 +0000203
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000204 /// ValueMgr - Object that manages the data for all created RVals.
Ted Kremeneke070a1d2008-02-04 21:59:01 +0000205 ValueManager ValMgr;
Ted Kremenek9153f732008-02-05 07:17:49 +0000206
Ted Kremeneke070a1d2008-02-04 21:59:01 +0000207 /// SymMgr - Object that manages the symbol information.
208 SymbolManager SymMgr;
Ted Kremenek9153f732008-02-05 07:17:49 +0000209
210 /// Alloc - A BumpPtrAllocator to allocate states.
211 llvm::BumpPtrAllocator& Alloc;
Ted Kremeneke7d22112008-02-11 19:21:59 +0000212
213private:
214
215 ValueState::ExprBindingsTy Remove(ValueState::ExprBindingsTy B, Expr* E) {
216 return EXFactory.Remove(B, E);
217 }
218
219 ValueState::VarBindingsTy Remove(ValueState::VarBindingsTy B, VarDecl* V) {
220 return VBFactory.Remove(B, V);
221 }
Ted Kremenek9153f732008-02-05 07:17:49 +0000222
Ted Kremeneke7d22112008-02-11 19:21:59 +0000223 inline ValueState::ExprBindingsTy Remove(const ValueStateImpl& V, Expr* E) {
224 return Remove(V.BlockExprBindings, E);
225 }
226
227 inline ValueState::VarBindingsTy Remove(const ValueStateImpl& V, VarDecl* D) {
228 return Remove(V.VarBindings, D);
229 }
230
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000231 ValueState BindVar(ValueState St, VarDecl* D, RVal V);
Ted Kremeneke7d22112008-02-11 19:21:59 +0000232 ValueState UnbindVar(ValueState St, VarDecl* D);
Ted Kremeneke070a1d2008-02-04 21:59:01 +0000233
234public:
Ted Kremenek9153f732008-02-05 07:17:49 +0000235 ValueStateManager(ASTContext& Ctx, llvm::BumpPtrAllocator& alloc)
Ted Kremenek8158a0e2008-02-11 23:12:59 +0000236 : ISetFactory(alloc),
237 EXFactory(alloc),
238 VBFactory(alloc),
239 CNEFactory(alloc),
240 CEFactory(alloc),
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000241 ValMgr(Ctx, alloc),
242 Alloc(alloc) {}
Ted Kremeneke070a1d2008-02-04 21:59:01 +0000243
Ted Kremeneke7d22112008-02-11 19:21:59 +0000244 ValueState getInitialState();
Ted Kremeneke070a1d2008-02-04 21:59:01 +0000245
246 ValueManager& getValueManager() { return ValMgr; }
247 SymbolManager& getSymbolManager() { return SymMgr; }
248
Ted Kremeneke7d22112008-02-11 19:21:59 +0000249 ValueState RemoveDeadBindings(ValueState St, Stmt* Loc,
250 const LiveVariables& Liveness);
Ted Kremenekb87d9092008-02-08 19:17:19 +0000251
Ted Kremeneke7d22112008-02-11 19:21:59 +0000252 ValueState RemoveSubExprBindings(ValueState St) {
253 ValueStateImpl NewSt = *St;
254 NewSt.SubExprBindings = EXFactory.GetEmptyMap();
255 return getPersistentState(NewSt);
256 }
Ted Kremeneke7d22112008-02-11 19:21:59 +0000257
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000258 ValueState SetRVal(ValueState St, Expr* E, bool isBlkExpr, RVal V);
259 ValueState SetRVal(ValueState St, LVal LV, RVal V);
Ted Kremeneke070a1d2008-02-04 21:59:01 +0000260
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000261 RVal GetRVal(ValueState St, Expr* E, bool* hasVal = NULL);
262 RVal GetRVal(ValueState St, const LVal& LV, QualType T = QualType());
263 RVal GetLVal(ValueState St, Expr* E);
Ted Kremenekb87d9092008-02-08 19:17:19 +0000264
Ted Kremeneke7d22112008-02-11 19:21:59 +0000265 ValueState getPersistentState(const ValueStateImpl& Impl);
Ted Kremenek016f52f2008-02-08 21:10:02 +0000266
Ted Kremeneke7d22112008-02-11 19:21:59 +0000267 ValueState AddEQ(ValueState St, SymbolID sym, const llvm::APSInt& V);
268 ValueState AddNE(ValueState St, SymbolID sym, const llvm::APSInt& V);
Ted Kremeneke070a1d2008-02-04 21:59:01 +0000269};
270
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000271} // end clang namespace
272
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000273#endif