blob: 2d1ba56f7e194174c02caaba2db26d2a55bf6a21 [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();
832 llvm::APInt One(getContext()->getTypeSize(T,U->getLocStart()), 1);
833 RValue R2 = RValue::GetRValue(ValMgr, One);
834
835 RValue Result = R1.EvalAdd(ValMgr, R2);
836 Nodify(Dst, U, N1, SetValue(SetValue(St, U, R1), L1, Result));
837 break;
838 }
839
840 case UnaryOperator::PostDec: {
841 const LValue& L1 = GetLValue(St, U->getSubExpr());
842 RValue R1 = cast<RValue>(GetValue(St, L1));
843
844 QualType T = U->getType();
845 llvm::APInt One(getContext()->getTypeSize(T,U->getLocStart()), 1);
846 RValue R2 = RValue::GetRValue(ValMgr, One);
847
848 RValue Result = R1.EvalSub(ValMgr, R2);
849 Nodify(Dst, U, N1, SetValue(SetValue(St, U, R1), L1, Result));
850 break;
851 }
852
853 case UnaryOperator::PreInc: {
854 const LValue& L1 = GetLValue(St, U->getSubExpr());
855 RValue R1 = cast<RValue>(GetValue(St, L1));
856
857 QualType T = U->getType();
858 llvm::APInt One(getContext()->getTypeSize(T,U->getLocStart()), 1);
859 RValue R2 = RValue::GetRValue(ValMgr, One);
860
861 RValue Result = R1.EvalAdd(ValMgr, R2);
862 Nodify(Dst, U, N1, SetValue(SetValue(St, U, Result), L1, Result));
863 break;
864 }
865
866 case UnaryOperator::PreDec: {
867 const LValue& L1 = GetLValue(St, U->getSubExpr());
868 RValue R1 = cast<RValue>(GetValue(St, L1));
869
870 QualType T = U->getType();
871 llvm::APInt One(getContext()->getTypeSize(T,U->getLocStart()), 1);
872 RValue R2 = RValue::GetRValue(ValMgr, One);
873
874 RValue Result = R1.EvalSub(ValMgr, R2);
875 Nodify(Dst, U, N1, SetValue(SetValue(St, U, Result), L1, Result));
876 break;
877 }
878
Ted Kremenekdacbb4f2008-01-24 08:20:02 +0000879 case UnaryOperator::Minus: {
880 const RValue& R1 = cast<RValue>(GetValue(St, U->getSubExpr()));
881 Nodify(Dst, U, N1, SetValue(St, U, R1.EvalMinus(ValMgr, U)));
882 break;
883 }
884
Ted Kremenek7b8009a2008-01-24 02:28:56 +0000885 default: ;
886 assert (false && "Not implemented.");
887 }
888 }
889}
890
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000891void GRConstants::VisitBinaryOperator(BinaryOperator* B,
892 GRConstants::NodeTy* Pred,
893 GRConstants::NodeSet& Dst) {
894 NodeSet S1;
895 Visit(B->getLHS(), Pred, S1);
Ted Kremenekcb448ca2008-01-16 00:53:15 +0000896
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000897 for (NodeSet::iterator I1=S1.begin(), E1=S1.end(); I1 != E1; ++I1) {
898 NodeTy* N1 = *I1;
Ted Kremeneke00fe3f2008-01-17 00:52:48 +0000899
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000900 // When getting the value for the LHS, check if we are in an assignment.
901 // In such cases, we want to (initially) treat the LHS as an LValue,
902 // so we use GetLValue instead of GetValue so that DeclRefExpr's are
903 // evaluated to LValueDecl's instead of to an RValue.
904 const ExprValue& V1 =
905 B->isAssignmentOp() ? GetLValue(N1->getState(), B->getLHS())
906 : GetValue(N1->getState(), B->getLHS());
Ted Kremenekcb448ca2008-01-16 00:53:15 +0000907
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000908 NodeSet S2;
909 Visit(B->getRHS(), N1, S2);
910
911 for (NodeSet::iterator I2=S2.begin(), E2=S2.end(); I2 != E2; ++I2) {
912 NodeTy* N2 = *I2;
913 StateTy St = N2->getState();
914 const ExprValue& V2 = GetValue(St, B->getRHS());
915
916 switch (B->getOpcode()) {
917 case BinaryOperator::Add: {
918 const RValue& R1 = cast<RValue>(V1);
919 const RValue& R2 = cast<RValue>(V2);
920
Ted Kremenek874d63f2008-01-24 02:02:54 +0000921 Nodify(Dst, B, N2, SetValue(St, B, R1.EvalAdd(ValMgr, R2)));
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000922 break;
923 }
924
925 case BinaryOperator::Sub: {
926 const RValue& R1 = cast<RValue>(V1);
927 const RValue& R2 = cast<RValue>(V2);
Ted Kremenek874d63f2008-01-24 02:02:54 +0000928 Nodify(Dst, B, N2, SetValue(St, B, R1.EvalSub(ValMgr, R2)));
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000929 break;
930 }
931
Ted Kremenek2eafd0e2008-01-23 23:42:27 +0000932 case BinaryOperator::Mul: {
933 const RValue& R1 = cast<RValue>(V1);
934 const RValue& R2 = cast<RValue>(V2);
Ted Kremenek874d63f2008-01-24 02:02:54 +0000935 Nodify(Dst, B, N2, SetValue(St, B, R1.EvalMul(ValMgr, R2)));
Ted Kremenek2eafd0e2008-01-23 23:42:27 +0000936 break;
937 }
938
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000939 case BinaryOperator::Assign: {
940 const LValue& L1 = cast<LValue>(V1);
941 const RValue& R2 = cast<RValue>(V2);
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000942 Nodify(Dst, B, N2, SetValue(SetValue(St, B, R2), L1, R2));
943 break;
944 }
Ted Kremenekb4ae33f2008-01-23 23:38:00 +0000945
946 case BinaryOperator::AddAssign: {
947 const LValue& L1 = cast<LValue>(V1);
948 RValue R1 = cast<RValue>(GetValue(N1->getState(), L1));
Ted Kremenek874d63f2008-01-24 02:02:54 +0000949 RValue Result = R1.EvalAdd(ValMgr, cast<RValue>(V2));
Ted Kremenekb4ae33f2008-01-23 23:38:00 +0000950 Nodify(Dst, B, N2, SetValue(SetValue(St, B, Result), L1, Result));
951 break;
952 }
953
954 case BinaryOperator::SubAssign: {
955 const LValue& L1 = cast<LValue>(V1);
956 RValue R1 = cast<RValue>(GetValue(N1->getState(), L1));
Ted Kremenek874d63f2008-01-24 02:02:54 +0000957 RValue Result = R1.EvalSub(ValMgr, cast<RValue>(V2));
Ted Kremenekb4ae33f2008-01-23 23:38:00 +0000958 Nodify(Dst, B, N2, SetValue(SetValue(St, B, Result), L1, Result));
959 break;
960 }
Ted Kremenek2eafd0e2008-01-23 23:42:27 +0000961
962 case BinaryOperator::MulAssign: {
963 const LValue& L1 = cast<LValue>(V1);
964 RValue R1 = cast<RValue>(GetValue(N1->getState(), L1));
Ted Kremenek874d63f2008-01-24 02:02:54 +0000965 RValue Result = R1.EvalMul(ValMgr, cast<RValue>(V2));
Ted Kremenek2eafd0e2008-01-23 23:42:27 +0000966 Nodify(Dst, B, N2, SetValue(SetValue(St, B, Result), L1, Result));
967 break;
968 }
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000969
970 default:
971 Dst.Add(N2);
972 break;
973 }
Ted Kremenekcb448ca2008-01-16 00:53:15 +0000974 }
Ted Kremenekd27f8162008-01-15 23:55:06 +0000975 }
Ted Kremenekd27f8162008-01-15 23:55:06 +0000976}
Ted Kremenekee985462008-01-16 18:18:48 +0000977
Ted Kremenek1ccd31c2008-01-16 19:42:59 +0000978
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000979void GRConstants::Visit(Stmt* S, GRConstants::NodeTy* Pred,
980 GRConstants::NodeSet& Dst) {
981
982 // FIXME: add metadata to the CFG so that we can disable
983 // this check when we KNOW that there is no block-level subexpression.
984 // The motivation is that this check requires a hashtable lookup.
985
986 if (S != CurrentStmt && getCFG().isBlkExpr(S)) {
987 Dst.Add(Pred);
988 return;
989 }
990
991 switch (S->getStmtClass()) {
992 case Stmt::BinaryOperatorClass:
Ted Kremenekb4ae33f2008-01-23 23:38:00 +0000993 case Stmt::CompoundAssignOperatorClass:
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000994 VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Dst);
995 break;
996
Ted Kremenek7b8009a2008-01-24 02:28:56 +0000997 case Stmt::UnaryOperatorClass:
998 VisitUnaryOperator(cast<UnaryOperator>(S), Pred, Dst);
999 break;
1000
Ted Kremenekab2b8c52008-01-23 19:59:44 +00001001 case Stmt::ParenExprClass:
1002 Visit(cast<ParenExpr>(S)->getSubExpr(), Pred, Dst);
1003 break;
1004
Ted Kremenek874d63f2008-01-24 02:02:54 +00001005 case Stmt::ImplicitCastExprClass: {
1006 ImplicitCastExpr* C = cast<ImplicitCastExpr>(S);
1007 VisitCast(C, C->getSubExpr(), Pred, Dst);
1008 break;
1009 }
1010
1011 case Stmt::CastExprClass: {
1012 CastExpr* C = cast<CastExpr>(S);
1013 VisitCast(C, C->getSubExpr(), Pred, Dst);
1014 break;
1015 }
1016
Ted Kremenekab2b8c52008-01-23 19:59:44 +00001017 default:
1018 Dst.Add(Pred); // No-op. Simply propagate the current state unchanged.
1019 break;
Ted Kremenek79649df2008-01-17 18:25:22 +00001020 }
Ted Kremenek1ccd31c2008-01-16 19:42:59 +00001021}
1022
Ted Kremenekee985462008-01-16 18:18:48 +00001023//===----------------------------------------------------------------------===//
1024// Driver.
1025//===----------------------------------------------------------------------===//
1026
Ted Kremenekaa66a322008-01-16 21:46:15 +00001027#ifndef NDEBUG
1028namespace llvm {
1029template<>
1030struct VISIBILITY_HIDDEN DOTGraphTraits<GRConstants::NodeTy*> :
1031 public DefaultDOTGraphTraits {
1032
Ted Kremenek803c9ed2008-01-23 22:30:44 +00001033 static void PrintKind(std::ostringstream& Out, ValueKey::Kind kind) {
1034 switch (kind) {
1035 case ValueKey::IsSubExp: Out << "Sub-Expressions:\\l"; break;
1036 case ValueKey::IsDecl: Out << "Variables:\\l"; break;
1037 case ValueKey::IsBlkExpr: Out << "Block-level Expressions:\\l"; break;
1038 default: assert (false && "Unknown ValueKey type.");
1039 }
1040 }
1041
Ted Kremenekaa66a322008-01-16 21:46:15 +00001042 static std::string getNodeLabel(const GRConstants::NodeTy* N, void*) {
1043 std::ostringstream Out;
Ted Kremenek803c9ed2008-01-23 22:30:44 +00001044
1045 // Program Location.
Ted Kremenekaa66a322008-01-16 21:46:15 +00001046 ProgramPoint Loc = N->getLocation();
1047
1048 switch (Loc.getKind()) {
1049 case ProgramPoint::BlockEntranceKind:
1050 Out << "Block Entrance: B"
1051 << cast<BlockEntrance>(Loc).getBlock()->getBlockID();
1052 break;
1053
1054 case ProgramPoint::BlockExitKind:
1055 assert (false);
1056 break;
1057
1058 case ProgramPoint::PostStmtKind: {
1059 const PostStmt& L = cast<PostStmt>(Loc);
Ted Kremenek803c9ed2008-01-23 22:30:44 +00001060 Out << "(" << (void*) L.getStmt() << ") ";
Ted Kremenekaa66a322008-01-16 21:46:15 +00001061 L.getStmt()->printPretty(Out);
1062 break;
1063 }
1064
1065 default: {
1066 const BlockEdge& E = cast<BlockEdge>(Loc);
1067 Out << "Edge: (B" << E.getSrc()->getBlockID() << ", B"
1068 << E.getDst()->getBlockID() << ')';
1069 }
1070 }
1071
Ted Kremenek803c9ed2008-01-23 22:30:44 +00001072 Out << "\\|";
Ted Kremenekaa66a322008-01-16 21:46:15 +00001073
1074 GRConstants::StateTy M = N->getState();
1075 bool isFirst = true;
Ted Kremenek803c9ed2008-01-23 22:30:44 +00001076 ValueKey::Kind kind;
Ted Kremenekaa66a322008-01-16 21:46:15 +00001077
1078 for (GRConstants::StateTy::iterator I=M.begin(), E=M.end(); I!=E; ++I) {
Ted Kremenek803c9ed2008-01-23 22:30:44 +00001079 if (!isFirst) {
1080 ValueKey::Kind newKind = I.getKey().getKind();
1081
1082 if (newKind != kind) {
1083 Out << "\\l\\l";
1084 PrintKind(Out, newKind);
1085 }
1086 else
1087 Out << "\\l";
1088
1089 kind = newKind;
1090 }
1091 else {
1092 kind = I.getKey().getKind();
1093 PrintKind(Out, kind);
Ted Kremenekaa66a322008-01-16 21:46:15 +00001094 isFirst = false;
Ted Kremenek803c9ed2008-01-23 22:30:44 +00001095 }
1096
1097 Out << ' ';
Ted Kremenekaa66a322008-01-16 21:46:15 +00001098
1099 if (ValueDecl* V = dyn_cast<ValueDecl>(I.getKey())) {
Ted Kremenek803c9ed2008-01-23 22:30:44 +00001100 Out << V->getName();
Ted Kremenekaa66a322008-01-16 21:46:15 +00001101 }
1102 else {
1103 Stmt* E = cast<Stmt>(I.getKey());
Ted Kremenek803c9ed2008-01-23 22:30:44 +00001104 Out << " (" << (void*) E << ") ";
1105 E->printPretty(Out);
Ted Kremenekaa66a322008-01-16 21:46:15 +00001106 }
1107
Ted Kremenek803c9ed2008-01-23 22:30:44 +00001108 Out << " : ";
Ted Kremenekab2b8c52008-01-23 19:59:44 +00001109 I.getData().print(Out);
Ted Kremenekaa66a322008-01-16 21:46:15 +00001110 }
1111
Ted Kremenek803c9ed2008-01-23 22:30:44 +00001112 Out << "\\l";
Ted Kremenekaa66a322008-01-16 21:46:15 +00001113 return Out.str();
1114 }
1115};
1116} // end llvm namespace
1117#endif
1118
Ted Kremenekee985462008-01-16 18:18:48 +00001119namespace clang {
Ted Kremenek874d63f2008-01-24 02:02:54 +00001120void RunGRConstants(CFG& cfg, ASTContext& Ctx) {
1121 GREngine<GRConstants> Engine(cfg, Ctx);
Ted Kremenekee985462008-01-16 18:18:48 +00001122 Engine.ExecuteWorkList();
Ted Kremenekaa66a322008-01-16 21:46:15 +00001123#ifndef NDEBUG
1124 llvm::ViewGraph(*Engine.getGraph().roots_begin(),"GRConstants");
1125#endif
Ted Kremenekee985462008-01-16 18:18:48 +00001126}
Ted Kremenekab2b8c52008-01-23 19:59:44 +00001127} // end clang namespace