blob: 8d5437fe6ec06a3f4b7c4dba8d9fede397561311 [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 Kremenekcf78b6a2008-02-06 22:50:25 +0000153
Ted Kremenek1fbdb022008-02-05 21:32:43 +0000154 const llvm::APSInt& getValue(const llvm::APSInt& X);
155 const llvm::APSInt& getValue(uint64_t X, unsigned BitWidth, bool isUnsigned);
156 const llvm::APSInt& getValue(uint64_t X, QualType T,
157 SourceLocation Loc = SourceLocation());
158
Ted Kremenek862d5bb2008-02-06 00:54:14 +0000159 inline const llvm::APSInt& getZeroWithPtrWidth() {
Ted Kremenekcf78b6a2008-02-06 22:50:25 +0000160 return getValue( 0,
161 Ctx.getTypeSize(Ctx.VoidPtrTy, SourceLocation()),
162 true );
163 }
164
165 inline const llvm::APSInt& getTruthValue(bool b) {
166 return getValue( b ? 1 : 0,
167 Ctx.getTypeSize(Ctx.IntTy, SourceLocation()),
168 false );
169
Ted Kremenek862d5bb2008-02-06 00:54:14 +0000170 }
171
Ted Kremenek1fbdb022008-02-05 21:32:43 +0000172 const SymIntConstraint& getConstraint(SymbolID sym, BinaryOperator::Opcode Op,
173 const llvm::APSInt& V);
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000174};
Ted Kremenek0f10d502008-02-05 22:21:54 +0000175
176} // end clang namespace
177
178//==------------------------------------------------------------------------==//
179// Casting machinery to get cast<> and dyn_cast<> working with SymbolData.
180//==------------------------------------------------------------------------==//
181
182namespace llvm {
183
184 template<> inline bool
185 isa<clang::ParmVarDecl,clang::SymbolData>(const clang::SymbolData& V) {
186 return V.getKind() == clang::SymbolData::ParmKind;
187 }
188
189 template<> struct cast_retty_impl<clang::ParmVarDecl,clang::SymbolData> {
190 typedef const clang::ParmVarDecl* ret_type;
191 };
192
193 template<> struct simplify_type<clang::SymbolData> {
194 typedef void* SimpleType;
195 static inline SimpleType getSimplifiedValue(const clang::SymbolData &V) {
196 return V.getPtr();
197 }
198 };
199
200} // end llvm namespace
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000201
202//==------------------------------------------------------------------------==//
203// Base RValue types.
204//==------------------------------------------------------------------------==//
205
Ted Kremenek0f10d502008-02-05 22:21:54 +0000206namespace clang {
207
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000208class RValue {
209public:
210 enum BaseKind { LValueKind=0x0,
211 NonLValueKind=0x1,
212 UninitializedKind=0x2,
213 InvalidKind=0x3 };
214
215 enum { BaseBits = 2,
216 BaseMask = 0x3 };
217
218private:
219 void* Data;
220 unsigned Kind;
221
222protected:
223 RValue(const void* d, bool isLValue, unsigned ValKind)
224 : Data(const_cast<void*>(d)),
225 Kind((isLValue ? LValueKind : NonLValueKind) | (ValKind << BaseBits)) {}
226
227 explicit RValue(BaseKind k)
228 : Data(0), Kind(k) {}
229
230 void* getRawPtr() const {
231 return reinterpret_cast<void*>(Data);
232 }
233
234public:
235 ~RValue() {};
236
Ted Kremenekcba2e432008-02-05 19:35:18 +0000237 /// BufferTy - A temporary buffer to hold a set of RValues.
238 typedef llvm::SmallVector<RValue,5> BufferTy;
239
240
Ted Kremenekcf78b6a2008-02-06 22:50:25 +0000241 RValue EvalCast(ValueManager& ValMgr, Expr* CastExpr) const;
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000242
243 unsigned getRawKind() const { return Kind; }
244 BaseKind getBaseKind() const { return (BaseKind) (Kind & BaseMask); }
245 unsigned getSubKind() const { return (Kind & ~BaseMask) >> BaseBits; }
246
247 void Profile(llvm::FoldingSetNodeID& ID) const {
248 ID.AddInteger((unsigned) getRawKind());
249 ID.AddPointer(reinterpret_cast<void*>(Data));
250 }
251
252 bool operator==(const RValue& RHS) const {
253 return getRawKind() == RHS.getRawKind() && Data == RHS.Data;
254 }
255
256 static RValue GetSymbolValue(SymbolManager& SymMgr, ParmVarDecl *D);
257
Ted Kremenekcf78b6a2008-02-06 22:50:25 +0000258
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000259 inline bool isValid() const { return getRawKind() != InvalidKind; }
260 inline bool isInvalid() const { return getRawKind() == InvalidKind; }
261
262 void print(std::ostream& OS) const;
Ted Kremenek5b6dc2d2008-02-07 01:08:27 +0000263 void print() const;
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000264
265 // Implement isa<T> support.
266 static inline bool classof(const RValue*) { return true; }
267};
268
269class InvalidValue : public RValue {
270public:
271 InvalidValue() : RValue(InvalidKind) {}
272
273 static inline bool classof(const RValue* V) {
274 return V->getBaseKind() == InvalidKind;
275 }
276};
277
278class UninitializedValue : public RValue {
279public:
280 UninitializedValue() : RValue(UninitializedKind) {}
281
282 static inline bool classof(const RValue* V) {
283 return V->getBaseKind() == UninitializedKind;
284 }
285};
286
287class NonLValue : public RValue {
288protected:
289 NonLValue(unsigned SubKind, const void* d) : RValue(d, false, SubKind) {}
290
291public:
292 void print(std::ostream& Out) const;
293
Ted Kremenekcf78b6a2008-02-06 22:50:25 +0000294 NonLValue EvalBinaryOp(ValueManager& ValMgr,
295 BinaryOperator::Opcode Op,
296 const NonLValue& RHS) const;
Ted Kremeneka6e4d212008-02-01 06:36:40 +0000297
Ted Kremenekcf78b6a2008-02-06 22:50:25 +0000298 RValue EvalCast(ValueManager& ValMgr, Expr* CastExpr) const;
299 NonLValue EvalMinus(ValueManager& ValMgr, UnaryOperator* U) const;
300 NonLValue EvalComplement(ValueManager& ValMgr) const;
Ted Kremeneka6e4d212008-02-01 06:36:40 +0000301
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000302 // Utility methods to create NonLValues.
303 static NonLValue GetValue(ValueManager& ValMgr, uint64_t X, QualType T,
304 SourceLocation Loc = SourceLocation());
305
306 static NonLValue GetValue(ValueManager& ValMgr, IntegerLiteral* I);
307
Ted Kremenekcf78b6a2008-02-06 22:50:25 +0000308 static NonLValue GetIntTruthValue(ValueManager& ValMgr, bool b);
309
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000310 // Implement isa<T> support.
311 static inline bool classof(const RValue* V) {
312 return V->getBaseKind() >= NonLValueKind;
313 }
314};
315
316class LValue : public RValue {
317protected:
Ted Kremenek516f91b2008-01-31 22:17:03 +0000318 LValue(unsigned SubKind, const void* D) : RValue(const_cast<void*>(D),
319 true, SubKind) {}
Ted Kremeneka6e4d212008-02-01 06:36:40 +0000320
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000321 // Equality operators.
322 NonLValue EQ(ValueManager& ValMgr, const LValue& RHS) const;
323 NonLValue NE(ValueManager& ValMgr, const LValue& RHS) const;
324
Ted Kremenekcf78b6a2008-02-06 22:50:25 +0000325public:
Ted Kremenek5b6dc2d2008-02-07 01:08:27 +0000326// void print(std::ostream& Out) const;
Ted Kremenekcf78b6a2008-02-06 22:50:25 +0000327
328 RValue EvalBinaryOp(ValueManager& ValMgr, BinaryOperator::Opcode Op,
329 const LValue& RHS) const;
330
331 RValue EvalCast(ValueManager& ValMgr, Expr* CastExpr) const;
332
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000333 // Implement isa<T> support.
334 static inline bool classof(const RValue* V) {
Ted Kremenek3271f8d2008-02-07 04:16:04 +0000335 return V->getBaseKind() != NonLValueKind;
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000336 }
337};
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000338
339//==------------------------------------------------------------------------==//
340// Subclasses of NonLValue.
341//==------------------------------------------------------------------------==//
342
Ted Kremenek329f8542008-02-05 21:52:21 +0000343namespace nonlval {
344
345 enum Kind { SymbolValKind,
Ted Kremenek9466aa82008-02-05 22:10:48 +0000346 SymIntConstraintValKind,
Ted Kremenek329f8542008-02-05 21:52:21 +0000347 ConcreteIntKind,
348 NumKind };
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000349
Ted Kremenek329f8542008-02-05 21:52:21 +0000350 class SymbolVal : public NonLValue {
351 public:
352 SymbolVal(unsigned SymID)
353 : NonLValue(SymbolValKind,
354 reinterpret_cast<void*>((uintptr_t) SymID)) {}
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000355
Ted Kremenek0806acf2008-02-05 23:08:41 +0000356 SymbolID getSymbol() const {
Ted Kremenek329f8542008-02-05 21:52:21 +0000357 return (SymbolID) reinterpret_cast<uintptr_t>(getRawPtr());
358 }
359
360 static inline bool classof(const RValue* V) {
Ted Kremenek9466aa82008-02-05 22:10:48 +0000361 return isa<NonLValue>(V) && V->getSubKind() == SymbolValKind;
362 }
363 };
364
365 class SymIntConstraintVal : public NonLValue {
366 public:
367 SymIntConstraintVal(const SymIntConstraint& C)
368 : NonLValue(SymIntConstraintValKind, reinterpret_cast<const void*>(&C)) {}
369
370 const SymIntConstraint& getConstraint() const {
371 return *reinterpret_cast<SymIntConstraint*>(getRawPtr());
372 }
373
374 static inline bool classof(const RValue* V) {
375 return isa<NonLValue>(V) && V->getSubKind() == SymIntConstraintValKind;
376 }
Ted Kremenek329f8542008-02-05 21:52:21 +0000377 };
378
379 class ConcreteInt : public NonLValue {
380 public:
381 ConcreteInt(const llvm::APSInt& V) : NonLValue(ConcreteIntKind, &V) {}
382
383 const llvm::APSInt& getValue() const {
384 return *static_cast<llvm::APSInt*>(getRawPtr());
385 }
386
Ted Kremenekcf78b6a2008-02-06 22:50:25 +0000387 // Transfer functions for binary/unary operations on ConcreteInts.
388 ConcreteInt EvalBinaryOp(ValueManager& ValMgr,
389 BinaryOperator::Opcode Op,
390 const ConcreteInt& RHS) const;
Ted Kremenek329f8542008-02-05 21:52:21 +0000391
Ted Kremenekcf78b6a2008-02-06 22:50:25 +0000392 ConcreteInt EvalComplement(ValueManager& ValMgr) const;
393 ConcreteInt EvalMinus(ValueManager& ValMgr, UnaryOperator* U) const;
Ted Kremenek329f8542008-02-05 21:52:21 +0000394
395 // Implement isa<T> support.
396 static inline bool classof(const RValue* V) {
Ted Kremenek9466aa82008-02-05 22:10:48 +0000397 return isa<NonLValue>(V) && V->getSubKind() == ConcreteIntKind;
Ted Kremenek329f8542008-02-05 21:52:21 +0000398 }
Ted Kremenekcf78b6a2008-02-06 22:50:25 +0000399
400 static inline bool classof(const NonLValue* V) {
401 return V->getSubKind() == ConcreteIntKind;
402 }
Ted Kremenek329f8542008-02-05 21:52:21 +0000403 };
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000404
Ted Kremenek329f8542008-02-05 21:52:21 +0000405} // end namespace clang::nonlval
Ted Kremenek516f91b2008-01-31 22:17:03 +0000406
407//==------------------------------------------------------------------------==//
408// Subclasses of LValue.
409//==------------------------------------------------------------------------==//
410
Ted Kremenek329f8542008-02-05 21:52:21 +0000411namespace lval {
Ted Kremeneka6e4d212008-02-01 06:36:40 +0000412
Ted Kremenek329f8542008-02-05 21:52:21 +0000413 enum Kind { SymbolValKind,
414 DeclValKind,
415 ConcreteIntKind,
416 NumKind };
Ted Kremenek516f91b2008-01-31 22:17:03 +0000417
Ted Kremenek329f8542008-02-05 21:52:21 +0000418 class SymbolVal : public LValue {
419 public:
420 SymbolVal(unsigned SymID)
421 : LValue(SymbolValKind, reinterpret_cast<void*>((uintptr_t) SymID)) {}
422
Ted Kremenek0806acf2008-02-05 23:08:41 +0000423 SymbolID getSymbol() const {
Ted Kremenek329f8542008-02-05 21:52:21 +0000424 return (SymbolID) reinterpret_cast<uintptr_t>(getRawPtr());
425 }
426
427 static inline bool classof(const RValue* V) {
428 return V->getSubKind() == SymbolValKind;
429 }
430 };
Ted Kremenek0806acf2008-02-05 23:08:41 +0000431
Ted Kremenek329f8542008-02-05 21:52:21 +0000432 class DeclVal : public LValue {
433 public:
434 DeclVal(const ValueDecl* vd) : LValue(DeclValKind,vd) {}
435
436 ValueDecl* getDecl() const {
437 return static_cast<ValueDecl*>(getRawPtr());
438 }
439
440 inline bool operator==(const DeclVal& R) const {
441 return getDecl() == R.getDecl();
442 }
443
444 inline bool operator!=(const DeclVal& R) const {
445 return getDecl() != R.getDecl();
446 }
447
448 // Implement isa<T> support.
449 static inline bool classof(const RValue* V) {
450 return V->getSubKind() == DeclValKind;
451 }
452 };
Ted Kremenek516f91b2008-01-31 22:17:03 +0000453
Ted Kremenek329f8542008-02-05 21:52:21 +0000454 class ConcreteInt : public LValue {
455 public:
456 ConcreteInt(const llvm::APSInt& V) : LValue(ConcreteIntKind, &V) {}
457
458 const llvm::APSInt& getValue() const {
459 return *static_cast<llvm::APSInt*>(getRawPtr());
460 }
461
Ted Kremenekcf78b6a2008-02-06 22:50:25 +0000462
463 // Transfer functions for binary/unary operations on ConcreteInts.
464 ConcreteInt EvalBinaryOp(ValueManager& ValMgr,
465 BinaryOperator::Opcode Op,
466 const ConcreteInt& RHS) const;
467
Ted Kremenek329f8542008-02-05 21:52:21 +0000468 // Implement isa<T> support.
469 static inline bool classof(const RValue* V) {
Ted Kremenekcf78b6a2008-02-06 22:50:25 +0000470 return isa<LValue>(V) && V->getSubKind() == ConcreteIntKind;
471 }
472
473 static inline bool classof(const LValue* V) {
Ted Kremenek329f8542008-02-05 21:52:21 +0000474 return V->getSubKind() == ConcreteIntKind;
475 }
Ted Kremenekcf78b6a2008-02-06 22:50:25 +0000476
Ted Kremenek329f8542008-02-05 21:52:21 +0000477 };
478} // end clang::lval namespace
Ted Kremenek516f91b2008-01-31 22:17:03 +0000479
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000480
481} // end clang namespace
482
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000483#endif