blob: 35758c672e79ea9c42ba9e144f4a86bd0cb56d04 [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 Kremenekab2b8c52008-01-23 19:59:44 +000052 enum Kind { IsSubExp=0x0, IsDecl=0x1, IsBlkExpr=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
59 ValueKey(Stmt* S, bool isBlkExpr)
60 : 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 {
71 return Raw == X.Raw;
72 }
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();
80
81 return k == Xk ? getPtr() < X.getPtr()
82 : ((unsigned) k) < ((unsigned) Xk);
Ted Kremenekb3d2dca2008-01-16 23:33:44 +000083 }
Ted Kremenekd27f8162008-01-15 23:55:06 +000084};
85} // end anonymous namespace
86
Ted Kremenekab2b8c52008-01-23 19:59:44 +000087// Machinery to get cast<> and dyn_cast<> working with ValueKey.
Ted Kremenekd27f8162008-01-15 23:55:06 +000088namespace llvm {
Ted Kremenekab2b8c52008-01-23 19:59:44 +000089 template<> inline bool isa<ValueDecl,ValueKey>(const ValueKey& V) {
90 return V.getKind() == ValueKey::IsDecl;
Ted Kremenekd27f8162008-01-15 23:55:06 +000091 }
Ted Kremenekab2b8c52008-01-23 19:59:44 +000092 template<> inline bool isa<Stmt,ValueKey>(const ValueKey& V) {
93 return ((unsigned) V.getKind()) != ValueKey::IsDecl;
Ted Kremenekd27f8162008-01-15 23:55:06 +000094 }
Ted Kremenekab2b8c52008-01-23 19:59:44 +000095 template<> struct VISIBILITY_HIDDEN cast_retty_impl<ValueDecl,ValueKey> {
Ted Kremenekaa66a322008-01-16 21:46:15 +000096 typedef const ValueDecl* ret_type;
Ted Kremenekd27f8162008-01-15 23:55:06 +000097 };
Ted Kremenekab2b8c52008-01-23 19:59:44 +000098 template<> struct VISIBILITY_HIDDEN cast_retty_impl<Stmt,ValueKey> {
Ted Kremenekd27f8162008-01-15 23:55:06 +000099 typedef const Stmt* ret_type;
100 };
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000101 template<> struct VISIBILITY_HIDDEN simplify_type<ValueKey> {
Ted Kremenekd27f8162008-01-15 23:55:06 +0000102 typedef void* SimpleType;
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000103 static inline SimpleType getSimplifiedValue(const ValueKey &V) {
Ted Kremenekd27f8162008-01-15 23:55:06 +0000104 return V.getPtr();
105 }
106 };
107} // end llvm namespace
108
109//===----------------------------------------------------------------------===//
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000110// ValueManager.
Ted Kremenekd27f8162008-01-15 23:55:06 +0000111//===----------------------------------------------------------------------===//
112
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000113namespace {
114
115typedef llvm::ImmutableSet<llvm::APSInt > APSIntSetTy;
116
117class VISIBILITY_HIDDEN ValueManager {
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000118 APSIntSetTy::Factory APSIntSetFactory;
Ted Kremenek874d63f2008-01-24 02:02:54 +0000119 ASTContext* Ctx;
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000120
121public:
122 ValueManager() {}
123 ~ValueManager() {}
124
Ted Kremenek874d63f2008-01-24 02:02:54 +0000125 void setContext(ASTContext* ctx) { Ctx = ctx; }
126 ASTContext* getContext() const { return Ctx; }
127
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000128 APSIntSetTy GetEmptyAPSIntSet() {
129 return APSIntSetFactory.GetEmptySet();
130 }
131
132 APSIntSetTy AddToSet(const APSIntSetTy& Set, const llvm::APSInt& Val) {
133 return APSIntSetFactory.Add(Set, Val);
Ted Kremenekd27f8162008-01-15 23:55:06 +0000134 }
135};
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000136} // end anonymous namespace
137
138//===----------------------------------------------------------------------===//
139// Expression Values.
140//===----------------------------------------------------------------------===//
141
142namespace {
143
144class VISIBILITY_HIDDEN ExprValue {
145public:
146 enum Kind { // L-Values.
147 LValueDeclKind = 0x0,
148 // Special "Invalid" value.
149 InvalidValueKind = 0x1,
150 // R-Values.
151 RValueMayEqualSetKind = 0x2,
152 // Note that the Lvalue and RValue "kinds" overlap;
153 // the "InvalidValue" class can be used either as
154 // an LValue or RValue.
155 MinLValueKind = 0x0, MaxLValueKind = 0x1,
156 MinRValueKind = 0x1, MaxRValueKind = 0x2 };
157
158private:
159 enum Kind kind;
160 void* Data;
161
162protected:
163 ExprValue(Kind k, void* d) : kind(k), Data(d) {}
164
165 void* getRawPtr() const { return Data; }
166
167public:
168 ~ExprValue() {};
169
Ted Kremenek874d63f2008-01-24 02:02:54 +0000170 ExprValue EvalCast(ValueManager& ValMgr, Expr* CastExpr) const;
171
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000172 void Profile(llvm::FoldingSetNodeID& ID) const {
173 ID.AddInteger((unsigned) getKind());
174 ID.AddPointer(Data);
175 }
176
177 bool operator==(const ExprValue& RHS) const {
178 return kind == RHS.kind && Data == RHS.Data;
179 }
180
181 Kind getKind() const { return kind; }
182 bool isValid() const { return getKind() != InvalidValueKind; }
183
184 void print(std::ostream& OS) const;
185 void print() const { print(*llvm::cerr.stream()); }
186
187 // Implement isa<T> support.
188 static inline bool classof(const ExprValue*) { return true; }
189};
190
191class VISIBILITY_HIDDEN InvalidValue : public ExprValue {
192public:
193 InvalidValue() : ExprValue(InvalidValueKind, NULL) {}
194
195 static inline bool classof(const ExprValue* V) {
196 return V->getKind() == InvalidValueKind;
197 }
198};
199
200} // end anonymous namespace
201
202//===----------------------------------------------------------------------===//
203// "R-Values": Interface.
204//===----------------------------------------------------------------------===//
205
206namespace {
207class VISIBILITY_HIDDEN RValue : public ExprValue {
208protected:
209 RValue(Kind k, void* d) : ExprValue(k,d) {}
210
211public:
Ted Kremenek874d63f2008-01-24 02:02:54 +0000212 RValue EvalAdd(ValueManager& ValMgr, const RValue& RHS) const;
213 RValue EvalSub(ValueManager& ValMgr, const RValue& RHS) const;
214 RValue EvalMul(ValueManager& ValMgr, const RValue& RHS) const;
Ted Kremenekdacbb4f2008-01-24 08:20:02 +0000215 RValue EvalMinus(ValueManager& ValMgr, UnaryOperator* U) const;
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000216
Ted Kremenek7b8009a2008-01-24 02:28:56 +0000217 static RValue GetRValue(ValueManager& ValMgr, const llvm::APSInt& V);
Ted Kremenekdacbb4f2008-01-24 08:20:02 +0000218 static RValue GetRValue(ValueManager& ValMgr, IntegerLiteral* I);
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000219
220 // Implement isa<T> support.
221 static inline bool classof(const ExprValue* V) {
222 return V->getKind() >= MinRValueKind;
223 }
224};
225
226class VISIBILITY_HIDDEN RValueMayEqualSet : public RValue {
227public:
228 RValueMayEqualSet(const APSIntSetTy& S)
229 : RValue(RValueMayEqualSetKind, S.getRoot()) {}
230
231 APSIntSetTy GetValues() const {
232 return APSIntSetTy(reinterpret_cast<APSIntSetTy::TreeTy*>(getRawPtr()));
233 }
234
Ted Kremenek874d63f2008-01-24 02:02:54 +0000235 RValueMayEqualSet EvalAdd(ValueManager& ValMgr,
236 const RValueMayEqualSet& V) const;
237
238 RValueMayEqualSet EvalSub(ValueManager& ValMgr,
239 const RValueMayEqualSet& V) const;
240
241 RValueMayEqualSet EvalMul(ValueManager& ValMgr,
242 const RValueMayEqualSet& V) const;
243
244 RValueMayEqualSet EvalCast(ValueManager& ValMgr, Expr* CastExpr) const;
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000245
Ted Kremenekdacbb4f2008-01-24 08:20:02 +0000246 RValueMayEqualSet EvalMinus(ValueManager& ValMgr, UnaryOperator* U) const;
247
248
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000249 // Implement isa<T> support.
250 static inline bool classof(const ExprValue* V) {
251 return V->getKind() == RValueMayEqualSetKind;
252 }
253};
254} // end anonymous namespace
255
256//===----------------------------------------------------------------------===//
Ted Kremenek874d63f2008-01-24 02:02:54 +0000257// Transfer functions: Casts.
258//===----------------------------------------------------------------------===//
259
260ExprValue ExprValue::EvalCast(ValueManager& ValMgr, Expr* CastExpr) const {
261 switch (getKind()) {
262 case RValueMayEqualSetKind:
263 return cast<RValueMayEqualSet>(this)->EvalCast(ValMgr, CastExpr);
264 default:
265 return InvalidValue();
266 }
267}
268
269RValueMayEqualSet
270RValueMayEqualSet::EvalCast(ValueManager& ValMgr, Expr* CastExpr) const {
271 QualType T = CastExpr->getType();
272 assert (T->isIntegerType());
273
274 APSIntSetTy S1 = GetValues();
275 APSIntSetTy S2 = ValMgr.GetEmptyAPSIntSet();
276
277 for (APSIntSetTy::iterator I=S1.begin(), E=S1.end(); I!=E; ++I) {
278 llvm::APSInt X = *I;
279 X.setIsSigned(T->isSignedIntegerType());
280 X.extOrTrunc(ValMgr.getContext()->getTypeSize(T,CastExpr->getLocStart()));
281 S2 = ValMgr.AddToSet(S2, X);
282 }
283
284 return S2;
285}
286
287//===----------------------------------------------------------------------===//
Ted Kremenekdacbb4f2008-01-24 08:20:02 +0000288// Transfer functions: Unary Operations over R-Values.
289//===----------------------------------------------------------------------===//
290
291RValue RValue::EvalMinus(ValueManager& ValMgr, UnaryOperator* U) const {
292 switch (getKind()) {
293 case RValueMayEqualSetKind:
294 return cast<RValueMayEqualSet>(this)->EvalMinus(ValMgr, U);
295 default:
296 return cast<RValue>(InvalidValue());
297 }
298}
299
300RValueMayEqualSet
301RValueMayEqualSet::EvalMinus(ValueManager& ValMgr, UnaryOperator* U) const {
302
303 assert (U->getType() == U->getSubExpr()->getType());
304 assert (U->getType()->isIntegerType());
305
306 APSIntSetTy S1 = GetValues();
307 APSIntSetTy S2 = ValMgr.GetEmptyAPSIntSet();
308
309 for (APSIntSetTy::iterator I=S1.begin(), E=S1.end(); I!=E; ++I) {
310 assert ((*I).isSigned());
311
312 // FIXME: Shouldn't operator- on APSInt return an APSInt with the proper
313 // sign?
314 llvm::APSInt X(-(*I));
315 X.setIsSigned(true);
316
317 S2 = ValMgr.AddToSet(S2, X);
318 }
319
320 return S2;
321}
322
323
324
325//===----------------------------------------------------------------------===//
Ted Kremenek874d63f2008-01-24 02:02:54 +0000326// Transfer functions: Binary Operations over R-Values.
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000327//===----------------------------------------------------------------------===//
328
329#define RVALUE_DISPATCH_CASE(k1,k2,Op)\
330case ((k1##Kind+(MaxRValueKind-MinRValueKind))+(k2##Kind - MinRValueKind)):\
Ted Kremenek874d63f2008-01-24 02:02:54 +0000331 return cast<k1>(*this).Eval##Op(ValMgr,cast<k2>(RHS));
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000332
333#define RVALUE_DISPATCH(Op)\
334switch (getKind()+(MaxRValueKind-MinRValueKind)+(RHS.getKind()-MinRValueKind)){\
335 RVALUE_DISPATCH_CASE(RValueMayEqualSet,RValueMayEqualSet,Op)\
336 default:\
337 assert (!isValid() || !RHS.isValid() && "Missing case.");\
338 break;\
339}\
340return cast<RValue>(InvalidValue());
341
Ted Kremenek874d63f2008-01-24 02:02:54 +0000342RValue RValue::EvalAdd(ValueManager& ValMgr, const RValue& RHS) const {
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000343 RVALUE_DISPATCH(Add)
344}
345
Ted Kremenek874d63f2008-01-24 02:02:54 +0000346RValue RValue::EvalSub(ValueManager& ValMgr, const RValue& RHS) const {
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000347 RVALUE_DISPATCH(Sub)
348}
349
Ted Kremenek874d63f2008-01-24 02:02:54 +0000350RValue RValue::EvalMul(ValueManager& ValMgr, const RValue& RHS) const {
Ted Kremenek2eafd0e2008-01-23 23:42:27 +0000351 RVALUE_DISPATCH(Mul)
352}
353
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000354#undef RVALUE_DISPATCH_CASE
355#undef RVALUE_DISPATCH
356
357RValueMayEqualSet
Ted Kremenek874d63f2008-01-24 02:02:54 +0000358RValueMayEqualSet::EvalAdd(ValueManager& ValMgr,
359 const RValueMayEqualSet& RHS) const {
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000360
361 APSIntSetTy S1 = GetValues();
362 APSIntSetTy S2 = RHS.GetValues();
363
364 APSIntSetTy M = ValMgr.GetEmptyAPSIntSet();
365
366 for (APSIntSetTy::iterator I1=S1.begin(), E1=S2.end(); I1!=E1; ++I1)
Ted Kremenekdacbb4f2008-01-24 08:20:02 +0000367 for (APSIntSetTy::iterator I2=S2.begin(), E2=S2.end(); I2!=E2; ++I2) {
368 // FIXME: operator- on APSInt is really operator* on APInt, which loses
369 // the "signess" information (although the bits are correct).
370 const llvm::APSInt& X = *I1;
371 llvm::APSInt Y = X + *I2;
372 Y.setIsSigned(X.isSigned());
373 M = ValMgr.AddToSet(M, Y);
374 }
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000375
376 return M;
377}
378
379RValueMayEqualSet
Ted Kremenek874d63f2008-01-24 02:02:54 +0000380RValueMayEqualSet::EvalSub(ValueManager& ValMgr,
381 const RValueMayEqualSet& RHS) const {
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000382
383 APSIntSetTy S1 = GetValues();
384 APSIntSetTy S2 = RHS.GetValues();
385
386 APSIntSetTy M = ValMgr.GetEmptyAPSIntSet();
387
388 for (APSIntSetTy::iterator I1=S1.begin(), E1=S2.end(); I1!=E1; ++I1)
Ted Kremenekdacbb4f2008-01-24 08:20:02 +0000389 for (APSIntSetTy::iterator I2=S2.begin(), E2=S2.end(); I2!=E2; ++I2) {
390 // FIXME: operator- on APSInt is really operator* on APInt, which loses
391 // the "signess" information (although the bits are correct).
392 const llvm::APSInt& X = *I1;
393 llvm::APSInt Y = X - *I2;
394 Y.setIsSigned(X.isSigned());
395 M = ValMgr.AddToSet(M, Y);
396 }
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000397
398 return M;
399}
400
Ted Kremenek2eafd0e2008-01-23 23:42:27 +0000401RValueMayEqualSet
Ted Kremenek874d63f2008-01-24 02:02:54 +0000402RValueMayEqualSet::EvalMul(ValueManager& ValMgr,
403 const RValueMayEqualSet& RHS) const {
Ted Kremenek2eafd0e2008-01-23 23:42:27 +0000404
405 APSIntSetTy S1 = GetValues();
406 APSIntSetTy S2 = RHS.GetValues();
407
408 APSIntSetTy M = ValMgr.GetEmptyAPSIntSet();
409
410 for (APSIntSetTy::iterator I1=S1.begin(), E1=S2.end(); I1!=E1; ++I1)
Ted Kremenekdacbb4f2008-01-24 08:20:02 +0000411 for (APSIntSetTy::iterator I2=S2.begin(), E2=S2.end(); I2!=E2; ++I2) {
412 // FIXME: operator* on APSInt is really operator* on APInt, which loses
413 // the "signess" information (although the bits are correct).
414 const llvm::APSInt& X = *I1;
415 llvm::APSInt Y = X * *I2;
416 Y.setIsSigned(X.isSigned());
417 M = ValMgr.AddToSet(M, Y);
418 }
Ted Kremenek2eafd0e2008-01-23 23:42:27 +0000419
420 return M;
421}
422
Ted Kremenek7b8009a2008-01-24 02:28:56 +0000423RValue RValue::GetRValue(ValueManager& ValMgr, const llvm::APSInt& V) {
424 return RValueMayEqualSet(ValMgr.AddToSet(ValMgr.GetEmptyAPSIntSet(), V));
Ted Kremenekdacbb4f2008-01-24 08:20:02 +0000425}
426
427RValue RValue::GetRValue(ValueManager& ValMgr, IntegerLiteral* I) {
428 llvm::APSInt X(I->getValue());
429 X.setIsSigned(I->getType()->isSignedIntegerType());
430 return GetRValue(ValMgr, X);
431}
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000432
433//===----------------------------------------------------------------------===//
434// "L-Values".
435//===----------------------------------------------------------------------===//
436
437namespace {
438
439class VISIBILITY_HIDDEN LValue : public ExprValue {
440protected:
441 LValue(Kind k, void* D) : ExprValue(k, D) {}
442
443public:
444 // Implement isa<T> support.
445 static inline bool classof(const ExprValue* V) {
446 return V->getKind() <= MaxLValueKind;
447 }
448};
449
450class VISIBILITY_HIDDEN LValueDecl : public LValue {
451public:
452 LValueDecl(ValueDecl* vd) : LValue(LValueDeclKind,vd) {}
453
454 ValueDecl* getDecl() const {
455 return static_cast<ValueDecl*>(getRawPtr());
456 }
457
458 // Implement isa<T> support.
459 static inline bool classof(const ExprValue* V) {
460 return V->getKind() == LValueDeclKind;
461 }
462};
463} // end anonymous namespace
464
465//===----------------------------------------------------------------------===//
466// Pretty-Printing.
467//===----------------------------------------------------------------------===//
468
469void ExprValue::print(std::ostream& Out) const {
470 switch (getKind()) {
471 case InvalidValueKind:
472 Out << "Invalid"; break;
473
474 case RValueMayEqualSetKind: {
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000475 APSIntSetTy S = cast<RValueMayEqualSet>(this)->GetValues();
Ted Kremenek803c9ed2008-01-23 22:30:44 +0000476 bool first = true;
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000477
Ted Kremenek803c9ed2008-01-23 22:30:44 +0000478 for (APSIntSetTy::iterator I=S.begin(), E=S.end(); I!=E; ++I) {
479 if (first) first = false;
480 else Out << " | ";
481
482 Out << (*I).toString();
483 }
484
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000485 break;
486 }
487
488 default:
489 assert (false && "Pretty-printed not implemented for this ExprValue.");
490 break;
491 }
492}
493
494//===----------------------------------------------------------------------===//
495// ValueMapTy - A ImmutableMap type Stmt*/Decl* to ExprValues.
496//===----------------------------------------------------------------------===//
497
498typedef llvm::ImmutableMap<ValueKey,ExprValue> ValueMapTy;
499
500namespace clang {
501 template<>
502 struct VISIBILITY_HIDDEN GRTrait<ValueMapTy> {
503 static inline void* toPtr(ValueMapTy M) {
504 return reinterpret_cast<void*>(M.getRoot());
505 }
506 static inline ValueMapTy toState(void* P) {
507 return ValueMapTy(static_cast<ValueMapTy::TreeTy*>(P));
508 }
509 };
Ted Kremenekd27f8162008-01-15 23:55:06 +0000510}
511
512//===----------------------------------------------------------------------===//
513// The Checker!
514//===----------------------------------------------------------------------===//
515
516namespace {
Ted Kremenekd27f8162008-01-15 23:55:06 +0000517
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000518class VISIBILITY_HIDDEN GRConstants {
Ted Kremenekd27f8162008-01-15 23:55:06 +0000519
520public:
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000521 typedef ValueMapTy StateTy;
Ted Kremenekd27f8162008-01-15 23:55:06 +0000522 typedef GRNodeBuilder<GRConstants> NodeBuilder;
523 typedef ExplodedNode<StateTy> NodeTy;
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000524
525 class NodeSet {
526 typedef llvm::SmallVector<NodeTy*,3> ImplTy;
527 ImplTy Impl;
528 public:
529
530 NodeSet() {}
531 NodeSet(NodeTy* N) { assert (N && !N->isInfeasible()); Impl.push_back(N); }
532
533 void Add(NodeTy* N) { if (N && !N->isInfeasible()) Impl.push_back(N); }
534
535 typedef ImplTy::iterator iterator;
536 typedef ImplTy::const_iterator const_iterator;
537
538 unsigned size() const { return Impl.size(); }
539
540 iterator begin() { return Impl.begin(); }
541 iterator end() { return Impl.end(); }
542
543 const_iterator begin() const { return Impl.begin(); }
544 const_iterator end() const { return Impl.end(); }
545 };
Ted Kremenekd27f8162008-01-15 23:55:06 +0000546
547protected:
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000548 /// Liveness - live-variables information the ValueDecl* and block-level
549 /// Expr* in the CFG. Used to prune out dead state.
Ted Kremenekd27f8162008-01-15 23:55:06 +0000550 LiveVariables* Liveness;
551
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000552 /// Builder - The current GRNodeBuilder which is used when building the nodes
553 /// for a given statement.
Ted Kremenekd27f8162008-01-15 23:55:06 +0000554 NodeBuilder* Builder;
555
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000556 /// StateMgr - Object that manages the data for all created states.
557 ValueMapTy::Factory StateMgr;
Ted Kremenekd27f8162008-01-15 23:55:06 +0000558
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000559 /// ValueMgr - Object that manages the data for all created ExprValues.
560 ValueManager ValMgr;
561
562 /// cfg - the current CFG.
Ted Kremenekd27f8162008-01-15 23:55:06 +0000563 CFG* cfg;
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000564
565 /// StmtEntryNode - The immediate predecessor node.
566 NodeTy* StmtEntryNode;
567
568 /// CurrentStmt - The current block-level statement.
569 Stmt* CurrentStmt;
570
571 bool StateCleaned;
Ted Kremenekd27f8162008-01-15 23:55:06 +0000572
Ted Kremenek7b8009a2008-01-24 02:28:56 +0000573 ASTContext* getContext() const { return ValMgr.getContext(); }
574
Ted Kremenekd27f8162008-01-15 23:55:06 +0000575public:
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000576 GRConstants() : Liveness(NULL), Builder(NULL), cfg(NULL),
577 StmtEntryNode(NULL), CurrentStmt(NULL) {}
Ted Kremenekd27f8162008-01-15 23:55:06 +0000578
579 ~GRConstants() { delete Liveness; }
580
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000581 /// getCFG - Returns the CFG associated with this analysis.
Ted Kremenekd27f8162008-01-15 23:55:06 +0000582 CFG& getCFG() { assert (cfg); return *cfg; }
583
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000584 /// Initialize - Initialize the checker's state based on the specified
585 /// CFG. This results in liveness information being computed for
586 /// each block-level statement in the CFG.
Ted Kremenek874d63f2008-01-24 02:02:54 +0000587 void Initialize(CFG& c, ASTContext& ctx) {
588 cfg = &c;
589 ValMgr.setContext(&ctx);
Ted Kremenekd27f8162008-01-15 23:55:06 +0000590 Liveness = new LiveVariables(c);
591 Liveness->runOnCFG(c);
Ted Kremenek79649df2008-01-17 18:25:22 +0000592 Liveness->runOnAllBlocks(c, NULL, true);
Ted Kremenekd27f8162008-01-15 23:55:06 +0000593 }
594
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000595 /// getInitialState - Return the initial state used for the root vertex
596 /// in the ExplodedGraph.
Ted Kremenekd27f8162008-01-15 23:55:06 +0000597 StateTy getInitialState() {
Ted Kremenekcb448ca2008-01-16 00:53:15 +0000598 return StateMgr.GetEmptyMap();
Ted Kremenekd27f8162008-01-15 23:55:06 +0000599 }
Ted Kremenekd27f8162008-01-15 23:55:06 +0000600
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000601 /// ProcessStmt - Called by GREngine. Used to generate new successor
602 /// nodes by processing the 'effects' of a block-level statement.
603 void ProcessStmt(Stmt* S, NodeBuilder& builder);
604
605 /// RemoveDeadBindings - Return a new state that is the same as 'M' except
606 /// that all subexpression mappings are removed and that any
607 /// block-level expressions that are not live at 'S' also have their
608 /// mappings removed.
609 StateTy RemoveDeadBindings(Stmt* S, StateTy M);
610
611 StateTy SetValue(StateTy St, Stmt* S, const ExprValue& V,
612 bool isBlkExpr = false);
613
614 StateTy SetValue(StateTy St, const LValue& LV, const ExprValue& V);
Ted Kremenek1ccd31c2008-01-16 19:42:59 +0000615
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000616 ExprValue GetValue(const StateTy& St, Stmt* S);
617 ExprValue GetValue(const StateTy& St, const LValue& LV);
618 LValue GetLValue(const StateTy& St, Stmt* S);
Ted Kremenekd27f8162008-01-15 23:55:06 +0000619
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000620 void Nodify(NodeSet& Dst, Stmt* S, NodeTy* Pred, StateTy St);
Ted Kremenekd27f8162008-01-15 23:55:06 +0000621
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000622 /// Visit - Transfer function logic for all statements. Dispatches to
623 /// other functions that handle specific kinds of statements.
624 void Visit(Stmt* S, NodeTy* Pred, NodeSet& Dst);
Ted Kremenek874d63f2008-01-24 02:02:54 +0000625
626 /// VisitCast - Transfer function logic for all casts (implicit and explicit).
627 void VisitCast(Expr* CastE, Expr* E, NodeTy* Pred, NodeSet& Dst);
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000628
Ted Kremenek7b8009a2008-01-24 02:28:56 +0000629 /// VisitUnaryOperator - Transfer function logic for unary operators.
630 void VisitUnaryOperator(UnaryOperator* B, NodeTy* Pred, NodeSet& Dst);
631
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000632 /// VisitBinaryOperator - Transfer function logic for binary operators.
633 void VisitBinaryOperator(BinaryOperator* B, NodeTy* Pred, NodeSet& Dst);
Ted Kremenekd27f8162008-01-15 23:55:06 +0000634};
635} // end anonymous namespace
636
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000637
Ted Kremenekd27f8162008-01-15 23:55:06 +0000638void GRConstants::ProcessStmt(Stmt* S, NodeBuilder& builder) {
639 Builder = &builder;
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000640
641 StmtEntryNode = builder.getLastNode();
642 CurrentStmt = S;
643 NodeSet Dst;
644 StateCleaned = false;
645
646 Visit(S, StmtEntryNode, Dst);
647
648 // If no nodes were generated, generate a new node that has all the
649 // dead mappings removed.
650 if (Dst.size() == 1 && *Dst.begin() == StmtEntryNode) {
651 StateTy St = RemoveDeadBindings(S, StmtEntryNode->getState());
652 builder.generateNode(S, St, StmtEntryNode);
653 }
Ted Kremenekf84469b2008-01-18 00:41:32 +0000654
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000655 CurrentStmt = NULL;
656 StmtEntryNode = NULL;
657 Builder = NULL;
Ted Kremenekd27f8162008-01-15 23:55:06 +0000658}
659
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000660
661ExprValue GRConstants::GetValue(const StateTy& St, const LValue& LV) {
662 switch (LV.getKind()) {
663 case ExprValue::LValueDeclKind: {
664 StateTy::TreeTy* T = St.SlimFind(cast<LValueDecl>(LV).getDecl());
665 return T ? T->getValue().second : InvalidValue();
666 }
667 default:
668 assert (false && "Invalid LValue.");
Ted Kremenekca3e8572008-01-16 22:28:08 +0000669 break;
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000670 }
671
672 return InvalidValue();
673}
674
675ExprValue GRConstants::GetValue(const StateTy& St, Stmt* S) {
Ted Kremenek671c9e82008-01-24 00:50:08 +0000676 for (;;) {
677 switch (S->getStmtClass()) {
678 case Stmt::ParenExprClass:
679 S = cast<ParenExpr>(S)->getSubExpr();
680 continue;
681
682 case Stmt::DeclRefExprClass:
683 return GetValue(St, LValueDecl(cast<DeclRefExpr>(S)->getDecl()));
Ted Kremenekca3e8572008-01-16 22:28:08 +0000684
Ted Kremenek671c9e82008-01-24 00:50:08 +0000685 case Stmt::IntegerLiteralClass:
Ted Kremenekdacbb4f2008-01-24 08:20:02 +0000686 return RValue::GetRValue(ValMgr, cast<IntegerLiteral>(S));
Ted Kremenek874d63f2008-01-24 02:02:54 +0000687
688 case Stmt::ImplicitCastExprClass: {
689 ImplicitCastExpr* C = cast<ImplicitCastExpr>(S);
690 if (C->getType() == C->getSubExpr()->getType()) {
691 S = C->getSubExpr();
692 continue;
693 }
694 break;
695 }
696
697 case Stmt::CastExprClass: {
698 CastExpr* C = cast<CastExpr>(S);
699 if (C->getType() == C->getSubExpr()->getType()) {
700 S = C->getSubExpr();
701 continue;
702 }
703 break;
704 }
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000705
Ted Kremenek671c9e82008-01-24 00:50:08 +0000706 default:
707 break;
708 };
709
710 break;
711 }
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000712
713 StateTy::TreeTy* T = St.SlimFind(ValueKey(S, getCFG().isBlkExpr(S)));
Ted Kremenek874d63f2008-01-24 02:02:54 +0000714
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000715 return T ? T->getValue().second : InvalidValue();
716}
717
718LValue GRConstants::GetLValue(const StateTy& St, Stmt* S) {
719 if (Expr* E = dyn_cast<Expr>(S))
720 S = E->IgnoreParens();
721
722 if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(S))
723 return LValueDecl(DR->getDecl());
724
725 return cast<LValue>(GetValue(St, S));
726}
727
728GRConstants::StateTy GRConstants::SetValue(StateTy St, Stmt* S,
729 const ExprValue& V, bool isBlkExpr) {
730
731 if (!StateCleaned) {
732 St = RemoveDeadBindings(CurrentStmt, St);
733 StateCleaned = true;
734 }
735
736 return V.isValid() ? StateMgr.Add(St, ValueKey(S,isBlkExpr), V)
737 : St;
738}
739
740GRConstants::StateTy GRConstants::SetValue(StateTy St, const LValue& LV,
741 const ExprValue& V) {
742 if (!LV.isValid())
743 return St;
744
745 if (!StateCleaned) {
746 St = RemoveDeadBindings(CurrentStmt, St);
747 StateCleaned = true;
Ted Kremenekca3e8572008-01-16 22:28:08 +0000748 }
Ted Kremenek0525a4f2008-01-16 19:47:19 +0000749
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000750 switch (LV.getKind()) {
751 case ExprValue::LValueDeclKind:
752 return V.isValid() ? StateMgr.Add(St, cast<LValueDecl>(LV).getDecl(), V)
753 : StateMgr.Remove(St, cast<LValueDecl>(LV).getDecl());
754
755 default:
756 assert ("SetValue for given LValue type not yet implemented.");
757 return St;
758 }
Ted Kremenekd27f8162008-01-15 23:55:06 +0000759}
760
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000761GRConstants::StateTy GRConstants::RemoveDeadBindings(Stmt* Loc, StateTy M) {
Ted Kremenekf84469b2008-01-18 00:41:32 +0000762 // Note: in the code below, we can assign a new map to M since the
763 // iterators are iterating over the tree of the *original* map.
Ted Kremenekf84469b2008-01-18 00:41:32 +0000764 StateTy::iterator I = M.begin(), E = M.end();
765
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000766 // Remove old bindings for subexpressions.
767 for (; I!=E && I.getKey().getKind() == ValueKey::IsSubExp; ++I)
Ted Kremeneke00fe3f2008-01-17 00:52:48 +0000768 M = StateMgr.Remove(M, I.getKey());
Ted Kremenekf84469b2008-01-18 00:41:32 +0000769
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000770 // Remove bindings for "dead" decls.
771 for (; I!=E && I.getKey().getKind() == ValueKey::IsDecl; ++I)
772 if (VarDecl* V = dyn_cast<VarDecl>(cast<ValueDecl>(I.getKey())))
773 if (!Liveness->isLive(Loc, V))
774 M = StateMgr.Remove(M, I.getKey());
775
776 // Remove bindings for "dead" block-level expressions.
777 for (; I!=E; ++I)
778 if (!Liveness->isLive(Loc, cast<Stmt>(I.getKey())))
779 M = StateMgr.Remove(M, I.getKey());
Ted Kremeneke00fe3f2008-01-17 00:52:48 +0000780
781 return M;
Ted Kremeneke00fe3f2008-01-17 00:52:48 +0000782}
783
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000784void GRConstants::Nodify(NodeSet& Dst, Stmt* S, GRConstants::NodeTy* Pred,
785 GRConstants::StateTy St) {
786
787 // If the state hasn't changed, don't generate a new node.
788 if (St == Pred->getState())
789 return;
Ted Kremenekcb448ca2008-01-16 00:53:15 +0000790
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000791 Dst.Add(Builder->generateNode(S, St, Pred));
Ted Kremenekcb448ca2008-01-16 00:53:15 +0000792}
Ted Kremenekd27f8162008-01-15 23:55:06 +0000793
Ted Kremenek874d63f2008-01-24 02:02:54 +0000794void GRConstants::VisitCast(Expr* CastE, Expr* E, GRConstants::NodeTy* Pred,
795 GRConstants::NodeSet& Dst) {
796
797 QualType T = CastE->getType();
798
799 // Check for redundant casts.
800 if (E->getType() == T) {
801 Dst.Add(Pred);
802 return;
803 }
804
805 NodeSet S1;
806 Visit(E, Pred, S1);
807
808 for (NodeSet::iterator I1=S1.begin(), E1=S1.end(); I1 != E1; ++I1) {
809 NodeTy* N = *I1;
810 StateTy St = N->getState();
811 const ExprValue& V = GetValue(St, E);
812 Nodify(Dst, CastE, N, SetValue(St, CastE, V.EvalCast(ValMgr, CastE)));
813 }
814 }
815
Ted Kremenek7b8009a2008-01-24 02:28:56 +0000816void GRConstants::VisitUnaryOperator(UnaryOperator* U,
817 GRConstants::NodeTy* Pred,
818 GRConstants::NodeSet& Dst) {
819 NodeSet S1;
820 Visit(U->getSubExpr(), Pred, S1);
821
822 for (NodeSet::iterator I1=S1.begin(), E1=S1.end(); I1 != E1; ++I1) {
823 NodeTy* N1 = *I1;
824 StateTy St = N1->getState();
825
826 switch (U->getOpcode()) {
827 case UnaryOperator::PostInc: {
828 const LValue& L1 = GetLValue(St, U->getSubExpr());
829 RValue R1 = cast<RValue>(GetValue(St, L1));
830
831 QualType T = U->getType();
Ted Kremeneke0cf9c82008-01-24 19:00:57 +0000832 unsigned bits = getContext()->getTypeSize(T, U->getLocStart());
833 llvm::APSInt One(llvm::APInt(bits, 1), T->isUnsignedIntegerType());
834 RValue R2 = RValue::GetRValue(ValMgr, One);
835
Ted Kremenek7b8009a2008-01-24 02:28:56 +0000836 RValue Result = R1.EvalAdd(ValMgr, R2);
837 Nodify(Dst, U, N1, SetValue(SetValue(St, U, R1), L1, Result));
838 break;
839 }
840
841 case UnaryOperator::PostDec: {
842 const LValue& L1 = GetLValue(St, U->getSubExpr());
843 RValue R1 = cast<RValue>(GetValue(St, L1));
844
845 QualType T = U->getType();
Ted Kremeneke0cf9c82008-01-24 19:00:57 +0000846 unsigned bits = getContext()->getTypeSize(T, U->getLocStart());
847 llvm::APSInt One(llvm::APInt(bits, 1), T->isUnsignedIntegerType());
848 RValue R2 = RValue::GetRValue(ValMgr, One);
Ted Kremenek7b8009a2008-01-24 02:28:56 +0000849
850 RValue Result = R1.EvalSub(ValMgr, R2);
851 Nodify(Dst, U, N1, SetValue(SetValue(St, U, R1), L1, Result));
852 break;
853 }
854
855 case UnaryOperator::PreInc: {
856 const LValue& L1 = GetLValue(St, U->getSubExpr());
857 RValue R1 = cast<RValue>(GetValue(St, L1));
858
859 QualType T = U->getType();
Ted Kremeneke0cf9c82008-01-24 19:00:57 +0000860 unsigned bits = getContext()->getTypeSize(T, U->getLocStart());
861 llvm::APSInt One(llvm::APInt(bits, 1), T->isUnsignedIntegerType());
Ted Kremenek7b8009a2008-01-24 02:28:56 +0000862 RValue R2 = RValue::GetRValue(ValMgr, One);
863
864 RValue Result = R1.EvalAdd(ValMgr, R2);
865 Nodify(Dst, U, N1, SetValue(SetValue(St, U, Result), L1, Result));
866 break;
867 }
868
869 case UnaryOperator::PreDec: {
870 const LValue& L1 = GetLValue(St, U->getSubExpr());
871 RValue R1 = cast<RValue>(GetValue(St, L1));
872
873 QualType T = U->getType();
Ted Kremeneke0cf9c82008-01-24 19:00:57 +0000874 unsigned bits = getContext()->getTypeSize(T, U->getLocStart());
875 llvm::APSInt One(llvm::APInt(bits, 1), T->isUnsignedIntegerType());
876 RValue R2 = RValue::GetRValue(ValMgr, One);
Ted Kremenek7b8009a2008-01-24 02:28:56 +0000877
878 RValue Result = R1.EvalSub(ValMgr, R2);
879 Nodify(Dst, U, N1, SetValue(SetValue(St, U, Result), L1, Result));
880 break;
881 }
882
Ted Kremenekdacbb4f2008-01-24 08:20:02 +0000883 case UnaryOperator::Minus: {
884 const RValue& R1 = cast<RValue>(GetValue(St, U->getSubExpr()));
885 Nodify(Dst, U, N1, SetValue(St, U, R1.EvalMinus(ValMgr, U)));
886 break;
887 }
888
Ted Kremenek7b8009a2008-01-24 02:28:56 +0000889 default: ;
890 assert (false && "Not implemented.");
891 }
892 }
893}
894
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000895void GRConstants::VisitBinaryOperator(BinaryOperator* B,
896 GRConstants::NodeTy* Pred,
897 GRConstants::NodeSet& Dst) {
898 NodeSet S1;
899 Visit(B->getLHS(), Pred, S1);
Ted Kremenekcb448ca2008-01-16 00:53:15 +0000900
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000901 for (NodeSet::iterator I1=S1.begin(), E1=S1.end(); I1 != E1; ++I1) {
902 NodeTy* N1 = *I1;
Ted Kremeneke00fe3f2008-01-17 00:52:48 +0000903
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000904 // When getting the value for the LHS, check if we are in an assignment.
905 // In such cases, we want to (initially) treat the LHS as an LValue,
906 // so we use GetLValue instead of GetValue so that DeclRefExpr's are
907 // evaluated to LValueDecl's instead of to an RValue.
908 const ExprValue& V1 =
909 B->isAssignmentOp() ? GetLValue(N1->getState(), B->getLHS())
910 : GetValue(N1->getState(), B->getLHS());
Ted Kremenekcb448ca2008-01-16 00:53:15 +0000911
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000912 NodeSet S2;
913 Visit(B->getRHS(), N1, S2);
914
915 for (NodeSet::iterator I2=S2.begin(), E2=S2.end(); I2 != E2; ++I2) {
916 NodeTy* N2 = *I2;
917 StateTy St = N2->getState();
918 const ExprValue& V2 = GetValue(St, B->getRHS());
919
920 switch (B->getOpcode()) {
921 case BinaryOperator::Add: {
922 const RValue& R1 = cast<RValue>(V1);
923 const RValue& R2 = cast<RValue>(V2);
924
Ted Kremenek874d63f2008-01-24 02:02:54 +0000925 Nodify(Dst, B, N2, SetValue(St, B, R1.EvalAdd(ValMgr, R2)));
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000926 break;
927 }
928
929 case BinaryOperator::Sub: {
930 const RValue& R1 = cast<RValue>(V1);
931 const RValue& R2 = cast<RValue>(V2);
Ted Kremenek874d63f2008-01-24 02:02:54 +0000932 Nodify(Dst, B, N2, SetValue(St, B, R1.EvalSub(ValMgr, R2)));
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000933 break;
934 }
935
Ted Kremenek2eafd0e2008-01-23 23:42:27 +0000936 case BinaryOperator::Mul: {
937 const RValue& R1 = cast<RValue>(V1);
938 const RValue& R2 = cast<RValue>(V2);
Ted Kremenek874d63f2008-01-24 02:02:54 +0000939 Nodify(Dst, B, N2, SetValue(St, B, R1.EvalMul(ValMgr, R2)));
Ted Kremenek2eafd0e2008-01-23 23:42:27 +0000940 break;
941 }
942
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000943 case BinaryOperator::Assign: {
944 const LValue& L1 = cast<LValue>(V1);
945 const RValue& R2 = cast<RValue>(V2);
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000946 Nodify(Dst, B, N2, SetValue(SetValue(St, B, R2), L1, R2));
947 break;
948 }
Ted Kremenekb4ae33f2008-01-23 23:38:00 +0000949
950 case BinaryOperator::AddAssign: {
951 const LValue& L1 = cast<LValue>(V1);
952 RValue R1 = cast<RValue>(GetValue(N1->getState(), L1));
Ted Kremenek874d63f2008-01-24 02:02:54 +0000953 RValue Result = R1.EvalAdd(ValMgr, cast<RValue>(V2));
Ted Kremenekb4ae33f2008-01-23 23:38:00 +0000954 Nodify(Dst, B, N2, SetValue(SetValue(St, B, Result), L1, Result));
955 break;
956 }
957
958 case BinaryOperator::SubAssign: {
959 const LValue& L1 = cast<LValue>(V1);
960 RValue R1 = cast<RValue>(GetValue(N1->getState(), L1));
Ted Kremenek874d63f2008-01-24 02:02:54 +0000961 RValue Result = R1.EvalSub(ValMgr, cast<RValue>(V2));
Ted Kremenekb4ae33f2008-01-23 23:38:00 +0000962 Nodify(Dst, B, N2, SetValue(SetValue(St, B, Result), L1, Result));
963 break;
964 }
Ted Kremenek2eafd0e2008-01-23 23:42:27 +0000965
966 case BinaryOperator::MulAssign: {
967 const LValue& L1 = cast<LValue>(V1);
968 RValue R1 = cast<RValue>(GetValue(N1->getState(), L1));
Ted Kremenek874d63f2008-01-24 02:02:54 +0000969 RValue Result = R1.EvalMul(ValMgr, cast<RValue>(V2));
Ted Kremenek2eafd0e2008-01-23 23:42:27 +0000970 Nodify(Dst, B, N2, SetValue(SetValue(St, B, Result), L1, Result));
971 break;
972 }
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000973
974 default:
975 Dst.Add(N2);
976 break;
977 }
Ted Kremenekcb448ca2008-01-16 00:53:15 +0000978 }
Ted Kremenekd27f8162008-01-15 23:55:06 +0000979 }
Ted Kremenekd27f8162008-01-15 23:55:06 +0000980}
Ted Kremenekee985462008-01-16 18:18:48 +0000981
Ted Kremenek1ccd31c2008-01-16 19:42:59 +0000982
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000983void GRConstants::Visit(Stmt* S, GRConstants::NodeTy* Pred,
984 GRConstants::NodeSet& Dst) {
985
986 // FIXME: add metadata to the CFG so that we can disable
987 // this check when we KNOW that there is no block-level subexpression.
988 // The motivation is that this check requires a hashtable lookup.
989
990 if (S != CurrentStmt && getCFG().isBlkExpr(S)) {
991 Dst.Add(Pred);
992 return;
993 }
994
995 switch (S->getStmtClass()) {
996 case Stmt::BinaryOperatorClass:
Ted Kremenekb4ae33f2008-01-23 23:38:00 +0000997 case Stmt::CompoundAssignOperatorClass:
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000998 VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Dst);
999 break;
1000
Ted Kremenek7b8009a2008-01-24 02:28:56 +00001001 case Stmt::UnaryOperatorClass:
1002 VisitUnaryOperator(cast<UnaryOperator>(S), Pred, Dst);
1003 break;
1004
Ted Kremenekab2b8c52008-01-23 19:59:44 +00001005 case Stmt::ParenExprClass:
1006 Visit(cast<ParenExpr>(S)->getSubExpr(), Pred, Dst);
1007 break;
1008
Ted Kremenek874d63f2008-01-24 02:02:54 +00001009 case Stmt::ImplicitCastExprClass: {
1010 ImplicitCastExpr* C = cast<ImplicitCastExpr>(S);
1011 VisitCast(C, C->getSubExpr(), Pred, Dst);
1012 break;
1013 }
1014
1015 case Stmt::CastExprClass: {
1016 CastExpr* C = cast<CastExpr>(S);
1017 VisitCast(C, C->getSubExpr(), Pred, Dst);
1018 break;
1019 }
1020
Ted Kremenekab2b8c52008-01-23 19:59:44 +00001021 default:
1022 Dst.Add(Pred); // No-op. Simply propagate the current state unchanged.
1023 break;
Ted Kremenek79649df2008-01-17 18:25:22 +00001024 }
Ted Kremenek1ccd31c2008-01-16 19:42:59 +00001025}
1026
Ted Kremenekee985462008-01-16 18:18:48 +00001027//===----------------------------------------------------------------------===//
1028// Driver.
1029//===----------------------------------------------------------------------===//
1030
Ted Kremenekaa66a322008-01-16 21:46:15 +00001031#ifndef NDEBUG
1032namespace llvm {
1033template<>
1034struct VISIBILITY_HIDDEN DOTGraphTraits<GRConstants::NodeTy*> :
1035 public DefaultDOTGraphTraits {
1036
Ted Kremenek803c9ed2008-01-23 22:30:44 +00001037 static void PrintKind(std::ostringstream& Out, ValueKey::Kind kind) {
1038 switch (kind) {
1039 case ValueKey::IsSubExp: Out << "Sub-Expressions:\\l"; break;
1040 case ValueKey::IsDecl: Out << "Variables:\\l"; break;
1041 case ValueKey::IsBlkExpr: Out << "Block-level Expressions:\\l"; break;
1042 default: assert (false && "Unknown ValueKey type.");
1043 }
1044 }
1045
Ted Kremenekaa66a322008-01-16 21:46:15 +00001046 static std::string getNodeLabel(const GRConstants::NodeTy* N, void*) {
1047 std::ostringstream Out;
Ted Kremenek803c9ed2008-01-23 22:30:44 +00001048
1049 // Program Location.
Ted Kremenekaa66a322008-01-16 21:46:15 +00001050 ProgramPoint Loc = N->getLocation();
1051
1052 switch (Loc.getKind()) {
1053 case ProgramPoint::BlockEntranceKind:
1054 Out << "Block Entrance: B"
1055 << cast<BlockEntrance>(Loc).getBlock()->getBlockID();
1056 break;
1057
1058 case ProgramPoint::BlockExitKind:
1059 assert (false);
1060 break;
1061
1062 case ProgramPoint::PostStmtKind: {
1063 const PostStmt& L = cast<PostStmt>(Loc);
Ted Kremenek803c9ed2008-01-23 22:30:44 +00001064 Out << "(" << (void*) L.getStmt() << ") ";
Ted Kremenekaa66a322008-01-16 21:46:15 +00001065 L.getStmt()->printPretty(Out);
1066 break;
1067 }
1068
1069 default: {
1070 const BlockEdge& E = cast<BlockEdge>(Loc);
1071 Out << "Edge: (B" << E.getSrc()->getBlockID() << ", B"
1072 << E.getDst()->getBlockID() << ')';
1073 }
1074 }
1075
Ted Kremenek803c9ed2008-01-23 22:30:44 +00001076 Out << "\\|";
Ted Kremenekaa66a322008-01-16 21:46:15 +00001077
1078 GRConstants::StateTy M = N->getState();
1079 bool isFirst = true;
Ted Kremenek803c9ed2008-01-23 22:30:44 +00001080 ValueKey::Kind kind;
Ted Kremenekaa66a322008-01-16 21:46:15 +00001081
1082 for (GRConstants::StateTy::iterator I=M.begin(), E=M.end(); I!=E; ++I) {
Ted Kremenek803c9ed2008-01-23 22:30:44 +00001083 if (!isFirst) {
1084 ValueKey::Kind newKind = I.getKey().getKind();
1085
1086 if (newKind != kind) {
1087 Out << "\\l\\l";
1088 PrintKind(Out, newKind);
1089 }
1090 else
1091 Out << "\\l";
1092
1093 kind = newKind;
1094 }
1095 else {
1096 kind = I.getKey().getKind();
1097 PrintKind(Out, kind);
Ted Kremenekaa66a322008-01-16 21:46:15 +00001098 isFirst = false;
Ted Kremenek803c9ed2008-01-23 22:30:44 +00001099 }
1100
1101 Out << ' ';
Ted Kremenekaa66a322008-01-16 21:46:15 +00001102
1103 if (ValueDecl* V = dyn_cast<ValueDecl>(I.getKey())) {
Ted Kremenek803c9ed2008-01-23 22:30:44 +00001104 Out << V->getName();
Ted Kremenekaa66a322008-01-16 21:46:15 +00001105 }
1106 else {
1107 Stmt* E = cast<Stmt>(I.getKey());
Ted Kremenek803c9ed2008-01-23 22:30:44 +00001108 Out << " (" << (void*) E << ") ";
1109 E->printPretty(Out);
Ted Kremenekaa66a322008-01-16 21:46:15 +00001110 }
1111
Ted Kremenek803c9ed2008-01-23 22:30:44 +00001112 Out << " : ";
Ted Kremenekab2b8c52008-01-23 19:59:44 +00001113 I.getData().print(Out);
Ted Kremenekaa66a322008-01-16 21:46:15 +00001114 }
1115
Ted Kremenek803c9ed2008-01-23 22:30:44 +00001116 Out << "\\l";
Ted Kremenekaa66a322008-01-16 21:46:15 +00001117 return Out.str();
1118 }
1119};
1120} // end llvm namespace
1121#endif
1122
Ted Kremenekee985462008-01-16 18:18:48 +00001123namespace clang {
Ted Kremenek874d63f2008-01-24 02:02:54 +00001124void RunGRConstants(CFG& cfg, ASTContext& Ctx) {
1125 GREngine<GRConstants> Engine(cfg, Ctx);
Ted Kremenekee985462008-01-16 18:18:48 +00001126 Engine.ExecuteWorkList();
Ted Kremenekaa66a322008-01-16 21:46:15 +00001127#ifndef NDEBUG
1128 llvm::ViewGraph(*Engine.getGraph().roots_begin(),"GRConstants");
1129#endif
Ted Kremenekee985462008-01-16 18:18:48 +00001130}
Ted Kremenekab2b8c52008-01-23 19:59:44 +00001131} // end clang namespace