blob: 0c827baec75e3d616dc7f2a44657abbcb0a4571c [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 Kremenekab2b8c52008-01-23 19:59:44 +0000215
Ted Kremenek7b8009a2008-01-24 02:28:56 +0000216 static RValue GetRValue(ValueManager& ValMgr, const llvm::APSInt& V);
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000217
218 // Implement isa<T> support.
219 static inline bool classof(const ExprValue* V) {
220 return V->getKind() >= MinRValueKind;
221 }
222};
223
224class VISIBILITY_HIDDEN RValueMayEqualSet : public RValue {
225public:
226 RValueMayEqualSet(const APSIntSetTy& S)
227 : RValue(RValueMayEqualSetKind, S.getRoot()) {}
228
229 APSIntSetTy GetValues() const {
230 return APSIntSetTy(reinterpret_cast<APSIntSetTy::TreeTy*>(getRawPtr()));
231 }
232
Ted Kremenek874d63f2008-01-24 02:02:54 +0000233 RValueMayEqualSet EvalAdd(ValueManager& ValMgr,
234 const RValueMayEqualSet& V) const;
235
236 RValueMayEqualSet EvalSub(ValueManager& ValMgr,
237 const RValueMayEqualSet& V) const;
238
239 RValueMayEqualSet EvalMul(ValueManager& ValMgr,
240 const RValueMayEqualSet& V) const;
241
242 RValueMayEqualSet EvalCast(ValueManager& ValMgr, Expr* CastExpr) const;
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000243
244 // Implement isa<T> support.
245 static inline bool classof(const ExprValue* V) {
246 return V->getKind() == RValueMayEqualSetKind;
247 }
248};
249} // end anonymous namespace
250
251//===----------------------------------------------------------------------===//
Ted Kremenek874d63f2008-01-24 02:02:54 +0000252// Transfer functions: Casts.
253//===----------------------------------------------------------------------===//
254
255ExprValue ExprValue::EvalCast(ValueManager& ValMgr, Expr* CastExpr) const {
256 switch (getKind()) {
257 case RValueMayEqualSetKind:
258 return cast<RValueMayEqualSet>(this)->EvalCast(ValMgr, CastExpr);
259 default:
260 return InvalidValue();
261 }
262}
263
264RValueMayEqualSet
265RValueMayEqualSet::EvalCast(ValueManager& ValMgr, Expr* CastExpr) const {
266 QualType T = CastExpr->getType();
267 assert (T->isIntegerType());
268
269 APSIntSetTy S1 = GetValues();
270 APSIntSetTy S2 = ValMgr.GetEmptyAPSIntSet();
271
272 for (APSIntSetTy::iterator I=S1.begin(), E=S1.end(); I!=E; ++I) {
273 llvm::APSInt X = *I;
274 X.setIsSigned(T->isSignedIntegerType());
275 X.extOrTrunc(ValMgr.getContext()->getTypeSize(T,CastExpr->getLocStart()));
276 S2 = ValMgr.AddToSet(S2, X);
277 }
278
279 return S2;
280}
281
282//===----------------------------------------------------------------------===//
283// Transfer functions: Binary Operations over R-Values.
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000284//===----------------------------------------------------------------------===//
285
286#define RVALUE_DISPATCH_CASE(k1,k2,Op)\
287case ((k1##Kind+(MaxRValueKind-MinRValueKind))+(k2##Kind - MinRValueKind)):\
Ted Kremenek874d63f2008-01-24 02:02:54 +0000288 return cast<k1>(*this).Eval##Op(ValMgr,cast<k2>(RHS));
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000289
290#define RVALUE_DISPATCH(Op)\
291switch (getKind()+(MaxRValueKind-MinRValueKind)+(RHS.getKind()-MinRValueKind)){\
292 RVALUE_DISPATCH_CASE(RValueMayEqualSet,RValueMayEqualSet,Op)\
293 default:\
294 assert (!isValid() || !RHS.isValid() && "Missing case.");\
295 break;\
296}\
297return cast<RValue>(InvalidValue());
298
Ted Kremenek874d63f2008-01-24 02:02:54 +0000299RValue RValue::EvalAdd(ValueManager& ValMgr, const RValue& RHS) const {
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000300 RVALUE_DISPATCH(Add)
301}
302
Ted Kremenek874d63f2008-01-24 02:02:54 +0000303RValue RValue::EvalSub(ValueManager& ValMgr, const RValue& RHS) const {
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000304 RVALUE_DISPATCH(Sub)
305}
306
Ted Kremenek874d63f2008-01-24 02:02:54 +0000307RValue RValue::EvalMul(ValueManager& ValMgr, const RValue& RHS) const {
Ted Kremenek2eafd0e2008-01-23 23:42:27 +0000308 RVALUE_DISPATCH(Mul)
309}
310
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000311#undef RVALUE_DISPATCH_CASE
312#undef RVALUE_DISPATCH
313
314RValueMayEqualSet
Ted Kremenek874d63f2008-01-24 02:02:54 +0000315RValueMayEqualSet::EvalAdd(ValueManager& ValMgr,
316 const RValueMayEqualSet& RHS) const {
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000317
318 APSIntSetTy S1 = GetValues();
319 APSIntSetTy S2 = RHS.GetValues();
320
321 APSIntSetTy M = ValMgr.GetEmptyAPSIntSet();
322
323 for (APSIntSetTy::iterator I1=S1.begin(), E1=S2.end(); I1!=E1; ++I1)
324 for (APSIntSetTy::iterator I2=S2.begin(), E2=S2.end(); I2!=E2; ++I2)
325 M = ValMgr.AddToSet(M, *I1 + *I2);
326
327 return M;
328}
329
330RValueMayEqualSet
Ted Kremenek874d63f2008-01-24 02:02:54 +0000331RValueMayEqualSet::EvalSub(ValueManager& ValMgr,
332 const RValueMayEqualSet& RHS) const {
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000333
334 APSIntSetTy S1 = GetValues();
335 APSIntSetTy S2 = RHS.GetValues();
336
337 APSIntSetTy M = ValMgr.GetEmptyAPSIntSet();
338
339 for (APSIntSetTy::iterator I1=S1.begin(), E1=S2.end(); I1!=E1; ++I1)
340 for (APSIntSetTy::iterator I2=S2.begin(), E2=S2.end(); I2!=E2; ++I2)
341 M = ValMgr.AddToSet(M, *I1 - *I2);
342
343 return M;
344}
345
Ted Kremenek2eafd0e2008-01-23 23:42:27 +0000346RValueMayEqualSet
Ted Kremenek874d63f2008-01-24 02:02:54 +0000347RValueMayEqualSet::EvalMul(ValueManager& ValMgr,
348 const RValueMayEqualSet& RHS) const {
Ted Kremenek2eafd0e2008-01-23 23:42:27 +0000349
350 APSIntSetTy S1 = GetValues();
351 APSIntSetTy S2 = RHS.GetValues();
352
353 APSIntSetTy M = ValMgr.GetEmptyAPSIntSet();
354
355 for (APSIntSetTy::iterator I1=S1.begin(), E1=S2.end(); I1!=E1; ++I1)
356 for (APSIntSetTy::iterator I2=S2.begin(), E2=S2.end(); I2!=E2; ++I2)
357 M = ValMgr.AddToSet(M, *I1 * *I2);
358
359 return M;
360}
361
Ted Kremenek7b8009a2008-01-24 02:28:56 +0000362RValue RValue::GetRValue(ValueManager& ValMgr, const llvm::APSInt& V) {
363 return RValueMayEqualSet(ValMgr.AddToSet(ValMgr.GetEmptyAPSIntSet(), V));
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000364}
365
366//===----------------------------------------------------------------------===//
367// "L-Values".
368//===----------------------------------------------------------------------===//
369
370namespace {
371
372class VISIBILITY_HIDDEN LValue : public ExprValue {
373protected:
374 LValue(Kind k, void* D) : ExprValue(k, D) {}
375
376public:
377 // Implement isa<T> support.
378 static inline bool classof(const ExprValue* V) {
379 return V->getKind() <= MaxLValueKind;
380 }
381};
382
383class VISIBILITY_HIDDEN LValueDecl : public LValue {
384public:
385 LValueDecl(ValueDecl* vd) : LValue(LValueDeclKind,vd) {}
386
387 ValueDecl* getDecl() const {
388 return static_cast<ValueDecl*>(getRawPtr());
389 }
390
391 // Implement isa<T> support.
392 static inline bool classof(const ExprValue* V) {
393 return V->getKind() == LValueDeclKind;
394 }
395};
396} // end anonymous namespace
397
398//===----------------------------------------------------------------------===//
399// Pretty-Printing.
400//===----------------------------------------------------------------------===//
401
402void ExprValue::print(std::ostream& Out) const {
403 switch (getKind()) {
404 case InvalidValueKind:
405 Out << "Invalid"; break;
406
407 case RValueMayEqualSetKind: {
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000408 APSIntSetTy S = cast<RValueMayEqualSet>(this)->GetValues();
Ted Kremenek803c9ed2008-01-23 22:30:44 +0000409 bool first = true;
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000410
Ted Kremenek803c9ed2008-01-23 22:30:44 +0000411 for (APSIntSetTy::iterator I=S.begin(), E=S.end(); I!=E; ++I) {
412 if (first) first = false;
413 else Out << " | ";
414
415 Out << (*I).toString();
416 }
417
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000418 break;
419 }
420
421 default:
422 assert (false && "Pretty-printed not implemented for this ExprValue.");
423 break;
424 }
425}
426
427//===----------------------------------------------------------------------===//
428// ValueMapTy - A ImmutableMap type Stmt*/Decl* to ExprValues.
429//===----------------------------------------------------------------------===//
430
431typedef llvm::ImmutableMap<ValueKey,ExprValue> ValueMapTy;
432
433namespace clang {
434 template<>
435 struct VISIBILITY_HIDDEN GRTrait<ValueMapTy> {
436 static inline void* toPtr(ValueMapTy M) {
437 return reinterpret_cast<void*>(M.getRoot());
438 }
439 static inline ValueMapTy toState(void* P) {
440 return ValueMapTy(static_cast<ValueMapTy::TreeTy*>(P));
441 }
442 };
Ted Kremenekd27f8162008-01-15 23:55:06 +0000443}
444
445//===----------------------------------------------------------------------===//
446// The Checker!
447//===----------------------------------------------------------------------===//
448
449namespace {
Ted Kremenekd27f8162008-01-15 23:55:06 +0000450
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000451class VISIBILITY_HIDDEN GRConstants {
Ted Kremenekd27f8162008-01-15 23:55:06 +0000452
453public:
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000454 typedef ValueMapTy StateTy;
Ted Kremenekd27f8162008-01-15 23:55:06 +0000455 typedef GRNodeBuilder<GRConstants> NodeBuilder;
456 typedef ExplodedNode<StateTy> NodeTy;
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000457
458 class NodeSet {
459 typedef llvm::SmallVector<NodeTy*,3> ImplTy;
460 ImplTy Impl;
461 public:
462
463 NodeSet() {}
464 NodeSet(NodeTy* N) { assert (N && !N->isInfeasible()); Impl.push_back(N); }
465
466 void Add(NodeTy* N) { if (N && !N->isInfeasible()) Impl.push_back(N); }
467
468 typedef ImplTy::iterator iterator;
469 typedef ImplTy::const_iterator const_iterator;
470
471 unsigned size() const { return Impl.size(); }
472
473 iterator begin() { return Impl.begin(); }
474 iterator end() { return Impl.end(); }
475
476 const_iterator begin() const { return Impl.begin(); }
477 const_iterator end() const { return Impl.end(); }
478 };
Ted Kremenekd27f8162008-01-15 23:55:06 +0000479
480protected:
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000481 /// Liveness - live-variables information the ValueDecl* and block-level
482 /// Expr* in the CFG. Used to prune out dead state.
Ted Kremenekd27f8162008-01-15 23:55:06 +0000483 LiveVariables* Liveness;
484
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000485 /// Builder - The current GRNodeBuilder which is used when building the nodes
486 /// for a given statement.
Ted Kremenekd27f8162008-01-15 23:55:06 +0000487 NodeBuilder* Builder;
488
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000489 /// StateMgr - Object that manages the data for all created states.
490 ValueMapTy::Factory StateMgr;
Ted Kremenekd27f8162008-01-15 23:55:06 +0000491
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000492 /// ValueMgr - Object that manages the data for all created ExprValues.
493 ValueManager ValMgr;
494
495 /// cfg - the current CFG.
Ted Kremenekd27f8162008-01-15 23:55:06 +0000496 CFG* cfg;
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000497
498 /// StmtEntryNode - The immediate predecessor node.
499 NodeTy* StmtEntryNode;
500
501 /// CurrentStmt - The current block-level statement.
502 Stmt* CurrentStmt;
503
504 bool StateCleaned;
Ted Kremenekd27f8162008-01-15 23:55:06 +0000505
Ted Kremenek7b8009a2008-01-24 02:28:56 +0000506 ASTContext* getContext() const { return ValMgr.getContext(); }
507
Ted Kremenekd27f8162008-01-15 23:55:06 +0000508public:
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000509 GRConstants() : Liveness(NULL), Builder(NULL), cfg(NULL),
510 StmtEntryNode(NULL), CurrentStmt(NULL) {}
Ted Kremenekd27f8162008-01-15 23:55:06 +0000511
512 ~GRConstants() { delete Liveness; }
513
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000514 /// getCFG - Returns the CFG associated with this analysis.
Ted Kremenekd27f8162008-01-15 23:55:06 +0000515 CFG& getCFG() { assert (cfg); return *cfg; }
516
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000517 /// Initialize - Initialize the checker's state based on the specified
518 /// CFG. This results in liveness information being computed for
519 /// each block-level statement in the CFG.
Ted Kremenek874d63f2008-01-24 02:02:54 +0000520 void Initialize(CFG& c, ASTContext& ctx) {
521 cfg = &c;
522 ValMgr.setContext(&ctx);
Ted Kremenekd27f8162008-01-15 23:55:06 +0000523 Liveness = new LiveVariables(c);
524 Liveness->runOnCFG(c);
Ted Kremenek79649df2008-01-17 18:25:22 +0000525 Liveness->runOnAllBlocks(c, NULL, true);
Ted Kremenekd27f8162008-01-15 23:55:06 +0000526 }
527
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000528 /// getInitialState - Return the initial state used for the root vertex
529 /// in the ExplodedGraph.
Ted Kremenekd27f8162008-01-15 23:55:06 +0000530 StateTy getInitialState() {
Ted Kremenekcb448ca2008-01-16 00:53:15 +0000531 return StateMgr.GetEmptyMap();
Ted Kremenekd27f8162008-01-15 23:55:06 +0000532 }
Ted Kremenekd27f8162008-01-15 23:55:06 +0000533
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000534 /// ProcessStmt - Called by GREngine. Used to generate new successor
535 /// nodes by processing the 'effects' of a block-level statement.
536 void ProcessStmt(Stmt* S, NodeBuilder& builder);
537
538 /// RemoveDeadBindings - Return a new state that is the same as 'M' except
539 /// that all subexpression mappings are removed and that any
540 /// block-level expressions that are not live at 'S' also have their
541 /// mappings removed.
542 StateTy RemoveDeadBindings(Stmt* S, StateTy M);
543
544 StateTy SetValue(StateTy St, Stmt* S, const ExprValue& V,
545 bool isBlkExpr = false);
546
547 StateTy SetValue(StateTy St, const LValue& LV, const ExprValue& V);
Ted Kremenek1ccd31c2008-01-16 19:42:59 +0000548
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000549 ExprValue GetValue(const StateTy& St, Stmt* S);
550 ExprValue GetValue(const StateTy& St, const LValue& LV);
551 LValue GetLValue(const StateTy& St, Stmt* S);
Ted Kremenekd27f8162008-01-15 23:55:06 +0000552
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000553 void Nodify(NodeSet& Dst, Stmt* S, NodeTy* Pred, StateTy St);
Ted Kremenekd27f8162008-01-15 23:55:06 +0000554
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000555 /// Visit - Transfer function logic for all statements. Dispatches to
556 /// other functions that handle specific kinds of statements.
557 void Visit(Stmt* S, NodeTy* Pred, NodeSet& Dst);
Ted Kremenek874d63f2008-01-24 02:02:54 +0000558
559 /// VisitCast - Transfer function logic for all casts (implicit and explicit).
560 void VisitCast(Expr* CastE, Expr* E, NodeTy* Pred, NodeSet& Dst);
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000561
Ted Kremenek7b8009a2008-01-24 02:28:56 +0000562 /// VisitUnaryOperator - Transfer function logic for unary operators.
563 void VisitUnaryOperator(UnaryOperator* B, NodeTy* Pred, NodeSet& Dst);
564
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000565 /// VisitBinaryOperator - Transfer function logic for binary operators.
566 void VisitBinaryOperator(BinaryOperator* B, NodeTy* Pred, NodeSet& Dst);
Ted Kremenekd27f8162008-01-15 23:55:06 +0000567};
568} // end anonymous namespace
569
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000570
Ted Kremenekd27f8162008-01-15 23:55:06 +0000571void GRConstants::ProcessStmt(Stmt* S, NodeBuilder& builder) {
572 Builder = &builder;
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000573
574 StmtEntryNode = builder.getLastNode();
575 CurrentStmt = S;
576 NodeSet Dst;
577 StateCleaned = false;
578
579 Visit(S, StmtEntryNode, Dst);
580
581 // If no nodes were generated, generate a new node that has all the
582 // dead mappings removed.
583 if (Dst.size() == 1 && *Dst.begin() == StmtEntryNode) {
584 StateTy St = RemoveDeadBindings(S, StmtEntryNode->getState());
585 builder.generateNode(S, St, StmtEntryNode);
586 }
Ted Kremenekf84469b2008-01-18 00:41:32 +0000587
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000588 CurrentStmt = NULL;
589 StmtEntryNode = NULL;
590 Builder = NULL;
Ted Kremenekd27f8162008-01-15 23:55:06 +0000591}
592
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000593
594ExprValue GRConstants::GetValue(const StateTy& St, const LValue& LV) {
595 switch (LV.getKind()) {
596 case ExprValue::LValueDeclKind: {
597 StateTy::TreeTy* T = St.SlimFind(cast<LValueDecl>(LV).getDecl());
598 return T ? T->getValue().second : InvalidValue();
599 }
600 default:
601 assert (false && "Invalid LValue.");
Ted Kremenekca3e8572008-01-16 22:28:08 +0000602 break;
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000603 }
604
605 return InvalidValue();
606}
607
608ExprValue GRConstants::GetValue(const StateTy& St, Stmt* S) {
Ted Kremenek671c9e82008-01-24 00:50:08 +0000609 for (;;) {
610 switch (S->getStmtClass()) {
611 case Stmt::ParenExprClass:
612 S = cast<ParenExpr>(S)->getSubExpr();
613 continue;
614
615 case Stmt::DeclRefExprClass:
616 return GetValue(St, LValueDecl(cast<DeclRefExpr>(S)->getDecl()));
Ted Kremenekca3e8572008-01-16 22:28:08 +0000617
Ted Kremenek671c9e82008-01-24 00:50:08 +0000618 case Stmt::IntegerLiteralClass:
Ted Kremenek7b8009a2008-01-24 02:28:56 +0000619 return RValue::GetRValue(ValMgr, cast<IntegerLiteral>(S)->getValue());
Ted Kremenek874d63f2008-01-24 02:02:54 +0000620
621 case Stmt::ImplicitCastExprClass: {
622 ImplicitCastExpr* C = cast<ImplicitCastExpr>(S);
623 if (C->getType() == C->getSubExpr()->getType()) {
624 S = C->getSubExpr();
625 continue;
626 }
627 break;
628 }
629
630 case Stmt::CastExprClass: {
631 CastExpr* C = cast<CastExpr>(S);
632 if (C->getType() == C->getSubExpr()->getType()) {
633 S = C->getSubExpr();
634 continue;
635 }
636 break;
637 }
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000638
Ted Kremenek671c9e82008-01-24 00:50:08 +0000639 default:
640 break;
641 };
642
643 break;
644 }
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000645
646 StateTy::TreeTy* T = St.SlimFind(ValueKey(S, getCFG().isBlkExpr(S)));
Ted Kremenek874d63f2008-01-24 02:02:54 +0000647
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000648 return T ? T->getValue().second : InvalidValue();
649}
650
651LValue GRConstants::GetLValue(const StateTy& St, Stmt* S) {
652 if (Expr* E = dyn_cast<Expr>(S))
653 S = E->IgnoreParens();
654
655 if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(S))
656 return LValueDecl(DR->getDecl());
657
658 return cast<LValue>(GetValue(St, S));
659}
660
661GRConstants::StateTy GRConstants::SetValue(StateTy St, Stmt* S,
662 const ExprValue& V, bool isBlkExpr) {
663
664 if (!StateCleaned) {
665 St = RemoveDeadBindings(CurrentStmt, St);
666 StateCleaned = true;
667 }
668
669 return V.isValid() ? StateMgr.Add(St, ValueKey(S,isBlkExpr), V)
670 : St;
671}
672
673GRConstants::StateTy GRConstants::SetValue(StateTy St, const LValue& LV,
674 const ExprValue& V) {
675 if (!LV.isValid())
676 return St;
677
678 if (!StateCleaned) {
679 St = RemoveDeadBindings(CurrentStmt, St);
680 StateCleaned = true;
Ted Kremenekca3e8572008-01-16 22:28:08 +0000681 }
Ted Kremenek0525a4f2008-01-16 19:47:19 +0000682
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000683 switch (LV.getKind()) {
684 case ExprValue::LValueDeclKind:
685 return V.isValid() ? StateMgr.Add(St, cast<LValueDecl>(LV).getDecl(), V)
686 : StateMgr.Remove(St, cast<LValueDecl>(LV).getDecl());
687
688 default:
689 assert ("SetValue for given LValue type not yet implemented.");
690 return St;
691 }
Ted Kremenekd27f8162008-01-15 23:55:06 +0000692}
693
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000694GRConstants::StateTy GRConstants::RemoveDeadBindings(Stmt* Loc, StateTy M) {
Ted Kremenekf84469b2008-01-18 00:41:32 +0000695 // Note: in the code below, we can assign a new map to M since the
696 // iterators are iterating over the tree of the *original* map.
Ted Kremenekf84469b2008-01-18 00:41:32 +0000697 StateTy::iterator I = M.begin(), E = M.end();
698
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000699 // Remove old bindings for subexpressions.
700 for (; I!=E && I.getKey().getKind() == ValueKey::IsSubExp; ++I)
Ted Kremeneke00fe3f2008-01-17 00:52:48 +0000701 M = StateMgr.Remove(M, I.getKey());
Ted Kremenekf84469b2008-01-18 00:41:32 +0000702
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000703 // Remove bindings for "dead" decls.
704 for (; I!=E && I.getKey().getKind() == ValueKey::IsDecl; ++I)
705 if (VarDecl* V = dyn_cast<VarDecl>(cast<ValueDecl>(I.getKey())))
706 if (!Liveness->isLive(Loc, V))
707 M = StateMgr.Remove(M, I.getKey());
708
709 // Remove bindings for "dead" block-level expressions.
710 for (; I!=E; ++I)
711 if (!Liveness->isLive(Loc, cast<Stmt>(I.getKey())))
712 M = StateMgr.Remove(M, I.getKey());
Ted Kremeneke00fe3f2008-01-17 00:52:48 +0000713
714 return M;
Ted Kremeneke00fe3f2008-01-17 00:52:48 +0000715}
716
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000717void GRConstants::Nodify(NodeSet& Dst, Stmt* S, GRConstants::NodeTy* Pred,
718 GRConstants::StateTy St) {
719
720 // If the state hasn't changed, don't generate a new node.
721 if (St == Pred->getState())
722 return;
Ted Kremenekcb448ca2008-01-16 00:53:15 +0000723
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000724 Dst.Add(Builder->generateNode(S, St, Pred));
Ted Kremenekcb448ca2008-01-16 00:53:15 +0000725}
Ted Kremenekd27f8162008-01-15 23:55:06 +0000726
Ted Kremenek874d63f2008-01-24 02:02:54 +0000727void GRConstants::VisitCast(Expr* CastE, Expr* E, GRConstants::NodeTy* Pred,
728 GRConstants::NodeSet& Dst) {
729
730 QualType T = CastE->getType();
731
732 // Check for redundant casts.
733 if (E->getType() == T) {
734 Dst.Add(Pred);
735 return;
736 }
737
738 NodeSet S1;
739 Visit(E, Pred, S1);
740
741 for (NodeSet::iterator I1=S1.begin(), E1=S1.end(); I1 != E1; ++I1) {
742 NodeTy* N = *I1;
743 StateTy St = N->getState();
744 const ExprValue& V = GetValue(St, E);
745 Nodify(Dst, CastE, N, SetValue(St, CastE, V.EvalCast(ValMgr, CastE)));
746 }
747 }
748
Ted Kremenek7b8009a2008-01-24 02:28:56 +0000749void GRConstants::VisitUnaryOperator(UnaryOperator* U,
750 GRConstants::NodeTy* Pred,
751 GRConstants::NodeSet& Dst) {
752 NodeSet S1;
753 Visit(U->getSubExpr(), Pred, S1);
754
755 for (NodeSet::iterator I1=S1.begin(), E1=S1.end(); I1 != E1; ++I1) {
756 NodeTy* N1 = *I1;
757 StateTy St = N1->getState();
758
759 switch (U->getOpcode()) {
760 case UnaryOperator::PostInc: {
761 const LValue& L1 = GetLValue(St, U->getSubExpr());
762 RValue R1 = cast<RValue>(GetValue(St, L1));
763
764 QualType T = U->getType();
765 llvm::APInt One(getContext()->getTypeSize(T,U->getLocStart()), 1);
766 RValue R2 = RValue::GetRValue(ValMgr, One);
767
768 RValue Result = R1.EvalAdd(ValMgr, R2);
769 Nodify(Dst, U, N1, SetValue(SetValue(St, U, R1), L1, Result));
770 break;
771 }
772
773 case UnaryOperator::PostDec: {
774 const LValue& L1 = GetLValue(St, U->getSubExpr());
775 RValue R1 = cast<RValue>(GetValue(St, L1));
776
777 QualType T = U->getType();
778 llvm::APInt One(getContext()->getTypeSize(T,U->getLocStart()), 1);
779 RValue R2 = RValue::GetRValue(ValMgr, One);
780
781 RValue Result = R1.EvalSub(ValMgr, R2);
782 Nodify(Dst, U, N1, SetValue(SetValue(St, U, R1), L1, Result));
783 break;
784 }
785
786 case UnaryOperator::PreInc: {
787 const LValue& L1 = GetLValue(St, U->getSubExpr());
788 RValue R1 = cast<RValue>(GetValue(St, L1));
789
790 QualType T = U->getType();
791 llvm::APInt One(getContext()->getTypeSize(T,U->getLocStart()), 1);
792 RValue R2 = RValue::GetRValue(ValMgr, One);
793
794 RValue Result = R1.EvalAdd(ValMgr, R2);
795 Nodify(Dst, U, N1, SetValue(SetValue(St, U, Result), L1, Result));
796 break;
797 }
798
799 case UnaryOperator::PreDec: {
800 const LValue& L1 = GetLValue(St, U->getSubExpr());
801 RValue R1 = cast<RValue>(GetValue(St, L1));
802
803 QualType T = U->getType();
804 llvm::APInt One(getContext()->getTypeSize(T,U->getLocStart()), 1);
805 RValue R2 = RValue::GetRValue(ValMgr, One);
806
807 RValue Result = R1.EvalSub(ValMgr, R2);
808 Nodify(Dst, U, N1, SetValue(SetValue(St, U, Result), L1, Result));
809 break;
810 }
811
812 default: ;
813 assert (false && "Not implemented.");
814 }
815 }
816}
817
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000818void GRConstants::VisitBinaryOperator(BinaryOperator* B,
819 GRConstants::NodeTy* Pred,
820 GRConstants::NodeSet& Dst) {
821 NodeSet S1;
822 Visit(B->getLHS(), Pred, S1);
Ted Kremenekcb448ca2008-01-16 00:53:15 +0000823
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000824 for (NodeSet::iterator I1=S1.begin(), E1=S1.end(); I1 != E1; ++I1) {
825 NodeTy* N1 = *I1;
Ted Kremeneke00fe3f2008-01-17 00:52:48 +0000826
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000827 // When getting the value for the LHS, check if we are in an assignment.
828 // In such cases, we want to (initially) treat the LHS as an LValue,
829 // so we use GetLValue instead of GetValue so that DeclRefExpr's are
830 // evaluated to LValueDecl's instead of to an RValue.
831 const ExprValue& V1 =
832 B->isAssignmentOp() ? GetLValue(N1->getState(), B->getLHS())
833 : GetValue(N1->getState(), B->getLHS());
Ted Kremenekcb448ca2008-01-16 00:53:15 +0000834
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000835 NodeSet S2;
836 Visit(B->getRHS(), N1, S2);
837
838 for (NodeSet::iterator I2=S2.begin(), E2=S2.end(); I2 != E2; ++I2) {
839 NodeTy* N2 = *I2;
840 StateTy St = N2->getState();
841 const ExprValue& V2 = GetValue(St, B->getRHS());
842
843 switch (B->getOpcode()) {
844 case BinaryOperator::Add: {
845 const RValue& R1 = cast<RValue>(V1);
846 const RValue& R2 = cast<RValue>(V2);
847
Ted Kremenek874d63f2008-01-24 02:02:54 +0000848 Nodify(Dst, B, N2, SetValue(St, B, R1.EvalAdd(ValMgr, R2)));
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000849 break;
850 }
851
852 case BinaryOperator::Sub: {
853 const RValue& R1 = cast<RValue>(V1);
854 const RValue& R2 = cast<RValue>(V2);
Ted Kremenek874d63f2008-01-24 02:02:54 +0000855 Nodify(Dst, B, N2, SetValue(St, B, R1.EvalSub(ValMgr, R2)));
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000856 break;
857 }
858
Ted Kremenek2eafd0e2008-01-23 23:42:27 +0000859 case BinaryOperator::Mul: {
860 const RValue& R1 = cast<RValue>(V1);
861 const RValue& R2 = cast<RValue>(V2);
Ted Kremenek874d63f2008-01-24 02:02:54 +0000862 Nodify(Dst, B, N2, SetValue(St, B, R1.EvalMul(ValMgr, R2)));
Ted Kremenek2eafd0e2008-01-23 23:42:27 +0000863 break;
864 }
865
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000866 case BinaryOperator::Assign: {
867 const LValue& L1 = cast<LValue>(V1);
868 const RValue& R2 = cast<RValue>(V2);
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000869 Nodify(Dst, B, N2, SetValue(SetValue(St, B, R2), L1, R2));
870 break;
871 }
Ted Kremenekb4ae33f2008-01-23 23:38:00 +0000872
873 case BinaryOperator::AddAssign: {
874 const LValue& L1 = cast<LValue>(V1);
875 RValue R1 = cast<RValue>(GetValue(N1->getState(), L1));
Ted Kremenek874d63f2008-01-24 02:02:54 +0000876 RValue Result = R1.EvalAdd(ValMgr, cast<RValue>(V2));
Ted Kremenekb4ae33f2008-01-23 23:38:00 +0000877 Nodify(Dst, B, N2, SetValue(SetValue(St, B, Result), L1, Result));
878 break;
879 }
880
881 case BinaryOperator::SubAssign: {
882 const LValue& L1 = cast<LValue>(V1);
883 RValue R1 = cast<RValue>(GetValue(N1->getState(), L1));
Ted Kremenek874d63f2008-01-24 02:02:54 +0000884 RValue Result = R1.EvalSub(ValMgr, cast<RValue>(V2));
Ted Kremenekb4ae33f2008-01-23 23:38:00 +0000885 Nodify(Dst, B, N2, SetValue(SetValue(St, B, Result), L1, Result));
886 break;
887 }
Ted Kremenek2eafd0e2008-01-23 23:42:27 +0000888
889 case BinaryOperator::MulAssign: {
890 const LValue& L1 = cast<LValue>(V1);
891 RValue R1 = cast<RValue>(GetValue(N1->getState(), L1));
Ted Kremenek874d63f2008-01-24 02:02:54 +0000892 RValue Result = R1.EvalMul(ValMgr, cast<RValue>(V2));
Ted Kremenek2eafd0e2008-01-23 23:42:27 +0000893 Nodify(Dst, B, N2, SetValue(SetValue(St, B, Result), L1, Result));
894 break;
895 }
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000896
897 default:
898 Dst.Add(N2);
899 break;
900 }
Ted Kremenekcb448ca2008-01-16 00:53:15 +0000901 }
Ted Kremenekd27f8162008-01-15 23:55:06 +0000902 }
Ted Kremenekd27f8162008-01-15 23:55:06 +0000903}
Ted Kremenekee985462008-01-16 18:18:48 +0000904
Ted Kremenek1ccd31c2008-01-16 19:42:59 +0000905
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000906void GRConstants::Visit(Stmt* S, GRConstants::NodeTy* Pred,
907 GRConstants::NodeSet& Dst) {
908
909 // FIXME: add metadata to the CFG so that we can disable
910 // this check when we KNOW that there is no block-level subexpression.
911 // The motivation is that this check requires a hashtable lookup.
912
913 if (S != CurrentStmt && getCFG().isBlkExpr(S)) {
914 Dst.Add(Pred);
915 return;
916 }
917
918 switch (S->getStmtClass()) {
919 case Stmt::BinaryOperatorClass:
Ted Kremenekb4ae33f2008-01-23 23:38:00 +0000920 case Stmt::CompoundAssignOperatorClass:
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000921 VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Dst);
922 break;
923
Ted Kremenek7b8009a2008-01-24 02:28:56 +0000924 case Stmt::UnaryOperatorClass:
925 VisitUnaryOperator(cast<UnaryOperator>(S), Pred, Dst);
926 break;
927
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000928 case Stmt::ParenExprClass:
929 Visit(cast<ParenExpr>(S)->getSubExpr(), Pred, Dst);
930 break;
931
Ted Kremenek874d63f2008-01-24 02:02:54 +0000932 case Stmt::ImplicitCastExprClass: {
933 ImplicitCastExpr* C = cast<ImplicitCastExpr>(S);
934 VisitCast(C, C->getSubExpr(), Pred, Dst);
935 break;
936 }
937
938 case Stmt::CastExprClass: {
939 CastExpr* C = cast<CastExpr>(S);
940 VisitCast(C, C->getSubExpr(), Pred, Dst);
941 break;
942 }
943
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000944 default:
945 Dst.Add(Pred); // No-op. Simply propagate the current state unchanged.
946 break;
Ted Kremenek79649df2008-01-17 18:25:22 +0000947 }
Ted Kremenek1ccd31c2008-01-16 19:42:59 +0000948}
949
Ted Kremenekee985462008-01-16 18:18:48 +0000950//===----------------------------------------------------------------------===//
951// Driver.
952//===----------------------------------------------------------------------===//
953
Ted Kremenekaa66a322008-01-16 21:46:15 +0000954#ifndef NDEBUG
955namespace llvm {
956template<>
957struct VISIBILITY_HIDDEN DOTGraphTraits<GRConstants::NodeTy*> :
958 public DefaultDOTGraphTraits {
959
Ted Kremenek803c9ed2008-01-23 22:30:44 +0000960 static void PrintKind(std::ostringstream& Out, ValueKey::Kind kind) {
961 switch (kind) {
962 case ValueKey::IsSubExp: Out << "Sub-Expressions:\\l"; break;
963 case ValueKey::IsDecl: Out << "Variables:\\l"; break;
964 case ValueKey::IsBlkExpr: Out << "Block-level Expressions:\\l"; break;
965 default: assert (false && "Unknown ValueKey type.");
966 }
967 }
968
Ted Kremenekaa66a322008-01-16 21:46:15 +0000969 static std::string getNodeLabel(const GRConstants::NodeTy* N, void*) {
970 std::ostringstream Out;
Ted Kremenek803c9ed2008-01-23 22:30:44 +0000971
972 // Program Location.
Ted Kremenekaa66a322008-01-16 21:46:15 +0000973 ProgramPoint Loc = N->getLocation();
974
975 switch (Loc.getKind()) {
976 case ProgramPoint::BlockEntranceKind:
977 Out << "Block Entrance: B"
978 << cast<BlockEntrance>(Loc).getBlock()->getBlockID();
979 break;
980
981 case ProgramPoint::BlockExitKind:
982 assert (false);
983 break;
984
985 case ProgramPoint::PostStmtKind: {
986 const PostStmt& L = cast<PostStmt>(Loc);
Ted Kremenek803c9ed2008-01-23 22:30:44 +0000987 Out << "(" << (void*) L.getStmt() << ") ";
Ted Kremenekaa66a322008-01-16 21:46:15 +0000988 L.getStmt()->printPretty(Out);
989 break;
990 }
991
992 default: {
993 const BlockEdge& E = cast<BlockEdge>(Loc);
994 Out << "Edge: (B" << E.getSrc()->getBlockID() << ", B"
995 << E.getDst()->getBlockID() << ')';
996 }
997 }
998
Ted Kremenek803c9ed2008-01-23 22:30:44 +0000999 Out << "\\|";
Ted Kremenekaa66a322008-01-16 21:46:15 +00001000
1001 GRConstants::StateTy M = N->getState();
1002 bool isFirst = true;
Ted Kremenek803c9ed2008-01-23 22:30:44 +00001003 ValueKey::Kind kind;
Ted Kremenekaa66a322008-01-16 21:46:15 +00001004
1005 for (GRConstants::StateTy::iterator I=M.begin(), E=M.end(); I!=E; ++I) {
Ted Kremenek803c9ed2008-01-23 22:30:44 +00001006 if (!isFirst) {
1007 ValueKey::Kind newKind = I.getKey().getKind();
1008
1009 if (newKind != kind) {
1010 Out << "\\l\\l";
1011 PrintKind(Out, newKind);
1012 }
1013 else
1014 Out << "\\l";
1015
1016 kind = newKind;
1017 }
1018 else {
1019 kind = I.getKey().getKind();
1020 PrintKind(Out, kind);
Ted Kremenekaa66a322008-01-16 21:46:15 +00001021 isFirst = false;
Ted Kremenek803c9ed2008-01-23 22:30:44 +00001022 }
1023
1024 Out << ' ';
Ted Kremenekaa66a322008-01-16 21:46:15 +00001025
1026 if (ValueDecl* V = dyn_cast<ValueDecl>(I.getKey())) {
Ted Kremenek803c9ed2008-01-23 22:30:44 +00001027 Out << V->getName();
Ted Kremenekaa66a322008-01-16 21:46:15 +00001028 }
1029 else {
1030 Stmt* E = cast<Stmt>(I.getKey());
Ted Kremenek803c9ed2008-01-23 22:30:44 +00001031 Out << " (" << (void*) E << ") ";
1032 E->printPretty(Out);
Ted Kremenekaa66a322008-01-16 21:46:15 +00001033 }
1034
Ted Kremenek803c9ed2008-01-23 22:30:44 +00001035 Out << " : ";
Ted Kremenekab2b8c52008-01-23 19:59:44 +00001036 I.getData().print(Out);
Ted Kremenekaa66a322008-01-16 21:46:15 +00001037 }
1038
Ted Kremenek803c9ed2008-01-23 22:30:44 +00001039 Out << "\\l";
Ted Kremenekaa66a322008-01-16 21:46:15 +00001040 return Out.str();
1041 }
1042};
1043} // end llvm namespace
1044#endif
1045
Ted Kremenekee985462008-01-16 18:18:48 +00001046namespace clang {
Ted Kremenek874d63f2008-01-24 02:02:54 +00001047void RunGRConstants(CFG& cfg, ASTContext& Ctx) {
1048 GREngine<GRConstants> Engine(cfg, Ctx);
Ted Kremenekee985462008-01-16 18:18:48 +00001049 Engine.ExecuteWorkList();
Ted Kremenekaa66a322008-01-16 21:46:15 +00001050#ifndef NDEBUG
1051 llvm::ViewGraph(*Engine.getGraph().roots_begin(),"GRConstants");
1052#endif
Ted Kremenekee985462008-01-16 18:18:48 +00001053}
Ted Kremenekab2b8c52008-01-23 19:59:44 +00001054} // end clang namespace