blob: 6980a9bba44d353c79e2af5a54d21e11764bd954 [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};
155
156//==------------------------------------------------------------------------==//
157// Base RValue types.
158//==------------------------------------------------------------------------==//
159
160class RValue {
161public:
162 enum BaseKind { LValueKind=0x0,
163 NonLValueKind=0x1,
164 UninitializedKind=0x2,
165 InvalidKind=0x3 };
166
167 enum { BaseBits = 2,
168 BaseMask = 0x3 };
169
170private:
171 void* Data;
172 unsigned Kind;
173
174protected:
175 RValue(const void* d, bool isLValue, unsigned ValKind)
176 : Data(const_cast<void*>(d)),
177 Kind((isLValue ? LValueKind : NonLValueKind) | (ValKind << BaseBits)) {}
178
179 explicit RValue(BaseKind k)
180 : Data(0), Kind(k) {}
181
182 void* getRawPtr() const {
183 return reinterpret_cast<void*>(Data);
184 }
185
186public:
187 ~RValue() {};
188
Ted Kremenekcba2e432008-02-05 19:35:18 +0000189 /// BufferTy - A temporary buffer to hold a set of RValues.
190 typedef llvm::SmallVector<RValue,5> BufferTy;
191
192
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000193 RValue Cast(ValueManager& ValMgr, Expr* CastExpr) const;
194
195 unsigned getRawKind() const { return Kind; }
196 BaseKind getBaseKind() const { return (BaseKind) (Kind & BaseMask); }
197 unsigned getSubKind() const { return (Kind & ~BaseMask) >> BaseBits; }
198
199 void Profile(llvm::FoldingSetNodeID& ID) const {
200 ID.AddInteger((unsigned) getRawKind());
201 ID.AddPointer(reinterpret_cast<void*>(Data));
202 }
203
204 bool operator==(const RValue& RHS) const {
205 return getRawKind() == RHS.getRawKind() && Data == RHS.Data;
206 }
207
208 static RValue GetSymbolValue(SymbolManager& SymMgr, ParmVarDecl *D);
209
210 inline bool isValid() const { return getRawKind() != InvalidKind; }
211 inline bool isInvalid() const { return getRawKind() == InvalidKind; }
212
213 void print(std::ostream& OS) const;
214 void print() const { print(*llvm::cerr.stream()); }
215
216 // Implement isa<T> support.
217 static inline bool classof(const RValue*) { return true; }
218};
219
220class InvalidValue : public RValue {
221public:
222 InvalidValue() : RValue(InvalidKind) {}
223
224 static inline bool classof(const RValue* V) {
225 return V->getBaseKind() == InvalidKind;
226 }
227};
228
229class UninitializedValue : public RValue {
230public:
231 UninitializedValue() : RValue(UninitializedKind) {}
232
233 static inline bool classof(const RValue* V) {
234 return V->getBaseKind() == UninitializedKind;
235 }
236};
237
238class NonLValue : public RValue {
239protected:
240 NonLValue(unsigned SubKind, const void* d) : RValue(d, false, SubKind) {}
241
242public:
243 void print(std::ostream& Out) const;
244
Ted Kremeneka6e4d212008-02-01 06:36:40 +0000245 RValue Cast(ValueManager& ValMgr, Expr* CastExpr) const;
246
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000247 // Arithmetic operators.
248 NonLValue Add(ValueManager& ValMgr, const NonLValue& RHS) const;
249 NonLValue Sub(ValueManager& ValMgr, const NonLValue& RHS) const;
250 NonLValue Mul(ValueManager& ValMgr, const NonLValue& RHS) const;
251 NonLValue Div(ValueManager& ValMgr, const NonLValue& RHS) const;
252 NonLValue Rem(ValueManager& ValMgr, const NonLValue& RHS) const;
253 NonLValue UnaryMinus(ValueManager& ValMgr, UnaryOperator* U) const;
Ted Kremenekc5d3b4c2008-02-04 16:58:30 +0000254 NonLValue BitwiseComplement(ValueManager& ValMgr) const;
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000255
256 // Equality operators.
257 NonLValue EQ(ValueManager& ValMgr, const NonLValue& RHS) const;
258 NonLValue NE(ValueManager& ValMgr, const NonLValue& RHS) const;
259
Ted Kremeneka6e4d212008-02-01 06:36:40 +0000260
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000261 // Utility methods to create NonLValues.
262 static NonLValue GetValue(ValueManager& ValMgr, uint64_t X, QualType T,
263 SourceLocation Loc = SourceLocation());
264
265 static NonLValue GetValue(ValueManager& ValMgr, IntegerLiteral* I);
266
267 static inline NonLValue GetIntTruthValue(ValueManager& ValMgr, bool X) {
268 return GetValue(ValMgr, X ? 1U : 0U, ValMgr.getContext().IntTy);
269 }
270
271 // Implement isa<T> support.
272 static inline bool classof(const RValue* V) {
273 return V->getBaseKind() >= NonLValueKind;
274 }
275};
276
277class LValue : public RValue {
278protected:
Ted Kremenek516f91b2008-01-31 22:17:03 +0000279 LValue(unsigned SubKind, const void* D) : RValue(const_cast<void*>(D),
280 true, SubKind) {}
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000281
282public:
283 void print(std::ostream& Out) const;
284
Ted Kremeneka6e4d212008-02-01 06:36:40 +0000285 RValue Cast(ValueManager& ValMgr, Expr* CastExpr) const;
286
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000287 // Equality operators.
288 NonLValue EQ(ValueManager& ValMgr, const LValue& RHS) const;
289 NonLValue NE(ValueManager& ValMgr, const LValue& RHS) const;
290
291 // Implement isa<T> support.
292 static inline bool classof(const RValue* V) {
293 return V->getBaseKind() == LValueKind;
294 }
295};
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000296
297//==------------------------------------------------------------------------==//
298// Subclasses of NonLValue.
299//==------------------------------------------------------------------------==//
300
Ted Kremeneka6e4d212008-02-01 06:36:40 +0000301enum NonLValueKind { SymbolicNonLValueKind, ConcreteIntKind, NumNonLValueKind };
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000302
303class SymbolicNonLValue : public NonLValue {
304public:
305 SymbolicNonLValue(unsigned SymID)
306 : NonLValue(SymbolicNonLValueKind,
307 reinterpret_cast<void*>((uintptr_t) SymID)) {}
308
309 SymbolID getSymbolID() const {
310 return (SymbolID) reinterpret_cast<uintptr_t>(getRawPtr());
311 }
312
313 static inline bool classof(const RValue* V) {
314 return V->getSubKind() == SymbolicNonLValueKind;
315 }
316};
317
318class ConcreteInt : public NonLValue {
319public:
320 ConcreteInt(const llvm::APSInt& V) : NonLValue(ConcreteIntKind, &V) {}
321
322 const llvm::APSInt& getValue() const {
323 return *static_cast<llvm::APSInt*>(getRawPtr());
324 }
325
326 // Arithmetic operators.
327
328 ConcreteInt Add(ValueManager& ValMgr, const ConcreteInt& V) const {
329 return ValMgr.getValue(getValue() + V.getValue());
330 }
331
332 ConcreteInt Sub(ValueManager& ValMgr, const ConcreteInt& V) const {
333 return ValMgr.getValue(getValue() - V.getValue());
334 }
335
336 ConcreteInt Mul(ValueManager& ValMgr, const ConcreteInt& V) const {
337 return ValMgr.getValue(getValue() * V.getValue());
338 }
339
340 ConcreteInt Div(ValueManager& ValMgr, const ConcreteInt& V) const {
341 return ValMgr.getValue(getValue() / V.getValue());
342 }
343
344 ConcreteInt Rem(ValueManager& ValMgr, const ConcreteInt& V) const {
345 return ValMgr.getValue(getValue() % V.getValue());
346 }
347
348 ConcreteInt UnaryMinus(ValueManager& ValMgr, UnaryOperator* U) const {
349 assert (U->getType() == U->getSubExpr()->getType());
350 assert (U->getType()->isIntegerType());
351 return ValMgr.getValue(-getValue());
352 }
353
Ted Kremenekc5d3b4c2008-02-04 16:58:30 +0000354 ConcreteInt BitwiseComplement(ValueManager& ValMgr) const {
355 return ValMgr.getValue(~getValue());
356 }
357
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000358 // Casting.
359
360 ConcreteInt Cast(ValueManager& ValMgr, Expr* CastExpr) const {
361 assert (CastExpr->getType()->isIntegerType());
362
363 llvm::APSInt X(getValue());
364 X.extOrTrunc(ValMgr.getContext().getTypeSize(CastExpr->getType(),
365 CastExpr->getLocStart()));
366 return ValMgr.getValue(X);
367 }
368
369 // Equality operators.
370
371 ConcreteInt EQ(ValueManager& ValMgr, const ConcreteInt& V) const {
372 const llvm::APSInt& Val = getValue();
373 return ValMgr.getValue(Val == V.getValue() ? 1U : 0U,
374 Val.getBitWidth(), Val.isUnsigned());
375 }
376
377 ConcreteInt NE(ValueManager& ValMgr, const ConcreteInt& V) const {
378 const llvm::APSInt& Val = getValue();
379 return ValMgr.getValue(Val != V.getValue() ? 1U : 0U,
380 Val.getBitWidth(), Val.isUnsigned());
381 }
382
383 // Implement isa<T> support.
384 static inline bool classof(const RValue* V) {
385 return V->getSubKind() == ConcreteIntKind;
386 }
387};
Ted Kremenek516f91b2008-01-31 22:17:03 +0000388
389//==------------------------------------------------------------------------==//
390// Subclasses of LValue.
391//==------------------------------------------------------------------------==//
392
Ted Kremeneka6e4d212008-02-01 06:36:40 +0000393enum LValueKind { SymbolicLValueKind, LValueDeclKind, ConcreteIntLValueKind,
394 NumLValueKind };
395
Ted Kremenek516f91b2008-01-31 22:17:03 +0000396class SymbolicLValue : public LValue {
397public:
398 SymbolicLValue(unsigned SymID)
399 : LValue(SymbolicLValueKind, reinterpret_cast<void*>((uintptr_t) SymID)) {}
400
401 SymbolID getSymbolID() const {
402 return (SymbolID) reinterpret_cast<uintptr_t>(getRawPtr());
403 }
404
405 static inline bool classof(const RValue* V) {
406 return V->getSubKind() == SymbolicLValueKind;
407 }
408};
409
410class LValueDecl : public LValue {
411public:
412 LValueDecl(const ValueDecl* vd) : LValue(LValueDeclKind,vd) {}
413
414 ValueDecl* getDecl() const {
415 return static_cast<ValueDecl*>(getRawPtr());
416 }
417
418 inline bool operator==(const LValueDecl& R) const {
419 return getDecl() == R.getDecl();
420 }
421
422 inline bool operator!=(const LValueDecl& R) const {
423 return getDecl() != R.getDecl();
424 }
425
426 // Implement isa<T> support.
427 static inline bool classof(const RValue* V) {
428 return V->getSubKind() == LValueDeclKind;
429 }
430};
431
432class ConcreteIntLValue : public LValue {
433public:
434 ConcreteIntLValue(const llvm::APSInt& V) : LValue(ConcreteIntLValueKind, &V) {}
435
436 const llvm::APSInt& getValue() const {
437 return *static_cast<llvm::APSInt*>(getRawPtr());
438 }
439
440 // Arithmetic operators.
441
442 ConcreteIntLValue Add(ValueManager& ValMgr, const ConcreteInt& V) const {
443 return ValMgr.getValue(getValue() + V.getValue());
444 }
445
446 ConcreteIntLValue Sub(ValueManager& ValMgr, const ConcreteInt& V) const {
447 return ValMgr.getValue(getValue() - V.getValue());
448 }
449
450 // Equality operators.
451
452 ConcreteInt EQ(ValueManager& ValMgr, const ConcreteIntLValue& V) const {
453 const llvm::APSInt& Val = getValue();
454 return ValMgr.getValue(Val == V.getValue() ? 1U : 0U,
455 Val.getBitWidth(), Val.isUnsigned());
456 }
457
458 ConcreteInt NE(ValueManager& ValMgr, const ConcreteIntLValue& V) const {
459 const llvm::APSInt& Val = getValue();
460 return ValMgr.getValue(Val != V.getValue() ? 1U : 0U,
461 Val.getBitWidth(), Val.isUnsigned());
462 }
463
464 // Implement isa<T> support.
465 static inline bool classof(const RValue* V) {
466 return V->getSubKind() == ConcreteIntLValueKind;
467 }
468};
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000469
470} // end clang namespace
471
472//==------------------------------------------------------------------------==//
473// Casting machinery to get cast<> and dyn_cast<> working with SymbolData.
474//==------------------------------------------------------------------------==//
475
476namespace llvm {
477
478template<> inline bool
479isa<clang::ParmVarDecl,clang::SymbolData>(const clang::SymbolData& V) {
480 return V.getKind() == clang::SymbolData::ParmKind;
481}
482
483template<> struct cast_retty_impl<clang::ParmVarDecl,clang::SymbolData> {
484 typedef const clang::ParmVarDecl* ret_type;
485};
486
487template<> struct simplify_type<clang::SymbolData> {
488 typedef void* SimpleType;
489 static inline SimpleType getSimplifiedValue(const clang::SymbolData &V) {
490 return V.getPtr();
491 }
492};
493
494} // end llvm namespace
495
496#endif