blob: ad072d2e8ce5ee7b2464fd4718f11dc65e249e42 [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"
31
Ted Kremenekab2b8c52008-01-23 19:59:44 +000032#include "llvm/Support/Streams.h"
33
Ted Kremenekaa66a322008-01-16 21:46:15 +000034#ifndef NDEBUG
35#include "llvm/Support/GraphWriter.h"
36#include <sstream>
37#endif
38
Ted Kremenekd27f8162008-01-15 23:55:06 +000039using namespace clang;
Ted Kremenekd27f8162008-01-15 23:55:06 +000040using llvm::dyn_cast;
41using llvm::cast;
42
43//===----------------------------------------------------------------------===//
Ted Kremenekab2b8c52008-01-23 19:59:44 +000044/// ValueKey - A variant smart pointer that wraps either a ValueDecl* or a
Ted Kremenekd27f8162008-01-15 23:55:06 +000045/// Stmt*. Use cast<> or dyn_cast<> to get actual pointer type
46//===----------------------------------------------------------------------===//
47namespace {
Ted Kremenekab2b8c52008-01-23 19:59:44 +000048
49class VISIBILITY_HIDDEN ValueKey {
Ted Kremenek0525a4f2008-01-16 19:47:19 +000050 uintptr_t Raw;
Ted Kremenekd27f8162008-01-15 23:55:06 +000051public:
Ted Kremenek5c1b9962008-01-24 19:43:37 +000052 enum Kind { IsSubExp=0x0, IsBlkExpr=0x1, IsDecl=0x2, Flags=0x3 };
Ted Kremenekd27f8162008-01-15 23:55:06 +000053 inline void* getPtr() const { return reinterpret_cast<void*>(Raw & ~Flags); }
Ted Kremenekab2b8c52008-01-23 19:59:44 +000054 inline Kind getKind() const { return (Kind) (Raw & Flags); }
Ted Kremenekd27f8162008-01-15 23:55:06 +000055
Ted Kremenekab2b8c52008-01-23 19:59:44 +000056 ValueKey(const ValueDecl* VD)
57 : Raw(reinterpret_cast<uintptr_t>(VD) | IsDecl) {}
58
Ted Kremenek5c1b9962008-01-24 19:43:37 +000059 ValueKey(Stmt* S, bool isBlkExpr = false)
Ted Kremenekab2b8c52008-01-23 19:59:44 +000060 : Raw(reinterpret_cast<uintptr_t>(S) | (isBlkExpr ? IsBlkExpr : IsSubExp)){}
Ted Kremenekd27f8162008-01-15 23:55:06 +000061
62 bool isSubExpr() const { return getKind() == IsSubExp; }
Ted Kremenekab2b8c52008-01-23 19:59:44 +000063 bool isDecl() const { return getKind() == IsDecl; }
Ted Kremenekd27f8162008-01-15 23:55:06 +000064
65 inline void Profile(llvm::FoldingSetNodeID& ID) const {
Ted Kremenek98491852008-01-16 05:51:13 +000066 ID.AddPointer(getPtr());
67 ID.AddInteger((unsigned) getKind());
Ted Kremenekab2b8c52008-01-23 19:59:44 +000068 }
69
70 inline bool operator==(const ValueKey& X) const {
Ted Kremenek5c1b9962008-01-24 19:43:37 +000071 return getPtr() == X.getPtr();
Ted Kremenekab2b8c52008-01-23 19:59:44 +000072 }
73
74 inline bool operator!=(const ValueKey& X) const {
75 return !operator==(X);
76 }
77
78 inline bool operator<(const ValueKey& X) const {
79 Kind k = getKind(), Xk = X.getKind();
Ted Kremenek5c1b9962008-01-24 19:43:37 +000080
81 if (k == IsDecl) {
82 if (Xk != IsDecl)
83 return false;
84 }
85 else {
86 if (Xk == IsDecl)
87 return true;
88 }
Ted Kremenekab2b8c52008-01-23 19:59:44 +000089
Ted Kremenek5c1b9962008-01-24 19:43:37 +000090 return getPtr() < X.getPtr();
Ted Kremenekb3d2dca2008-01-16 23:33:44 +000091 }
Ted Kremenekd27f8162008-01-15 23:55:06 +000092};
93} // end anonymous namespace
94
Ted Kremenekab2b8c52008-01-23 19:59:44 +000095// Machinery to get cast<> and dyn_cast<> working with ValueKey.
Ted Kremenekd27f8162008-01-15 23:55:06 +000096namespace llvm {
Ted Kremenekab2b8c52008-01-23 19:59:44 +000097 template<> inline bool isa<ValueDecl,ValueKey>(const ValueKey& V) {
98 return V.getKind() == ValueKey::IsDecl;
Ted Kremenekd27f8162008-01-15 23:55:06 +000099 }
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000100 template<> inline bool isa<Stmt,ValueKey>(const ValueKey& V) {
101 return ((unsigned) V.getKind()) != ValueKey::IsDecl;
Ted Kremenekd27f8162008-01-15 23:55:06 +0000102 }
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000103 template<> struct VISIBILITY_HIDDEN cast_retty_impl<ValueDecl,ValueKey> {
Ted Kremenekaa66a322008-01-16 21:46:15 +0000104 typedef const ValueDecl* ret_type;
Ted Kremenekd27f8162008-01-15 23:55:06 +0000105 };
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000106 template<> struct VISIBILITY_HIDDEN cast_retty_impl<Stmt,ValueKey> {
Ted Kremenekd27f8162008-01-15 23:55:06 +0000107 typedef const Stmt* ret_type;
108 };
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000109 template<> struct VISIBILITY_HIDDEN simplify_type<ValueKey> {
Ted Kremenekd27f8162008-01-15 23:55:06 +0000110 typedef void* SimpleType;
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000111 static inline SimpleType getSimplifiedValue(const ValueKey &V) {
Ted Kremenekd27f8162008-01-15 23:55:06 +0000112 return V.getPtr();
113 }
114 };
115} // end llvm namespace
116
117//===----------------------------------------------------------------------===//
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000118// ValueManager.
Ted Kremenekd27f8162008-01-15 23:55:06 +0000119//===----------------------------------------------------------------------===//
120
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000121namespace {
122
123typedef llvm::ImmutableSet<llvm::APSInt > APSIntSetTy;
124
125class VISIBILITY_HIDDEN ValueManager {
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000126 APSIntSetTy::Factory APSIntSetFactory;
Ted Kremenek874d63f2008-01-24 02:02:54 +0000127 ASTContext* Ctx;
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000128
129public:
130 ValueManager() {}
131 ~ValueManager() {}
132
Ted Kremenek874d63f2008-01-24 02:02:54 +0000133 void setContext(ASTContext* ctx) { Ctx = ctx; }
134 ASTContext* getContext() const { return Ctx; }
135
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000136 APSIntSetTy GetEmptyAPSIntSet() {
137 return APSIntSetFactory.GetEmptySet();
138 }
139
140 APSIntSetTy AddToSet(const APSIntSetTy& Set, const llvm::APSInt& Val) {
141 return APSIntSetFactory.Add(Set, Val);
Ted Kremenekd27f8162008-01-15 23:55:06 +0000142 }
143};
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000144} // end anonymous namespace
145
146//===----------------------------------------------------------------------===//
147// Expression Values.
148//===----------------------------------------------------------------------===//
149
150namespace {
151
152class VISIBILITY_HIDDEN ExprValue {
153public:
154 enum Kind { // L-Values.
155 LValueDeclKind = 0x0,
156 // Special "Invalid" value.
157 InvalidValueKind = 0x1,
158 // R-Values.
159 RValueMayEqualSetKind = 0x2,
160 // Note that the Lvalue and RValue "kinds" overlap;
161 // the "InvalidValue" class can be used either as
162 // an LValue or RValue.
163 MinLValueKind = 0x0, MaxLValueKind = 0x1,
164 MinRValueKind = 0x1, MaxRValueKind = 0x2 };
165
166private:
167 enum Kind kind;
168 void* Data;
169
170protected:
171 ExprValue(Kind k, void* d) : kind(k), Data(d) {}
172
173 void* getRawPtr() const { return Data; }
174
175public:
176 ~ExprValue() {};
177
Ted Kremenek874d63f2008-01-24 02:02:54 +0000178 ExprValue EvalCast(ValueManager& ValMgr, Expr* CastExpr) const;
179
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000180 void Profile(llvm::FoldingSetNodeID& ID) const {
181 ID.AddInteger((unsigned) getKind());
182 ID.AddPointer(Data);
183 }
184
185 bool operator==(const ExprValue& RHS) const {
186 return kind == RHS.kind && Data == RHS.Data;
187 }
188
189 Kind getKind() const { return kind; }
190 bool isValid() const { return getKind() != InvalidValueKind; }
191
192 void print(std::ostream& OS) const;
193 void print() const { print(*llvm::cerr.stream()); }
194
195 // Implement isa<T> support.
196 static inline bool classof(const ExprValue*) { return true; }
197};
198
199class VISIBILITY_HIDDEN InvalidValue : public ExprValue {
200public:
201 InvalidValue() : ExprValue(InvalidValueKind, NULL) {}
202
203 static inline bool classof(const ExprValue* V) {
204 return V->getKind() == InvalidValueKind;
205 }
206};
207
208} // end anonymous namespace
209
210//===----------------------------------------------------------------------===//
211// "R-Values": Interface.
212//===----------------------------------------------------------------------===//
213
214namespace {
215class VISIBILITY_HIDDEN RValue : public ExprValue {
216protected:
217 RValue(Kind k, void* d) : ExprValue(k,d) {}
218
219public:
Ted Kremenek874d63f2008-01-24 02:02:54 +0000220 RValue EvalAdd(ValueManager& ValMgr, const RValue& RHS) const;
221 RValue EvalSub(ValueManager& ValMgr, const RValue& RHS) const;
222 RValue EvalMul(ValueManager& ValMgr, const RValue& RHS) const;
Ted Kremenekdacbb4f2008-01-24 08:20:02 +0000223 RValue EvalMinus(ValueManager& ValMgr, UnaryOperator* U) const;
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000224
Ted Kremenek7b8009a2008-01-24 02:28:56 +0000225 static RValue GetRValue(ValueManager& ValMgr, const llvm::APSInt& V);
Ted Kremenekdacbb4f2008-01-24 08:20:02 +0000226 static RValue GetRValue(ValueManager& ValMgr, IntegerLiteral* I);
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000227
228 // Implement isa<T> support.
229 static inline bool classof(const ExprValue* V) {
230 return V->getKind() >= MinRValueKind;
231 }
232};
233
234class VISIBILITY_HIDDEN RValueMayEqualSet : public RValue {
235public:
236 RValueMayEqualSet(const APSIntSetTy& S)
237 : RValue(RValueMayEqualSetKind, S.getRoot()) {}
238
239 APSIntSetTy GetValues() const {
240 return APSIntSetTy(reinterpret_cast<APSIntSetTy::TreeTy*>(getRawPtr()));
241 }
242
Ted Kremenek874d63f2008-01-24 02:02:54 +0000243 RValueMayEqualSet EvalAdd(ValueManager& ValMgr,
244 const RValueMayEqualSet& V) const;
245
246 RValueMayEqualSet EvalSub(ValueManager& ValMgr,
247 const RValueMayEqualSet& V) const;
248
249 RValueMayEqualSet EvalMul(ValueManager& ValMgr,
250 const RValueMayEqualSet& V) const;
251
252 RValueMayEqualSet EvalCast(ValueManager& ValMgr, Expr* CastExpr) const;
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000253
Ted Kremenekdacbb4f2008-01-24 08:20:02 +0000254 RValueMayEqualSet EvalMinus(ValueManager& ValMgr, UnaryOperator* U) const;
255
256
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000257 // Implement isa<T> support.
258 static inline bool classof(const ExprValue* V) {
259 return V->getKind() == RValueMayEqualSetKind;
260 }
261};
262} // end anonymous namespace
263
264//===----------------------------------------------------------------------===//
Ted Kremenek874d63f2008-01-24 02:02:54 +0000265// Transfer functions: Casts.
266//===----------------------------------------------------------------------===//
267
268ExprValue ExprValue::EvalCast(ValueManager& ValMgr, Expr* CastExpr) const {
269 switch (getKind()) {
270 case RValueMayEqualSetKind:
271 return cast<RValueMayEqualSet>(this)->EvalCast(ValMgr, CastExpr);
272 default:
273 return InvalidValue();
274 }
275}
276
277RValueMayEqualSet
278RValueMayEqualSet::EvalCast(ValueManager& ValMgr, Expr* CastExpr) const {
279 QualType T = CastExpr->getType();
280 assert (T->isIntegerType());
281
282 APSIntSetTy S1 = GetValues();
283 APSIntSetTy S2 = ValMgr.GetEmptyAPSIntSet();
284
285 for (APSIntSetTy::iterator I=S1.begin(), E=S1.end(); I!=E; ++I) {
286 llvm::APSInt X = *I;
287 X.setIsSigned(T->isSignedIntegerType());
288 X.extOrTrunc(ValMgr.getContext()->getTypeSize(T,CastExpr->getLocStart()));
289 S2 = ValMgr.AddToSet(S2, X);
290 }
291
292 return S2;
293}
294
295//===----------------------------------------------------------------------===//
Ted Kremenekdacbb4f2008-01-24 08:20:02 +0000296// Transfer functions: Unary Operations over R-Values.
297//===----------------------------------------------------------------------===//
298
299RValue RValue::EvalMinus(ValueManager& ValMgr, UnaryOperator* U) const {
300 switch (getKind()) {
301 case RValueMayEqualSetKind:
302 return cast<RValueMayEqualSet>(this)->EvalMinus(ValMgr, U);
303 default:
304 return cast<RValue>(InvalidValue());
305 }
306}
307
308RValueMayEqualSet
309RValueMayEqualSet::EvalMinus(ValueManager& ValMgr, UnaryOperator* U) const {
310
311 assert (U->getType() == U->getSubExpr()->getType());
312 assert (U->getType()->isIntegerType());
313
314 APSIntSetTy S1 = GetValues();
315 APSIntSetTy S2 = ValMgr.GetEmptyAPSIntSet();
316
317 for (APSIntSetTy::iterator I=S1.begin(), E=S1.end(); I!=E; ++I) {
318 assert ((*I).isSigned());
319
320 // FIXME: Shouldn't operator- on APSInt return an APSInt with the proper
321 // sign?
322 llvm::APSInt X(-(*I));
323 X.setIsSigned(true);
324
325 S2 = ValMgr.AddToSet(S2, X);
326 }
327
328 return S2;
329}
330
331
332
333//===----------------------------------------------------------------------===//
Ted Kremenek874d63f2008-01-24 02:02:54 +0000334// Transfer functions: Binary Operations over R-Values.
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000335//===----------------------------------------------------------------------===//
336
337#define RVALUE_DISPATCH_CASE(k1,k2,Op)\
338case ((k1##Kind+(MaxRValueKind-MinRValueKind))+(k2##Kind - MinRValueKind)):\
Ted Kremenek874d63f2008-01-24 02:02:54 +0000339 return cast<k1>(*this).Eval##Op(ValMgr,cast<k2>(RHS));
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000340
341#define RVALUE_DISPATCH(Op)\
342switch (getKind()+(MaxRValueKind-MinRValueKind)+(RHS.getKind()-MinRValueKind)){\
343 RVALUE_DISPATCH_CASE(RValueMayEqualSet,RValueMayEqualSet,Op)\
344 default:\
345 assert (!isValid() || !RHS.isValid() && "Missing case.");\
346 break;\
347}\
348return cast<RValue>(InvalidValue());
349
Ted Kremenek874d63f2008-01-24 02:02:54 +0000350RValue RValue::EvalAdd(ValueManager& ValMgr, const RValue& RHS) const {
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000351 RVALUE_DISPATCH(Add)
352}
353
Ted Kremenek874d63f2008-01-24 02:02:54 +0000354RValue RValue::EvalSub(ValueManager& ValMgr, const RValue& RHS) const {
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000355 RVALUE_DISPATCH(Sub)
356}
357
Ted Kremenek874d63f2008-01-24 02:02:54 +0000358RValue RValue::EvalMul(ValueManager& ValMgr, const RValue& RHS) const {
Ted Kremenek2eafd0e2008-01-23 23:42:27 +0000359 RVALUE_DISPATCH(Mul)
360}
361
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000362#undef RVALUE_DISPATCH_CASE
363#undef RVALUE_DISPATCH
364
365RValueMayEqualSet
Ted Kremenek874d63f2008-01-24 02:02:54 +0000366RValueMayEqualSet::EvalAdd(ValueManager& ValMgr,
367 const RValueMayEqualSet& RHS) const {
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000368
369 APSIntSetTy S1 = GetValues();
370 APSIntSetTy S2 = RHS.GetValues();
371
372 APSIntSetTy M = ValMgr.GetEmptyAPSIntSet();
373
374 for (APSIntSetTy::iterator I1=S1.begin(), E1=S2.end(); I1!=E1; ++I1)
Ted Kremenekdacbb4f2008-01-24 08:20:02 +0000375 for (APSIntSetTy::iterator I2=S2.begin(), E2=S2.end(); I2!=E2; ++I2) {
376 // FIXME: operator- on APSInt is really operator* on APInt, which loses
377 // the "signess" information (although the bits are correct).
378 const llvm::APSInt& X = *I1;
379 llvm::APSInt Y = X + *I2;
380 Y.setIsSigned(X.isSigned());
381 M = ValMgr.AddToSet(M, Y);
382 }
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000383
384 return M;
385}
386
387RValueMayEqualSet
Ted Kremenek874d63f2008-01-24 02:02:54 +0000388RValueMayEqualSet::EvalSub(ValueManager& ValMgr,
389 const RValueMayEqualSet& RHS) const {
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000390
391 APSIntSetTy S1 = GetValues();
392 APSIntSetTy S2 = RHS.GetValues();
393
394 APSIntSetTy M = ValMgr.GetEmptyAPSIntSet();
395
396 for (APSIntSetTy::iterator I1=S1.begin(), E1=S2.end(); I1!=E1; ++I1)
Ted Kremenekdacbb4f2008-01-24 08:20:02 +0000397 for (APSIntSetTy::iterator I2=S2.begin(), E2=S2.end(); I2!=E2; ++I2) {
398 // FIXME: operator- on APSInt is really operator* on APInt, which loses
399 // the "signess" information (although the bits are correct).
400 const llvm::APSInt& X = *I1;
401 llvm::APSInt Y = X - *I2;
402 Y.setIsSigned(X.isSigned());
403 M = ValMgr.AddToSet(M, Y);
404 }
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000405
406 return M;
407}
408
Ted Kremenek2eafd0e2008-01-23 23:42:27 +0000409RValueMayEqualSet
Ted Kremenek874d63f2008-01-24 02:02:54 +0000410RValueMayEqualSet::EvalMul(ValueManager& ValMgr,
411 const RValueMayEqualSet& RHS) const {
Ted Kremenek2eafd0e2008-01-23 23:42:27 +0000412
413 APSIntSetTy S1 = GetValues();
414 APSIntSetTy S2 = RHS.GetValues();
415
416 APSIntSetTy M = ValMgr.GetEmptyAPSIntSet();
417
418 for (APSIntSetTy::iterator I1=S1.begin(), E1=S2.end(); I1!=E1; ++I1)
Ted Kremenekdacbb4f2008-01-24 08:20:02 +0000419 for (APSIntSetTy::iterator I2=S2.begin(), E2=S2.end(); I2!=E2; ++I2) {
420 // FIXME: operator* on APSInt is really operator* on APInt, which loses
421 // the "signess" information (although the bits are correct).
422 const llvm::APSInt& X = *I1;
423 llvm::APSInt Y = X * *I2;
424 Y.setIsSigned(X.isSigned());
425 M = ValMgr.AddToSet(M, Y);
426 }
Ted Kremenek2eafd0e2008-01-23 23:42:27 +0000427
428 return M;
429}
430
Ted Kremenek7b8009a2008-01-24 02:28:56 +0000431RValue RValue::GetRValue(ValueManager& ValMgr, const llvm::APSInt& V) {
432 return RValueMayEqualSet(ValMgr.AddToSet(ValMgr.GetEmptyAPSIntSet(), V));
Ted Kremenekdacbb4f2008-01-24 08:20:02 +0000433}
434
435RValue RValue::GetRValue(ValueManager& ValMgr, IntegerLiteral* I) {
436 llvm::APSInt X(I->getValue());
437 X.setIsSigned(I->getType()->isSignedIntegerType());
438 return GetRValue(ValMgr, X);
439}
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000440
441//===----------------------------------------------------------------------===//
442// "L-Values".
443//===----------------------------------------------------------------------===//
444
445namespace {
446
447class VISIBILITY_HIDDEN LValue : public ExprValue {
448protected:
449 LValue(Kind k, void* D) : ExprValue(k, D) {}
450
451public:
452 // Implement isa<T> support.
453 static inline bool classof(const ExprValue* V) {
454 return V->getKind() <= MaxLValueKind;
455 }
456};
457
458class VISIBILITY_HIDDEN LValueDecl : public LValue {
459public:
460 LValueDecl(ValueDecl* vd) : LValue(LValueDeclKind,vd) {}
461
462 ValueDecl* getDecl() const {
463 return static_cast<ValueDecl*>(getRawPtr());
464 }
465
466 // Implement isa<T> support.
467 static inline bool classof(const ExprValue* V) {
468 return V->getKind() == LValueDeclKind;
469 }
470};
471} // end anonymous namespace
472
473//===----------------------------------------------------------------------===//
474// Pretty-Printing.
475//===----------------------------------------------------------------------===//
476
477void ExprValue::print(std::ostream& Out) const {
478 switch (getKind()) {
479 case InvalidValueKind:
480 Out << "Invalid"; break;
481
482 case RValueMayEqualSetKind: {
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000483 APSIntSetTy S = cast<RValueMayEqualSet>(this)->GetValues();
Ted Kremenek803c9ed2008-01-23 22:30:44 +0000484 bool first = true;
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000485
Ted Kremenek803c9ed2008-01-23 22:30:44 +0000486 for (APSIntSetTy::iterator I=S.begin(), E=S.end(); I!=E; ++I) {
487 if (first) first = false;
488 else Out << " | ";
489
490 Out << (*I).toString();
491 }
492
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000493 break;
494 }
495
496 default:
497 assert (false && "Pretty-printed not implemented for this ExprValue.");
498 break;
499 }
500}
501
502//===----------------------------------------------------------------------===//
503// ValueMapTy - A ImmutableMap type Stmt*/Decl* to ExprValues.
504//===----------------------------------------------------------------------===//
505
506typedef llvm::ImmutableMap<ValueKey,ExprValue> ValueMapTy;
507
508namespace clang {
509 template<>
510 struct VISIBILITY_HIDDEN GRTrait<ValueMapTy> {
511 static inline void* toPtr(ValueMapTy M) {
512 return reinterpret_cast<void*>(M.getRoot());
513 }
514 static inline ValueMapTy toState(void* P) {
515 return ValueMapTy(static_cast<ValueMapTy::TreeTy*>(P));
516 }
517 };
Ted Kremenekd27f8162008-01-15 23:55:06 +0000518}
519
520//===----------------------------------------------------------------------===//
521// The Checker!
522//===----------------------------------------------------------------------===//
523
524namespace {
Ted Kremenekd27f8162008-01-15 23:55:06 +0000525
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000526class VISIBILITY_HIDDEN GRConstants {
Ted Kremenekd27f8162008-01-15 23:55:06 +0000527
528public:
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000529 typedef ValueMapTy StateTy;
Ted Kremenekd27f8162008-01-15 23:55:06 +0000530 typedef GRNodeBuilder<GRConstants> NodeBuilder;
531 typedef ExplodedNode<StateTy> NodeTy;
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000532
533 class NodeSet {
534 typedef llvm::SmallVector<NodeTy*,3> ImplTy;
535 ImplTy Impl;
536 public:
537
538 NodeSet() {}
539 NodeSet(NodeTy* N) { assert (N && !N->isInfeasible()); Impl.push_back(N); }
540
541 void Add(NodeTy* N) { if (N && !N->isInfeasible()) Impl.push_back(N); }
542
543 typedef ImplTy::iterator iterator;
544 typedef ImplTy::const_iterator const_iterator;
545
546 unsigned size() const { return Impl.size(); }
547
548 iterator begin() { return Impl.begin(); }
549 iterator end() { return Impl.end(); }
550
551 const_iterator begin() const { return Impl.begin(); }
552 const_iterator end() const { return Impl.end(); }
553 };
Ted Kremenekd27f8162008-01-15 23:55:06 +0000554
555protected:
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000556 /// Liveness - live-variables information the ValueDecl* and block-level
557 /// Expr* in the CFG. Used to prune out dead state.
Ted Kremenekd27f8162008-01-15 23:55:06 +0000558 LiveVariables* Liveness;
559
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000560 /// Builder - The current GRNodeBuilder which is used when building the nodes
561 /// for a given statement.
Ted Kremenekd27f8162008-01-15 23:55:06 +0000562 NodeBuilder* Builder;
563
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000564 /// StateMgr - Object that manages the data for all created states.
565 ValueMapTy::Factory StateMgr;
Ted Kremenekd27f8162008-01-15 23:55:06 +0000566
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000567 /// ValueMgr - Object that manages the data for all created ExprValues.
568 ValueManager ValMgr;
569
570 /// cfg - the current CFG.
Ted Kremenekd27f8162008-01-15 23:55:06 +0000571 CFG* cfg;
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000572
573 /// StmtEntryNode - The immediate predecessor node.
574 NodeTy* StmtEntryNode;
575
576 /// CurrentStmt - The current block-level statement.
577 Stmt* CurrentStmt;
578
579 bool StateCleaned;
Ted Kremenekd27f8162008-01-15 23:55:06 +0000580
Ted Kremenek7b8009a2008-01-24 02:28:56 +0000581 ASTContext* getContext() const { return ValMgr.getContext(); }
582
Ted Kremenekd27f8162008-01-15 23:55:06 +0000583public:
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000584 GRConstants() : Liveness(NULL), Builder(NULL), cfg(NULL),
585 StmtEntryNode(NULL), CurrentStmt(NULL) {}
Ted Kremenekd27f8162008-01-15 23:55:06 +0000586
587 ~GRConstants() { delete Liveness; }
588
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000589 /// getCFG - Returns the CFG associated with this analysis.
Ted Kremenekd27f8162008-01-15 23:55:06 +0000590 CFG& getCFG() { assert (cfg); return *cfg; }
591
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000592 /// Initialize - Initialize the checker's state based on the specified
593 /// CFG. This results in liveness information being computed for
594 /// each block-level statement in the CFG.
Ted Kremenek874d63f2008-01-24 02:02:54 +0000595 void Initialize(CFG& c, ASTContext& ctx) {
596 cfg = &c;
597 ValMgr.setContext(&ctx);
Ted Kremenekd27f8162008-01-15 23:55:06 +0000598 Liveness = new LiveVariables(c);
599 Liveness->runOnCFG(c);
Ted Kremenek79649df2008-01-17 18:25:22 +0000600 Liveness->runOnAllBlocks(c, NULL, true);
Ted Kremenekd27f8162008-01-15 23:55:06 +0000601 }
602
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000603 /// getInitialState - Return the initial state used for the root vertex
604 /// in the ExplodedGraph.
Ted Kremenekd27f8162008-01-15 23:55:06 +0000605 StateTy getInitialState() {
Ted Kremenekcb448ca2008-01-16 00:53:15 +0000606 return StateMgr.GetEmptyMap();
Ted Kremenekd27f8162008-01-15 23:55:06 +0000607 }
Ted Kremenekd27f8162008-01-15 23:55:06 +0000608
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000609 /// ProcessStmt - Called by GREngine. Used to generate new successor
610 /// nodes by processing the 'effects' of a block-level statement.
611 void ProcessStmt(Stmt* S, NodeBuilder& builder);
612
613 /// RemoveDeadBindings - Return a new state that is the same as 'M' except
614 /// that all subexpression mappings are removed and that any
615 /// block-level expressions that are not live at 'S' also have their
616 /// mappings removed.
617 StateTy RemoveDeadBindings(Stmt* S, StateTy M);
618
Ted Kremenekdaadf452008-01-24 19:28:01 +0000619 StateTy SetValue(StateTy St, Stmt* S, const ExprValue& V);
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000620
621 StateTy SetValue(StateTy St, const LValue& LV, const ExprValue& V);
Ted Kremenek1ccd31c2008-01-16 19:42:59 +0000622
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000623 ExprValue GetValue(const StateTy& St, Stmt* S);
624 ExprValue GetValue(const StateTy& St, const LValue& LV);
625 LValue GetLValue(const StateTy& St, Stmt* S);
Ted Kremenekd27f8162008-01-15 23:55:06 +0000626
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000627 void Nodify(NodeSet& Dst, Stmt* S, NodeTy* Pred, StateTy St);
Ted Kremenekd27f8162008-01-15 23:55:06 +0000628
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000629 /// Visit - Transfer function logic for all statements. Dispatches to
630 /// other functions that handle specific kinds of statements.
631 void Visit(Stmt* S, NodeTy* Pred, NodeSet& Dst);
Ted Kremenek874d63f2008-01-24 02:02:54 +0000632
633 /// VisitCast - Transfer function logic for all casts (implicit and explicit).
634 void VisitCast(Expr* CastE, Expr* E, NodeTy* Pred, NodeSet& Dst);
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000635
Ted Kremenek7b8009a2008-01-24 02:28:56 +0000636 /// VisitUnaryOperator - Transfer function logic for unary operators.
637 void VisitUnaryOperator(UnaryOperator* B, NodeTy* Pred, NodeSet& Dst);
638
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000639 /// VisitBinaryOperator - Transfer function logic for binary operators.
640 void VisitBinaryOperator(BinaryOperator* B, NodeTy* Pred, NodeSet& Dst);
Ted Kremenekd27f8162008-01-15 23:55:06 +0000641};
642} // end anonymous namespace
643
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000644
Ted Kremenekd27f8162008-01-15 23:55:06 +0000645void GRConstants::ProcessStmt(Stmt* S, NodeBuilder& builder) {
646 Builder = &builder;
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000647
648 StmtEntryNode = builder.getLastNode();
649 CurrentStmt = S;
650 NodeSet Dst;
651 StateCleaned = false;
652
653 Visit(S, StmtEntryNode, Dst);
654
655 // If no nodes were generated, generate a new node that has all the
656 // dead mappings removed.
657 if (Dst.size() == 1 && *Dst.begin() == StmtEntryNode) {
658 StateTy St = RemoveDeadBindings(S, StmtEntryNode->getState());
659 builder.generateNode(S, St, StmtEntryNode);
660 }
Ted Kremenekf84469b2008-01-18 00:41:32 +0000661
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000662 CurrentStmt = NULL;
663 StmtEntryNode = NULL;
664 Builder = NULL;
Ted Kremenekd27f8162008-01-15 23:55:06 +0000665}
666
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000667
668ExprValue GRConstants::GetValue(const StateTy& St, const LValue& LV) {
669 switch (LV.getKind()) {
670 case ExprValue::LValueDeclKind: {
671 StateTy::TreeTy* T = St.SlimFind(cast<LValueDecl>(LV).getDecl());
672 return T ? T->getValue().second : InvalidValue();
673 }
674 default:
675 assert (false && "Invalid LValue.");
Ted Kremenekca3e8572008-01-16 22:28:08 +0000676 break;
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000677 }
678
679 return InvalidValue();
680}
681
682ExprValue GRConstants::GetValue(const StateTy& St, Stmt* S) {
Ted Kremenek671c9e82008-01-24 00:50:08 +0000683 for (;;) {
684 switch (S->getStmtClass()) {
685 case Stmt::ParenExprClass:
686 S = cast<ParenExpr>(S)->getSubExpr();
687 continue;
688
689 case Stmt::DeclRefExprClass:
690 return GetValue(St, LValueDecl(cast<DeclRefExpr>(S)->getDecl()));
Ted Kremenekca3e8572008-01-16 22:28:08 +0000691
Ted Kremenek671c9e82008-01-24 00:50:08 +0000692 case Stmt::IntegerLiteralClass:
Ted Kremenekdacbb4f2008-01-24 08:20:02 +0000693 return RValue::GetRValue(ValMgr, cast<IntegerLiteral>(S));
Ted Kremenek874d63f2008-01-24 02:02:54 +0000694
695 case Stmt::ImplicitCastExprClass: {
696 ImplicitCastExpr* C = cast<ImplicitCastExpr>(S);
697 if (C->getType() == C->getSubExpr()->getType()) {
698 S = C->getSubExpr();
699 continue;
700 }
701 break;
702 }
703
704 case Stmt::CastExprClass: {
705 CastExpr* C = cast<CastExpr>(S);
706 if (C->getType() == C->getSubExpr()->getType()) {
707 S = C->getSubExpr();
708 continue;
709 }
710 break;
711 }
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000712
Ted Kremenek671c9e82008-01-24 00:50:08 +0000713 default:
714 break;
715 };
716
717 break;
718 }
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000719
Ted Kremenek5c1b9962008-01-24 19:43:37 +0000720 StateTy::TreeTy* T = St.SlimFind(S);
Ted Kremenek874d63f2008-01-24 02:02:54 +0000721
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000722 return T ? T->getValue().second : InvalidValue();
723}
724
725LValue GRConstants::GetLValue(const StateTy& St, Stmt* S) {
726 if (Expr* E = dyn_cast<Expr>(S))
727 S = E->IgnoreParens();
728
729 if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(S))
730 return LValueDecl(DR->getDecl());
731
732 return cast<LValue>(GetValue(St, S));
733}
734
735GRConstants::StateTy GRConstants::SetValue(StateTy St, Stmt* S,
Ted Kremenekdaadf452008-01-24 19:28:01 +0000736 const ExprValue& V) {
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000737
738 if (!StateCleaned) {
739 St = RemoveDeadBindings(CurrentStmt, St);
740 StateCleaned = true;
741 }
742
Ted Kremenekdaadf452008-01-24 19:28:01 +0000743 bool isBlkExpr = S == CurrentStmt && getCFG().isBlkExpr(S);
744
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000745 return V.isValid() ? StateMgr.Add(St, ValueKey(S,isBlkExpr), V)
746 : St;
747}
748
749GRConstants::StateTy GRConstants::SetValue(StateTy St, const LValue& LV,
750 const ExprValue& V) {
751 if (!LV.isValid())
752 return St;
753
754 if (!StateCleaned) {
755 St = RemoveDeadBindings(CurrentStmt, St);
756 StateCleaned = true;
Ted Kremenekca3e8572008-01-16 22:28:08 +0000757 }
Ted Kremenek0525a4f2008-01-16 19:47:19 +0000758
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000759 switch (LV.getKind()) {
760 case ExprValue::LValueDeclKind:
761 return V.isValid() ? StateMgr.Add(St, cast<LValueDecl>(LV).getDecl(), V)
762 : StateMgr.Remove(St, cast<LValueDecl>(LV).getDecl());
763
764 default:
765 assert ("SetValue for given LValue type not yet implemented.");
766 return St;
767 }
Ted Kremenekd27f8162008-01-15 23:55:06 +0000768}
769
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000770GRConstants::StateTy GRConstants::RemoveDeadBindings(Stmt* Loc, StateTy M) {
Ted Kremenekf84469b2008-01-18 00:41:32 +0000771 // Note: in the code below, we can assign a new map to M since the
772 // iterators are iterating over the tree of the *original* map.
Ted Kremenekf84469b2008-01-18 00:41:32 +0000773 StateTy::iterator I = M.begin(), E = M.end();
774
Ted Kremenek5c1b9962008-01-24 19:43:37 +0000775 // Remove old bindings for subexpressions and "dead" block-level expressions.
776 for (; I!=E && !I.getKey().isDecl(); ++I) {
777 if (I.getKey().isSubExpr() || !Liveness->isLive(Loc,cast<Stmt>(I.getKey())))
778 M = StateMgr.Remove(M, I.getKey());
779 }
Ted Kremenekf84469b2008-01-18 00:41:32 +0000780
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000781 // Remove bindings for "dead" decls.
Ted Kremenek5c1b9962008-01-24 19:43:37 +0000782 for (; I!=E ; ++I) {
783 assert (I.getKey().isDecl());
784
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000785 if (VarDecl* V = dyn_cast<VarDecl>(cast<ValueDecl>(I.getKey())))
786 if (!Liveness->isLive(Loc, V))
787 M = StateMgr.Remove(M, I.getKey());
Ted Kremenek5c1b9962008-01-24 19:43:37 +0000788 }
Ted Kremeneke00fe3f2008-01-17 00:52:48 +0000789
790 return M;
Ted Kremeneke00fe3f2008-01-17 00:52:48 +0000791}
792
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000793void GRConstants::Nodify(NodeSet& Dst, Stmt* S, GRConstants::NodeTy* Pred,
794 GRConstants::StateTy St) {
795
796 // If the state hasn't changed, don't generate a new node.
797 if (St == Pred->getState())
798 return;
Ted Kremenekcb448ca2008-01-16 00:53:15 +0000799
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000800 Dst.Add(Builder->generateNode(S, St, Pred));
Ted Kremenekcb448ca2008-01-16 00:53:15 +0000801}
Ted Kremenekd27f8162008-01-15 23:55:06 +0000802
Ted Kremenek874d63f2008-01-24 02:02:54 +0000803void GRConstants::VisitCast(Expr* CastE, Expr* E, GRConstants::NodeTy* Pred,
804 GRConstants::NodeSet& Dst) {
805
806 QualType T = CastE->getType();
807
808 // Check for redundant casts.
809 if (E->getType() == T) {
810 Dst.Add(Pred);
811 return;
812 }
813
814 NodeSet S1;
815 Visit(E, Pred, S1);
816
817 for (NodeSet::iterator I1=S1.begin(), E1=S1.end(); I1 != E1; ++I1) {
818 NodeTy* N = *I1;
819 StateTy St = N->getState();
820 const ExprValue& V = GetValue(St, E);
821 Nodify(Dst, CastE, N, SetValue(St, CastE, V.EvalCast(ValMgr, CastE)));
822 }
823 }
824
Ted Kremenek7b8009a2008-01-24 02:28:56 +0000825void GRConstants::VisitUnaryOperator(UnaryOperator* U,
826 GRConstants::NodeTy* Pred,
827 GRConstants::NodeSet& Dst) {
828 NodeSet S1;
829 Visit(U->getSubExpr(), Pred, S1);
830
831 for (NodeSet::iterator I1=S1.begin(), E1=S1.end(); I1 != E1; ++I1) {
832 NodeTy* N1 = *I1;
833 StateTy St = N1->getState();
834
835 switch (U->getOpcode()) {
836 case UnaryOperator::PostInc: {
837 const LValue& L1 = GetLValue(St, U->getSubExpr());
838 RValue R1 = cast<RValue>(GetValue(St, L1));
839
840 QualType T = U->getType();
Ted Kremeneke0cf9c82008-01-24 19:00:57 +0000841 unsigned bits = getContext()->getTypeSize(T, U->getLocStart());
842 llvm::APSInt One(llvm::APInt(bits, 1), T->isUnsignedIntegerType());
843 RValue R2 = RValue::GetRValue(ValMgr, One);
844
Ted Kremenek7b8009a2008-01-24 02:28:56 +0000845 RValue Result = R1.EvalAdd(ValMgr, R2);
846 Nodify(Dst, U, N1, SetValue(SetValue(St, U, R1), L1, Result));
847 break;
848 }
849
850 case UnaryOperator::PostDec: {
851 const LValue& L1 = GetLValue(St, U->getSubExpr());
852 RValue R1 = cast<RValue>(GetValue(St, L1));
853
854 QualType T = U->getType();
Ted Kremeneke0cf9c82008-01-24 19:00:57 +0000855 unsigned bits = getContext()->getTypeSize(T, U->getLocStart());
856 llvm::APSInt One(llvm::APInt(bits, 1), T->isUnsignedIntegerType());
857 RValue R2 = RValue::GetRValue(ValMgr, One);
Ted Kremenek7b8009a2008-01-24 02:28:56 +0000858
859 RValue Result = R1.EvalSub(ValMgr, R2);
860 Nodify(Dst, U, N1, SetValue(SetValue(St, U, R1), L1, Result));
861 break;
862 }
863
864 case UnaryOperator::PreInc: {
865 const LValue& L1 = GetLValue(St, U->getSubExpr());
866 RValue R1 = cast<RValue>(GetValue(St, L1));
867
868 QualType T = U->getType();
Ted Kremeneke0cf9c82008-01-24 19:00:57 +0000869 unsigned bits = getContext()->getTypeSize(T, U->getLocStart());
870 llvm::APSInt One(llvm::APInt(bits, 1), T->isUnsignedIntegerType());
Ted Kremenek7b8009a2008-01-24 02:28:56 +0000871 RValue R2 = RValue::GetRValue(ValMgr, One);
872
873 RValue Result = R1.EvalAdd(ValMgr, R2);
874 Nodify(Dst, U, N1, SetValue(SetValue(St, U, Result), L1, Result));
875 break;
876 }
877
878 case UnaryOperator::PreDec: {
879 const LValue& L1 = GetLValue(St, U->getSubExpr());
880 RValue R1 = cast<RValue>(GetValue(St, L1));
881
882 QualType T = U->getType();
Ted Kremeneke0cf9c82008-01-24 19:00:57 +0000883 unsigned bits = getContext()->getTypeSize(T, U->getLocStart());
884 llvm::APSInt One(llvm::APInt(bits, 1), T->isUnsignedIntegerType());
885 RValue R2 = RValue::GetRValue(ValMgr, One);
Ted Kremenek7b8009a2008-01-24 02:28:56 +0000886
887 RValue Result = R1.EvalSub(ValMgr, R2);
888 Nodify(Dst, U, N1, SetValue(SetValue(St, U, Result), L1, Result));
889 break;
890 }
891
Ted Kremenekdacbb4f2008-01-24 08:20:02 +0000892 case UnaryOperator::Minus: {
893 const RValue& R1 = cast<RValue>(GetValue(St, U->getSubExpr()));
894 Nodify(Dst, U, N1, SetValue(St, U, R1.EvalMinus(ValMgr, U)));
895 break;
896 }
897
Ted Kremenek7b8009a2008-01-24 02:28:56 +0000898 default: ;
899 assert (false && "Not implemented.");
900 }
901 }
902}
903
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000904void GRConstants::VisitBinaryOperator(BinaryOperator* B,
905 GRConstants::NodeTy* Pred,
906 GRConstants::NodeSet& Dst) {
907 NodeSet S1;
908 Visit(B->getLHS(), Pred, S1);
Ted Kremenekcb448ca2008-01-16 00:53:15 +0000909
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000910 for (NodeSet::iterator I1=S1.begin(), E1=S1.end(); I1 != E1; ++I1) {
911 NodeTy* N1 = *I1;
Ted Kremeneke00fe3f2008-01-17 00:52:48 +0000912
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000913 // When getting the value for the LHS, check if we are in an assignment.
914 // In such cases, we want to (initially) treat the LHS as an LValue,
915 // so we use GetLValue instead of GetValue so that DeclRefExpr's are
916 // evaluated to LValueDecl's instead of to an RValue.
917 const ExprValue& V1 =
918 B->isAssignmentOp() ? GetLValue(N1->getState(), B->getLHS())
919 : GetValue(N1->getState(), B->getLHS());
Ted Kremenekcb448ca2008-01-16 00:53:15 +0000920
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000921 NodeSet S2;
922 Visit(B->getRHS(), N1, S2);
923
924 for (NodeSet::iterator I2=S2.begin(), E2=S2.end(); I2 != E2; ++I2) {
925 NodeTy* N2 = *I2;
926 StateTy St = N2->getState();
927 const ExprValue& V2 = GetValue(St, B->getRHS());
928
929 switch (B->getOpcode()) {
930 case BinaryOperator::Add: {
931 const RValue& R1 = cast<RValue>(V1);
932 const RValue& R2 = cast<RValue>(V2);
933
Ted Kremenek874d63f2008-01-24 02:02:54 +0000934 Nodify(Dst, B, N2, SetValue(St, B, R1.EvalAdd(ValMgr, R2)));
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000935 break;
936 }
937
938 case BinaryOperator::Sub: {
939 const RValue& R1 = cast<RValue>(V1);
940 const RValue& R2 = cast<RValue>(V2);
Ted Kremenek874d63f2008-01-24 02:02:54 +0000941 Nodify(Dst, B, N2, SetValue(St, B, R1.EvalSub(ValMgr, R2)));
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000942 break;
943 }
944
Ted Kremenek2eafd0e2008-01-23 23:42:27 +0000945 case BinaryOperator::Mul: {
946 const RValue& R1 = cast<RValue>(V1);
947 const RValue& R2 = cast<RValue>(V2);
Ted Kremenek874d63f2008-01-24 02:02:54 +0000948 Nodify(Dst, B, N2, SetValue(St, B, R1.EvalMul(ValMgr, R2)));
Ted Kremenek2eafd0e2008-01-23 23:42:27 +0000949 break;
950 }
951
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000952 case BinaryOperator::Assign: {
953 const LValue& L1 = cast<LValue>(V1);
954 const RValue& R2 = cast<RValue>(V2);
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000955 Nodify(Dst, B, N2, SetValue(SetValue(St, B, R2), L1, R2));
956 break;
957 }
Ted Kremenekb4ae33f2008-01-23 23:38:00 +0000958
959 case BinaryOperator::AddAssign: {
960 const LValue& L1 = cast<LValue>(V1);
961 RValue R1 = cast<RValue>(GetValue(N1->getState(), L1));
Ted Kremenek874d63f2008-01-24 02:02:54 +0000962 RValue Result = R1.EvalAdd(ValMgr, cast<RValue>(V2));
Ted Kremenekb4ae33f2008-01-23 23:38:00 +0000963 Nodify(Dst, B, N2, SetValue(SetValue(St, B, Result), L1, Result));
964 break;
965 }
966
967 case BinaryOperator::SubAssign: {
968 const LValue& L1 = cast<LValue>(V1);
969 RValue R1 = cast<RValue>(GetValue(N1->getState(), L1));
Ted Kremenek874d63f2008-01-24 02:02:54 +0000970 RValue Result = R1.EvalSub(ValMgr, cast<RValue>(V2));
Ted Kremenekb4ae33f2008-01-23 23:38:00 +0000971 Nodify(Dst, B, N2, SetValue(SetValue(St, B, Result), L1, Result));
972 break;
973 }
Ted Kremenek2eafd0e2008-01-23 23:42:27 +0000974
975 case BinaryOperator::MulAssign: {
976 const LValue& L1 = cast<LValue>(V1);
977 RValue R1 = cast<RValue>(GetValue(N1->getState(), L1));
Ted Kremenek874d63f2008-01-24 02:02:54 +0000978 RValue Result = R1.EvalMul(ValMgr, cast<RValue>(V2));
Ted Kremenek2eafd0e2008-01-23 23:42:27 +0000979 Nodify(Dst, B, N2, SetValue(SetValue(St, B, Result), L1, Result));
980 break;
981 }
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000982
983 default:
984 Dst.Add(N2);
985 break;
986 }
Ted Kremenekcb448ca2008-01-16 00:53:15 +0000987 }
Ted Kremenekd27f8162008-01-15 23:55:06 +0000988 }
Ted Kremenekd27f8162008-01-15 23:55:06 +0000989}
Ted Kremenekee985462008-01-16 18:18:48 +0000990
Ted Kremenek1ccd31c2008-01-16 19:42:59 +0000991
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000992void GRConstants::Visit(Stmt* S, GRConstants::NodeTy* Pred,
993 GRConstants::NodeSet& Dst) {
994
995 // FIXME: add metadata to the CFG so that we can disable
996 // this check when we KNOW that there is no block-level subexpression.
997 // The motivation is that this check requires a hashtable lookup.
998
999 if (S != CurrentStmt && getCFG().isBlkExpr(S)) {
1000 Dst.Add(Pred);
1001 return;
1002 }
1003
1004 switch (S->getStmtClass()) {
1005 case Stmt::BinaryOperatorClass:
Ted Kremenekb4ae33f2008-01-23 23:38:00 +00001006 case Stmt::CompoundAssignOperatorClass:
Ted Kremenekab2b8c52008-01-23 19:59:44 +00001007 VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Dst);
1008 break;
1009
Ted Kremenek7b8009a2008-01-24 02:28:56 +00001010 case Stmt::UnaryOperatorClass:
1011 VisitUnaryOperator(cast<UnaryOperator>(S), Pred, Dst);
1012 break;
1013
Ted Kremenekab2b8c52008-01-23 19:59:44 +00001014 case Stmt::ParenExprClass:
1015 Visit(cast<ParenExpr>(S)->getSubExpr(), Pred, Dst);
1016 break;
1017
Ted Kremenek874d63f2008-01-24 02:02:54 +00001018 case Stmt::ImplicitCastExprClass: {
1019 ImplicitCastExpr* C = cast<ImplicitCastExpr>(S);
1020 VisitCast(C, C->getSubExpr(), Pred, Dst);
1021 break;
1022 }
1023
1024 case Stmt::CastExprClass: {
1025 CastExpr* C = cast<CastExpr>(S);
1026 VisitCast(C, C->getSubExpr(), Pred, Dst);
1027 break;
1028 }
1029
Ted Kremenekab2b8c52008-01-23 19:59:44 +00001030 default:
1031 Dst.Add(Pred); // No-op. Simply propagate the current state unchanged.
1032 break;
Ted Kremenek79649df2008-01-17 18:25:22 +00001033 }
Ted Kremenek1ccd31c2008-01-16 19:42:59 +00001034}
1035
Ted Kremenekee985462008-01-16 18:18:48 +00001036//===----------------------------------------------------------------------===//
1037// Driver.
1038//===----------------------------------------------------------------------===//
1039
Ted Kremenekaa66a322008-01-16 21:46:15 +00001040#ifndef NDEBUG
1041namespace llvm {
1042template<>
1043struct VISIBILITY_HIDDEN DOTGraphTraits<GRConstants::NodeTy*> :
1044 public DefaultDOTGraphTraits {
1045
Ted Kremenek803c9ed2008-01-23 22:30:44 +00001046 static void PrintKind(std::ostringstream& Out, ValueKey::Kind kind) {
1047 switch (kind) {
1048 case ValueKey::IsSubExp: Out << "Sub-Expressions:\\l"; break;
1049 case ValueKey::IsDecl: Out << "Variables:\\l"; break;
1050 case ValueKey::IsBlkExpr: Out << "Block-level Expressions:\\l"; break;
1051 default: assert (false && "Unknown ValueKey type.");
1052 }
1053 }
1054
Ted Kremenekaa66a322008-01-16 21:46:15 +00001055 static std::string getNodeLabel(const GRConstants::NodeTy* N, void*) {
1056 std::ostringstream Out;
Ted Kremenek803c9ed2008-01-23 22:30:44 +00001057
1058 // Program Location.
Ted Kremenekaa66a322008-01-16 21:46:15 +00001059 ProgramPoint Loc = N->getLocation();
1060
1061 switch (Loc.getKind()) {
1062 case ProgramPoint::BlockEntranceKind:
1063 Out << "Block Entrance: B"
1064 << cast<BlockEntrance>(Loc).getBlock()->getBlockID();
1065 break;
1066
1067 case ProgramPoint::BlockExitKind:
1068 assert (false);
1069 break;
1070
1071 case ProgramPoint::PostStmtKind: {
1072 const PostStmt& L = cast<PostStmt>(Loc);
Ted Kremenek803c9ed2008-01-23 22:30:44 +00001073 Out << "(" << (void*) L.getStmt() << ") ";
Ted Kremenekaa66a322008-01-16 21:46:15 +00001074 L.getStmt()->printPretty(Out);
1075 break;
1076 }
1077
1078 default: {
1079 const BlockEdge& E = cast<BlockEdge>(Loc);
1080 Out << "Edge: (B" << E.getSrc()->getBlockID() << ", B"
1081 << E.getDst()->getBlockID() << ')';
1082 }
1083 }
1084
Ted Kremenek803c9ed2008-01-23 22:30:44 +00001085 Out << "\\|";
Ted Kremenekaa66a322008-01-16 21:46:15 +00001086
1087 GRConstants::StateTy M = N->getState();
1088 bool isFirst = true;
Ted Kremenek803c9ed2008-01-23 22:30:44 +00001089 ValueKey::Kind kind;
Ted Kremenekaa66a322008-01-16 21:46:15 +00001090
1091 for (GRConstants::StateTy::iterator I=M.begin(), E=M.end(); I!=E; ++I) {
Ted Kremenek803c9ed2008-01-23 22:30:44 +00001092 if (!isFirst) {
1093 ValueKey::Kind newKind = I.getKey().getKind();
1094
1095 if (newKind != kind) {
1096 Out << "\\l\\l";
1097 PrintKind(Out, newKind);
1098 }
1099 else
1100 Out << "\\l";
1101
1102 kind = newKind;
1103 }
1104 else {
1105 kind = I.getKey().getKind();
1106 PrintKind(Out, kind);
Ted Kremenekaa66a322008-01-16 21:46:15 +00001107 isFirst = false;
Ted Kremenek803c9ed2008-01-23 22:30:44 +00001108 }
1109
1110 Out << ' ';
Ted Kremenekaa66a322008-01-16 21:46:15 +00001111
1112 if (ValueDecl* V = dyn_cast<ValueDecl>(I.getKey())) {
Ted Kremenek803c9ed2008-01-23 22:30:44 +00001113 Out << V->getName();
Ted Kremenekaa66a322008-01-16 21:46:15 +00001114 }
1115 else {
1116 Stmt* E = cast<Stmt>(I.getKey());
Ted Kremenek803c9ed2008-01-23 22:30:44 +00001117 Out << " (" << (void*) E << ") ";
1118 E->printPretty(Out);
Ted Kremenekaa66a322008-01-16 21:46:15 +00001119 }
1120
Ted Kremenek803c9ed2008-01-23 22:30:44 +00001121 Out << " : ";
Ted Kremenekab2b8c52008-01-23 19:59:44 +00001122 I.getData().print(Out);
Ted Kremenekaa66a322008-01-16 21:46:15 +00001123 }
1124
Ted Kremenek803c9ed2008-01-23 22:30:44 +00001125 Out << "\\l";
Ted Kremenekaa66a322008-01-16 21:46:15 +00001126 return Out.str();
1127 }
1128};
1129} // end llvm namespace
1130#endif
1131
Ted Kremenekee985462008-01-16 18:18:48 +00001132namespace clang {
Ted Kremenek874d63f2008-01-24 02:02:54 +00001133void RunGRConstants(CFG& cfg, ASTContext& Ctx) {
1134 GREngine<GRConstants> Engine(cfg, Ctx);
Ted Kremenekee985462008-01-16 18:18:48 +00001135 Engine.ExecuteWorkList();
Ted Kremenekaa66a322008-01-16 21:46:15 +00001136#ifndef NDEBUG
1137 llvm::ViewGraph(*Engine.getGraph().roots_begin(),"GRConstants");
1138#endif
Ted Kremenekee985462008-01-16 18:18:48 +00001139}
Ted Kremenekab2b8c52008-01-23 19:59:44 +00001140} // end clang namespace