blob: db897b451212f28a6515e09b91c5513ee22307d4 [file] [log] [blame]
Ted Kremenekd27f8162008-01-15 23:55:06 +00001//===-- GRConstants.cpp - Simple, Path-Sens. Constant Prop. ------*- C++ -*-==//
2//
Ted Kremenekab2b8c52008-01-23 19:59:44 +00003// The LLValM Compiler Infrastructure
Ted Kremenekd27f8162008-01-15 23:55:06 +00004//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// Constant Propagation via Graph Reachability
11//
12// This files defines a simple analysis that performs path-sensitive
13// constant propagation within a function. An example use of this analysis
14// is to perform simple checks for NULL dereferences.
15//
16//===----------------------------------------------------------------------===//
17
18#include "clang/Analysis/PathSensitive/GREngine.h"
19#include "clang/AST/Expr.h"
Ted Kremenek874d63f2008-01-24 02:02:54 +000020#include "clang/AST/ASTContext.h"
Ted Kremenekd27f8162008-01-15 23:55:06 +000021#include "clang/Analysis/Analyses/LiveVariables.h"
Ted Kremenekd27f8162008-01-15 23:55:06 +000022
23#include "llvm/Support/Casting.h"
24#include "llvm/Support/DataTypes.h"
25#include "llvm/ADT/APSInt.h"
26#include "llvm/ADT/FoldingSet.h"
27#include "llvm/ADT/ImmutableMap.h"
Ted Kremenek3c6c6722008-01-16 17:56:25 +000028#include "llvm/ADT/SmallVector.h"
Ted Kremenekab2b8c52008-01-23 19:59:44 +000029#include "llvm/Support/Allocator.h"
Ted Kremenekd27f8162008-01-15 23:55:06 +000030#include "llvm/Support/Compiler.h"
Ted Kremenekab2b8c52008-01-23 19:59:44 +000031#include "llvm/Support/Streams.h"
32
Ted Kremenek5ee4ff82008-01-25 22:55:56 +000033#include <functional>
34
Ted Kremenekaa66a322008-01-16 21:46:15 +000035#ifndef NDEBUG
36#include "llvm/Support/GraphWriter.h"
37#include <sstream>
38#endif
39
Ted Kremenekd27f8162008-01-15 23:55:06 +000040using namespace clang;
Ted Kremenekd27f8162008-01-15 23:55:06 +000041using llvm::dyn_cast;
42using llvm::cast;
Ted Kremenek5ee4ff82008-01-25 22:55:56 +000043using llvm::APSInt;
Ted Kremenekd27f8162008-01-15 23:55:06 +000044
45//===----------------------------------------------------------------------===//
Ted Kremenekab2b8c52008-01-23 19:59:44 +000046/// ValueKey - A variant smart pointer that wraps either a ValueDecl* or a
Ted Kremenekd27f8162008-01-15 23:55:06 +000047/// Stmt*. Use cast<> or dyn_cast<> to get actual pointer type
48//===----------------------------------------------------------------------===//
49namespace {
Ted Kremenekab2b8c52008-01-23 19:59:44 +000050
51class VISIBILITY_HIDDEN ValueKey {
Ted Kremenek0525a4f2008-01-16 19:47:19 +000052 uintptr_t Raw;
Ted Kremenekd27f8162008-01-15 23:55:06 +000053public:
Ted Kremenek565256e2008-01-24 22:44:24 +000054 enum Kind { IsSubExpr=0x0, IsBlkExpr=0x1, IsDecl=0x2, Flags=0x3 };
Ted Kremenekd27f8162008-01-15 23:55:06 +000055 inline void* getPtr() const { return reinterpret_cast<void*>(Raw & ~Flags); }
Ted Kremenekab2b8c52008-01-23 19:59:44 +000056 inline Kind getKind() const { return (Kind) (Raw & Flags); }
Ted Kremenekd27f8162008-01-15 23:55:06 +000057
Ted Kremenekab2b8c52008-01-23 19:59:44 +000058 ValueKey(const ValueDecl* VD)
59 : Raw(reinterpret_cast<uintptr_t>(VD) | IsDecl) {}
60
Ted Kremenek5c1b9962008-01-24 19:43:37 +000061 ValueKey(Stmt* S, bool isBlkExpr = false)
Ted Kremenek5ee4ff82008-01-25 22:55:56 +000062 : Raw(reinterpret_cast<uintptr_t>(S) | isBlkExpr ? IsBlkExpr : IsSubExpr) {}
Ted Kremenekd27f8162008-01-15 23:55:06 +000063
Ted Kremenek565256e2008-01-24 22:44:24 +000064 bool isSubExpr() const { return getKind() == IsSubExpr; }
Ted Kremenekab2b8c52008-01-23 19:59:44 +000065 bool isDecl() const { return getKind() == IsDecl; }
Ted Kremenekd27f8162008-01-15 23:55:06 +000066
67 inline void Profile(llvm::FoldingSetNodeID& ID) const {
Ted Kremenek98491852008-01-16 05:51:13 +000068 ID.AddPointer(getPtr());
69 ID.AddInteger((unsigned) getKind());
Ted Kremenekab2b8c52008-01-23 19:59:44 +000070 }
71
72 inline bool operator==(const ValueKey& X) const {
Ted Kremenek5c1b9962008-01-24 19:43:37 +000073 return getPtr() == X.getPtr();
Ted Kremenekab2b8c52008-01-23 19:59:44 +000074 }
75
76 inline bool operator!=(const ValueKey& X) const {
77 return !operator==(X);
78 }
79
80 inline bool operator<(const ValueKey& X) const {
81 Kind k = getKind(), Xk = X.getKind();
Ted Kremenek5c1b9962008-01-24 19:43:37 +000082
83 if (k == IsDecl) {
84 if (Xk != IsDecl)
85 return false;
86 }
87 else {
88 if (Xk == IsDecl)
89 return true;
90 }
Ted Kremenekab2b8c52008-01-23 19:59:44 +000091
Ted Kremenek5c1b9962008-01-24 19:43:37 +000092 return getPtr() < X.getPtr();
Ted Kremenekb3d2dca2008-01-16 23:33:44 +000093 }
Ted Kremenekd27f8162008-01-15 23:55:06 +000094};
95} // end anonymous namespace
96
Ted Kremenekab2b8c52008-01-23 19:59:44 +000097// Machinery to get cast<> and dyn_cast<> working with ValueKey.
Ted Kremenekd27f8162008-01-15 23:55:06 +000098namespace llvm {
Ted Kremenekab2b8c52008-01-23 19:59:44 +000099 template<> inline bool isa<ValueDecl,ValueKey>(const ValueKey& V) {
100 return V.getKind() == ValueKey::IsDecl;
Ted Kremenekd27f8162008-01-15 23:55:06 +0000101 }
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000102 template<> inline bool isa<Stmt,ValueKey>(const ValueKey& V) {
103 return ((unsigned) V.getKind()) != ValueKey::IsDecl;
Ted Kremenekd27f8162008-01-15 23:55:06 +0000104 }
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000105 template<> struct VISIBILITY_HIDDEN cast_retty_impl<ValueDecl,ValueKey> {
Ted Kremenekaa66a322008-01-16 21:46:15 +0000106 typedef const ValueDecl* ret_type;
Ted Kremenekd27f8162008-01-15 23:55:06 +0000107 };
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000108 template<> struct VISIBILITY_HIDDEN cast_retty_impl<Stmt,ValueKey> {
Ted Kremenekd27f8162008-01-15 23:55:06 +0000109 typedef const Stmt* ret_type;
110 };
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000111 template<> struct VISIBILITY_HIDDEN simplify_type<ValueKey> {
Ted Kremenekd27f8162008-01-15 23:55:06 +0000112 typedef void* SimpleType;
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000113 static inline SimpleType getSimplifiedValue(const ValueKey &V) {
Ted Kremenekd27f8162008-01-15 23:55:06 +0000114 return V.getPtr();
115 }
116 };
117} // end llvm namespace
118
119//===----------------------------------------------------------------------===//
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000120// ValueManager.
Ted Kremenekd27f8162008-01-15 23:55:06 +0000121//===----------------------------------------------------------------------===//
122
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000123namespace {
124
Ted Kremenek5ee4ff82008-01-25 22:55:56 +0000125typedef llvm::ImmutableSet<APSInt > APSIntSetTy;
126
127
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000128class VISIBILITY_HIDDEN ValueManager {
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000129 APSIntSetTy::Factory APSIntSetFactory;
Ted Kremenek874d63f2008-01-24 02:02:54 +0000130 ASTContext* Ctx;
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000131
132public:
133 ValueManager() {}
134 ~ValueManager() {}
135
Ted Kremenek874d63f2008-01-24 02:02:54 +0000136 void setContext(ASTContext* ctx) { Ctx = ctx; }
137 ASTContext* getContext() const { return Ctx; }
138
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000139 APSIntSetTy GetEmptyAPSIntSet() {
140 return APSIntSetFactory.GetEmptySet();
141 }
142
Ted Kremenek5ee4ff82008-01-25 22:55:56 +0000143 APSIntSetTy AddToSet(const APSIntSetTy& Set, const APSInt& Val) {
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000144 return APSIntSetFactory.Add(Set, Val);
Ted Kremenekd27f8162008-01-15 23:55:06 +0000145 }
146};
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000147} // end anonymous namespace
148
Ted Kremenek5ee4ff82008-01-25 22:55:56 +0000149template <typename OpTy>
150static inline APSIntSetTy APSIntSetOp(ValueManager& ValMgr,
151 APSIntSetTy S1, APSIntSetTy S2,
152 OpTy Op) {
153
154 APSIntSetTy M = ValMgr.GetEmptyAPSIntSet();
155
156 for (APSIntSetTy::iterator I1=S1.begin(), E1=S2.end(); I1!=E1; ++I1)
157 for (APSIntSetTy::iterator I2=S2.begin(), E2=S2.end(); I2!=E2; ++I2)
158 M = ValMgr.AddToSet(M, Op(*I1,*I2));
159
160 return M;
161}
162
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000163//===----------------------------------------------------------------------===//
164// Expression Values.
165//===----------------------------------------------------------------------===//
Ted Kremenekf13794e2008-01-24 23:19:54 +0000166
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000167namespace {
168
169class VISIBILITY_HIDDEN ExprValue {
170public:
Ted Kremenekf13794e2008-01-24 23:19:54 +0000171 enum BaseKind { LValueKind=0x1, RValueKind=0x2, InvalidKind=0x0 };
172
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000173private:
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000174 void* Data;
Ted Kremenekf13794e2008-01-24 23:19:54 +0000175 unsigned Kind;
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000176
177protected:
Ted Kremenekf13794e2008-01-24 23:19:54 +0000178 ExprValue(void* d, bool isRValue, unsigned ValKind)
179 : Data(d),
180 Kind((isRValue ? RValueKind : LValueKind) | (ValKind << 2)) {}
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000181
Ted Kremenekf13794e2008-01-24 23:19:54 +0000182 ExprValue() : Data(NULL), Kind(0) {}
183
184 void* getRawPtr() const { return Data; }
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000185
186public:
187 ~ExprValue() {};
188
Ted Kremenek874d63f2008-01-24 02:02:54 +0000189 ExprValue EvalCast(ValueManager& ValMgr, Expr* CastExpr) const;
190
Ted Kremenekf13794e2008-01-24 23:19:54 +0000191 unsigned getRawKind() const { return Kind; }
192 BaseKind getBaseKind() const { return (BaseKind) (Kind & 0x3); }
193 unsigned getSubKind() const { return (Kind & ~0x3) >> 2; }
194
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000195 void Profile(llvm::FoldingSetNodeID& ID) const {
Ted Kremenekf13794e2008-01-24 23:19:54 +0000196 ID.AddInteger((unsigned) getRawKind());
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000197 ID.AddPointer(Data);
198 }
199
200 bool operator==(const ExprValue& RHS) const {
Ted Kremenekf13794e2008-01-24 23:19:54 +0000201 return getRawKind() == RHS.getRawKind() && Data == RHS.Data;
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000202 }
203
Ted Kremenekf13794e2008-01-24 23:19:54 +0000204 inline bool isValid() const { return getRawKind() != InvalidKind; }
205 inline bool isInvalid() const { return getRawKind() == InvalidKind; }
206
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000207
208 void print(std::ostream& OS) const;
209 void print() const { print(*llvm::cerr.stream()); }
210
211 // Implement isa<T> support.
212 static inline bool classof(const ExprValue*) { return true; }
213};
214
215class VISIBILITY_HIDDEN InvalidValue : public ExprValue {
216public:
Ted Kremenekf13794e2008-01-24 23:19:54 +0000217 InvalidValue() {}
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000218
219 static inline bool classof(const ExprValue* V) {
Ted Kremenekf13794e2008-01-24 23:19:54 +0000220 return V->getBaseKind() == InvalidKind;
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000221 }
222};
223
Ted Kremenekf13794e2008-01-24 23:19:54 +0000224class VISIBILITY_HIDDEN LValue : public ExprValue {
225protected:
226 LValue(unsigned SubKind, void* D) : ExprValue(D, false, SubKind) {}
227
228public:
229 // Implement isa<T> support.
230 static inline bool classof(const ExprValue* V) {
231 return V->getBaseKind() == LValueKind;
232 }
233};
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000234
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000235class VISIBILITY_HIDDEN RValue : public ExprValue {
236protected:
Ted Kremenekf13794e2008-01-24 23:19:54 +0000237 RValue(unsigned SubKind, void* d) : ExprValue(d, true, SubKind) {}
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000238
239public:
Ted Kremenekf13794e2008-01-24 23:19:54 +0000240 void print(std::ostream& Out) const;
241
Ted Kremenek874d63f2008-01-24 02:02:54 +0000242 RValue EvalAdd(ValueManager& ValMgr, const RValue& RHS) const;
243 RValue EvalSub(ValueManager& ValMgr, const RValue& RHS) const;
244 RValue EvalMul(ValueManager& ValMgr, const RValue& RHS) const;
Ted Kremenek5ee4ff82008-01-25 22:55:56 +0000245 RValue EvalDiv(ValueManager& ValMgr, const RValue& RHS) const;
Ted Kremenekdacbb4f2008-01-24 08:20:02 +0000246 RValue EvalMinus(ValueManager& ValMgr, UnaryOperator* U) const;
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000247
Ted Kremenek5ee4ff82008-01-25 22:55:56 +0000248 static RValue GetRValue(ValueManager& ValMgr, const APSInt& V);
Ted Kremenekdacbb4f2008-01-24 08:20:02 +0000249 static RValue GetRValue(ValueManager& ValMgr, IntegerLiteral* I);
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000250
251 // Implement isa<T> support.
252 static inline bool classof(const ExprValue* V) {
Ted Kremenekf13794e2008-01-24 23:19:54 +0000253 return V->getBaseKind() == RValueKind;
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000254 }
255};
Ted Kremenekf13794e2008-01-24 23:19:54 +0000256
257} // end anonymous namespace
258
259//===----------------------------------------------------------------------===//
260// "R-Values": Interface.
261//===----------------------------------------------------------------------===//
262
263namespace {
264
Ted Kremenek5ee4ff82008-01-25 22:55:56 +0000265enum { RValEqualityORSetKind,
266 RValInequalityANDSetKind,
267 NumRValueKind };
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000268
Ted Kremenek5ee4ff82008-01-25 22:55:56 +0000269class VISIBILITY_HIDDEN RValEqualityORSet : public RValue {
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000270public:
Ted Kremenek5ee4ff82008-01-25 22:55:56 +0000271 RValEqualityORSet(const APSIntSetTy& S)
272 : RValue(RValEqualityORSetKind, S.getRoot()) {}
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000273
274 APSIntSetTy GetValues() const {
275 return APSIntSetTy(reinterpret_cast<APSIntSetTy::TreeTy*>(getRawPtr()));
276 }
277
Ted Kremenek5ee4ff82008-01-25 22:55:56 +0000278 RValEqualityORSet
279 EvalAdd(ValueManager& ValMgr, const RValEqualityORSet& V) const {
280 return APSIntSetOp(ValMgr, GetValues(), V.GetValues(),
281 std::plus<APSInt>());
282 }
Ted Kremenek874d63f2008-01-24 02:02:54 +0000283
Ted Kremenek5ee4ff82008-01-25 22:55:56 +0000284 RValEqualityORSet
285 EvalSub(ValueManager& ValMgr, const RValEqualityORSet& V) const {
286 return APSIntSetOp(ValMgr, GetValues(), V.GetValues(),
287 std::minus<APSInt>());
288 }
Ted Kremenek874d63f2008-01-24 02:02:54 +0000289
Ted Kremenek5ee4ff82008-01-25 22:55:56 +0000290 RValEqualityORSet
291 EvalMul(ValueManager& ValMgr, const RValEqualityORSet& V) const {
292 return APSIntSetOp(ValMgr, GetValues(), V.GetValues(),
293 std::multiplies<APSInt>());
294 }
295
296 RValEqualityORSet
297 EvalDiv(ValueManager& ValMgr, const RValEqualityORSet& V) const {
298 return APSIntSetOp(ValMgr, GetValues(), V.GetValues(),
299 std::divides<APSInt>());
300 }
Ted Kremenek874d63f2008-01-24 02:02:54 +0000301
Ted Kremenek5ee4ff82008-01-25 22:55:56 +0000302 RValEqualityORSet
Ted Kremenek2cd65c82008-01-25 22:06:07 +0000303 EvalCast(ValueManager& ValMgr, Expr* CastExpr) const;
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000304
Ted Kremenek5ee4ff82008-01-25 22:55:56 +0000305 RValEqualityORSet
Ted Kremenek2cd65c82008-01-25 22:06:07 +0000306 EvalMinus(ValueManager& ValMgr, UnaryOperator* U) const;
Ted Kremenekdacbb4f2008-01-24 08:20:02 +0000307
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000308 // Implement isa<T> support.
309 static inline bool classof(const ExprValue* V) {
Ted Kremenek5ee4ff82008-01-25 22:55:56 +0000310 return V->getSubKind() == RValEqualityORSetKind;
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000311 }
312};
Ted Kremenek5ee4ff82008-01-25 22:55:56 +0000313
314class VISIBILITY_HIDDEN RValInequalityANDSet : public RValue {
315public:
316 RValInequalityANDSet(const APSIntSetTy& S)
317 : RValue(RValInequalityANDSetKind, S.getRoot()) {}
318
319 APSIntSetTy GetValues() const {
320 return APSIntSetTy(reinterpret_cast<APSIntSetTy::TreeTy*>(getRawPtr()));
321 }
322
323 RValInequalityANDSet
324 EvalAdd(ValueManager& ValMgr, const RValInequalityANDSet& V) const;
325
326 RValInequalityANDSet
327 EvalSub(ValueManager& ValMgr, const RValInequalityANDSet& V) const;
328
329 RValInequalityANDSet
330 EvalMul(ValueManager& ValMgr, const RValInequalityANDSet& V) const;
331
332 RValInequalityANDSet
333 EvalDiv(ValueManager& ValMgr, const RValInequalityANDSet& V) const;
334
335 RValInequalityANDSet
336 EvalCast(ValueManager& ValMgr, Expr* CastExpr) const;
337
338 RValInequalityANDSet
339 EvalMinus(ValueManager& ValMgr, UnaryOperator* U) const;
340
341 // Implement isa<T> support.
342 static inline bool classof(const ExprValue* V) {
343 return V->getSubKind() == RValInequalityANDSetKind;
344 }
345};
346
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000347} // end anonymous namespace
348
349//===----------------------------------------------------------------------===//
Ted Kremenek874d63f2008-01-24 02:02:54 +0000350// Transfer functions: Casts.
351//===----------------------------------------------------------------------===//
352
353ExprValue ExprValue::EvalCast(ValueManager& ValMgr, Expr* CastExpr) const {
Ted Kremenekf13794e2008-01-24 23:19:54 +0000354 switch (getSubKind()) {
Ted Kremenek5ee4ff82008-01-25 22:55:56 +0000355 case RValEqualityORSetKind:
356 return cast<RValEqualityORSet>(this)->EvalCast(ValMgr, CastExpr);
Ted Kremenek874d63f2008-01-24 02:02:54 +0000357 default:
358 return InvalidValue();
359 }
360}
361
Ted Kremenek5ee4ff82008-01-25 22:55:56 +0000362RValEqualityORSet
363RValEqualityORSet::EvalCast(ValueManager& ValMgr, Expr* CastExpr) const {
Ted Kremenek874d63f2008-01-24 02:02:54 +0000364 QualType T = CastExpr->getType();
365 assert (T->isIntegerType());
366
367 APSIntSetTy S1 = GetValues();
368 APSIntSetTy S2 = ValMgr.GetEmptyAPSIntSet();
369
370 for (APSIntSetTy::iterator I=S1.begin(), E=S1.end(); I!=E; ++I) {
Ted Kremenek5ee4ff82008-01-25 22:55:56 +0000371 APSInt X = *I;
Ted Kremenek874d63f2008-01-24 02:02:54 +0000372 X.setIsSigned(T->isSignedIntegerType());
373 X.extOrTrunc(ValMgr.getContext()->getTypeSize(T,CastExpr->getLocStart()));
374 S2 = ValMgr.AddToSet(S2, X);
375 }
376
377 return S2;
378}
379
380//===----------------------------------------------------------------------===//
Ted Kremenekdacbb4f2008-01-24 08:20:02 +0000381// Transfer functions: Unary Operations over R-Values.
382//===----------------------------------------------------------------------===//
383
384RValue RValue::EvalMinus(ValueManager& ValMgr, UnaryOperator* U) const {
Ted Kremenekf13794e2008-01-24 23:19:54 +0000385 switch (getSubKind()) {
Ted Kremenek5ee4ff82008-01-25 22:55:56 +0000386 case RValEqualityORSetKind:
387 return cast<RValEqualityORSet>(this)->EvalMinus(ValMgr, U);
Ted Kremenekdacbb4f2008-01-24 08:20:02 +0000388 default:
389 return cast<RValue>(InvalidValue());
390 }
391}
392
Ted Kremenek5ee4ff82008-01-25 22:55:56 +0000393RValEqualityORSet
394RValEqualityORSet::EvalMinus(ValueManager& ValMgr, UnaryOperator* U) const{
Ted Kremenekdacbb4f2008-01-24 08:20:02 +0000395
396 assert (U->getType() == U->getSubExpr()->getType());
397 assert (U->getType()->isIntegerType());
398
399 APSIntSetTy S1 = GetValues();
400 APSIntSetTy S2 = ValMgr.GetEmptyAPSIntSet();
401
402 for (APSIntSetTy::iterator I=S1.begin(), E=S1.end(); I!=E; ++I) {
403 assert ((*I).isSigned());
404
405 // FIXME: Shouldn't operator- on APSInt return an APSInt with the proper
406 // sign?
Ted Kremenek5ee4ff82008-01-25 22:55:56 +0000407 APSInt X(-(*I));
Ted Kremenekdacbb4f2008-01-24 08:20:02 +0000408 X.setIsSigned(true);
409
410 S2 = ValMgr.AddToSet(S2, X);
411 }
412
413 return S2;
414}
415
Ted Kremenekdacbb4f2008-01-24 08:20:02 +0000416//===----------------------------------------------------------------------===//
Ted Kremenek874d63f2008-01-24 02:02:54 +0000417// Transfer functions: Binary Operations over R-Values.
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000418//===----------------------------------------------------------------------===//
419
420#define RVALUE_DISPATCH_CASE(k1,k2,Op)\
Ted Kremenekf13794e2008-01-24 23:19:54 +0000421case (k1##Kind*NumRValueKind+k2##Kind):\
Ted Kremenek874d63f2008-01-24 02:02:54 +0000422 return cast<k1>(*this).Eval##Op(ValMgr,cast<k2>(RHS));
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000423
424#define RVALUE_DISPATCH(Op)\
Ted Kremenekf13794e2008-01-24 23:19:54 +0000425switch (getSubKind()*NumRValueKind+RHS.getSubKind()){\
Ted Kremenek5ee4ff82008-01-25 22:55:56 +0000426 RVALUE_DISPATCH_CASE(RValEqualityORSet,RValEqualityORSet,Op)\
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000427 default:\
428 assert (!isValid() || !RHS.isValid() && "Missing case.");\
429 break;\
430}\
431return cast<RValue>(InvalidValue());
432
Ted Kremenek874d63f2008-01-24 02:02:54 +0000433RValue RValue::EvalAdd(ValueManager& ValMgr, const RValue& RHS) const {
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000434 RVALUE_DISPATCH(Add)
435}
436
Ted Kremenek874d63f2008-01-24 02:02:54 +0000437RValue RValue::EvalSub(ValueManager& ValMgr, const RValue& RHS) const {
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000438 RVALUE_DISPATCH(Sub)
439}
440
Ted Kremenek874d63f2008-01-24 02:02:54 +0000441RValue RValue::EvalMul(ValueManager& ValMgr, const RValue& RHS) const {
Ted Kremenek2eafd0e2008-01-23 23:42:27 +0000442 RVALUE_DISPATCH(Mul)
443}
444
Ted Kremenek5ee4ff82008-01-25 22:55:56 +0000445RValue RValue::EvalDiv(ValueManager& ValMgr, const RValue& RHS) const {
446 RVALUE_DISPATCH(Div)
447}
448
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000449#undef RVALUE_DISPATCH_CASE
450#undef RVALUE_DISPATCH
451
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000452
Ted Kremenek5ee4ff82008-01-25 22:55:56 +0000453RValue RValue::GetRValue(ValueManager& ValMgr, const APSInt& V) {
454 return RValEqualityORSet(ValMgr.AddToSet(ValMgr.GetEmptyAPSIntSet(), V));
Ted Kremenekdacbb4f2008-01-24 08:20:02 +0000455}
456
457RValue RValue::GetRValue(ValueManager& ValMgr, IntegerLiteral* I) {
Ted Kremenek5ee4ff82008-01-25 22:55:56 +0000458 return GetRValue(ValMgr,
459 APSInt(I->getValue(),I->getType()->isUnsignedIntegerType()));
Ted Kremenekdacbb4f2008-01-24 08:20:02 +0000460}
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000461
462//===----------------------------------------------------------------------===//
463// "L-Values".
464//===----------------------------------------------------------------------===//
465
466namespace {
Ted Kremenekf13794e2008-01-24 23:19:54 +0000467
Ted Kremenek5ee4ff82008-01-25 22:55:56 +0000468enum { LValueDeclKind, MaxLValueKind };
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000469
470class VISIBILITY_HIDDEN LValueDecl : public LValue {
471public:
Ted Kremenek9de04c42008-01-24 20:55:43 +0000472 LValueDecl(const ValueDecl* vd)
473 : LValue(LValueDeclKind,const_cast<ValueDecl*>(vd)) {}
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000474
475 ValueDecl* getDecl() const {
476 return static_cast<ValueDecl*>(getRawPtr());
477 }
478
479 // Implement isa<T> support.
480 static inline bool classof(const ExprValue* V) {
Ted Kremenekf13794e2008-01-24 23:19:54 +0000481 return V->getSubKind() == LValueDeclKind;
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000482 }
483};
484} // end anonymous namespace
485
486//===----------------------------------------------------------------------===//
487// Pretty-Printing.
488//===----------------------------------------------------------------------===//
489
490void ExprValue::print(std::ostream& Out) const {
Ted Kremenekf13794e2008-01-24 23:19:54 +0000491 switch (getBaseKind()) {
492 case InvalidKind:
493 Out << "Invalid";
494 break;
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000495
Ted Kremenekf13794e2008-01-24 23:19:54 +0000496 case RValueKind:
497 cast<RValue>(this)->print(Out);
498 break;
499
500 case LValueKind:
501 assert (false && "FIXME: LValue printing not implemented.");
502 break;
503
504 default:
505 assert (false && "Invalid ExprValue.");
506 }
507}
508
509void RValue::print(std::ostream& Out) const {
510 switch (getSubKind()) {
Ted Kremenek5ee4ff82008-01-25 22:55:56 +0000511 case RValEqualityORSetKind: {
512 APSIntSetTy S = cast<RValEqualityORSet>(this)->GetValues();
Ted Kremenek803c9ed2008-01-23 22:30:44 +0000513 bool first = true;
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000514
Ted Kremenek803c9ed2008-01-23 22:30:44 +0000515 for (APSIntSetTy::iterator I=S.begin(), E=S.end(); I!=E; ++I) {
516 if (first) first = false;
517 else Out << " | ";
518
519 Out << (*I).toString();
520 }
521
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000522 break;
523 }
524
525 default:
Ted Kremenekf13794e2008-01-24 23:19:54 +0000526 assert (false && "Pretty-printed not implemented for this RValue.");
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000527 break;
528 }
529}
530
531//===----------------------------------------------------------------------===//
532// ValueMapTy - A ImmutableMap type Stmt*/Decl* to ExprValues.
533//===----------------------------------------------------------------------===//
534
535typedef llvm::ImmutableMap<ValueKey,ExprValue> ValueMapTy;
536
537namespace clang {
538 template<>
539 struct VISIBILITY_HIDDEN GRTrait<ValueMapTy> {
540 static inline void* toPtr(ValueMapTy M) {
541 return reinterpret_cast<void*>(M.getRoot());
542 }
543 static inline ValueMapTy toState(void* P) {
544 return ValueMapTy(static_cast<ValueMapTy::TreeTy*>(P));
545 }
546 };
Ted Kremenekd27f8162008-01-15 23:55:06 +0000547}
548
549//===----------------------------------------------------------------------===//
550// The Checker!
551//===----------------------------------------------------------------------===//
552
553namespace {
Ted Kremenekd27f8162008-01-15 23:55:06 +0000554
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000555class VISIBILITY_HIDDEN GRConstants {
Ted Kremenekd27f8162008-01-15 23:55:06 +0000556
557public:
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000558 typedef ValueMapTy StateTy;
Ted Kremenekd27f8162008-01-15 23:55:06 +0000559 typedef GRNodeBuilder<GRConstants> NodeBuilder;
560 typedef ExplodedNode<StateTy> NodeTy;
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000561
562 class NodeSet {
563 typedef llvm::SmallVector<NodeTy*,3> ImplTy;
564 ImplTy Impl;
565 public:
566
567 NodeSet() {}
568 NodeSet(NodeTy* N) { assert (N && !N->isInfeasible()); Impl.push_back(N); }
569
570 void Add(NodeTy* N) { if (N && !N->isInfeasible()) Impl.push_back(N); }
571
572 typedef ImplTy::iterator iterator;
573 typedef ImplTy::const_iterator const_iterator;
574
575 unsigned size() const { return Impl.size(); }
Ted Kremenek9de04c42008-01-24 20:55:43 +0000576 bool empty() const { return Impl.empty(); }
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000577
578 iterator begin() { return Impl.begin(); }
579 iterator end() { return Impl.end(); }
580
581 const_iterator begin() const { return Impl.begin(); }
582 const_iterator end() const { return Impl.end(); }
583 };
Ted Kremenekd27f8162008-01-15 23:55:06 +0000584
585protected:
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000586 /// Liveness - live-variables information the ValueDecl* and block-level
587 /// Expr* in the CFG. Used to prune out dead state.
Ted Kremenekd27f8162008-01-15 23:55:06 +0000588 LiveVariables* Liveness;
589
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000590 /// Builder - The current GRNodeBuilder which is used when building the nodes
591 /// for a given statement.
Ted Kremenekd27f8162008-01-15 23:55:06 +0000592 NodeBuilder* Builder;
593
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000594 /// StateMgr - Object that manages the data for all created states.
595 ValueMapTy::Factory StateMgr;
Ted Kremenekd27f8162008-01-15 23:55:06 +0000596
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000597 /// ValueMgr - Object that manages the data for all created ExprValues.
598 ValueManager ValMgr;
599
600 /// cfg - the current CFG.
Ted Kremenekd27f8162008-01-15 23:55:06 +0000601 CFG* cfg;
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000602
603 /// StmtEntryNode - The immediate predecessor node.
604 NodeTy* StmtEntryNode;
605
606 /// CurrentStmt - The current block-level statement.
607 Stmt* CurrentStmt;
608
609 bool StateCleaned;
Ted Kremenekd27f8162008-01-15 23:55:06 +0000610
Ted Kremenek7b8009a2008-01-24 02:28:56 +0000611 ASTContext* getContext() const { return ValMgr.getContext(); }
612
Ted Kremenekd27f8162008-01-15 23:55:06 +0000613public:
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000614 GRConstants() : Liveness(NULL), Builder(NULL), cfg(NULL),
615 StmtEntryNode(NULL), CurrentStmt(NULL) {}
Ted Kremenekd27f8162008-01-15 23:55:06 +0000616
617 ~GRConstants() { delete Liveness; }
618
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000619 /// getCFG - Returns the CFG associated with this analysis.
Ted Kremenekd27f8162008-01-15 23:55:06 +0000620 CFG& getCFG() { assert (cfg); return *cfg; }
621
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000622 /// Initialize - Initialize the checker's state based on the specified
623 /// CFG. This results in liveness information being computed for
624 /// each block-level statement in the CFG.
Ted Kremenek874d63f2008-01-24 02:02:54 +0000625 void Initialize(CFG& c, ASTContext& ctx) {
626 cfg = &c;
627 ValMgr.setContext(&ctx);
Ted Kremenekd27f8162008-01-15 23:55:06 +0000628 Liveness = new LiveVariables(c);
629 Liveness->runOnCFG(c);
Ted Kremenek79649df2008-01-17 18:25:22 +0000630 Liveness->runOnAllBlocks(c, NULL, true);
Ted Kremenekd27f8162008-01-15 23:55:06 +0000631 }
632
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000633 /// getInitialState - Return the initial state used for the root vertex
634 /// in the ExplodedGraph.
Ted Kremenekd27f8162008-01-15 23:55:06 +0000635 StateTy getInitialState() {
Ted Kremenekcb448ca2008-01-16 00:53:15 +0000636 return StateMgr.GetEmptyMap();
Ted Kremenekd27f8162008-01-15 23:55:06 +0000637 }
Ted Kremenekd27f8162008-01-15 23:55:06 +0000638
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000639 /// ProcessStmt - Called by GREngine. Used to generate new successor
640 /// nodes by processing the 'effects' of a block-level statement.
641 void ProcessStmt(Stmt* S, NodeBuilder& builder);
642
643 /// RemoveDeadBindings - Return a new state that is the same as 'M' except
644 /// that all subexpression mappings are removed and that any
645 /// block-level expressions that are not live at 'S' also have their
646 /// mappings removed.
647 StateTy RemoveDeadBindings(Stmt* S, StateTy M);
648
Ted Kremenek9de04c42008-01-24 20:55:43 +0000649 StateTy SetValue(StateTy St, Stmt* S, const ExprValue& V);
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000650
Ted Kremenek9de04c42008-01-24 20:55:43 +0000651 StateTy SetValue(StateTy St, const Stmt* S, const ExprValue& V) {
652 return SetValue(St, const_cast<Stmt*>(S), V);
653 }
654
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000655 StateTy SetValue(StateTy St, const LValue& LV, const ExprValue& V);
Ted Kremenek1ccd31c2008-01-16 19:42:59 +0000656
Ted Kremenek9de04c42008-01-24 20:55:43 +0000657 ExprValue GetValue(const StateTy& St, Stmt* S);
658 inline ExprValue GetValue(const StateTy& St, const Stmt* S) {
659 return GetValue(St, const_cast<Stmt*>(S));
660 }
661
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000662 ExprValue GetValue(const StateTy& St, const LValue& LV);
663 LValue GetLValue(const StateTy& St, Stmt* S);
Ted Kremenekd27f8162008-01-15 23:55:06 +0000664
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000665 void Nodify(NodeSet& Dst, Stmt* S, NodeTy* Pred, StateTy St);
Ted Kremenekd27f8162008-01-15 23:55:06 +0000666
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000667 /// Visit - Transfer function logic for all statements. Dispatches to
668 /// other functions that handle specific kinds of statements.
669 void Visit(Stmt* S, NodeTy* Pred, NodeSet& Dst);
Ted Kremenek874d63f2008-01-24 02:02:54 +0000670
671 /// VisitCast - Transfer function logic for all casts (implicit and explicit).
672 void VisitCast(Expr* CastE, Expr* E, NodeTy* Pred, NodeSet& Dst);
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000673
Ted Kremenek7b8009a2008-01-24 02:28:56 +0000674 /// VisitUnaryOperator - Transfer function logic for unary operators.
675 void VisitUnaryOperator(UnaryOperator* B, NodeTy* Pred, NodeSet& Dst);
676
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000677 /// VisitBinaryOperator - Transfer function logic for binary operators.
Ted Kremenek9de04c42008-01-24 20:55:43 +0000678 void VisitBinaryOperator(BinaryOperator* B, NodeTy* Pred, NodeSet& Dst);
679
680 /// VisitDeclStmt - Transfer function logic for DeclStmts.
681 void VisitDeclStmt(DeclStmt* DS, NodeTy* Pred, NodeSet& Dst);
Ted Kremenekd27f8162008-01-15 23:55:06 +0000682};
683} // end anonymous namespace
684
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000685
Ted Kremenekd27f8162008-01-15 23:55:06 +0000686void GRConstants::ProcessStmt(Stmt* S, NodeBuilder& builder) {
687 Builder = &builder;
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000688
689 StmtEntryNode = builder.getLastNode();
690 CurrentStmt = S;
691 NodeSet Dst;
692 StateCleaned = false;
693
694 Visit(S, StmtEntryNode, Dst);
695
696 // If no nodes were generated, generate a new node that has all the
697 // dead mappings removed.
698 if (Dst.size() == 1 && *Dst.begin() == StmtEntryNode) {
699 StateTy St = RemoveDeadBindings(S, StmtEntryNode->getState());
700 builder.generateNode(S, St, StmtEntryNode);
701 }
Ted Kremenekf84469b2008-01-18 00:41:32 +0000702
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000703 CurrentStmt = NULL;
704 StmtEntryNode = NULL;
705 Builder = NULL;
Ted Kremenekd27f8162008-01-15 23:55:06 +0000706}
707
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000708
709ExprValue GRConstants::GetValue(const StateTy& St, const LValue& LV) {
Ted Kremenekf13794e2008-01-24 23:19:54 +0000710 switch (LV.getSubKind()) {
711 case LValueDeclKind: {
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000712 StateTy::TreeTy* T = St.SlimFind(cast<LValueDecl>(LV).getDecl());
713 return T ? T->getValue().second : InvalidValue();
714 }
715 default:
716 assert (false && "Invalid LValue.");
Ted Kremenekca3e8572008-01-16 22:28:08 +0000717 break;
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000718 }
719
720 return InvalidValue();
721}
722
723ExprValue GRConstants::GetValue(const StateTy& St, Stmt* S) {
Ted Kremenek671c9e82008-01-24 00:50:08 +0000724 for (;;) {
725 switch (S->getStmtClass()) {
726 case Stmt::ParenExprClass:
727 S = cast<ParenExpr>(S)->getSubExpr();
728 continue;
729
730 case Stmt::DeclRefExprClass:
731 return GetValue(St, LValueDecl(cast<DeclRefExpr>(S)->getDecl()));
Ted Kremenekca3e8572008-01-16 22:28:08 +0000732
Ted Kremenek671c9e82008-01-24 00:50:08 +0000733 case Stmt::IntegerLiteralClass:
Ted Kremenekdacbb4f2008-01-24 08:20:02 +0000734 return RValue::GetRValue(ValMgr, cast<IntegerLiteral>(S));
Ted Kremenek874d63f2008-01-24 02:02:54 +0000735
736 case Stmt::ImplicitCastExprClass: {
737 ImplicitCastExpr* C = cast<ImplicitCastExpr>(S);
738 if (C->getType() == C->getSubExpr()->getType()) {
739 S = C->getSubExpr();
740 continue;
741 }
742 break;
743 }
744
745 case Stmt::CastExprClass: {
746 CastExpr* C = cast<CastExpr>(S);
747 if (C->getType() == C->getSubExpr()->getType()) {
748 S = C->getSubExpr();
749 continue;
750 }
751 break;
752 }
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000753
Ted Kremenek671c9e82008-01-24 00:50:08 +0000754 default:
755 break;
756 };
757
758 break;
759 }
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000760
Ted Kremenek5c1b9962008-01-24 19:43:37 +0000761 StateTy::TreeTy* T = St.SlimFind(S);
Ted Kremenek874d63f2008-01-24 02:02:54 +0000762
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000763 return T ? T->getValue().second : InvalidValue();
764}
765
766LValue GRConstants::GetLValue(const StateTy& St, Stmt* S) {
767 if (Expr* E = dyn_cast<Expr>(S))
768 S = E->IgnoreParens();
769
770 if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(S))
771 return LValueDecl(DR->getDecl());
772
773 return cast<LValue>(GetValue(St, S));
774}
775
776GRConstants::StateTy GRConstants::SetValue(StateTy St, Stmt* S,
Ted Kremenekdaadf452008-01-24 19:28:01 +0000777 const ExprValue& V) {
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000778
779 if (!StateCleaned) {
780 St = RemoveDeadBindings(CurrentStmt, St);
781 StateCleaned = true;
782 }
783
Ted Kremenek9ff731d2008-01-24 22:27:20 +0000784 bool isBlkExpr = false;
785
786 if (S == CurrentStmt) {
787 isBlkExpr = getCFG().isBlkExpr(S);
788
789 if (!isBlkExpr)
790 return St;
791 }
Ted Kremenekdaadf452008-01-24 19:28:01 +0000792
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000793 return V.isValid() ? StateMgr.Add(St, ValueKey(S,isBlkExpr), V)
794 : St;
795}
796
797GRConstants::StateTy GRConstants::SetValue(StateTy St, const LValue& LV,
798 const ExprValue& V) {
799 if (!LV.isValid())
800 return St;
801
802 if (!StateCleaned) {
803 St = RemoveDeadBindings(CurrentStmt, St);
804 StateCleaned = true;
Ted Kremenekca3e8572008-01-16 22:28:08 +0000805 }
Ted Kremenek0525a4f2008-01-16 19:47:19 +0000806
Ted Kremenekf13794e2008-01-24 23:19:54 +0000807 switch (LV.getSubKind()) {
808 case LValueDeclKind:
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000809 return V.isValid() ? StateMgr.Add(St, cast<LValueDecl>(LV).getDecl(), V)
810 : StateMgr.Remove(St, cast<LValueDecl>(LV).getDecl());
811
812 default:
813 assert ("SetValue for given LValue type not yet implemented.");
814 return St;
815 }
Ted Kremenekd27f8162008-01-15 23:55:06 +0000816}
817
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000818GRConstants::StateTy GRConstants::RemoveDeadBindings(Stmt* Loc, StateTy M) {
Ted Kremenekf84469b2008-01-18 00:41:32 +0000819 // Note: in the code below, we can assign a new map to M since the
820 // iterators are iterating over the tree of the *original* map.
Ted Kremenekf84469b2008-01-18 00:41:32 +0000821 StateTy::iterator I = M.begin(), E = M.end();
822
Ted Kremenek5c1b9962008-01-24 19:43:37 +0000823 // Remove old bindings for subexpressions and "dead" block-level expressions.
824 for (; I!=E && !I.getKey().isDecl(); ++I) {
825 if (I.getKey().isSubExpr() || !Liveness->isLive(Loc,cast<Stmt>(I.getKey())))
826 M = StateMgr.Remove(M, I.getKey());
827 }
Ted Kremenekf84469b2008-01-18 00:41:32 +0000828
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000829 // Remove bindings for "dead" decls.
Ted Kremenek5c1b9962008-01-24 19:43:37 +0000830 for (; I!=E ; ++I) {
831 assert (I.getKey().isDecl());
832
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000833 if (VarDecl* V = dyn_cast<VarDecl>(cast<ValueDecl>(I.getKey())))
834 if (!Liveness->isLive(Loc, V))
835 M = StateMgr.Remove(M, I.getKey());
Ted Kremenek5c1b9962008-01-24 19:43:37 +0000836 }
Ted Kremenek565256e2008-01-24 22:44:24 +0000837
Ted Kremeneke00fe3f2008-01-17 00:52:48 +0000838 return M;
Ted Kremeneke00fe3f2008-01-17 00:52:48 +0000839}
840
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000841void GRConstants::Nodify(NodeSet& Dst, Stmt* S, GRConstants::NodeTy* Pred,
842 GRConstants::StateTy St) {
843
844 // If the state hasn't changed, don't generate a new node.
845 if (St == Pred->getState())
846 return;
Ted Kremenekcb448ca2008-01-16 00:53:15 +0000847
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000848 Dst.Add(Builder->generateNode(S, St, Pred));
Ted Kremenekcb448ca2008-01-16 00:53:15 +0000849}
Ted Kremenekd27f8162008-01-15 23:55:06 +0000850
Ted Kremenek874d63f2008-01-24 02:02:54 +0000851void GRConstants::VisitCast(Expr* CastE, Expr* E, GRConstants::NodeTy* Pred,
852 GRConstants::NodeSet& Dst) {
853
854 QualType T = CastE->getType();
855
856 // Check for redundant casts.
857 if (E->getType() == T) {
858 Dst.Add(Pred);
859 return;
860 }
861
862 NodeSet S1;
863 Visit(E, Pred, S1);
864
865 for (NodeSet::iterator I1=S1.begin(), E1=S1.end(); I1 != E1; ++I1) {
866 NodeTy* N = *I1;
867 StateTy St = N->getState();
868 const ExprValue& V = GetValue(St, E);
869 Nodify(Dst, CastE, N, SetValue(St, CastE, V.EvalCast(ValMgr, CastE)));
870 }
Ted Kremenek9de04c42008-01-24 20:55:43 +0000871}
872
873void GRConstants::VisitDeclStmt(DeclStmt* DS, GRConstants::NodeTy* Pred,
874 GRConstants::NodeSet& Dst) {
875
876 StateTy St = Pred->getState();
877
878 for (const ScopedDecl* D = DS->getDecl(); D; D = D->getNextDeclarator())
879 if (const VarDecl* VD = dyn_cast<VarDecl>(D))
880 St = SetValue(St, LValueDecl(VD), GetValue(St, VD->getInit()));
881
882 Nodify(Dst, DS, Pred, St);
883
884 if (Dst.empty())
885 Dst.Add(Pred);
886}
Ted Kremenek874d63f2008-01-24 02:02:54 +0000887
Ted Kremenek7b8009a2008-01-24 02:28:56 +0000888void GRConstants::VisitUnaryOperator(UnaryOperator* U,
889 GRConstants::NodeTy* Pred,
890 GRConstants::NodeSet& Dst) {
891 NodeSet S1;
892 Visit(U->getSubExpr(), Pred, S1);
893
894 for (NodeSet::iterator I1=S1.begin(), E1=S1.end(); I1 != E1; ++I1) {
895 NodeTy* N1 = *I1;
896 StateTy St = N1->getState();
897
898 switch (U->getOpcode()) {
899 case UnaryOperator::PostInc: {
900 const LValue& L1 = GetLValue(St, U->getSubExpr());
901 RValue R1 = cast<RValue>(GetValue(St, L1));
902
903 QualType T = U->getType();
Ted Kremeneke0cf9c82008-01-24 19:00:57 +0000904 unsigned bits = getContext()->getTypeSize(T, U->getLocStart());
Ted Kremenek5ee4ff82008-01-25 22:55:56 +0000905 APSInt One(llvm::APInt(bits, 1), T->isUnsignedIntegerType());
Ted Kremeneke0cf9c82008-01-24 19:00:57 +0000906 RValue R2 = RValue::GetRValue(ValMgr, One);
907
Ted Kremenek7b8009a2008-01-24 02:28:56 +0000908 RValue Result = R1.EvalAdd(ValMgr, R2);
909 Nodify(Dst, U, N1, SetValue(SetValue(St, U, R1), L1, Result));
910 break;
911 }
912
913 case UnaryOperator::PostDec: {
914 const LValue& L1 = GetLValue(St, U->getSubExpr());
915 RValue R1 = cast<RValue>(GetValue(St, L1));
916
917 QualType T = U->getType();
Ted Kremeneke0cf9c82008-01-24 19:00:57 +0000918 unsigned bits = getContext()->getTypeSize(T, U->getLocStart());
Ted Kremenek5ee4ff82008-01-25 22:55:56 +0000919 APSInt One(llvm::APInt(bits, 1), T->isUnsignedIntegerType());
Ted Kremeneke0cf9c82008-01-24 19:00:57 +0000920 RValue R2 = RValue::GetRValue(ValMgr, One);
Ted Kremenek7b8009a2008-01-24 02:28:56 +0000921
922 RValue Result = R1.EvalSub(ValMgr, R2);
923 Nodify(Dst, U, N1, SetValue(SetValue(St, U, R1), L1, Result));
924 break;
925 }
926
927 case UnaryOperator::PreInc: {
928 const LValue& L1 = GetLValue(St, U->getSubExpr());
929 RValue R1 = cast<RValue>(GetValue(St, L1));
930
931 QualType T = U->getType();
Ted Kremeneke0cf9c82008-01-24 19:00:57 +0000932 unsigned bits = getContext()->getTypeSize(T, U->getLocStart());
Ted Kremenek5ee4ff82008-01-25 22:55:56 +0000933 APSInt One(llvm::APInt(bits, 1), T->isUnsignedIntegerType());
Ted Kremenek7b8009a2008-01-24 02:28:56 +0000934 RValue R2 = RValue::GetRValue(ValMgr, One);
935
936 RValue Result = R1.EvalAdd(ValMgr, R2);
937 Nodify(Dst, U, N1, SetValue(SetValue(St, U, Result), L1, Result));
938 break;
939 }
940
941 case UnaryOperator::PreDec: {
942 const LValue& L1 = GetLValue(St, U->getSubExpr());
943 RValue R1 = cast<RValue>(GetValue(St, L1));
944
945 QualType T = U->getType();
Ted Kremeneke0cf9c82008-01-24 19:00:57 +0000946 unsigned bits = getContext()->getTypeSize(T, U->getLocStart());
Ted Kremenek5ee4ff82008-01-25 22:55:56 +0000947 APSInt One(llvm::APInt(bits, 1), T->isUnsignedIntegerType());
Ted Kremeneke0cf9c82008-01-24 19:00:57 +0000948 RValue R2 = RValue::GetRValue(ValMgr, One);
Ted Kremenek7b8009a2008-01-24 02:28:56 +0000949
950 RValue Result = R1.EvalSub(ValMgr, R2);
951 Nodify(Dst, U, N1, SetValue(SetValue(St, U, Result), L1, Result));
952 break;
953 }
954
Ted Kremenekdacbb4f2008-01-24 08:20:02 +0000955 case UnaryOperator::Minus: {
956 const RValue& R1 = cast<RValue>(GetValue(St, U->getSubExpr()));
957 Nodify(Dst, U, N1, SetValue(St, U, R1.EvalMinus(ValMgr, U)));
958 break;
959 }
960
Ted Kremenek7b8009a2008-01-24 02:28:56 +0000961 default: ;
962 assert (false && "Not implemented.");
963 }
964 }
965}
966
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000967void GRConstants::VisitBinaryOperator(BinaryOperator* B,
968 GRConstants::NodeTy* Pred,
969 GRConstants::NodeSet& Dst) {
970 NodeSet S1;
971 Visit(B->getLHS(), Pred, S1);
Ted Kremenekcb448ca2008-01-16 00:53:15 +0000972
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000973 for (NodeSet::iterator I1=S1.begin(), E1=S1.end(); I1 != E1; ++I1) {
974 NodeTy* N1 = *I1;
Ted Kremeneke00fe3f2008-01-17 00:52:48 +0000975
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000976 // When getting the value for the LHS, check if we are in an assignment.
977 // In such cases, we want to (initially) treat the LHS as an LValue,
978 // so we use GetLValue instead of GetValue so that DeclRefExpr's are
979 // evaluated to LValueDecl's instead of to an RValue.
980 const ExprValue& V1 =
981 B->isAssignmentOp() ? GetLValue(N1->getState(), B->getLHS())
982 : GetValue(N1->getState(), B->getLHS());
Ted Kremenekcb448ca2008-01-16 00:53:15 +0000983
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000984 NodeSet S2;
985 Visit(B->getRHS(), N1, S2);
986
987 for (NodeSet::iterator I2=S2.begin(), E2=S2.end(); I2 != E2; ++I2) {
988 NodeTy* N2 = *I2;
989 StateTy St = N2->getState();
990 const ExprValue& V2 = GetValue(St, B->getRHS());
991
992 switch (B->getOpcode()) {
993 case BinaryOperator::Add: {
994 const RValue& R1 = cast<RValue>(V1);
995 const RValue& R2 = cast<RValue>(V2);
996
Ted Kremenek874d63f2008-01-24 02:02:54 +0000997 Nodify(Dst, B, N2, SetValue(St, B, R1.EvalAdd(ValMgr, R2)));
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000998 break;
999 }
1000
1001 case BinaryOperator::Sub: {
1002 const RValue& R1 = cast<RValue>(V1);
1003 const RValue& R2 = cast<RValue>(V2);
Ted Kremenek874d63f2008-01-24 02:02:54 +00001004 Nodify(Dst, B, N2, SetValue(St, B, R1.EvalSub(ValMgr, R2)));
Ted Kremenekab2b8c52008-01-23 19:59:44 +00001005 break;
1006 }
1007
Ted Kremenek2eafd0e2008-01-23 23:42:27 +00001008 case BinaryOperator::Mul: {
1009 const RValue& R1 = cast<RValue>(V1);
1010 const RValue& R2 = cast<RValue>(V2);
Ted Kremenek874d63f2008-01-24 02:02:54 +00001011 Nodify(Dst, B, N2, SetValue(St, B, R1.EvalMul(ValMgr, R2)));
Ted Kremenek2eafd0e2008-01-23 23:42:27 +00001012 break;
1013 }
1014
Ted Kremenek5ee4ff82008-01-25 22:55:56 +00001015 case BinaryOperator::Div: {
1016 const RValue& R1 = cast<RValue>(V1);
1017 const RValue& R2 = cast<RValue>(V2);
1018 Nodify(Dst, B, N2, SetValue(St, B, R1.EvalDiv(ValMgr, R2)));
1019 break;
1020 }
1021
Ted Kremenekab2b8c52008-01-23 19:59:44 +00001022 case BinaryOperator::Assign: {
1023 const LValue& L1 = cast<LValue>(V1);
1024 const RValue& R2 = cast<RValue>(V2);
Ted Kremenekab2b8c52008-01-23 19:59:44 +00001025 Nodify(Dst, B, N2, SetValue(SetValue(St, B, R2), L1, R2));
1026 break;
1027 }
Ted Kremenekb4ae33f2008-01-23 23:38:00 +00001028
1029 case BinaryOperator::AddAssign: {
1030 const LValue& L1 = cast<LValue>(V1);
1031 RValue R1 = cast<RValue>(GetValue(N1->getState(), L1));
Ted Kremenek874d63f2008-01-24 02:02:54 +00001032 RValue Result = R1.EvalAdd(ValMgr, cast<RValue>(V2));
Ted Kremenekb4ae33f2008-01-23 23:38:00 +00001033 Nodify(Dst, B, N2, SetValue(SetValue(St, B, Result), L1, Result));
1034 break;
1035 }
1036
1037 case BinaryOperator::SubAssign: {
1038 const LValue& L1 = cast<LValue>(V1);
1039 RValue R1 = cast<RValue>(GetValue(N1->getState(), L1));
Ted Kremenek874d63f2008-01-24 02:02:54 +00001040 RValue Result = R1.EvalSub(ValMgr, cast<RValue>(V2));
Ted Kremenekb4ae33f2008-01-23 23:38:00 +00001041 Nodify(Dst, B, N2, SetValue(SetValue(St, B, Result), L1, Result));
1042 break;
1043 }
Ted Kremenek2eafd0e2008-01-23 23:42:27 +00001044
1045 case BinaryOperator::MulAssign: {
1046 const LValue& L1 = cast<LValue>(V1);
1047 RValue R1 = cast<RValue>(GetValue(N1->getState(), L1));
Ted Kremenek874d63f2008-01-24 02:02:54 +00001048 RValue Result = R1.EvalMul(ValMgr, cast<RValue>(V2));
Ted Kremenek2eafd0e2008-01-23 23:42:27 +00001049 Nodify(Dst, B, N2, SetValue(SetValue(St, B, Result), L1, Result));
1050 break;
1051 }
Ted Kremenekab2b8c52008-01-23 19:59:44 +00001052
1053 default:
1054 Dst.Add(N2);
1055 break;
1056 }
Ted Kremenekcb448ca2008-01-16 00:53:15 +00001057 }
Ted Kremenekd27f8162008-01-15 23:55:06 +00001058 }
Ted Kremenekd27f8162008-01-15 23:55:06 +00001059}
Ted Kremenekee985462008-01-16 18:18:48 +00001060
Ted Kremenek1ccd31c2008-01-16 19:42:59 +00001061
Ted Kremenekab2b8c52008-01-23 19:59:44 +00001062void GRConstants::Visit(Stmt* S, GRConstants::NodeTy* Pred,
1063 GRConstants::NodeSet& Dst) {
1064
1065 // FIXME: add metadata to the CFG so that we can disable
1066 // this check when we KNOW that there is no block-level subexpression.
1067 // The motivation is that this check requires a hashtable lookup.
1068
1069 if (S != CurrentStmt && getCFG().isBlkExpr(S)) {
1070 Dst.Add(Pred);
1071 return;
1072 }
1073
1074 switch (S->getStmtClass()) {
1075 case Stmt::BinaryOperatorClass:
Ted Kremenekb4ae33f2008-01-23 23:38:00 +00001076 case Stmt::CompoundAssignOperatorClass:
Ted Kremenekab2b8c52008-01-23 19:59:44 +00001077 VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Dst);
1078 break;
1079
Ted Kremenek7b8009a2008-01-24 02:28:56 +00001080 case Stmt::UnaryOperatorClass:
1081 VisitUnaryOperator(cast<UnaryOperator>(S), Pred, Dst);
1082 break;
1083
Ted Kremenekab2b8c52008-01-23 19:59:44 +00001084 case Stmt::ParenExprClass:
1085 Visit(cast<ParenExpr>(S)->getSubExpr(), Pred, Dst);
1086 break;
1087
Ted Kremenek874d63f2008-01-24 02:02:54 +00001088 case Stmt::ImplicitCastExprClass: {
1089 ImplicitCastExpr* C = cast<ImplicitCastExpr>(S);
1090 VisitCast(C, C->getSubExpr(), Pred, Dst);
1091 break;
1092 }
1093
1094 case Stmt::CastExprClass: {
1095 CastExpr* C = cast<CastExpr>(S);
1096 VisitCast(C, C->getSubExpr(), Pred, Dst);
1097 break;
1098 }
1099
Ted Kremenek9de04c42008-01-24 20:55:43 +00001100 case Stmt::DeclStmtClass:
1101 VisitDeclStmt(cast<DeclStmt>(S), Pred, Dst);
1102 break;
1103
Ted Kremenekab2b8c52008-01-23 19:59:44 +00001104 default:
1105 Dst.Add(Pred); // No-op. Simply propagate the current state unchanged.
1106 break;
Ted Kremenek79649df2008-01-17 18:25:22 +00001107 }
Ted Kremenek1ccd31c2008-01-16 19:42:59 +00001108}
1109
Ted Kremenekee985462008-01-16 18:18:48 +00001110//===----------------------------------------------------------------------===//
1111// Driver.
1112//===----------------------------------------------------------------------===//
1113
Ted Kremenekaa66a322008-01-16 21:46:15 +00001114#ifndef NDEBUG
1115namespace llvm {
1116template<>
1117struct VISIBILITY_HIDDEN DOTGraphTraits<GRConstants::NodeTy*> :
1118 public DefaultDOTGraphTraits {
Ted Kremenek9ff731d2008-01-24 22:27:20 +00001119
1120 static void PrintKindLabel(std::ostream& Out, ValueKey::Kind kind) {
Ted Kremenek803c9ed2008-01-23 22:30:44 +00001121 switch (kind) {
Ted Kremenek565256e2008-01-24 22:44:24 +00001122 case ValueKey::IsSubExpr: Out << "Sub-Expressions:\\l"; break;
Ted Kremenek803c9ed2008-01-23 22:30:44 +00001123 case ValueKey::IsDecl: Out << "Variables:\\l"; break;
1124 case ValueKey::IsBlkExpr: Out << "Block-level Expressions:\\l"; break;
1125 default: assert (false && "Unknown ValueKey type.");
1126 }
1127 }
1128
Ted Kremenek9ff731d2008-01-24 22:27:20 +00001129 static void PrintKind(std::ostream& Out, GRConstants::StateTy M,
1130 ValueKey::Kind kind, bool isFirstGroup = false) {
1131 bool isFirst = true;
1132
1133 for (GRConstants::StateTy::iterator I=M.begin(), E=M.end();I!=E;++I) {
1134 if (I.getKey().getKind() != kind)
1135 continue;
1136
1137 if (isFirst) {
1138 if (!isFirstGroup) Out << "\\l\\l";
1139 PrintKindLabel(Out, kind);
1140 isFirst = false;
1141 }
1142 else
1143 Out << "\\l";
1144
1145 Out << ' ';
1146
1147 if (ValueDecl* V = dyn_cast<ValueDecl>(I.getKey()))
1148 Out << V->getName();
1149 else {
1150 Stmt* E = cast<Stmt>(I.getKey());
1151 Out << " (" << (void*) E << ") ";
1152 E->printPretty(Out);
1153 }
1154
1155 Out << " : ";
1156 I.getData().print(Out);
1157 }
1158 }
1159
Ted Kremenekaa66a322008-01-16 21:46:15 +00001160 static std::string getNodeLabel(const GRConstants::NodeTy* N, void*) {
1161 std::ostringstream Out;
Ted Kremenek803c9ed2008-01-23 22:30:44 +00001162
1163 // Program Location.
Ted Kremenekaa66a322008-01-16 21:46:15 +00001164 ProgramPoint Loc = N->getLocation();
1165
1166 switch (Loc.getKind()) {
1167 case ProgramPoint::BlockEntranceKind:
1168 Out << "Block Entrance: B"
1169 << cast<BlockEntrance>(Loc).getBlock()->getBlockID();
1170 break;
1171
1172 case ProgramPoint::BlockExitKind:
1173 assert (false);
1174 break;
1175
1176 case ProgramPoint::PostStmtKind: {
1177 const PostStmt& L = cast<PostStmt>(Loc);
Ted Kremenek9ff731d2008-01-24 22:27:20 +00001178 Out << L.getStmt()->getStmtClassName() << ':'
1179 << (void*) L.getStmt() << ' ';
1180
Ted Kremenekaa66a322008-01-16 21:46:15 +00001181 L.getStmt()->printPretty(Out);
1182 break;
1183 }
1184
1185 default: {
1186 const BlockEdge& E = cast<BlockEdge>(Loc);
1187 Out << "Edge: (B" << E.getSrc()->getBlockID() << ", B"
1188 << E.getDst()->getBlockID() << ')';
1189 }
1190 }
1191
Ted Kremenek803c9ed2008-01-23 22:30:44 +00001192 Out << "\\|";
Ted Kremenekaa66a322008-01-16 21:46:15 +00001193
Ted Kremenek9ff731d2008-01-24 22:27:20 +00001194 PrintKind(Out, N->getState(), ValueKey::IsDecl, true);
1195 PrintKind(Out, N->getState(), ValueKey::IsBlkExpr);
Ted Kremenek565256e2008-01-24 22:44:24 +00001196 PrintKind(Out, N->getState(), ValueKey::IsSubExpr);
Ted Kremenek803c9ed2008-01-23 22:30:44 +00001197
Ted Kremenek803c9ed2008-01-23 22:30:44 +00001198 Out << "\\l";
Ted Kremenekaa66a322008-01-16 21:46:15 +00001199 return Out.str();
1200 }
1201};
1202} // end llvm namespace
1203#endif
1204
Ted Kremenekee985462008-01-16 18:18:48 +00001205namespace clang {
Ted Kremenek874d63f2008-01-24 02:02:54 +00001206void RunGRConstants(CFG& cfg, ASTContext& Ctx) {
1207 GREngine<GRConstants> Engine(cfg, Ctx);
Ted Kremenekee985462008-01-16 18:18:48 +00001208 Engine.ExecuteWorkList();
Ted Kremenekaa66a322008-01-16 21:46:15 +00001209#ifndef NDEBUG
1210 llvm::ViewGraph(*Engine.getGraph().roots_begin(),"GRConstants");
1211#endif
Ted Kremenekee985462008-01-16 18:18:48 +00001212}
Ted Kremenekab2b8c52008-01-23 19:59:44 +00001213} // end clang namespace