blob: b5b7873f633c9252da4446c31bd20da2faef8dca [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
146 RValue Cast(ValueManager& ValMgr, Expr* CastExpr) const;
147
148 unsigned getRawKind() const { return Kind; }
149 BaseKind getBaseKind() const { return (BaseKind) (Kind & BaseMask); }
150 unsigned getSubKind() const { return (Kind & ~BaseMask) >> BaseBits; }
151
152 void Profile(llvm::FoldingSetNodeID& ID) const {
153 ID.AddInteger((unsigned) getRawKind());
154 ID.AddPointer(reinterpret_cast<void*>(Data));
155 }
156
157 bool operator==(const RValue& RHS) const {
158 return getRawKind() == RHS.getRawKind() && Data == RHS.Data;
159 }
160
161 static RValue GetSymbolValue(SymbolManager& SymMgr, ParmVarDecl *D);
162
163 inline bool isValid() const { return getRawKind() != InvalidKind; }
164 inline bool isInvalid() const { return getRawKind() == InvalidKind; }
165
166 void print(std::ostream& OS) const;
167 void print() const { print(*llvm::cerr.stream()); }
168
169 // Implement isa<T> support.
170 static inline bool classof(const RValue*) { return true; }
171};
172
173class InvalidValue : public RValue {
174public:
175 InvalidValue() : RValue(InvalidKind) {}
176
177 static inline bool classof(const RValue* V) {
178 return V->getBaseKind() == InvalidKind;
179 }
180};
181
182class UninitializedValue : public RValue {
183public:
184 UninitializedValue() : RValue(UninitializedKind) {}
185
186 static inline bool classof(const RValue* V) {
187 return V->getBaseKind() == UninitializedKind;
188 }
189};
190
191class NonLValue : public RValue {
192protected:
193 NonLValue(unsigned SubKind, const void* d) : RValue(d, false, SubKind) {}
194
195public:
196 void print(std::ostream& Out) const;
197
Ted Kremeneka6e4d212008-02-01 06:36:40 +0000198 RValue Cast(ValueManager& ValMgr, Expr* CastExpr) const;
199
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000200 // Arithmetic operators.
201 NonLValue Add(ValueManager& ValMgr, const NonLValue& RHS) const;
202 NonLValue Sub(ValueManager& ValMgr, const NonLValue& RHS) const;
203 NonLValue Mul(ValueManager& ValMgr, const NonLValue& RHS) const;
204 NonLValue Div(ValueManager& ValMgr, const NonLValue& RHS) const;
205 NonLValue Rem(ValueManager& ValMgr, const NonLValue& RHS) const;
206 NonLValue UnaryMinus(ValueManager& ValMgr, UnaryOperator* U) const;
Ted Kremenekc5d3b4c2008-02-04 16:58:30 +0000207 NonLValue BitwiseComplement(ValueManager& ValMgr) const;
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000208
209 // Equality operators.
210 NonLValue EQ(ValueManager& ValMgr, const NonLValue& RHS) const;
211 NonLValue NE(ValueManager& ValMgr, const NonLValue& RHS) const;
212
Ted Kremeneka6e4d212008-02-01 06:36:40 +0000213
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000214 // Utility methods to create NonLValues.
215 static NonLValue GetValue(ValueManager& ValMgr, uint64_t X, QualType T,
216 SourceLocation Loc = SourceLocation());
217
218 static NonLValue GetValue(ValueManager& ValMgr, IntegerLiteral* I);
219
220 static inline NonLValue GetIntTruthValue(ValueManager& ValMgr, bool X) {
221 return GetValue(ValMgr, X ? 1U : 0U, ValMgr.getContext().IntTy);
222 }
223
224 // Implement isa<T> support.
225 static inline bool classof(const RValue* V) {
226 return V->getBaseKind() >= NonLValueKind;
227 }
228};
229
230class LValue : public RValue {
231protected:
Ted Kremenek516f91b2008-01-31 22:17:03 +0000232 LValue(unsigned SubKind, const void* D) : RValue(const_cast<void*>(D),
233 true, SubKind) {}
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000234
235public:
236 void print(std::ostream& Out) const;
237
Ted Kremeneka6e4d212008-02-01 06:36:40 +0000238 RValue Cast(ValueManager& ValMgr, Expr* CastExpr) const;
239
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000240 // Equality operators.
241 NonLValue EQ(ValueManager& ValMgr, const LValue& RHS) const;
242 NonLValue NE(ValueManager& ValMgr, const LValue& RHS) const;
243
244 // Implement isa<T> support.
245 static inline bool classof(const RValue* V) {
246 return V->getBaseKind() == LValueKind;
247 }
248};
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000249
250//==------------------------------------------------------------------------==//
251// Subclasses of NonLValue.
252//==------------------------------------------------------------------------==//
253
Ted Kremeneka6e4d212008-02-01 06:36:40 +0000254enum NonLValueKind { SymbolicNonLValueKind, ConcreteIntKind, NumNonLValueKind };
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000255
256class SymbolicNonLValue : public NonLValue {
257public:
258 SymbolicNonLValue(unsigned SymID)
259 : NonLValue(SymbolicNonLValueKind,
260 reinterpret_cast<void*>((uintptr_t) SymID)) {}
261
262 SymbolID getSymbolID() const {
263 return (SymbolID) reinterpret_cast<uintptr_t>(getRawPtr());
264 }
265
266 static inline bool classof(const RValue* V) {
267 return V->getSubKind() == SymbolicNonLValueKind;
268 }
269};
270
271class ConcreteInt : public NonLValue {
272public:
273 ConcreteInt(const llvm::APSInt& V) : NonLValue(ConcreteIntKind, &V) {}
274
275 const llvm::APSInt& getValue() const {
276 return *static_cast<llvm::APSInt*>(getRawPtr());
277 }
278
279 // Arithmetic operators.
280
281 ConcreteInt Add(ValueManager& ValMgr, const ConcreteInt& V) const {
282 return ValMgr.getValue(getValue() + V.getValue());
283 }
284
285 ConcreteInt Sub(ValueManager& ValMgr, const ConcreteInt& V) const {
286 return ValMgr.getValue(getValue() - V.getValue());
287 }
288
289 ConcreteInt Mul(ValueManager& ValMgr, const ConcreteInt& V) const {
290 return ValMgr.getValue(getValue() * V.getValue());
291 }
292
293 ConcreteInt Div(ValueManager& ValMgr, const ConcreteInt& V) const {
294 return ValMgr.getValue(getValue() / V.getValue());
295 }
296
297 ConcreteInt Rem(ValueManager& ValMgr, const ConcreteInt& V) const {
298 return ValMgr.getValue(getValue() % V.getValue());
299 }
300
301 ConcreteInt UnaryMinus(ValueManager& ValMgr, UnaryOperator* U) const {
302 assert (U->getType() == U->getSubExpr()->getType());
303 assert (U->getType()->isIntegerType());
304 return ValMgr.getValue(-getValue());
305 }
306
Ted Kremenekc5d3b4c2008-02-04 16:58:30 +0000307 ConcreteInt BitwiseComplement(ValueManager& ValMgr) const {
308 return ValMgr.getValue(~getValue());
309 }
310
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000311 // Casting.
312
313 ConcreteInt Cast(ValueManager& ValMgr, Expr* CastExpr) const {
314 assert (CastExpr->getType()->isIntegerType());
315
316 llvm::APSInt X(getValue());
317 X.extOrTrunc(ValMgr.getContext().getTypeSize(CastExpr->getType(),
318 CastExpr->getLocStart()));
319 return ValMgr.getValue(X);
320 }
321
322 // Equality operators.
323
324 ConcreteInt EQ(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 ConcreteInt NE(ValueManager& ValMgr, const ConcreteInt& V) const {
331 const llvm::APSInt& Val = getValue();
332 return ValMgr.getValue(Val != V.getValue() ? 1U : 0U,
333 Val.getBitWidth(), Val.isUnsigned());
334 }
335
336 // Implement isa<T> support.
337 static inline bool classof(const RValue* V) {
338 return V->getSubKind() == ConcreteIntKind;
339 }
340};
Ted Kremenek516f91b2008-01-31 22:17:03 +0000341
342//==------------------------------------------------------------------------==//
343// Subclasses of LValue.
344//==------------------------------------------------------------------------==//
345
Ted Kremeneka6e4d212008-02-01 06:36:40 +0000346enum LValueKind { SymbolicLValueKind, LValueDeclKind, ConcreteIntLValueKind,
347 NumLValueKind };
348
Ted Kremenek516f91b2008-01-31 22:17:03 +0000349class SymbolicLValue : public LValue {
350public:
351 SymbolicLValue(unsigned SymID)
352 : LValue(SymbolicLValueKind, reinterpret_cast<void*>((uintptr_t) SymID)) {}
353
354 SymbolID getSymbolID() const {
355 return (SymbolID) reinterpret_cast<uintptr_t>(getRawPtr());
356 }
357
358 static inline bool classof(const RValue* V) {
359 return V->getSubKind() == SymbolicLValueKind;
360 }
361};
362
363class LValueDecl : public LValue {
364public:
365 LValueDecl(const ValueDecl* vd) : LValue(LValueDeclKind,vd) {}
366
367 ValueDecl* getDecl() const {
368 return static_cast<ValueDecl*>(getRawPtr());
369 }
370
371 inline bool operator==(const LValueDecl& R) const {
372 return getDecl() == R.getDecl();
373 }
374
375 inline bool operator!=(const LValueDecl& R) const {
376 return getDecl() != R.getDecl();
377 }
378
379 // Implement isa<T> support.
380 static inline bool classof(const RValue* V) {
381 return V->getSubKind() == LValueDeclKind;
382 }
383};
384
385class ConcreteIntLValue : public LValue {
386public:
387 ConcreteIntLValue(const llvm::APSInt& V) : LValue(ConcreteIntLValueKind, &V) {}
388
389 const llvm::APSInt& getValue() const {
390 return *static_cast<llvm::APSInt*>(getRawPtr());
391 }
392
393 // Arithmetic operators.
394
395 ConcreteIntLValue Add(ValueManager& ValMgr, const ConcreteInt& V) const {
396 return ValMgr.getValue(getValue() + V.getValue());
397 }
398
399 ConcreteIntLValue Sub(ValueManager& ValMgr, const ConcreteInt& V) const {
400 return ValMgr.getValue(getValue() - V.getValue());
401 }
402
403 // Equality operators.
404
405 ConcreteInt EQ(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 ConcreteInt NE(ValueManager& ValMgr, const ConcreteIntLValue& V) const {
412 const llvm::APSInt& Val = getValue();
413 return ValMgr.getValue(Val != V.getValue() ? 1U : 0U,
414 Val.getBitWidth(), Val.isUnsigned());
415 }
416
417 // Implement isa<T> support.
418 static inline bool classof(const RValue* V) {
419 return V->getSubKind() == ConcreteIntLValueKind;
420 }
421};
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000422
423} // end clang namespace
424
425//==------------------------------------------------------------------------==//
426// Casting machinery to get cast<> and dyn_cast<> working with SymbolData.
427//==------------------------------------------------------------------------==//
428
429namespace llvm {
430
431template<> inline bool
432isa<clang::ParmVarDecl,clang::SymbolData>(const clang::SymbolData& V) {
433 return V.getKind() == clang::SymbolData::ParmKind;
434}
435
436template<> struct cast_retty_impl<clang::ParmVarDecl,clang::SymbolData> {
437 typedef const clang::ParmVarDecl* ret_type;
438};
439
440template<> struct simplify_type<clang::SymbolData> {
441 typedef void* SimpleType;
442 static inline SimpleType getSimplifiedValue(const clang::SymbolData &V) {
443 return V.getPtr();
444 }
445};
446
447} // end llvm namespace
448
449#endif