blob: c69a70a52d73280fbe60a5afc920045251f7b772 [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; }
Ted Kremenek174aea42008-02-05 18:51:06 +000053
54 void Profile(llvm::FoldingSetNodeID& ID) const { ID.AddInteger(Data); }
55
56 static inline void Profile(llvm::FoldingSetNodeID& ID, SymbolID X) {
57 X.Profile(ID);
58 }
Ted Kremeneka90ccfe2008-01-31 19:34:24 +000059};
60
61class SymbolData {
62 uintptr_t Data;
63public:
64 enum Kind { ParmKind = 0x0, Mask = 0x3 };
65
66 SymbolData(ParmVarDecl* D)
67 : Data(reinterpret_cast<uintptr_t>(D) | ParmKind) {}
68
69 inline Kind getKind() const { return (Kind) (Data & Mask); }
70 inline void* getPtr() const { return reinterpret_cast<void*>(Data & ~Mask); }
71 inline bool operator==(const SymbolData& R) const { return Data == R.Data; }
72};
73
74class SymbolManager {
75 std::vector<SymbolData> SymbolToData;
76
77 typedef llvm::DenseMap<void*,SymbolID> MapTy;
78 MapTy DataToSymbol;
79
80public:
81 SymbolManager();
82 ~SymbolManager();
83
84 SymbolData getSymbolData(SymbolID id) const {
85 assert (id < SymbolToData.size());
86 return SymbolToData[id];
87 }
88
89 SymbolID getSymbol(ParmVarDecl* D);
90};
91
92class ValueManager {
93 typedef llvm::FoldingSet<llvm::FoldingSetNodeWrapper<llvm::APSInt> >
94 APSIntSetTy;
95
96 ASTContext& Ctx;
97 APSIntSetTy APSIntSet;
Ted Kremenek768ad162008-02-05 05:15:51 +000098 llvm::BumpPtrAllocator& BPAlloc;
Ted Kremeneka90ccfe2008-01-31 19:34:24 +000099
100public:
Ted Kremenek768ad162008-02-05 05:15:51 +0000101 ValueManager(ASTContext& ctx, llvm::BumpPtrAllocator& Alloc)
102 : Ctx(ctx), BPAlloc(Alloc) {}
103
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000104 ~ValueManager();
105
106 ASTContext& getContext() const { return Ctx; }
107 llvm::APSInt& getValue(const llvm::APSInt& X);
108 llvm::APSInt& getValue(uint64_t X, unsigned BitWidth, bool isUnsigned);
109 llvm::APSInt& getValue(uint64_t X, QualType T,
110 SourceLocation Loc = SourceLocation());
111};
112
113//==------------------------------------------------------------------------==//
114// Base RValue types.
115//==------------------------------------------------------------------------==//
116
117class RValue {
118public:
119 enum BaseKind { LValueKind=0x0,
120 NonLValueKind=0x1,
121 UninitializedKind=0x2,
122 InvalidKind=0x3 };
123
124 enum { BaseBits = 2,
125 BaseMask = 0x3 };
126
127private:
128 void* Data;
129 unsigned Kind;
130
131protected:
132 RValue(const void* d, bool isLValue, unsigned ValKind)
133 : Data(const_cast<void*>(d)),
134 Kind((isLValue ? LValueKind : NonLValueKind) | (ValKind << BaseBits)) {}
135
136 explicit RValue(BaseKind k)
137 : Data(0), Kind(k) {}
138
139 void* getRawPtr() const {
140 return reinterpret_cast<void*>(Data);
141 }
142
143public:
144 ~RValue() {};
145
Ted Kremenekcba2e432008-02-05 19:35:18 +0000146 /// BufferTy - A temporary buffer to hold a set of RValues.
147 typedef llvm::SmallVector<RValue,5> BufferTy;
148
149
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000150 RValue Cast(ValueManager& ValMgr, Expr* CastExpr) const;
151
152 unsigned getRawKind() const { return Kind; }
153 BaseKind getBaseKind() const { return (BaseKind) (Kind & BaseMask); }
154 unsigned getSubKind() const { return (Kind & ~BaseMask) >> BaseBits; }
155
156 void Profile(llvm::FoldingSetNodeID& ID) const {
157 ID.AddInteger((unsigned) getRawKind());
158 ID.AddPointer(reinterpret_cast<void*>(Data));
159 }
160
161 bool operator==(const RValue& RHS) const {
162 return getRawKind() == RHS.getRawKind() && Data == RHS.Data;
163 }
164
165 static RValue GetSymbolValue(SymbolManager& SymMgr, ParmVarDecl *D);
166
167 inline bool isValid() const { return getRawKind() != InvalidKind; }
168 inline bool isInvalid() const { return getRawKind() == InvalidKind; }
169
170 void print(std::ostream& OS) const;
171 void print() const { print(*llvm::cerr.stream()); }
172
173 // Implement isa<T> support.
174 static inline bool classof(const RValue*) { return true; }
175};
176
177class InvalidValue : public RValue {
178public:
179 InvalidValue() : RValue(InvalidKind) {}
180
181 static inline bool classof(const RValue* V) {
182 return V->getBaseKind() == InvalidKind;
183 }
184};
185
186class UninitializedValue : public RValue {
187public:
188 UninitializedValue() : RValue(UninitializedKind) {}
189
190 static inline bool classof(const RValue* V) {
191 return V->getBaseKind() == UninitializedKind;
192 }
193};
194
195class NonLValue : public RValue {
196protected:
197 NonLValue(unsigned SubKind, const void* d) : RValue(d, false, SubKind) {}
198
199public:
200 void print(std::ostream& Out) const;
201
Ted Kremeneka6e4d212008-02-01 06:36:40 +0000202 RValue Cast(ValueManager& ValMgr, Expr* CastExpr) const;
203
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000204 // Arithmetic operators.
205 NonLValue Add(ValueManager& ValMgr, const NonLValue& RHS) const;
206 NonLValue Sub(ValueManager& ValMgr, const NonLValue& RHS) const;
207 NonLValue Mul(ValueManager& ValMgr, const NonLValue& RHS) const;
208 NonLValue Div(ValueManager& ValMgr, const NonLValue& RHS) const;
209 NonLValue Rem(ValueManager& ValMgr, const NonLValue& RHS) const;
210 NonLValue UnaryMinus(ValueManager& ValMgr, UnaryOperator* U) const;
Ted Kremenekc5d3b4c2008-02-04 16:58:30 +0000211 NonLValue BitwiseComplement(ValueManager& ValMgr) const;
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000212
213 // Equality operators.
214 NonLValue EQ(ValueManager& ValMgr, const NonLValue& RHS) const;
215 NonLValue NE(ValueManager& ValMgr, const NonLValue& RHS) const;
216
Ted Kremeneka6e4d212008-02-01 06:36:40 +0000217
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000218 // Utility methods to create NonLValues.
219 static NonLValue GetValue(ValueManager& ValMgr, uint64_t X, QualType T,
220 SourceLocation Loc = SourceLocation());
221
222 static NonLValue GetValue(ValueManager& ValMgr, IntegerLiteral* I);
223
224 static inline NonLValue GetIntTruthValue(ValueManager& ValMgr, bool X) {
225 return GetValue(ValMgr, X ? 1U : 0U, ValMgr.getContext().IntTy);
226 }
227
228 // Implement isa<T> support.
229 static inline bool classof(const RValue* V) {
230 return V->getBaseKind() >= NonLValueKind;
231 }
232};
233
234class LValue : public RValue {
235protected:
Ted Kremenek516f91b2008-01-31 22:17:03 +0000236 LValue(unsigned SubKind, const void* D) : RValue(const_cast<void*>(D),
237 true, SubKind) {}
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000238
239public:
240 void print(std::ostream& Out) const;
241
Ted Kremeneka6e4d212008-02-01 06:36:40 +0000242 RValue Cast(ValueManager& ValMgr, Expr* CastExpr) const;
243
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000244 // Equality operators.
245 NonLValue EQ(ValueManager& ValMgr, const LValue& RHS) const;
246 NonLValue NE(ValueManager& ValMgr, const LValue& RHS) const;
247
248 // Implement isa<T> support.
249 static inline bool classof(const RValue* V) {
250 return V->getBaseKind() == LValueKind;
251 }
252};
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000253
254//==------------------------------------------------------------------------==//
255// Subclasses of NonLValue.
256//==------------------------------------------------------------------------==//
257
Ted Kremeneka6e4d212008-02-01 06:36:40 +0000258enum NonLValueKind { SymbolicNonLValueKind, ConcreteIntKind, NumNonLValueKind };
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000259
260class SymbolicNonLValue : public NonLValue {
261public:
262 SymbolicNonLValue(unsigned SymID)
263 : NonLValue(SymbolicNonLValueKind,
264 reinterpret_cast<void*>((uintptr_t) SymID)) {}
265
266 SymbolID getSymbolID() const {
267 return (SymbolID) reinterpret_cast<uintptr_t>(getRawPtr());
268 }
269
270 static inline bool classof(const RValue* V) {
271 return V->getSubKind() == SymbolicNonLValueKind;
272 }
273};
274
275class ConcreteInt : public NonLValue {
276public:
277 ConcreteInt(const llvm::APSInt& V) : NonLValue(ConcreteIntKind, &V) {}
278
279 const llvm::APSInt& getValue() const {
280 return *static_cast<llvm::APSInt*>(getRawPtr());
281 }
282
283 // Arithmetic operators.
284
285 ConcreteInt Add(ValueManager& ValMgr, const ConcreteInt& V) const {
286 return ValMgr.getValue(getValue() + V.getValue());
287 }
288
289 ConcreteInt Sub(ValueManager& ValMgr, const ConcreteInt& V) const {
290 return ValMgr.getValue(getValue() - V.getValue());
291 }
292
293 ConcreteInt Mul(ValueManager& ValMgr, const ConcreteInt& V) const {
294 return ValMgr.getValue(getValue() * V.getValue());
295 }
296
297 ConcreteInt Div(ValueManager& ValMgr, const ConcreteInt& V) const {
298 return ValMgr.getValue(getValue() / V.getValue());
299 }
300
301 ConcreteInt Rem(ValueManager& ValMgr, const ConcreteInt& V) const {
302 return ValMgr.getValue(getValue() % V.getValue());
303 }
304
305 ConcreteInt UnaryMinus(ValueManager& ValMgr, UnaryOperator* U) const {
306 assert (U->getType() == U->getSubExpr()->getType());
307 assert (U->getType()->isIntegerType());
308 return ValMgr.getValue(-getValue());
309 }
310
Ted Kremenekc5d3b4c2008-02-04 16:58:30 +0000311 ConcreteInt BitwiseComplement(ValueManager& ValMgr) const {
312 return ValMgr.getValue(~getValue());
313 }
314
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000315 // Casting.
316
317 ConcreteInt Cast(ValueManager& ValMgr, Expr* CastExpr) const {
318 assert (CastExpr->getType()->isIntegerType());
319
320 llvm::APSInt X(getValue());
321 X.extOrTrunc(ValMgr.getContext().getTypeSize(CastExpr->getType(),
322 CastExpr->getLocStart()));
323 return ValMgr.getValue(X);
324 }
325
326 // Equality operators.
327
328 ConcreteInt EQ(ValueManager& ValMgr, const ConcreteInt& V) const {
329 const llvm::APSInt& Val = getValue();
330 return ValMgr.getValue(Val == V.getValue() ? 1U : 0U,
331 Val.getBitWidth(), Val.isUnsigned());
332 }
333
334 ConcreteInt NE(ValueManager& ValMgr, const ConcreteInt& V) const {
335 const llvm::APSInt& Val = getValue();
336 return ValMgr.getValue(Val != V.getValue() ? 1U : 0U,
337 Val.getBitWidth(), Val.isUnsigned());
338 }
339
340 // Implement isa<T> support.
341 static inline bool classof(const RValue* V) {
342 return V->getSubKind() == ConcreteIntKind;
343 }
344};
Ted Kremenek516f91b2008-01-31 22:17:03 +0000345
346//==------------------------------------------------------------------------==//
347// Subclasses of LValue.
348//==------------------------------------------------------------------------==//
349
Ted Kremeneka6e4d212008-02-01 06:36:40 +0000350enum LValueKind { SymbolicLValueKind, LValueDeclKind, ConcreteIntLValueKind,
351 NumLValueKind };
352
Ted Kremenek516f91b2008-01-31 22:17:03 +0000353class SymbolicLValue : public LValue {
354public:
355 SymbolicLValue(unsigned SymID)
356 : LValue(SymbolicLValueKind, reinterpret_cast<void*>((uintptr_t) SymID)) {}
357
358 SymbolID getSymbolID() const {
359 return (SymbolID) reinterpret_cast<uintptr_t>(getRawPtr());
360 }
361
362 static inline bool classof(const RValue* V) {
363 return V->getSubKind() == SymbolicLValueKind;
364 }
365};
366
367class LValueDecl : public LValue {
368public:
369 LValueDecl(const ValueDecl* vd) : LValue(LValueDeclKind,vd) {}
370
371 ValueDecl* getDecl() const {
372 return static_cast<ValueDecl*>(getRawPtr());
373 }
374
375 inline bool operator==(const LValueDecl& R) const {
376 return getDecl() == R.getDecl();
377 }
378
379 inline bool operator!=(const LValueDecl& R) const {
380 return getDecl() != R.getDecl();
381 }
382
383 // Implement isa<T> support.
384 static inline bool classof(const RValue* V) {
385 return V->getSubKind() == LValueDeclKind;
386 }
387};
388
389class ConcreteIntLValue : public LValue {
390public:
391 ConcreteIntLValue(const llvm::APSInt& V) : LValue(ConcreteIntLValueKind, &V) {}
392
393 const llvm::APSInt& getValue() const {
394 return *static_cast<llvm::APSInt*>(getRawPtr());
395 }
396
397 // Arithmetic operators.
398
399 ConcreteIntLValue Add(ValueManager& ValMgr, const ConcreteInt& V) const {
400 return ValMgr.getValue(getValue() + V.getValue());
401 }
402
403 ConcreteIntLValue Sub(ValueManager& ValMgr, const ConcreteInt& V) const {
404 return ValMgr.getValue(getValue() - V.getValue());
405 }
406
407 // Equality operators.
408
409 ConcreteInt EQ(ValueManager& ValMgr, const ConcreteIntLValue& V) const {
410 const llvm::APSInt& Val = getValue();
411 return ValMgr.getValue(Val == V.getValue() ? 1U : 0U,
412 Val.getBitWidth(), Val.isUnsigned());
413 }
414
415 ConcreteInt NE(ValueManager& ValMgr, const ConcreteIntLValue& V) const {
416 const llvm::APSInt& Val = getValue();
417 return ValMgr.getValue(Val != V.getValue() ? 1U : 0U,
418 Val.getBitWidth(), Val.isUnsigned());
419 }
420
421 // Implement isa<T> support.
422 static inline bool classof(const RValue* V) {
423 return V->getSubKind() == ConcreteIntLValueKind;
424 }
425};
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000426
427} // end clang namespace
428
429//==------------------------------------------------------------------------==//
430// Casting machinery to get cast<> and dyn_cast<> working with SymbolData.
431//==------------------------------------------------------------------------==//
432
433namespace llvm {
434
435template<> inline bool
436isa<clang::ParmVarDecl,clang::SymbolData>(const clang::SymbolData& V) {
437 return V.getKind() == clang::SymbolData::ParmKind;
438}
439
440template<> struct cast_retty_impl<clang::ParmVarDecl,clang::SymbolData> {
441 typedef const clang::ParmVarDecl* ret_type;
442};
443
444template<> struct simplify_type<clang::SymbolData> {
445 typedef void* SimpleType;
446 static inline SimpleType getSimplifiedValue(const clang::SymbolData &V) {
447 return V.getPtr();
448 }
449};
450
451} // end llvm namespace
452
453#endif