blob: bf3fe0dec9e98a68e901e77d4e5213b4961cde92 [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); }
Ted Kremenekfeb01f62008-02-06 17:32:17 +000074 inline bool operator==(const SymbolData& R) const { return Data == R.Data; }
75
76 QualType getType() const;
Ted Kremeneka90ccfe2008-01-31 19:34:24 +000077};
Ted Kremenek1fbdb022008-02-05 21:32:43 +000078
79
80class SymIntConstraint : public llvm::FoldingSetNode {
81 SymbolID Symbol;
82 BinaryOperator::Opcode Op;
83 const llvm::APSInt& Val;
84public:
85 SymIntConstraint(SymbolID sym, BinaryOperator::Opcode op,
86 const llvm::APSInt& V)
87 : Symbol(sym),
88 Op(op), Val(V) {}
89
90 BinaryOperator::Opcode getOpcode() const { return Op; }
91 SymbolID getSymbol() const { return Symbol; }
92 const llvm::APSInt& getInt() const { return Val; }
93
94 static inline void Profile(llvm::FoldingSetNodeID& ID,
95 const SymbolID& Symbol,
96 BinaryOperator::Opcode Op,
97 const llvm::APSInt& Val) {
98 Symbol.Profile(ID);
99 ID.AddInteger(Op);
100 ID.AddPointer(&Val);
101 }
102
103 void Profile(llvm::FoldingSetNodeID& ID) {
104 Profile(ID, Symbol, Op, Val);
105 }
106};
107
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000108
109class SymbolManager {
110 std::vector<SymbolData> SymbolToData;
111
112 typedef llvm::DenseMap<void*,SymbolID> MapTy;
113 MapTy DataToSymbol;
114
115public:
116 SymbolManager();
117 ~SymbolManager();
118
Ted Kremenekfeb01f62008-02-06 17:32:17 +0000119 SymbolID getSymbol(ParmVarDecl* D);
120
121 inline SymbolData getSymbolData(SymbolID ID) const {
122 assert (ID < SymbolToData.size());
123 return SymbolToData[ID];
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000124 }
125
Ted Kremenekfeb01f62008-02-06 17:32:17 +0000126 inline QualType getType(SymbolID ID) const {
127 return getSymbolData(ID).getType();
128 }
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000129};
Ted Kremenek1fbdb022008-02-05 21:32:43 +0000130
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000131
132class ValueManager {
133 typedef llvm::FoldingSet<llvm::FoldingSetNodeWrapper<llvm::APSInt> >
134 APSIntSetTy;
135
Ted Kremenek1fbdb022008-02-05 21:32:43 +0000136 typedef llvm::FoldingSet<SymIntConstraint>
137 SymIntCSetTy;
138
139
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000140 ASTContext& Ctx;
Ted Kremenek768ad162008-02-05 05:15:51 +0000141 llvm::BumpPtrAllocator& BPAlloc;
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000142
Ted Kremenek1fbdb022008-02-05 21:32:43 +0000143 APSIntSetTy APSIntSet;
144 SymIntCSetTy SymIntCSet;
145
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000146public:
Ted Kremenek768ad162008-02-05 05:15:51 +0000147 ValueManager(ASTContext& ctx, llvm::BumpPtrAllocator& Alloc)
148 : Ctx(ctx), BPAlloc(Alloc) {}
149
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000150 ~ValueManager();
151
152 ASTContext& getContext() const { return Ctx; }
Ted Kremenek1fbdb022008-02-05 21:32:43 +0000153 const llvm::APSInt& getValue(const llvm::APSInt& X);
154 const llvm::APSInt& getValue(uint64_t X, unsigned BitWidth, bool isUnsigned);
155 const llvm::APSInt& getValue(uint64_t X, QualType T,
156 SourceLocation Loc = SourceLocation());
157
Ted Kremenek862d5bb2008-02-06 00:54:14 +0000158 inline const llvm::APSInt& getZeroWithPtrWidth() {
159 return getValue(0, Ctx.getTypeSize(Ctx.VoidPtrTy, SourceLocation()), true);
160 }
161
Ted Kremenek1fbdb022008-02-05 21:32:43 +0000162 const SymIntConstraint& getConstraint(SymbolID sym, BinaryOperator::Opcode Op,
163 const llvm::APSInt& V);
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000164};
Ted Kremenek0f10d502008-02-05 22:21:54 +0000165
166} // end clang namespace
167
168//==------------------------------------------------------------------------==//
169// Casting machinery to get cast<> and dyn_cast<> working with SymbolData.
170//==------------------------------------------------------------------------==//
171
172namespace llvm {
173
174 template<> inline bool
175 isa<clang::ParmVarDecl,clang::SymbolData>(const clang::SymbolData& V) {
176 return V.getKind() == clang::SymbolData::ParmKind;
177 }
178
179 template<> struct cast_retty_impl<clang::ParmVarDecl,clang::SymbolData> {
180 typedef const clang::ParmVarDecl* ret_type;
181 };
182
183 template<> struct simplify_type<clang::SymbolData> {
184 typedef void* SimpleType;
185 static inline SimpleType getSimplifiedValue(const clang::SymbolData &V) {
186 return V.getPtr();
187 }
188 };
189
190} // end llvm namespace
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000191
192//==------------------------------------------------------------------------==//
193// Base RValue types.
194//==------------------------------------------------------------------------==//
195
Ted Kremenek0f10d502008-02-05 22:21:54 +0000196namespace clang {
197
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000198class RValue {
199public:
200 enum BaseKind { LValueKind=0x0,
201 NonLValueKind=0x1,
202 UninitializedKind=0x2,
203 InvalidKind=0x3 };
204
205 enum { BaseBits = 2,
206 BaseMask = 0x3 };
207
208private:
209 void* Data;
210 unsigned Kind;
211
212protected:
213 RValue(const void* d, bool isLValue, unsigned ValKind)
214 : Data(const_cast<void*>(d)),
215 Kind((isLValue ? LValueKind : NonLValueKind) | (ValKind << BaseBits)) {}
216
217 explicit RValue(BaseKind k)
218 : Data(0), Kind(k) {}
219
220 void* getRawPtr() const {
221 return reinterpret_cast<void*>(Data);
222 }
223
224public:
225 ~RValue() {};
226
Ted Kremenekcba2e432008-02-05 19:35:18 +0000227 /// BufferTy - A temporary buffer to hold a set of RValues.
228 typedef llvm::SmallVector<RValue,5> BufferTy;
229
230
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000231 RValue Cast(ValueManager& ValMgr, Expr* CastExpr) const;
232
233 unsigned getRawKind() const { return Kind; }
234 BaseKind getBaseKind() const { return (BaseKind) (Kind & BaseMask); }
235 unsigned getSubKind() const { return (Kind & ~BaseMask) >> BaseBits; }
236
237 void Profile(llvm::FoldingSetNodeID& ID) const {
238 ID.AddInteger((unsigned) getRawKind());
239 ID.AddPointer(reinterpret_cast<void*>(Data));
240 }
241
242 bool operator==(const RValue& RHS) const {
243 return getRawKind() == RHS.getRawKind() && Data == RHS.Data;
244 }
245
246 static RValue GetSymbolValue(SymbolManager& SymMgr, ParmVarDecl *D);
247
248 inline bool isValid() const { return getRawKind() != InvalidKind; }
249 inline bool isInvalid() const { return getRawKind() == InvalidKind; }
250
251 void print(std::ostream& OS) const;
252 void print() const { print(*llvm::cerr.stream()); }
253
254 // Implement isa<T> support.
255 static inline bool classof(const RValue*) { return true; }
256};
257
258class InvalidValue : public RValue {
259public:
260 InvalidValue() : RValue(InvalidKind) {}
261
262 static inline bool classof(const RValue* V) {
263 return V->getBaseKind() == InvalidKind;
264 }
265};
266
267class UninitializedValue : public RValue {
268public:
269 UninitializedValue() : RValue(UninitializedKind) {}
270
271 static inline bool classof(const RValue* V) {
272 return V->getBaseKind() == UninitializedKind;
273 }
274};
275
276class NonLValue : public RValue {
277protected:
278 NonLValue(unsigned SubKind, const void* d) : RValue(d, false, SubKind) {}
279
280public:
281 void print(std::ostream& Out) const;
282
Ted Kremeneka6e4d212008-02-01 06:36:40 +0000283 RValue Cast(ValueManager& ValMgr, Expr* CastExpr) const;
284
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000285 // Arithmetic operators.
286 NonLValue Add(ValueManager& ValMgr, const NonLValue& RHS) const;
287 NonLValue Sub(ValueManager& ValMgr, const NonLValue& RHS) const;
288 NonLValue Mul(ValueManager& ValMgr, const NonLValue& RHS) const;
289 NonLValue Div(ValueManager& ValMgr, const NonLValue& RHS) const;
290 NonLValue Rem(ValueManager& ValMgr, const NonLValue& RHS) const;
291 NonLValue UnaryMinus(ValueManager& ValMgr, UnaryOperator* U) const;
Ted Kremenekc5d3b4c2008-02-04 16:58:30 +0000292 NonLValue BitwiseComplement(ValueManager& ValMgr) const;
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000293
294 // Equality operators.
295 NonLValue EQ(ValueManager& ValMgr, const NonLValue& RHS) const;
296 NonLValue NE(ValueManager& ValMgr, const NonLValue& RHS) const;
297
Ted Kremeneka6e4d212008-02-01 06:36:40 +0000298
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000299 // Utility methods to create NonLValues.
300 static NonLValue GetValue(ValueManager& ValMgr, uint64_t X, QualType T,
301 SourceLocation Loc = SourceLocation());
302
303 static NonLValue GetValue(ValueManager& ValMgr, IntegerLiteral* I);
304
305 static inline NonLValue GetIntTruthValue(ValueManager& ValMgr, bool X) {
306 return GetValue(ValMgr, X ? 1U : 0U, ValMgr.getContext().IntTy);
307 }
308
309 // Implement isa<T> support.
310 static inline bool classof(const RValue* V) {
311 return V->getBaseKind() >= NonLValueKind;
312 }
313};
314
315class LValue : public RValue {
316protected:
Ted Kremenek516f91b2008-01-31 22:17:03 +0000317 LValue(unsigned SubKind, const void* D) : RValue(const_cast<void*>(D),
318 true, SubKind) {}
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000319
320public:
321 void print(std::ostream& Out) const;
322
Ted Kremeneka6e4d212008-02-01 06:36:40 +0000323 RValue Cast(ValueManager& ValMgr, Expr* CastExpr) const;
324
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000325 // Equality operators.
326 NonLValue EQ(ValueManager& ValMgr, const LValue& RHS) const;
327 NonLValue NE(ValueManager& ValMgr, const LValue& RHS) const;
328
329 // Implement isa<T> support.
330 static inline bool classof(const RValue* V) {
331 return V->getBaseKind() == LValueKind;
332 }
333};
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000334
335//==------------------------------------------------------------------------==//
336// Subclasses of NonLValue.
337//==------------------------------------------------------------------------==//
338
Ted Kremenek329f8542008-02-05 21:52:21 +0000339namespace nonlval {
340
341 enum Kind { SymbolValKind,
Ted Kremenek9466aa82008-02-05 22:10:48 +0000342 SymIntConstraintValKind,
Ted Kremenek329f8542008-02-05 21:52:21 +0000343 ConcreteIntKind,
344 NumKind };
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000345
Ted Kremenek329f8542008-02-05 21:52:21 +0000346 class SymbolVal : public NonLValue {
347 public:
348 SymbolVal(unsigned SymID)
349 : NonLValue(SymbolValKind,
350 reinterpret_cast<void*>((uintptr_t) SymID)) {}
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000351
Ted Kremenek0806acf2008-02-05 23:08:41 +0000352 SymbolID getSymbol() const {
Ted Kremenek329f8542008-02-05 21:52:21 +0000353 return (SymbolID) reinterpret_cast<uintptr_t>(getRawPtr());
354 }
355
356 static inline bool classof(const RValue* V) {
Ted Kremenek9466aa82008-02-05 22:10:48 +0000357 return isa<NonLValue>(V) && V->getSubKind() == SymbolValKind;
358 }
359 };
360
361 class SymIntConstraintVal : public NonLValue {
362 public:
363 SymIntConstraintVal(const SymIntConstraint& C)
364 : NonLValue(SymIntConstraintValKind, reinterpret_cast<const void*>(&C)) {}
365
366 const SymIntConstraint& getConstraint() const {
367 return *reinterpret_cast<SymIntConstraint*>(getRawPtr());
368 }
369
370 static inline bool classof(const RValue* V) {
371 return isa<NonLValue>(V) && V->getSubKind() == SymIntConstraintValKind;
372 }
Ted Kremenek329f8542008-02-05 21:52:21 +0000373 };
374
375 class ConcreteInt : public NonLValue {
376 public:
377 ConcreteInt(const llvm::APSInt& V) : NonLValue(ConcreteIntKind, &V) {}
378
379 const llvm::APSInt& getValue() const {
380 return *static_cast<llvm::APSInt*>(getRawPtr());
381 }
382
383 // Arithmetic operators.
384
385 ConcreteInt Add(ValueManager& ValMgr, const ConcreteInt& V) const {
386 return ValMgr.getValue(getValue() + V.getValue());
387 }
388
389 ConcreteInt Sub(ValueManager& ValMgr, const ConcreteInt& V) const {
390 return ValMgr.getValue(getValue() - V.getValue());
391 }
392
393 ConcreteInt Mul(ValueManager& ValMgr, const ConcreteInt& V) const {
394 return ValMgr.getValue(getValue() * V.getValue());
395 }
396
397 ConcreteInt Div(ValueManager& ValMgr, const ConcreteInt& V) const {
398 return ValMgr.getValue(getValue() / V.getValue());
399 }
400
401 ConcreteInt Rem(ValueManager& ValMgr, const ConcreteInt& V) const {
402 return ValMgr.getValue(getValue() % V.getValue());
403 }
404
405 ConcreteInt UnaryMinus(ValueManager& ValMgr, UnaryOperator* U) const {
406 assert (U->getType() == U->getSubExpr()->getType());
407 assert (U->getType()->isIntegerType());
408 return ValMgr.getValue(-getValue());
409 }
410
411 ConcreteInt BitwiseComplement(ValueManager& ValMgr) const {
412 return ValMgr.getValue(~getValue());
413 }
414
415 // Casting.
416
417 ConcreteInt Cast(ValueManager& ValMgr, Expr* CastExpr) const {
418 assert (CastExpr->getType()->isIntegerType());
419
420 llvm::APSInt X(getValue());
421 X.extOrTrunc(ValMgr.getContext().getTypeSize(CastExpr->getType(),
422 CastExpr->getLocStart()));
423 return ValMgr.getValue(X);
424 }
425
426 // Equality operators.
427
428 ConcreteInt EQ(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 ConcreteInt NE(ValueManager& ValMgr, const ConcreteInt& V) const {
435 const llvm::APSInt& Val = getValue();
436 return ValMgr.getValue(Val != V.getValue() ? 1U : 0U,
437 Val.getBitWidth(), Val.isUnsigned());
438 }
439
440 // Implement isa<T> support.
441 static inline bool classof(const RValue* V) {
Ted Kremenek9466aa82008-02-05 22:10:48 +0000442 return isa<NonLValue>(V) && V->getSubKind() == ConcreteIntKind;
Ted Kremenek329f8542008-02-05 21:52:21 +0000443 }
444 };
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000445
Ted Kremenek329f8542008-02-05 21:52:21 +0000446} // end namespace clang::nonlval
Ted Kremenek516f91b2008-01-31 22:17:03 +0000447
448//==------------------------------------------------------------------------==//
449// Subclasses of LValue.
450//==------------------------------------------------------------------------==//
451
Ted Kremenek329f8542008-02-05 21:52:21 +0000452namespace lval {
Ted Kremeneka6e4d212008-02-01 06:36:40 +0000453
Ted Kremenek329f8542008-02-05 21:52:21 +0000454 enum Kind { SymbolValKind,
455 DeclValKind,
456 ConcreteIntKind,
457 NumKind };
Ted Kremenek516f91b2008-01-31 22:17:03 +0000458
Ted Kremenek329f8542008-02-05 21:52:21 +0000459 class SymbolVal : public LValue {
460 public:
461 SymbolVal(unsigned SymID)
462 : LValue(SymbolValKind, reinterpret_cast<void*>((uintptr_t) SymID)) {}
463
Ted Kremenek0806acf2008-02-05 23:08:41 +0000464 SymbolID getSymbol() const {
Ted Kremenek329f8542008-02-05 21:52:21 +0000465 return (SymbolID) reinterpret_cast<uintptr_t>(getRawPtr());
466 }
467
468 static inline bool classof(const RValue* V) {
469 return V->getSubKind() == SymbolValKind;
470 }
471 };
Ted Kremenek0806acf2008-02-05 23:08:41 +0000472
Ted Kremenek329f8542008-02-05 21:52:21 +0000473 class DeclVal : public LValue {
474 public:
475 DeclVal(const ValueDecl* vd) : LValue(DeclValKind,vd) {}
476
477 ValueDecl* getDecl() const {
478 return static_cast<ValueDecl*>(getRawPtr());
479 }
480
481 inline bool operator==(const DeclVal& R) const {
482 return getDecl() == R.getDecl();
483 }
484
485 inline bool operator!=(const DeclVal& R) const {
486 return getDecl() != R.getDecl();
487 }
488
489 // Implement isa<T> support.
490 static inline bool classof(const RValue* V) {
491 return V->getSubKind() == DeclValKind;
492 }
493 };
Ted Kremenek516f91b2008-01-31 22:17:03 +0000494
Ted Kremenek329f8542008-02-05 21:52:21 +0000495 class ConcreteInt : public LValue {
496 public:
497 ConcreteInt(const llvm::APSInt& V) : LValue(ConcreteIntKind, &V) {}
498
499 const llvm::APSInt& getValue() const {
500 return *static_cast<llvm::APSInt*>(getRawPtr());
501 }
502
503 // Arithmetic operators.
504
505 ConcreteInt Add(ValueManager& ValMgr, const ConcreteInt& V) const {
506 return ValMgr.getValue(getValue() + V.getValue());
507 }
508
509 ConcreteInt Sub(ValueManager& ValMgr, const ConcreteInt& V) const {
510 return ValMgr.getValue(getValue() - V.getValue());
511 }
512
513 // Equality operators.
514
515 ConcreteInt EQ(ValueManager& ValMgr, const ConcreteInt& V) const {
516 const llvm::APSInt& Val = getValue();
517 return ValMgr.getValue(Val == V.getValue() ? 1U : 0U,
518 Val.getBitWidth(), Val.isUnsigned());
519 }
520
521 ConcreteInt NE(ValueManager& ValMgr, const ConcreteInt& V) const {
522 const llvm::APSInt& Val = getValue();
523 return ValMgr.getValue(Val != V.getValue() ? 1U : 0U,
524 Val.getBitWidth(), Val.isUnsigned());
525 }
526
527 // Implement isa<T> support.
528 static inline bool classof(const RValue* V) {
529 return V->getSubKind() == ConcreteIntKind;
530 }
531 };
532} // end clang::lval namespace
Ted Kremenek516f91b2008-01-31 22:17:03 +0000533
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000534
535} // end clang namespace
536
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000537#endif