blob: 9048c6753ae1cc0eece305bc2e1ca9193cd3887a [file] [log] [blame]
Ted Kremeneka90ccfe2008-01-31 19:34:24 +00001//== RValues.h - Abstract RValues for Path-Sens. Value Tracking -*- 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//
10// This files defines RValue, LValue, and NonLValue, classes that represent
11// abstract r-values for use with path-sensitive value tracking.
12//
13//===----------------------------------------------------------------------===//
14
15#ifndef LLVM_CLANG_ANALYSIS_RVALUE_H
16#define LLVM_CLANG_ANALYSIS_RVALUE_H
17
18// FIXME: reduce the number of includes.
19
20#include "clang/Analysis/PathSensitive/GREngine.h"
21#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
39//==------------------------------------------------------------------------==//
40// RValue "management" data structures.
41//==------------------------------------------------------------------------==//
42
43namespace clang {
44
45class SymbolID {
46 unsigned Data;
47public:
48 SymbolID() : Data(~0) {}
49 SymbolID(unsigned x) : Data(x) {}
50
51 bool isInitialized() const { return Data != (unsigned) ~0; }
52 operator unsigned() const { assert (isInitialized()); return Data; }
53};
54
55class SymbolData {
56 uintptr_t Data;
57public:
58 enum Kind { ParmKind = 0x0, Mask = 0x3 };
59
60 SymbolData(ParmVarDecl* D)
61 : Data(reinterpret_cast<uintptr_t>(D) | ParmKind) {}
62
63 inline Kind getKind() const { return (Kind) (Data & Mask); }
64 inline void* getPtr() const { return reinterpret_cast<void*>(Data & ~Mask); }
65 inline bool operator==(const SymbolData& R) const { return Data == R.Data; }
66};
67
68class SymbolManager {
69 std::vector<SymbolData> SymbolToData;
70
71 typedef llvm::DenseMap<void*,SymbolID> MapTy;
72 MapTy DataToSymbol;
73
74public:
75 SymbolManager();
76 ~SymbolManager();
77
78 SymbolData getSymbolData(SymbolID id) const {
79 assert (id < SymbolToData.size());
80 return SymbolToData[id];
81 }
82
83 SymbolID getSymbol(ParmVarDecl* D);
84};
85
86class ValueManager {
87 typedef llvm::FoldingSet<llvm::FoldingSetNodeWrapper<llvm::APSInt> >
88 APSIntSetTy;
89
90 ASTContext& Ctx;
91 APSIntSetTy APSIntSet;
Ted Kremenek768ad162008-02-05 05:15:51 +000092 llvm::BumpPtrAllocator& BPAlloc;
Ted Kremeneka90ccfe2008-01-31 19:34:24 +000093
94public:
Ted Kremenek768ad162008-02-05 05:15:51 +000095 ValueManager(ASTContext& ctx, llvm::BumpPtrAllocator& Alloc)
96 : Ctx(ctx), BPAlloc(Alloc) {}
97
Ted Kremeneka90ccfe2008-01-31 19:34:24 +000098 ~ValueManager();
99
100 ASTContext& getContext() const { return Ctx; }
101 llvm::APSInt& getValue(const llvm::APSInt& X);
102 llvm::APSInt& getValue(uint64_t X, unsigned BitWidth, bool isUnsigned);
103 llvm::APSInt& getValue(uint64_t X, QualType T,
104 SourceLocation Loc = SourceLocation());
105};
106
107//==------------------------------------------------------------------------==//
108// Base RValue types.
109//==------------------------------------------------------------------------==//
110
111class RValue {
112public:
113 enum BaseKind { LValueKind=0x0,
114 NonLValueKind=0x1,
115 UninitializedKind=0x2,
116 InvalidKind=0x3 };
117
118 enum { BaseBits = 2,
119 BaseMask = 0x3 };
120
121private:
122 void* Data;
123 unsigned Kind;
124
125protected:
126 RValue(const void* d, bool isLValue, unsigned ValKind)
127 : Data(const_cast<void*>(d)),
128 Kind((isLValue ? LValueKind : NonLValueKind) | (ValKind << BaseBits)) {}
129
130 explicit RValue(BaseKind k)
131 : Data(0), Kind(k) {}
132
133 void* getRawPtr() const {
134 return reinterpret_cast<void*>(Data);
135 }
136
137public:
138 ~RValue() {};
139
140 RValue Cast(ValueManager& ValMgr, Expr* CastExpr) const;
141
142 unsigned getRawKind() const { return Kind; }
143 BaseKind getBaseKind() const { return (BaseKind) (Kind & BaseMask); }
144 unsigned getSubKind() const { return (Kind & ~BaseMask) >> BaseBits; }
145
146 void Profile(llvm::FoldingSetNodeID& ID) const {
147 ID.AddInteger((unsigned) getRawKind());
148 ID.AddPointer(reinterpret_cast<void*>(Data));
149 }
150
151 bool operator==(const RValue& RHS) const {
152 return getRawKind() == RHS.getRawKind() && Data == RHS.Data;
153 }
154
155 static RValue GetSymbolValue(SymbolManager& SymMgr, ParmVarDecl *D);
156
157 inline bool isValid() const { return getRawKind() != InvalidKind; }
158 inline bool isInvalid() const { return getRawKind() == InvalidKind; }
159
160 void print(std::ostream& OS) const;
161 void print() const { print(*llvm::cerr.stream()); }
162
163 // Implement isa<T> support.
164 static inline bool classof(const RValue*) { return true; }
165};
166
167class InvalidValue : public RValue {
168public:
169 InvalidValue() : RValue(InvalidKind) {}
170
171 static inline bool classof(const RValue* V) {
172 return V->getBaseKind() == InvalidKind;
173 }
174};
175
176class UninitializedValue : public RValue {
177public:
178 UninitializedValue() : RValue(UninitializedKind) {}
179
180 static inline bool classof(const RValue* V) {
181 return V->getBaseKind() == UninitializedKind;
182 }
183};
184
185class NonLValue : public RValue {
186protected:
187 NonLValue(unsigned SubKind, const void* d) : RValue(d, false, SubKind) {}
188
189public:
190 void print(std::ostream& Out) const;
191
Ted Kremeneka6e4d212008-02-01 06:36:40 +0000192 RValue Cast(ValueManager& ValMgr, Expr* CastExpr) const;
193
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000194 // Arithmetic operators.
195 NonLValue Add(ValueManager& ValMgr, const NonLValue& RHS) const;
196 NonLValue Sub(ValueManager& ValMgr, const NonLValue& RHS) const;
197 NonLValue Mul(ValueManager& ValMgr, const NonLValue& RHS) const;
198 NonLValue Div(ValueManager& ValMgr, const NonLValue& RHS) const;
199 NonLValue Rem(ValueManager& ValMgr, const NonLValue& RHS) const;
200 NonLValue UnaryMinus(ValueManager& ValMgr, UnaryOperator* U) const;
Ted Kremenekc5d3b4c2008-02-04 16:58:30 +0000201 NonLValue BitwiseComplement(ValueManager& ValMgr) const;
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000202
203 // Equality operators.
204 NonLValue EQ(ValueManager& ValMgr, const NonLValue& RHS) const;
205 NonLValue NE(ValueManager& ValMgr, const NonLValue& RHS) const;
206
Ted Kremeneka6e4d212008-02-01 06:36:40 +0000207
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000208 // Utility methods to create NonLValues.
209 static NonLValue GetValue(ValueManager& ValMgr, uint64_t X, QualType T,
210 SourceLocation Loc = SourceLocation());
211
212 static NonLValue GetValue(ValueManager& ValMgr, IntegerLiteral* I);
213
214 static inline NonLValue GetIntTruthValue(ValueManager& ValMgr, bool X) {
215 return GetValue(ValMgr, X ? 1U : 0U, ValMgr.getContext().IntTy);
216 }
217
218 // Implement isa<T> support.
219 static inline bool classof(const RValue* V) {
220 return V->getBaseKind() >= NonLValueKind;
221 }
222};
223
224class LValue : public RValue {
225protected:
Ted Kremenek516f91b2008-01-31 22:17:03 +0000226 LValue(unsigned SubKind, const void* D) : RValue(const_cast<void*>(D),
227 true, SubKind) {}
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000228
229public:
230 void print(std::ostream& Out) const;
231
Ted Kremeneka6e4d212008-02-01 06:36:40 +0000232 RValue Cast(ValueManager& ValMgr, Expr* CastExpr) const;
233
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000234 // Equality operators.
235 NonLValue EQ(ValueManager& ValMgr, const LValue& RHS) const;
236 NonLValue NE(ValueManager& ValMgr, const LValue& RHS) const;
237
238 // Implement isa<T> support.
239 static inline bool classof(const RValue* V) {
240 return V->getBaseKind() == LValueKind;
241 }
242};
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000243
244//==------------------------------------------------------------------------==//
245// Subclasses of NonLValue.
246//==------------------------------------------------------------------------==//
247
Ted Kremeneka6e4d212008-02-01 06:36:40 +0000248enum NonLValueKind { SymbolicNonLValueKind, ConcreteIntKind, NumNonLValueKind };
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000249
250class SymbolicNonLValue : public NonLValue {
251public:
252 SymbolicNonLValue(unsigned SymID)
253 : NonLValue(SymbolicNonLValueKind,
254 reinterpret_cast<void*>((uintptr_t) SymID)) {}
255
256 SymbolID getSymbolID() const {
257 return (SymbolID) reinterpret_cast<uintptr_t>(getRawPtr());
258 }
259
260 static inline bool classof(const RValue* V) {
261 return V->getSubKind() == SymbolicNonLValueKind;
262 }
263};
264
265class ConcreteInt : public NonLValue {
266public:
267 ConcreteInt(const llvm::APSInt& V) : NonLValue(ConcreteIntKind, &V) {}
268
269 const llvm::APSInt& getValue() const {
270 return *static_cast<llvm::APSInt*>(getRawPtr());
271 }
272
273 // Arithmetic operators.
274
275 ConcreteInt Add(ValueManager& ValMgr, const ConcreteInt& V) const {
276 return ValMgr.getValue(getValue() + V.getValue());
277 }
278
279 ConcreteInt Sub(ValueManager& ValMgr, const ConcreteInt& V) const {
280 return ValMgr.getValue(getValue() - V.getValue());
281 }
282
283 ConcreteInt Mul(ValueManager& ValMgr, const ConcreteInt& V) const {
284 return ValMgr.getValue(getValue() * V.getValue());
285 }
286
287 ConcreteInt Div(ValueManager& ValMgr, const ConcreteInt& V) const {
288 return ValMgr.getValue(getValue() / V.getValue());
289 }
290
291 ConcreteInt Rem(ValueManager& ValMgr, const ConcreteInt& V) const {
292 return ValMgr.getValue(getValue() % V.getValue());
293 }
294
295 ConcreteInt UnaryMinus(ValueManager& ValMgr, UnaryOperator* U) const {
296 assert (U->getType() == U->getSubExpr()->getType());
297 assert (U->getType()->isIntegerType());
298 return ValMgr.getValue(-getValue());
299 }
300
Ted Kremenekc5d3b4c2008-02-04 16:58:30 +0000301 ConcreteInt BitwiseComplement(ValueManager& ValMgr) const {
302 return ValMgr.getValue(~getValue());
303 }
304
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000305 // Casting.
306
307 ConcreteInt Cast(ValueManager& ValMgr, Expr* CastExpr) const {
308 assert (CastExpr->getType()->isIntegerType());
309
310 llvm::APSInt X(getValue());
311 X.extOrTrunc(ValMgr.getContext().getTypeSize(CastExpr->getType(),
312 CastExpr->getLocStart()));
313 return ValMgr.getValue(X);
314 }
315
316 // Equality operators.
317
318 ConcreteInt EQ(ValueManager& ValMgr, const ConcreteInt& V) const {
319 const llvm::APSInt& Val = getValue();
320 return ValMgr.getValue(Val == V.getValue() ? 1U : 0U,
321 Val.getBitWidth(), Val.isUnsigned());
322 }
323
324 ConcreteInt NE(ValueManager& ValMgr, const ConcreteInt& V) const {
325 const llvm::APSInt& Val = getValue();
326 return ValMgr.getValue(Val != V.getValue() ? 1U : 0U,
327 Val.getBitWidth(), Val.isUnsigned());
328 }
329
330 // Implement isa<T> support.
331 static inline bool classof(const RValue* V) {
332 return V->getSubKind() == ConcreteIntKind;
333 }
334};
Ted Kremenek516f91b2008-01-31 22:17:03 +0000335
336//==------------------------------------------------------------------------==//
337// Subclasses of LValue.
338//==------------------------------------------------------------------------==//
339
Ted Kremeneka6e4d212008-02-01 06:36:40 +0000340enum LValueKind { SymbolicLValueKind, LValueDeclKind, ConcreteIntLValueKind,
341 NumLValueKind };
342
Ted Kremenek516f91b2008-01-31 22:17:03 +0000343class SymbolicLValue : public LValue {
344public:
345 SymbolicLValue(unsigned SymID)
346 : LValue(SymbolicLValueKind, reinterpret_cast<void*>((uintptr_t) SymID)) {}
347
348 SymbolID getSymbolID() const {
349 return (SymbolID) reinterpret_cast<uintptr_t>(getRawPtr());
350 }
351
352 static inline bool classof(const RValue* V) {
353 return V->getSubKind() == SymbolicLValueKind;
354 }
355};
356
357class LValueDecl : public LValue {
358public:
359 LValueDecl(const ValueDecl* vd) : LValue(LValueDeclKind,vd) {}
360
361 ValueDecl* getDecl() const {
362 return static_cast<ValueDecl*>(getRawPtr());
363 }
364
365 inline bool operator==(const LValueDecl& R) const {
366 return getDecl() == R.getDecl();
367 }
368
369 inline bool operator!=(const LValueDecl& R) const {
370 return getDecl() != R.getDecl();
371 }
372
373 // Implement isa<T> support.
374 static inline bool classof(const RValue* V) {
375 return V->getSubKind() == LValueDeclKind;
376 }
377};
378
379class ConcreteIntLValue : public LValue {
380public:
381 ConcreteIntLValue(const llvm::APSInt& V) : LValue(ConcreteIntLValueKind, &V) {}
382
383 const llvm::APSInt& getValue() const {
384 return *static_cast<llvm::APSInt*>(getRawPtr());
385 }
386
387 // Arithmetic operators.
388
389 ConcreteIntLValue Add(ValueManager& ValMgr, const ConcreteInt& V) const {
390 return ValMgr.getValue(getValue() + V.getValue());
391 }
392
393 ConcreteIntLValue Sub(ValueManager& ValMgr, const ConcreteInt& V) const {
394 return ValMgr.getValue(getValue() - V.getValue());
395 }
396
397 // Equality operators.
398
399 ConcreteInt EQ(ValueManager& ValMgr, const ConcreteIntLValue& V) const {
400 const llvm::APSInt& Val = getValue();
401 return ValMgr.getValue(Val == V.getValue() ? 1U : 0U,
402 Val.getBitWidth(), Val.isUnsigned());
403 }
404
405 ConcreteInt NE(ValueManager& ValMgr, const ConcreteIntLValue& V) const {
406 const llvm::APSInt& Val = getValue();
407 return ValMgr.getValue(Val != V.getValue() ? 1U : 0U,
408 Val.getBitWidth(), Val.isUnsigned());
409 }
410
411 // Implement isa<T> support.
412 static inline bool classof(const RValue* V) {
413 return V->getSubKind() == ConcreteIntLValueKind;
414 }
415};
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000416
417} // end clang namespace
418
419//==------------------------------------------------------------------------==//
420// Casting machinery to get cast<> and dyn_cast<> working with SymbolData.
421//==------------------------------------------------------------------------==//
422
423namespace llvm {
424
425template<> inline bool
426isa<clang::ParmVarDecl,clang::SymbolData>(const clang::SymbolData& V) {
427 return V.getKind() == clang::SymbolData::ParmKind;
428}
429
430template<> struct cast_retty_impl<clang::ParmVarDecl,clang::SymbolData> {
431 typedef const clang::ParmVarDecl* ret_type;
432};
433
434template<> struct simplify_type<clang::SymbolData> {
435 typedef void* SimpleType;
436 static inline SimpleType getSimplifiedValue(const clang::SymbolData &V) {
437 return V.getPtr();
438 }
439};
440
441} // end llvm namespace
442
443#endif