blob: 9c788cac354390ee589b2da52f8c12fd8f332bef [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
152 const SymIntConstraint& getConstraint(SymbolID sym, BinaryOperator::Opcode Op,
153 const llvm::APSInt& V);
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000154};
Ted Kremenek0f10d502008-02-05 22:21:54 +0000155
156} // end clang namespace
157
158//==------------------------------------------------------------------------==//
159// Casting machinery to get cast<> and dyn_cast<> working with SymbolData.
160//==------------------------------------------------------------------------==//
161
162namespace llvm {
163
164 template<> inline bool
165 isa<clang::ParmVarDecl,clang::SymbolData>(const clang::SymbolData& V) {
166 return V.getKind() == clang::SymbolData::ParmKind;
167 }
168
169 template<> struct cast_retty_impl<clang::ParmVarDecl,clang::SymbolData> {
170 typedef const clang::ParmVarDecl* ret_type;
171 };
172
173 template<> struct simplify_type<clang::SymbolData> {
174 typedef void* SimpleType;
175 static inline SimpleType getSimplifiedValue(const clang::SymbolData &V) {
176 return V.getPtr();
177 }
178 };
179
180} // end llvm namespace
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000181
182//==------------------------------------------------------------------------==//
183// Base RValue types.
184//==------------------------------------------------------------------------==//
185
Ted Kremenek0f10d502008-02-05 22:21:54 +0000186namespace clang {
187
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000188class RValue {
189public:
190 enum BaseKind { LValueKind=0x0,
191 NonLValueKind=0x1,
192 UninitializedKind=0x2,
193 InvalidKind=0x3 };
194
195 enum { BaseBits = 2,
196 BaseMask = 0x3 };
197
198private:
199 void* Data;
200 unsigned Kind;
201
202protected:
203 RValue(const void* d, bool isLValue, unsigned ValKind)
204 : Data(const_cast<void*>(d)),
205 Kind((isLValue ? LValueKind : NonLValueKind) | (ValKind << BaseBits)) {}
206
207 explicit RValue(BaseKind k)
208 : Data(0), Kind(k) {}
209
210 void* getRawPtr() const {
211 return reinterpret_cast<void*>(Data);
212 }
213
214public:
215 ~RValue() {};
216
Ted Kremenekcba2e432008-02-05 19:35:18 +0000217 /// BufferTy - A temporary buffer to hold a set of RValues.
218 typedef llvm::SmallVector<RValue,5> BufferTy;
219
220
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000221 RValue Cast(ValueManager& ValMgr, Expr* CastExpr) const;
222
223 unsigned getRawKind() const { return Kind; }
224 BaseKind getBaseKind() const { return (BaseKind) (Kind & BaseMask); }
225 unsigned getSubKind() const { return (Kind & ~BaseMask) >> BaseBits; }
226
227 void Profile(llvm::FoldingSetNodeID& ID) const {
228 ID.AddInteger((unsigned) getRawKind());
229 ID.AddPointer(reinterpret_cast<void*>(Data));
230 }
231
232 bool operator==(const RValue& RHS) const {
233 return getRawKind() == RHS.getRawKind() && Data == RHS.Data;
234 }
235
236 static RValue GetSymbolValue(SymbolManager& SymMgr, ParmVarDecl *D);
237
238 inline bool isValid() const { return getRawKind() != InvalidKind; }
239 inline bool isInvalid() const { return getRawKind() == InvalidKind; }
240
241 void print(std::ostream& OS) const;
242 void print() const { print(*llvm::cerr.stream()); }
243
244 // Implement isa<T> support.
245 static inline bool classof(const RValue*) { return true; }
246};
247
248class InvalidValue : public RValue {
249public:
250 InvalidValue() : RValue(InvalidKind) {}
251
252 static inline bool classof(const RValue* V) {
253 return V->getBaseKind() == InvalidKind;
254 }
255};
256
257class UninitializedValue : public RValue {
258public:
259 UninitializedValue() : RValue(UninitializedKind) {}
260
261 static inline bool classof(const RValue* V) {
262 return V->getBaseKind() == UninitializedKind;
263 }
264};
265
266class NonLValue : public RValue {
267protected:
268 NonLValue(unsigned SubKind, const void* d) : RValue(d, false, SubKind) {}
269
270public:
271 void print(std::ostream& Out) const;
272
Ted Kremeneka6e4d212008-02-01 06:36:40 +0000273 RValue Cast(ValueManager& ValMgr, Expr* CastExpr) const;
274
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000275 // Arithmetic operators.
276 NonLValue Add(ValueManager& ValMgr, const NonLValue& RHS) const;
277 NonLValue Sub(ValueManager& ValMgr, const NonLValue& RHS) const;
278 NonLValue Mul(ValueManager& ValMgr, const NonLValue& RHS) const;
279 NonLValue Div(ValueManager& ValMgr, const NonLValue& RHS) const;
280 NonLValue Rem(ValueManager& ValMgr, const NonLValue& RHS) const;
281 NonLValue UnaryMinus(ValueManager& ValMgr, UnaryOperator* U) const;
Ted Kremenekc5d3b4c2008-02-04 16:58:30 +0000282 NonLValue BitwiseComplement(ValueManager& ValMgr) const;
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000283
284 // Equality operators.
285 NonLValue EQ(ValueManager& ValMgr, const NonLValue& RHS) const;
286 NonLValue NE(ValueManager& ValMgr, const NonLValue& RHS) const;
287
Ted Kremeneka6e4d212008-02-01 06:36:40 +0000288
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000289 // Utility methods to create NonLValues.
290 static NonLValue GetValue(ValueManager& ValMgr, uint64_t X, QualType T,
291 SourceLocation Loc = SourceLocation());
292
293 static NonLValue GetValue(ValueManager& ValMgr, IntegerLiteral* I);
294
295 static inline NonLValue GetIntTruthValue(ValueManager& ValMgr, bool X) {
296 return GetValue(ValMgr, X ? 1U : 0U, ValMgr.getContext().IntTy);
297 }
298
299 // Implement isa<T> support.
300 static inline bool classof(const RValue* V) {
301 return V->getBaseKind() >= NonLValueKind;
302 }
303};
304
305class LValue : public RValue {
306protected:
Ted Kremenek516f91b2008-01-31 22:17:03 +0000307 LValue(unsigned SubKind, const void* D) : RValue(const_cast<void*>(D),
308 true, SubKind) {}
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000309
310public:
311 void print(std::ostream& Out) const;
312
Ted Kremeneka6e4d212008-02-01 06:36:40 +0000313 RValue Cast(ValueManager& ValMgr, Expr* CastExpr) const;
314
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000315 // Equality operators.
316 NonLValue EQ(ValueManager& ValMgr, const LValue& RHS) const;
317 NonLValue NE(ValueManager& ValMgr, const LValue& RHS) const;
318
319 // Implement isa<T> support.
320 static inline bool classof(const RValue* V) {
321 return V->getBaseKind() == LValueKind;
322 }
323};
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000324
325//==------------------------------------------------------------------------==//
326// Subclasses of NonLValue.
327//==------------------------------------------------------------------------==//
328
Ted Kremenek329f8542008-02-05 21:52:21 +0000329namespace nonlval {
330
331 enum Kind { SymbolValKind,
Ted Kremenek9466aa82008-02-05 22:10:48 +0000332 SymIntConstraintValKind,
Ted Kremenek329f8542008-02-05 21:52:21 +0000333 ConcreteIntKind,
334 NumKind };
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000335
Ted Kremenek329f8542008-02-05 21:52:21 +0000336 class SymbolVal : public NonLValue {
337 public:
338 SymbolVal(unsigned SymID)
339 : NonLValue(SymbolValKind,
340 reinterpret_cast<void*>((uintptr_t) SymID)) {}
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000341
Ted Kremenek0806acf2008-02-05 23:08:41 +0000342 SymbolID getSymbol() const {
Ted Kremenek329f8542008-02-05 21:52:21 +0000343 return (SymbolID) reinterpret_cast<uintptr_t>(getRawPtr());
344 }
345
346 static inline bool classof(const RValue* V) {
Ted Kremenek9466aa82008-02-05 22:10:48 +0000347 return isa<NonLValue>(V) && V->getSubKind() == SymbolValKind;
348 }
349 };
350
351 class SymIntConstraintVal : public NonLValue {
352 public:
353 SymIntConstraintVal(const SymIntConstraint& C)
354 : NonLValue(SymIntConstraintValKind, reinterpret_cast<const void*>(&C)) {}
355
356 const SymIntConstraint& getConstraint() const {
357 return *reinterpret_cast<SymIntConstraint*>(getRawPtr());
358 }
359
360 static inline bool classof(const RValue* V) {
361 return isa<NonLValue>(V) && V->getSubKind() == SymIntConstraintValKind;
362 }
Ted Kremenek329f8542008-02-05 21:52:21 +0000363 };
364
365 class ConcreteInt : public NonLValue {
366 public:
367 ConcreteInt(const llvm::APSInt& V) : NonLValue(ConcreteIntKind, &V) {}
368
369 const llvm::APSInt& getValue() const {
370 return *static_cast<llvm::APSInt*>(getRawPtr());
371 }
372
373 // Arithmetic operators.
374
375 ConcreteInt Add(ValueManager& ValMgr, const ConcreteInt& V) const {
376 return ValMgr.getValue(getValue() + V.getValue());
377 }
378
379 ConcreteInt Sub(ValueManager& ValMgr, const ConcreteInt& V) const {
380 return ValMgr.getValue(getValue() - V.getValue());
381 }
382
383 ConcreteInt Mul(ValueManager& ValMgr, const ConcreteInt& V) const {
384 return ValMgr.getValue(getValue() * V.getValue());
385 }
386
387 ConcreteInt Div(ValueManager& ValMgr, const ConcreteInt& V) const {
388 return ValMgr.getValue(getValue() / V.getValue());
389 }
390
391 ConcreteInt Rem(ValueManager& ValMgr, const ConcreteInt& V) const {
392 return ValMgr.getValue(getValue() % V.getValue());
393 }
394
395 ConcreteInt UnaryMinus(ValueManager& ValMgr, UnaryOperator* U) const {
396 assert (U->getType() == U->getSubExpr()->getType());
397 assert (U->getType()->isIntegerType());
398 return ValMgr.getValue(-getValue());
399 }
400
401 ConcreteInt BitwiseComplement(ValueManager& ValMgr) const {
402 return ValMgr.getValue(~getValue());
403 }
404
405 // Casting.
406
407 ConcreteInt Cast(ValueManager& ValMgr, Expr* CastExpr) const {
408 assert (CastExpr->getType()->isIntegerType());
409
410 llvm::APSInt X(getValue());
411 X.extOrTrunc(ValMgr.getContext().getTypeSize(CastExpr->getType(),
412 CastExpr->getLocStart()));
413 return ValMgr.getValue(X);
414 }
415
416 // Equality operators.
417
418 ConcreteInt EQ(ValueManager& ValMgr, const ConcreteInt& V) const {
419 const llvm::APSInt& Val = getValue();
420 return ValMgr.getValue(Val == V.getValue() ? 1U : 0U,
421 Val.getBitWidth(), Val.isUnsigned());
422 }
423
424 ConcreteInt NE(ValueManager& ValMgr, const ConcreteInt& V) const {
425 const llvm::APSInt& Val = getValue();
426 return ValMgr.getValue(Val != V.getValue() ? 1U : 0U,
427 Val.getBitWidth(), Val.isUnsigned());
428 }
429
430 // Implement isa<T> support.
431 static inline bool classof(const RValue* V) {
Ted Kremenek9466aa82008-02-05 22:10:48 +0000432 return isa<NonLValue>(V) && V->getSubKind() == ConcreteIntKind;
Ted Kremenek329f8542008-02-05 21:52:21 +0000433 }
434 };
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000435
Ted Kremenek329f8542008-02-05 21:52:21 +0000436} // end namespace clang::nonlval
Ted Kremenek516f91b2008-01-31 22:17:03 +0000437
438//==------------------------------------------------------------------------==//
439// Subclasses of LValue.
440//==------------------------------------------------------------------------==//
441
Ted Kremenek329f8542008-02-05 21:52:21 +0000442namespace lval {
Ted Kremeneka6e4d212008-02-01 06:36:40 +0000443
Ted Kremenek329f8542008-02-05 21:52:21 +0000444 enum Kind { SymbolValKind,
Ted Kremenek0806acf2008-02-05 23:08:41 +0000445 SymIntConstraintValKind,
Ted Kremenek329f8542008-02-05 21:52:21 +0000446 DeclValKind,
447 ConcreteIntKind,
448 NumKind };
Ted Kremenek516f91b2008-01-31 22:17:03 +0000449
Ted Kremenek329f8542008-02-05 21:52:21 +0000450 class SymbolVal : public LValue {
451 public:
452 SymbolVal(unsigned SymID)
453 : LValue(SymbolValKind, reinterpret_cast<void*>((uintptr_t) SymID)) {}
454
Ted Kremenek0806acf2008-02-05 23:08:41 +0000455 SymbolID getSymbol() const {
Ted Kremenek329f8542008-02-05 21:52:21 +0000456 return (SymbolID) reinterpret_cast<uintptr_t>(getRawPtr());
457 }
458
459 static inline bool classof(const RValue* V) {
460 return V->getSubKind() == SymbolValKind;
461 }
462 };
Ted Kremenek0806acf2008-02-05 23:08:41 +0000463
464 class SymIntConstraintVal : public LValue {
465 public:
466 SymIntConstraintVal(const SymIntConstraint& C)
467 : LValue(SymIntConstraintValKind, reinterpret_cast<const void*>(&C)) {}
468
469 const SymIntConstraint& getConstraint() const {
470 return *reinterpret_cast<SymIntConstraint*>(getRawPtr());
471 }
472
473 static inline bool classof(const RValue* V) {
474 return isa<LValue>(V) && V->getSubKind() == SymIntConstraintValKind;
475 }
476 };
Ted Kremenek516f91b2008-01-31 22:17:03 +0000477
Ted Kremenek329f8542008-02-05 21:52:21 +0000478 class DeclVal : public LValue {
479 public:
480 DeclVal(const ValueDecl* vd) : LValue(DeclValKind,vd) {}
481
482 ValueDecl* getDecl() const {
483 return static_cast<ValueDecl*>(getRawPtr());
484 }
485
486 inline bool operator==(const DeclVal& R) const {
487 return getDecl() == R.getDecl();
488 }
489
490 inline bool operator!=(const DeclVal& R) const {
491 return getDecl() != R.getDecl();
492 }
493
494 // Implement isa<T> support.
495 static inline bool classof(const RValue* V) {
496 return V->getSubKind() == DeclValKind;
497 }
498 };
Ted Kremenek516f91b2008-01-31 22:17:03 +0000499
Ted Kremenek329f8542008-02-05 21:52:21 +0000500 class ConcreteInt : public LValue {
501 public:
502 ConcreteInt(const llvm::APSInt& V) : LValue(ConcreteIntKind, &V) {}
503
504 const llvm::APSInt& getValue() const {
505 return *static_cast<llvm::APSInt*>(getRawPtr());
506 }
507
508 // Arithmetic operators.
509
510 ConcreteInt Add(ValueManager& ValMgr, const ConcreteInt& V) const {
511 return ValMgr.getValue(getValue() + V.getValue());
512 }
513
514 ConcreteInt Sub(ValueManager& ValMgr, const ConcreteInt& V) const {
515 return ValMgr.getValue(getValue() - V.getValue());
516 }
517
518 // Equality operators.
519
520 ConcreteInt EQ(ValueManager& ValMgr, const ConcreteInt& V) const {
521 const llvm::APSInt& Val = getValue();
522 return ValMgr.getValue(Val == V.getValue() ? 1U : 0U,
523 Val.getBitWidth(), Val.isUnsigned());
524 }
525
526 ConcreteInt NE(ValueManager& ValMgr, const ConcreteInt& V) const {
527 const llvm::APSInt& Val = getValue();
528 return ValMgr.getValue(Val != V.getValue() ? 1U : 0U,
529 Val.getBitWidth(), Val.isUnsigned());
530 }
531
532 // Implement isa<T> support.
533 static inline bool classof(const RValue* V) {
534 return V->getSubKind() == ConcreteIntKind;
535 }
536 };
537} // end clang::lval namespace
Ted Kremenek516f91b2008-01-31 22:17:03 +0000538
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000539
540} // end clang namespace
541
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000542#endif