blob: 9db8e7f19603c79ff281f27de0610642735596f4 [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
Ted Kremenekdaadf452008-01-24 19:28:01 +0000611 StateTy SetValue(StateTy St, Stmt* S, const ExprValue& V);
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000612
613 StateTy SetValue(StateTy St, const LValue& LV, const ExprValue& V);
Ted Kremenek1ccd31c2008-01-16 19:42:59 +0000614
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000615 ExprValue GetValue(const StateTy& St, Stmt* S);
616 ExprValue GetValue(const StateTy& St, const LValue& LV);
617 LValue GetLValue(const StateTy& St, Stmt* S);
Ted Kremenekd27f8162008-01-15 23:55:06 +0000618
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000619 void Nodify(NodeSet& Dst, Stmt* S, NodeTy* Pred, StateTy St);
Ted Kremenekd27f8162008-01-15 23:55:06 +0000620
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000621 /// Visit - Transfer function logic for all statements. Dispatches to
622 /// other functions that handle specific kinds of statements.
623 void Visit(Stmt* S, NodeTy* Pred, NodeSet& Dst);
Ted Kremenek874d63f2008-01-24 02:02:54 +0000624
625 /// VisitCast - Transfer function logic for all casts (implicit and explicit).
626 void VisitCast(Expr* CastE, Expr* E, NodeTy* Pred, NodeSet& Dst);
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000627
Ted Kremenek7b8009a2008-01-24 02:28:56 +0000628 /// VisitUnaryOperator - Transfer function logic for unary operators.
629 void VisitUnaryOperator(UnaryOperator* B, NodeTy* Pred, NodeSet& Dst);
630
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000631 /// VisitBinaryOperator - Transfer function logic for binary operators.
632 void VisitBinaryOperator(BinaryOperator* B, NodeTy* Pred, NodeSet& Dst);
Ted Kremenekd27f8162008-01-15 23:55:06 +0000633};
634} // end anonymous namespace
635
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000636
Ted Kremenekd27f8162008-01-15 23:55:06 +0000637void GRConstants::ProcessStmt(Stmt* S, NodeBuilder& builder) {
638 Builder = &builder;
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000639
640 StmtEntryNode = builder.getLastNode();
641 CurrentStmt = S;
642 NodeSet Dst;
643 StateCleaned = false;
644
645 Visit(S, StmtEntryNode, Dst);
646
647 // If no nodes were generated, generate a new node that has all the
648 // dead mappings removed.
649 if (Dst.size() == 1 && *Dst.begin() == StmtEntryNode) {
650 StateTy St = RemoveDeadBindings(S, StmtEntryNode->getState());
651 builder.generateNode(S, St, StmtEntryNode);
652 }
Ted Kremenekf84469b2008-01-18 00:41:32 +0000653
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000654 CurrentStmt = NULL;
655 StmtEntryNode = NULL;
656 Builder = NULL;
Ted Kremenekd27f8162008-01-15 23:55:06 +0000657}
658
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000659
660ExprValue GRConstants::GetValue(const StateTy& St, const LValue& LV) {
661 switch (LV.getKind()) {
662 case ExprValue::LValueDeclKind: {
663 StateTy::TreeTy* T = St.SlimFind(cast<LValueDecl>(LV).getDecl());
664 return T ? T->getValue().second : InvalidValue();
665 }
666 default:
667 assert (false && "Invalid LValue.");
Ted Kremenekca3e8572008-01-16 22:28:08 +0000668 break;
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000669 }
670
671 return InvalidValue();
672}
673
674ExprValue GRConstants::GetValue(const StateTy& St, Stmt* S) {
Ted Kremenek671c9e82008-01-24 00:50:08 +0000675 for (;;) {
676 switch (S->getStmtClass()) {
677 case Stmt::ParenExprClass:
678 S = cast<ParenExpr>(S)->getSubExpr();
679 continue;
680
681 case Stmt::DeclRefExprClass:
682 return GetValue(St, LValueDecl(cast<DeclRefExpr>(S)->getDecl()));
Ted Kremenekca3e8572008-01-16 22:28:08 +0000683
Ted Kremenek671c9e82008-01-24 00:50:08 +0000684 case Stmt::IntegerLiteralClass:
Ted Kremenekdacbb4f2008-01-24 08:20:02 +0000685 return RValue::GetRValue(ValMgr, cast<IntegerLiteral>(S));
Ted Kremenek874d63f2008-01-24 02:02:54 +0000686
687 case Stmt::ImplicitCastExprClass: {
688 ImplicitCastExpr* C = cast<ImplicitCastExpr>(S);
689 if (C->getType() == C->getSubExpr()->getType()) {
690 S = C->getSubExpr();
691 continue;
692 }
693 break;
694 }
695
696 case Stmt::CastExprClass: {
697 CastExpr* C = cast<CastExpr>(S);
698 if (C->getType() == C->getSubExpr()->getType()) {
699 S = C->getSubExpr();
700 continue;
701 }
702 break;
703 }
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000704
Ted Kremenek671c9e82008-01-24 00:50:08 +0000705 default:
706 break;
707 };
708
709 break;
710 }
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000711
712 StateTy::TreeTy* T = St.SlimFind(ValueKey(S, getCFG().isBlkExpr(S)));
Ted Kremenek874d63f2008-01-24 02:02:54 +0000713
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000714 return T ? T->getValue().second : InvalidValue();
715}
716
717LValue GRConstants::GetLValue(const StateTy& St, Stmt* S) {
718 if (Expr* E = dyn_cast<Expr>(S))
719 S = E->IgnoreParens();
720
721 if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(S))
722 return LValueDecl(DR->getDecl());
723
724 return cast<LValue>(GetValue(St, S));
725}
726
727GRConstants::StateTy GRConstants::SetValue(StateTy St, Stmt* S,
Ted Kremenekdaadf452008-01-24 19:28:01 +0000728 const ExprValue& V) {
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000729
730 if (!StateCleaned) {
731 St = RemoveDeadBindings(CurrentStmt, St);
732 StateCleaned = true;
733 }
734
Ted Kremenekdaadf452008-01-24 19:28:01 +0000735 bool isBlkExpr = S == CurrentStmt && getCFG().isBlkExpr(S);
736
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000737 return V.isValid() ? StateMgr.Add(St, ValueKey(S,isBlkExpr), V)
738 : St;
739}
740
741GRConstants::StateTy GRConstants::SetValue(StateTy St, const LValue& LV,
742 const ExprValue& V) {
743 if (!LV.isValid())
744 return St;
745
746 if (!StateCleaned) {
747 St = RemoveDeadBindings(CurrentStmt, St);
748 StateCleaned = true;
Ted Kremenekca3e8572008-01-16 22:28:08 +0000749 }
Ted Kremenek0525a4f2008-01-16 19:47:19 +0000750
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000751 switch (LV.getKind()) {
752 case ExprValue::LValueDeclKind:
753 return V.isValid() ? StateMgr.Add(St, cast<LValueDecl>(LV).getDecl(), V)
754 : StateMgr.Remove(St, cast<LValueDecl>(LV).getDecl());
755
756 default:
757 assert ("SetValue for given LValue type not yet implemented.");
758 return St;
759 }
Ted Kremenekd27f8162008-01-15 23:55:06 +0000760}
761
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000762GRConstants::StateTy GRConstants::RemoveDeadBindings(Stmt* Loc, StateTy M) {
Ted Kremenekf84469b2008-01-18 00:41:32 +0000763 // Note: in the code below, we can assign a new map to M since the
764 // iterators are iterating over the tree of the *original* map.
Ted Kremenekf84469b2008-01-18 00:41:32 +0000765 StateTy::iterator I = M.begin(), E = M.end();
766
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000767 // Remove old bindings for subexpressions.
768 for (; I!=E && I.getKey().getKind() == ValueKey::IsSubExp; ++I)
Ted Kremeneke00fe3f2008-01-17 00:52:48 +0000769 M = StateMgr.Remove(M, I.getKey());
Ted Kremenekf84469b2008-01-18 00:41:32 +0000770
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000771 // Remove bindings for "dead" decls.
772 for (; I!=E && I.getKey().getKind() == ValueKey::IsDecl; ++I)
773 if (VarDecl* V = dyn_cast<VarDecl>(cast<ValueDecl>(I.getKey())))
774 if (!Liveness->isLive(Loc, V))
775 M = StateMgr.Remove(M, I.getKey());
776
777 // Remove bindings for "dead" block-level expressions.
778 for (; I!=E; ++I)
779 if (!Liveness->isLive(Loc, cast<Stmt>(I.getKey())))
780 M = StateMgr.Remove(M, I.getKey());
Ted Kremeneke00fe3f2008-01-17 00:52:48 +0000781
782 return M;
Ted Kremeneke00fe3f2008-01-17 00:52:48 +0000783}
784
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000785void GRConstants::Nodify(NodeSet& Dst, Stmt* S, GRConstants::NodeTy* Pred,
786 GRConstants::StateTy St) {
787
788 // If the state hasn't changed, don't generate a new node.
789 if (St == Pred->getState())
790 return;
Ted Kremenekcb448ca2008-01-16 00:53:15 +0000791
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000792 Dst.Add(Builder->generateNode(S, St, Pred));
Ted Kremenekcb448ca2008-01-16 00:53:15 +0000793}
Ted Kremenekd27f8162008-01-15 23:55:06 +0000794
Ted Kremenek874d63f2008-01-24 02:02:54 +0000795void GRConstants::VisitCast(Expr* CastE, Expr* E, GRConstants::NodeTy* Pred,
796 GRConstants::NodeSet& Dst) {
797
798 QualType T = CastE->getType();
799
800 // Check for redundant casts.
801 if (E->getType() == T) {
802 Dst.Add(Pred);
803 return;
804 }
805
806 NodeSet S1;
807 Visit(E, Pred, S1);
808
809 for (NodeSet::iterator I1=S1.begin(), E1=S1.end(); I1 != E1; ++I1) {
810 NodeTy* N = *I1;
811 StateTy St = N->getState();
812 const ExprValue& V = GetValue(St, E);
813 Nodify(Dst, CastE, N, SetValue(St, CastE, V.EvalCast(ValMgr, CastE)));
814 }
815 }
816
Ted Kremenek7b8009a2008-01-24 02:28:56 +0000817void GRConstants::VisitUnaryOperator(UnaryOperator* U,
818 GRConstants::NodeTy* Pred,
819 GRConstants::NodeSet& Dst) {
820 NodeSet S1;
821 Visit(U->getSubExpr(), Pred, S1);
822
823 for (NodeSet::iterator I1=S1.begin(), E1=S1.end(); I1 != E1; ++I1) {
824 NodeTy* N1 = *I1;
825 StateTy St = N1->getState();
826
827 switch (U->getOpcode()) {
828 case UnaryOperator::PostInc: {
829 const LValue& L1 = GetLValue(St, U->getSubExpr());
830 RValue R1 = cast<RValue>(GetValue(St, L1));
831
832 QualType T = U->getType();
Ted Kremeneke0cf9c82008-01-24 19:00:57 +0000833 unsigned bits = getContext()->getTypeSize(T, U->getLocStart());
834 llvm::APSInt One(llvm::APInt(bits, 1), T->isUnsignedIntegerType());
835 RValue R2 = RValue::GetRValue(ValMgr, One);
836
Ted Kremenek7b8009a2008-01-24 02:28:56 +0000837 RValue Result = R1.EvalAdd(ValMgr, R2);
838 Nodify(Dst, U, N1, SetValue(SetValue(St, U, R1), L1, Result));
839 break;
840 }
841
842 case UnaryOperator::PostDec: {
843 const LValue& L1 = GetLValue(St, U->getSubExpr());
844 RValue R1 = cast<RValue>(GetValue(St, L1));
845
846 QualType T = U->getType();
Ted Kremeneke0cf9c82008-01-24 19:00:57 +0000847 unsigned bits = getContext()->getTypeSize(T, U->getLocStart());
848 llvm::APSInt One(llvm::APInt(bits, 1), T->isUnsignedIntegerType());
849 RValue R2 = RValue::GetRValue(ValMgr, One);
Ted Kremenek7b8009a2008-01-24 02:28:56 +0000850
851 RValue Result = R1.EvalSub(ValMgr, R2);
852 Nodify(Dst, U, N1, SetValue(SetValue(St, U, R1), L1, Result));
853 break;
854 }
855
856 case UnaryOperator::PreInc: {
857 const LValue& L1 = GetLValue(St, U->getSubExpr());
858 RValue R1 = cast<RValue>(GetValue(St, L1));
859
860 QualType T = U->getType();
Ted Kremeneke0cf9c82008-01-24 19:00:57 +0000861 unsigned bits = getContext()->getTypeSize(T, U->getLocStart());
862 llvm::APSInt One(llvm::APInt(bits, 1), T->isUnsignedIntegerType());
Ted Kremenek7b8009a2008-01-24 02:28:56 +0000863 RValue R2 = RValue::GetRValue(ValMgr, One);
864
865 RValue Result = R1.EvalAdd(ValMgr, R2);
866 Nodify(Dst, U, N1, SetValue(SetValue(St, U, Result), L1, Result));
867 break;
868 }
869
870 case UnaryOperator::PreDec: {
871 const LValue& L1 = GetLValue(St, U->getSubExpr());
872 RValue R1 = cast<RValue>(GetValue(St, L1));
873
874 QualType T = U->getType();
Ted Kremeneke0cf9c82008-01-24 19:00:57 +0000875 unsigned bits = getContext()->getTypeSize(T, U->getLocStart());
876 llvm::APSInt One(llvm::APInt(bits, 1), T->isUnsignedIntegerType());
877 RValue R2 = RValue::GetRValue(ValMgr, One);
Ted Kremenek7b8009a2008-01-24 02:28:56 +0000878
879 RValue Result = R1.EvalSub(ValMgr, R2);
880 Nodify(Dst, U, N1, SetValue(SetValue(St, U, Result), L1, Result));
881 break;
882 }
883
Ted Kremenekdacbb4f2008-01-24 08:20:02 +0000884 case UnaryOperator::Minus: {
885 const RValue& R1 = cast<RValue>(GetValue(St, U->getSubExpr()));
886 Nodify(Dst, U, N1, SetValue(St, U, R1.EvalMinus(ValMgr, U)));
887 break;
888 }
889
Ted Kremenek7b8009a2008-01-24 02:28:56 +0000890 default: ;
891 assert (false && "Not implemented.");
892 }
893 }
894}
895
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000896void GRConstants::VisitBinaryOperator(BinaryOperator* B,
897 GRConstants::NodeTy* Pred,
898 GRConstants::NodeSet& Dst) {
899 NodeSet S1;
900 Visit(B->getLHS(), Pred, S1);
Ted Kremenekcb448ca2008-01-16 00:53:15 +0000901
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000902 for (NodeSet::iterator I1=S1.begin(), E1=S1.end(); I1 != E1; ++I1) {
903 NodeTy* N1 = *I1;
Ted Kremeneke00fe3f2008-01-17 00:52:48 +0000904
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000905 // When getting the value for the LHS, check if we are in an assignment.
906 // In such cases, we want to (initially) treat the LHS as an LValue,
907 // so we use GetLValue instead of GetValue so that DeclRefExpr's are
908 // evaluated to LValueDecl's instead of to an RValue.
909 const ExprValue& V1 =
910 B->isAssignmentOp() ? GetLValue(N1->getState(), B->getLHS())
911 : GetValue(N1->getState(), B->getLHS());
Ted Kremenekcb448ca2008-01-16 00:53:15 +0000912
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000913 NodeSet S2;
914 Visit(B->getRHS(), N1, S2);
915
916 for (NodeSet::iterator I2=S2.begin(), E2=S2.end(); I2 != E2; ++I2) {
917 NodeTy* N2 = *I2;
918 StateTy St = N2->getState();
919 const ExprValue& V2 = GetValue(St, B->getRHS());
920
921 switch (B->getOpcode()) {
922 case BinaryOperator::Add: {
923 const RValue& R1 = cast<RValue>(V1);
924 const RValue& R2 = cast<RValue>(V2);
925
Ted Kremenek874d63f2008-01-24 02:02:54 +0000926 Nodify(Dst, B, N2, SetValue(St, B, R1.EvalAdd(ValMgr, R2)));
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000927 break;
928 }
929
930 case BinaryOperator::Sub: {
931 const RValue& R1 = cast<RValue>(V1);
932 const RValue& R2 = cast<RValue>(V2);
Ted Kremenek874d63f2008-01-24 02:02:54 +0000933 Nodify(Dst, B, N2, SetValue(St, B, R1.EvalSub(ValMgr, R2)));
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000934 break;
935 }
936
Ted Kremenek2eafd0e2008-01-23 23:42:27 +0000937 case BinaryOperator::Mul: {
938 const RValue& R1 = cast<RValue>(V1);
939 const RValue& R2 = cast<RValue>(V2);
Ted Kremenek874d63f2008-01-24 02:02:54 +0000940 Nodify(Dst, B, N2, SetValue(St, B, R1.EvalMul(ValMgr, R2)));
Ted Kremenek2eafd0e2008-01-23 23:42:27 +0000941 break;
942 }
943
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000944 case BinaryOperator::Assign: {
945 const LValue& L1 = cast<LValue>(V1);
946 const RValue& R2 = cast<RValue>(V2);
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000947 Nodify(Dst, B, N2, SetValue(SetValue(St, B, R2), L1, R2));
948 break;
949 }
Ted Kremenekb4ae33f2008-01-23 23:38:00 +0000950
951 case BinaryOperator::AddAssign: {
952 const LValue& L1 = cast<LValue>(V1);
953 RValue R1 = cast<RValue>(GetValue(N1->getState(), L1));
Ted Kremenek874d63f2008-01-24 02:02:54 +0000954 RValue Result = R1.EvalAdd(ValMgr, cast<RValue>(V2));
Ted Kremenekb4ae33f2008-01-23 23:38:00 +0000955 Nodify(Dst, B, N2, SetValue(SetValue(St, B, Result), L1, Result));
956 break;
957 }
958
959 case BinaryOperator::SubAssign: {
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.EvalSub(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 }
Ted Kremenek2eafd0e2008-01-23 23:42:27 +0000966
967 case BinaryOperator::MulAssign: {
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.EvalMul(ValMgr, cast<RValue>(V2));
Ted Kremenek2eafd0e2008-01-23 23:42:27 +0000971 Nodify(Dst, B, N2, SetValue(SetValue(St, B, Result), L1, Result));
972 break;
973 }
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000974
975 default:
976 Dst.Add(N2);
977 break;
978 }
Ted Kremenekcb448ca2008-01-16 00:53:15 +0000979 }
Ted Kremenekd27f8162008-01-15 23:55:06 +0000980 }
Ted Kremenekd27f8162008-01-15 23:55:06 +0000981}
Ted Kremenekee985462008-01-16 18:18:48 +0000982
Ted Kremenek1ccd31c2008-01-16 19:42:59 +0000983
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000984void GRConstants::Visit(Stmt* S, GRConstants::NodeTy* Pred,
985 GRConstants::NodeSet& Dst) {
986
987 // FIXME: add metadata to the CFG so that we can disable
988 // this check when we KNOW that there is no block-level subexpression.
989 // The motivation is that this check requires a hashtable lookup.
990
991 if (S != CurrentStmt && getCFG().isBlkExpr(S)) {
992 Dst.Add(Pred);
993 return;
994 }
995
996 switch (S->getStmtClass()) {
997 case Stmt::BinaryOperatorClass:
Ted Kremenekb4ae33f2008-01-23 23:38:00 +0000998 case Stmt::CompoundAssignOperatorClass:
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000999 VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Dst);
1000 break;
1001
Ted Kremenek7b8009a2008-01-24 02:28:56 +00001002 case Stmt::UnaryOperatorClass:
1003 VisitUnaryOperator(cast<UnaryOperator>(S), Pred, Dst);
1004 break;
1005
Ted Kremenekab2b8c52008-01-23 19:59:44 +00001006 case Stmt::ParenExprClass:
1007 Visit(cast<ParenExpr>(S)->getSubExpr(), Pred, Dst);
1008 break;
1009
Ted Kremenek874d63f2008-01-24 02:02:54 +00001010 case Stmt::ImplicitCastExprClass: {
1011 ImplicitCastExpr* C = cast<ImplicitCastExpr>(S);
1012 VisitCast(C, C->getSubExpr(), Pred, Dst);
1013 break;
1014 }
1015
1016 case Stmt::CastExprClass: {
1017 CastExpr* C = cast<CastExpr>(S);
1018 VisitCast(C, C->getSubExpr(), Pred, Dst);
1019 break;
1020 }
1021
Ted Kremenekab2b8c52008-01-23 19:59:44 +00001022 default:
1023 Dst.Add(Pred); // No-op. Simply propagate the current state unchanged.
1024 break;
Ted Kremenek79649df2008-01-17 18:25:22 +00001025 }
Ted Kremenek1ccd31c2008-01-16 19:42:59 +00001026}
1027
Ted Kremenekee985462008-01-16 18:18:48 +00001028//===----------------------------------------------------------------------===//
1029// Driver.
1030//===----------------------------------------------------------------------===//
1031
Ted Kremenekaa66a322008-01-16 21:46:15 +00001032#ifndef NDEBUG
1033namespace llvm {
1034template<>
1035struct VISIBILITY_HIDDEN DOTGraphTraits<GRConstants::NodeTy*> :
1036 public DefaultDOTGraphTraits {
1037
Ted Kremenek803c9ed2008-01-23 22:30:44 +00001038 static void PrintKind(std::ostringstream& Out, ValueKey::Kind kind) {
1039 switch (kind) {
1040 case ValueKey::IsSubExp: Out << "Sub-Expressions:\\l"; break;
1041 case ValueKey::IsDecl: Out << "Variables:\\l"; break;
1042 case ValueKey::IsBlkExpr: Out << "Block-level Expressions:\\l"; break;
1043 default: assert (false && "Unknown ValueKey type.");
1044 }
1045 }
1046
Ted Kremenekaa66a322008-01-16 21:46:15 +00001047 static std::string getNodeLabel(const GRConstants::NodeTy* N, void*) {
1048 std::ostringstream Out;
Ted Kremenek803c9ed2008-01-23 22:30:44 +00001049
1050 // Program Location.
Ted Kremenekaa66a322008-01-16 21:46:15 +00001051 ProgramPoint Loc = N->getLocation();
1052
1053 switch (Loc.getKind()) {
1054 case ProgramPoint::BlockEntranceKind:
1055 Out << "Block Entrance: B"
1056 << cast<BlockEntrance>(Loc).getBlock()->getBlockID();
1057 break;
1058
1059 case ProgramPoint::BlockExitKind:
1060 assert (false);
1061 break;
1062
1063 case ProgramPoint::PostStmtKind: {
1064 const PostStmt& L = cast<PostStmt>(Loc);
Ted Kremenek803c9ed2008-01-23 22:30:44 +00001065 Out << "(" << (void*) L.getStmt() << ") ";
Ted Kremenekaa66a322008-01-16 21:46:15 +00001066 L.getStmt()->printPretty(Out);
1067 break;
1068 }
1069
1070 default: {
1071 const BlockEdge& E = cast<BlockEdge>(Loc);
1072 Out << "Edge: (B" << E.getSrc()->getBlockID() << ", B"
1073 << E.getDst()->getBlockID() << ')';
1074 }
1075 }
1076
Ted Kremenek803c9ed2008-01-23 22:30:44 +00001077 Out << "\\|";
Ted Kremenekaa66a322008-01-16 21:46:15 +00001078
1079 GRConstants::StateTy M = N->getState();
1080 bool isFirst = true;
Ted Kremenek803c9ed2008-01-23 22:30:44 +00001081 ValueKey::Kind kind;
Ted Kremenekaa66a322008-01-16 21:46:15 +00001082
1083 for (GRConstants::StateTy::iterator I=M.begin(), E=M.end(); I!=E; ++I) {
Ted Kremenek803c9ed2008-01-23 22:30:44 +00001084 if (!isFirst) {
1085 ValueKey::Kind newKind = I.getKey().getKind();
1086
1087 if (newKind != kind) {
1088 Out << "\\l\\l";
1089 PrintKind(Out, newKind);
1090 }
1091 else
1092 Out << "\\l";
1093
1094 kind = newKind;
1095 }
1096 else {
1097 kind = I.getKey().getKind();
1098 PrintKind(Out, kind);
Ted Kremenekaa66a322008-01-16 21:46:15 +00001099 isFirst = false;
Ted Kremenek803c9ed2008-01-23 22:30:44 +00001100 }
1101
1102 Out << ' ';
Ted Kremenekaa66a322008-01-16 21:46:15 +00001103
1104 if (ValueDecl* V = dyn_cast<ValueDecl>(I.getKey())) {
Ted Kremenek803c9ed2008-01-23 22:30:44 +00001105 Out << V->getName();
Ted Kremenekaa66a322008-01-16 21:46:15 +00001106 }
1107 else {
1108 Stmt* E = cast<Stmt>(I.getKey());
Ted Kremenek803c9ed2008-01-23 22:30:44 +00001109 Out << " (" << (void*) E << ") ";
1110 E->printPretty(Out);
Ted Kremenekaa66a322008-01-16 21:46:15 +00001111 }
1112
Ted Kremenek803c9ed2008-01-23 22:30:44 +00001113 Out << " : ";
Ted Kremenekab2b8c52008-01-23 19:59:44 +00001114 I.getData().print(Out);
Ted Kremenekaa66a322008-01-16 21:46:15 +00001115 }
1116
Ted Kremenek803c9ed2008-01-23 22:30:44 +00001117 Out << "\\l";
Ted Kremenekaa66a322008-01-16 21:46:15 +00001118 return Out.str();
1119 }
1120};
1121} // end llvm namespace
1122#endif
1123
Ted Kremenekee985462008-01-16 18:18:48 +00001124namespace clang {
Ted Kremenek874d63f2008-01-24 02:02:54 +00001125void RunGRConstants(CFG& cfg, ASTContext& Ctx) {
1126 GREngine<GRConstants> Engine(cfg, Ctx);
Ted Kremenekee985462008-01-16 18:18:48 +00001127 Engine.ExecuteWorkList();
Ted Kremenekaa66a322008-01-16 21:46:15 +00001128#ifndef NDEBUG
1129 llvm::ViewGraph(*Engine.getGraph().roots_begin(),"GRConstants");
1130#endif
Ted Kremenekee985462008-01-16 18:18:48 +00001131}
Ted Kremenekab2b8c52008-01-23 19:59:44 +00001132} // end clang namespace