blob: cd74262384b73e58079eefb626f70b64db72b380 [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//==------------------------------------------------------------------------==//
Ted Kremenek1fbdb022008-02-05 21:32:43 +000040// Values and ValueManager.
Ted Kremeneka90ccfe2008-01-31 19:34:24 +000041//==------------------------------------------------------------------------==//
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
Ted Kremenek1fbdb022008-02-05 21:32:43 +000054 void Profile(llvm::FoldingSetNodeID& ID) const {
55 assert (isInitialized());
56 ID.AddInteger(Data);
57 }
Ted Kremenek174aea42008-02-05 18:51:06 +000058
59 static inline void Profile(llvm::FoldingSetNodeID& ID, SymbolID X) {
60 X.Profile(ID);
61 }
Ted Kremeneka90ccfe2008-01-31 19:34:24 +000062};
63
64class SymbolData {
65 uintptr_t Data;
66public:
67 enum Kind { ParmKind = 0x0, Mask = 0x3 };
68
69 SymbolData(ParmVarDecl* D)
70 : Data(reinterpret_cast<uintptr_t>(D) | ParmKind) {}
71
72 inline Kind getKind() const { return (Kind) (Data & Mask); }
73 inline void* getPtr() const { return reinterpret_cast<void*>(Data & ~Mask); }
74 inline bool operator==(const SymbolData& R) const { return Data == R.Data; }
75};
Ted Kremenek1fbdb022008-02-05 21:32:43 +000076
77
78class SymIntConstraint : public llvm::FoldingSetNode {
79 SymbolID Symbol;
80 BinaryOperator::Opcode Op;
81 const llvm::APSInt& Val;
82public:
83 SymIntConstraint(SymbolID sym, BinaryOperator::Opcode op,
84 const llvm::APSInt& V)
85 : Symbol(sym),
86 Op(op), Val(V) {}
87
88 BinaryOperator::Opcode getOpcode() const { return Op; }
89 SymbolID getSymbol() const { return Symbol; }
90 const llvm::APSInt& getInt() const { return Val; }
91
92 static inline void Profile(llvm::FoldingSetNodeID& ID,
93 const SymbolID& Symbol,
94 BinaryOperator::Opcode Op,
95 const llvm::APSInt& Val) {
96 Symbol.Profile(ID);
97 ID.AddInteger(Op);
98 ID.AddPointer(&Val);
99 }
100
101 void Profile(llvm::FoldingSetNodeID& ID) {
102 Profile(ID, Symbol, Op, Val);
103 }
104};
105
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000106
107class SymbolManager {
108 std::vector<SymbolData> SymbolToData;
109
110 typedef llvm::DenseMap<void*,SymbolID> MapTy;
111 MapTy DataToSymbol;
112
113public:
114 SymbolManager();
115 ~SymbolManager();
116
117 SymbolData getSymbolData(SymbolID id) const {
118 assert (id < SymbolToData.size());
119 return SymbolToData[id];
120 }
121
122 SymbolID getSymbol(ParmVarDecl* D);
123};
Ted Kremenek1fbdb022008-02-05 21:32:43 +0000124
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000125
126class ValueManager {
127 typedef llvm::FoldingSet<llvm::FoldingSetNodeWrapper<llvm::APSInt> >
128 APSIntSetTy;
129
Ted Kremenek1fbdb022008-02-05 21:32:43 +0000130 typedef llvm::FoldingSet<SymIntConstraint>
131 SymIntCSetTy;
132
133
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000134 ASTContext& Ctx;
Ted Kremenek768ad162008-02-05 05:15:51 +0000135 llvm::BumpPtrAllocator& BPAlloc;
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000136
Ted Kremenek1fbdb022008-02-05 21:32:43 +0000137 APSIntSetTy APSIntSet;
138 SymIntCSetTy SymIntCSet;
139
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000140public:
Ted Kremenek768ad162008-02-05 05:15:51 +0000141 ValueManager(ASTContext& ctx, llvm::BumpPtrAllocator& Alloc)
142 : Ctx(ctx), BPAlloc(Alloc) {}
143
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000144 ~ValueManager();
145
146 ASTContext& getContext() const { return Ctx; }
Ted Kremenek1fbdb022008-02-05 21:32:43 +0000147 const llvm::APSInt& getValue(const llvm::APSInt& X);
148 const llvm::APSInt& getValue(uint64_t X, unsigned BitWidth, bool isUnsigned);
149 const llvm::APSInt& getValue(uint64_t X, QualType T,
150 SourceLocation Loc = SourceLocation());
151
Ted Kremenek862d5bb2008-02-06 00:54:14 +0000152 inline const llvm::APSInt& getZeroWithPtrWidth() {
153 return getValue(0, Ctx.getTypeSize(Ctx.VoidPtrTy, SourceLocation()), true);
154 }
155
Ted Kremenek1fbdb022008-02-05 21:32:43 +0000156 const SymIntConstraint& getConstraint(SymbolID sym, BinaryOperator::Opcode Op,
157 const llvm::APSInt& V);
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000158};
Ted Kremenek0f10d502008-02-05 22:21:54 +0000159
160} // end clang namespace
161
162//==------------------------------------------------------------------------==//
163// Casting machinery to get cast<> and dyn_cast<> working with SymbolData.
164//==------------------------------------------------------------------------==//
165
166namespace llvm {
167
168 template<> inline bool
169 isa<clang::ParmVarDecl,clang::SymbolData>(const clang::SymbolData& V) {
170 return V.getKind() == clang::SymbolData::ParmKind;
171 }
172
173 template<> struct cast_retty_impl<clang::ParmVarDecl,clang::SymbolData> {
174 typedef const clang::ParmVarDecl* ret_type;
175 };
176
177 template<> struct simplify_type<clang::SymbolData> {
178 typedef void* SimpleType;
179 static inline SimpleType getSimplifiedValue(const clang::SymbolData &V) {
180 return V.getPtr();
181 }
182 };
183
184} // end llvm namespace
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000185
186//==------------------------------------------------------------------------==//
187// Base RValue types.
188//==------------------------------------------------------------------------==//
189
Ted Kremenek0f10d502008-02-05 22:21:54 +0000190namespace clang {
191
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000192class RValue {
193public:
194 enum BaseKind { LValueKind=0x0,
195 NonLValueKind=0x1,
196 UninitializedKind=0x2,
197 InvalidKind=0x3 };
198
199 enum { BaseBits = 2,
200 BaseMask = 0x3 };
201
202private:
203 void* Data;
204 unsigned Kind;
205
206protected:
207 RValue(const void* d, bool isLValue, unsigned ValKind)
208 : Data(const_cast<void*>(d)),
209 Kind((isLValue ? LValueKind : NonLValueKind) | (ValKind << BaseBits)) {}
210
211 explicit RValue(BaseKind k)
212 : Data(0), Kind(k) {}
213
214 void* getRawPtr() const {
215 return reinterpret_cast<void*>(Data);
216 }
217
218public:
219 ~RValue() {};
220
Ted Kremenekcba2e432008-02-05 19:35:18 +0000221 /// BufferTy - A temporary buffer to hold a set of RValues.
222 typedef llvm::SmallVector<RValue,5> BufferTy;
223
224
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000225 RValue Cast(ValueManager& ValMgr, Expr* CastExpr) const;
226
227 unsigned getRawKind() const { return Kind; }
228 BaseKind getBaseKind() const { return (BaseKind) (Kind & BaseMask); }
229 unsigned getSubKind() const { return (Kind & ~BaseMask) >> BaseBits; }
230
231 void Profile(llvm::FoldingSetNodeID& ID) const {
232 ID.AddInteger((unsigned) getRawKind());
233 ID.AddPointer(reinterpret_cast<void*>(Data));
234 }
235
236 bool operator==(const RValue& RHS) const {
237 return getRawKind() == RHS.getRawKind() && Data == RHS.Data;
238 }
239
240 static RValue GetSymbolValue(SymbolManager& SymMgr, ParmVarDecl *D);
241
242 inline bool isValid() const { return getRawKind() != InvalidKind; }
243 inline bool isInvalid() const { return getRawKind() == InvalidKind; }
244
245 void print(std::ostream& OS) const;
246 void print() const { print(*llvm::cerr.stream()); }
247
248 // Implement isa<T> support.
249 static inline bool classof(const RValue*) { return true; }
250};
251
252class InvalidValue : public RValue {
253public:
254 InvalidValue() : RValue(InvalidKind) {}
255
256 static inline bool classof(const RValue* V) {
257 return V->getBaseKind() == InvalidKind;
258 }
259};
260
261class UninitializedValue : public RValue {
262public:
263 UninitializedValue() : RValue(UninitializedKind) {}
264
265 static inline bool classof(const RValue* V) {
266 return V->getBaseKind() == UninitializedKind;
267 }
268};
269
270class NonLValue : public RValue {
271protected:
272 NonLValue(unsigned SubKind, const void* d) : RValue(d, false, SubKind) {}
273
274public:
275 void print(std::ostream& Out) const;
276
Ted Kremeneka6e4d212008-02-01 06:36:40 +0000277 RValue Cast(ValueManager& ValMgr, Expr* CastExpr) const;
278
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000279 // Arithmetic operators.
280 NonLValue Add(ValueManager& ValMgr, const NonLValue& RHS) const;
281 NonLValue Sub(ValueManager& ValMgr, const NonLValue& RHS) const;
282 NonLValue Mul(ValueManager& ValMgr, const NonLValue& RHS) const;
283 NonLValue Div(ValueManager& ValMgr, const NonLValue& RHS) const;
284 NonLValue Rem(ValueManager& ValMgr, const NonLValue& RHS) const;
285 NonLValue UnaryMinus(ValueManager& ValMgr, UnaryOperator* U) const;
Ted Kremenekc5d3b4c2008-02-04 16:58:30 +0000286 NonLValue BitwiseComplement(ValueManager& ValMgr) const;
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000287
288 // Equality operators.
289 NonLValue EQ(ValueManager& ValMgr, const NonLValue& RHS) const;
290 NonLValue NE(ValueManager& ValMgr, const NonLValue& RHS) const;
291
Ted Kremeneka6e4d212008-02-01 06:36:40 +0000292
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000293 // Utility methods to create NonLValues.
294 static NonLValue GetValue(ValueManager& ValMgr, uint64_t X, QualType T,
295 SourceLocation Loc = SourceLocation());
296
297 static NonLValue GetValue(ValueManager& ValMgr, IntegerLiteral* I);
298
299 static inline NonLValue GetIntTruthValue(ValueManager& ValMgr, bool X) {
300 return GetValue(ValMgr, X ? 1U : 0U, ValMgr.getContext().IntTy);
301 }
302
303 // Implement isa<T> support.
304 static inline bool classof(const RValue* V) {
305 return V->getBaseKind() >= NonLValueKind;
306 }
307};
308
309class LValue : public RValue {
310protected:
Ted Kremenek516f91b2008-01-31 22:17:03 +0000311 LValue(unsigned SubKind, const void* D) : RValue(const_cast<void*>(D),
312 true, SubKind) {}
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000313
314public:
315 void print(std::ostream& Out) const;
316
Ted Kremeneka6e4d212008-02-01 06:36:40 +0000317 RValue Cast(ValueManager& ValMgr, Expr* CastExpr) const;
318
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000319 // Equality operators.
320 NonLValue EQ(ValueManager& ValMgr, const LValue& RHS) const;
321 NonLValue NE(ValueManager& ValMgr, const LValue& RHS) const;
322
323 // Implement isa<T> support.
324 static inline bool classof(const RValue* V) {
325 return V->getBaseKind() == LValueKind;
326 }
327};
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000328
329//==------------------------------------------------------------------------==//
330// Subclasses of NonLValue.
331//==------------------------------------------------------------------------==//
332
Ted Kremenek329f8542008-02-05 21:52:21 +0000333namespace nonlval {
334
335 enum Kind { SymbolValKind,
Ted Kremenek9466aa82008-02-05 22:10:48 +0000336 SymIntConstraintValKind,
Ted Kremenek329f8542008-02-05 21:52:21 +0000337 ConcreteIntKind,
338 NumKind };
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000339
Ted Kremenek329f8542008-02-05 21:52:21 +0000340 class SymbolVal : public NonLValue {
341 public:
342 SymbolVal(unsigned SymID)
343 : NonLValue(SymbolValKind,
344 reinterpret_cast<void*>((uintptr_t) SymID)) {}
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000345
Ted Kremenek0806acf2008-02-05 23:08:41 +0000346 SymbolID getSymbol() const {
Ted Kremenek329f8542008-02-05 21:52:21 +0000347 return (SymbolID) reinterpret_cast<uintptr_t>(getRawPtr());
348 }
349
350 static inline bool classof(const RValue* V) {
Ted Kremenek9466aa82008-02-05 22:10:48 +0000351 return isa<NonLValue>(V) && V->getSubKind() == SymbolValKind;
352 }
353 };
354
355 class SymIntConstraintVal : public NonLValue {
356 public:
357 SymIntConstraintVal(const SymIntConstraint& C)
358 : NonLValue(SymIntConstraintValKind, reinterpret_cast<const void*>(&C)) {}
359
360 const SymIntConstraint& getConstraint() const {
361 return *reinterpret_cast<SymIntConstraint*>(getRawPtr());
362 }
363
364 static inline bool classof(const RValue* V) {
365 return isa<NonLValue>(V) && V->getSubKind() == SymIntConstraintValKind;
366 }
Ted Kremenek329f8542008-02-05 21:52:21 +0000367 };
368
369 class ConcreteInt : public NonLValue {
370 public:
371 ConcreteInt(const llvm::APSInt& V) : NonLValue(ConcreteIntKind, &V) {}
372
373 const llvm::APSInt& getValue() const {
374 return *static_cast<llvm::APSInt*>(getRawPtr());
375 }
376
377 // Arithmetic operators.
378
379 ConcreteInt Add(ValueManager& ValMgr, const ConcreteInt& V) const {
380 return ValMgr.getValue(getValue() + V.getValue());
381 }
382
383 ConcreteInt Sub(ValueManager& ValMgr, const ConcreteInt& V) const {
384 return ValMgr.getValue(getValue() - V.getValue());
385 }
386
387 ConcreteInt Mul(ValueManager& ValMgr, const ConcreteInt& V) const {
388 return ValMgr.getValue(getValue() * V.getValue());
389 }
390
391 ConcreteInt Div(ValueManager& ValMgr, const ConcreteInt& V) const {
392 return ValMgr.getValue(getValue() / V.getValue());
393 }
394
395 ConcreteInt Rem(ValueManager& ValMgr, const ConcreteInt& V) const {
396 return ValMgr.getValue(getValue() % V.getValue());
397 }
398
399 ConcreteInt UnaryMinus(ValueManager& ValMgr, UnaryOperator* U) const {
400 assert (U->getType() == U->getSubExpr()->getType());
401 assert (U->getType()->isIntegerType());
402 return ValMgr.getValue(-getValue());
403 }
404
405 ConcreteInt BitwiseComplement(ValueManager& ValMgr) const {
406 return ValMgr.getValue(~getValue());
407 }
408
409 // Casting.
410
411 ConcreteInt Cast(ValueManager& ValMgr, Expr* CastExpr) const {
412 assert (CastExpr->getType()->isIntegerType());
413
414 llvm::APSInt X(getValue());
415 X.extOrTrunc(ValMgr.getContext().getTypeSize(CastExpr->getType(),
416 CastExpr->getLocStart()));
417 return ValMgr.getValue(X);
418 }
419
420 // Equality operators.
421
422 ConcreteInt EQ(ValueManager& ValMgr, const ConcreteInt& V) const {
423 const llvm::APSInt& Val = getValue();
424 return ValMgr.getValue(Val == V.getValue() ? 1U : 0U,
425 Val.getBitWidth(), Val.isUnsigned());
426 }
427
428 ConcreteInt NE(ValueManager& ValMgr, const ConcreteInt& V) const {
429 const llvm::APSInt& Val = getValue();
430 return ValMgr.getValue(Val != V.getValue() ? 1U : 0U,
431 Val.getBitWidth(), Val.isUnsigned());
432 }
433
434 // Implement isa<T> support.
435 static inline bool classof(const RValue* V) {
Ted Kremenek9466aa82008-02-05 22:10:48 +0000436 return isa<NonLValue>(V) && V->getSubKind() == ConcreteIntKind;
Ted Kremenek329f8542008-02-05 21:52:21 +0000437 }
438 };
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000439
Ted Kremenek329f8542008-02-05 21:52:21 +0000440} // end namespace clang::nonlval
Ted Kremenek516f91b2008-01-31 22:17:03 +0000441
442//==------------------------------------------------------------------------==//
443// Subclasses of LValue.
444//==------------------------------------------------------------------------==//
445
Ted Kremenek329f8542008-02-05 21:52:21 +0000446namespace lval {
Ted Kremeneka6e4d212008-02-01 06:36:40 +0000447
Ted Kremenek329f8542008-02-05 21:52:21 +0000448 enum Kind { SymbolValKind,
Ted Kremenek0806acf2008-02-05 23:08:41 +0000449 SymIntConstraintValKind,
Ted Kremenek329f8542008-02-05 21:52:21 +0000450 DeclValKind,
451 ConcreteIntKind,
452 NumKind };
Ted Kremenek516f91b2008-01-31 22:17:03 +0000453
Ted Kremenek329f8542008-02-05 21:52:21 +0000454 class SymbolVal : public LValue {
455 public:
456 SymbolVal(unsigned SymID)
457 : LValue(SymbolValKind, reinterpret_cast<void*>((uintptr_t) SymID)) {}
458
Ted Kremenek0806acf2008-02-05 23:08:41 +0000459 SymbolID getSymbol() const {
Ted Kremenek329f8542008-02-05 21:52:21 +0000460 return (SymbolID) reinterpret_cast<uintptr_t>(getRawPtr());
461 }
462
463 static inline bool classof(const RValue* V) {
464 return V->getSubKind() == SymbolValKind;
465 }
466 };
Ted Kremenek0806acf2008-02-05 23:08:41 +0000467
468 class SymIntConstraintVal : public LValue {
469 public:
470 SymIntConstraintVal(const SymIntConstraint& C)
471 : LValue(SymIntConstraintValKind, reinterpret_cast<const void*>(&C)) {}
472
473 const SymIntConstraint& getConstraint() const {
474 return *reinterpret_cast<SymIntConstraint*>(getRawPtr());
475 }
476
477 static inline bool classof(const RValue* V) {
478 return isa<LValue>(V) && V->getSubKind() == SymIntConstraintValKind;
479 }
480 };
Ted Kremenek516f91b2008-01-31 22:17:03 +0000481
Ted Kremenek329f8542008-02-05 21:52:21 +0000482 class DeclVal : public LValue {
483 public:
484 DeclVal(const ValueDecl* vd) : LValue(DeclValKind,vd) {}
485
486 ValueDecl* getDecl() const {
487 return static_cast<ValueDecl*>(getRawPtr());
488 }
489
490 inline bool operator==(const DeclVal& R) const {
491 return getDecl() == R.getDecl();
492 }
493
494 inline bool operator!=(const DeclVal& R) const {
495 return getDecl() != R.getDecl();
496 }
497
498 // Implement isa<T> support.
499 static inline bool classof(const RValue* V) {
500 return V->getSubKind() == DeclValKind;
501 }
502 };
Ted Kremenek516f91b2008-01-31 22:17:03 +0000503
Ted Kremenek329f8542008-02-05 21:52:21 +0000504 class ConcreteInt : public LValue {
505 public:
506 ConcreteInt(const llvm::APSInt& V) : LValue(ConcreteIntKind, &V) {}
507
508 const llvm::APSInt& getValue() const {
509 return *static_cast<llvm::APSInt*>(getRawPtr());
510 }
511
512 // Arithmetic operators.
513
514 ConcreteInt Add(ValueManager& ValMgr, const ConcreteInt& V) const {
515 return ValMgr.getValue(getValue() + V.getValue());
516 }
517
518 ConcreteInt Sub(ValueManager& ValMgr, const ConcreteInt& V) const {
519 return ValMgr.getValue(getValue() - V.getValue());
520 }
521
522 // Equality operators.
523
524 ConcreteInt EQ(ValueManager& ValMgr, const ConcreteInt& V) const {
525 const llvm::APSInt& Val = getValue();
526 return ValMgr.getValue(Val == V.getValue() ? 1U : 0U,
527 Val.getBitWidth(), Val.isUnsigned());
528 }
529
530 ConcreteInt NE(ValueManager& ValMgr, const ConcreteInt& V) const {
531 const llvm::APSInt& Val = getValue();
532 return ValMgr.getValue(Val != V.getValue() ? 1U : 0U,
533 Val.getBitWidth(), Val.isUnsigned());
534 }
535
536 // Implement isa<T> support.
537 static inline bool classof(const RValue* V) {
538 return V->getSubKind() == ConcreteIntKind;
539 }
540 };
541} // end clang::lval namespace
Ted Kremenek516f91b2008-01-31 22:17:03 +0000542
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000543
544} // end clang namespace
545
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000546#endif