blob: 0a9c68a7fe2191762c4df31b7bfb51f3514042ee [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
216 static RValue GetRValue(ValueManager& ValMgr, IntegerLiteral* S);
217
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 Kremenekab2b8c52008-01-23 19:59:44 +0000362RValue RValue::GetRValue(ValueManager& ValMgr, IntegerLiteral* S) {
363 return RValueMayEqualSet(ValMgr.AddToSet(ValMgr.GetEmptyAPSIntSet(),
364 S->getValue()));
365}
366
367//===----------------------------------------------------------------------===//
368// "L-Values".
369//===----------------------------------------------------------------------===//
370
371namespace {
372
373class VISIBILITY_HIDDEN LValue : public ExprValue {
374protected:
375 LValue(Kind k, void* D) : ExprValue(k, D) {}
376
377public:
378 // Implement isa<T> support.
379 static inline bool classof(const ExprValue* V) {
380 return V->getKind() <= MaxLValueKind;
381 }
382};
383
384class VISIBILITY_HIDDEN LValueDecl : public LValue {
385public:
386 LValueDecl(ValueDecl* vd) : LValue(LValueDeclKind,vd) {}
387
388 ValueDecl* getDecl() const {
389 return static_cast<ValueDecl*>(getRawPtr());
390 }
391
392 // Implement isa<T> support.
393 static inline bool classof(const ExprValue* V) {
394 return V->getKind() == LValueDeclKind;
395 }
396};
397} // end anonymous namespace
398
399//===----------------------------------------------------------------------===//
400// Pretty-Printing.
401//===----------------------------------------------------------------------===//
402
403void ExprValue::print(std::ostream& Out) const {
404 switch (getKind()) {
405 case InvalidValueKind:
406 Out << "Invalid"; break;
407
408 case RValueMayEqualSetKind: {
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000409 APSIntSetTy S = cast<RValueMayEqualSet>(this)->GetValues();
Ted Kremenek803c9ed2008-01-23 22:30:44 +0000410 bool first = true;
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000411
Ted Kremenek803c9ed2008-01-23 22:30:44 +0000412 for (APSIntSetTy::iterator I=S.begin(), E=S.end(); I!=E; ++I) {
413 if (first) first = false;
414 else Out << " | ";
415
416 Out << (*I).toString();
417 }
418
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000419 break;
420 }
421
422 default:
423 assert (false && "Pretty-printed not implemented for this ExprValue.");
424 break;
425 }
426}
427
428//===----------------------------------------------------------------------===//
429// ValueMapTy - A ImmutableMap type Stmt*/Decl* to ExprValues.
430//===----------------------------------------------------------------------===//
431
432typedef llvm::ImmutableMap<ValueKey,ExprValue> ValueMapTy;
433
434namespace clang {
435 template<>
436 struct VISIBILITY_HIDDEN GRTrait<ValueMapTy> {
437 static inline void* toPtr(ValueMapTy M) {
438 return reinterpret_cast<void*>(M.getRoot());
439 }
440 static inline ValueMapTy toState(void* P) {
441 return ValueMapTy(static_cast<ValueMapTy::TreeTy*>(P));
442 }
443 };
Ted Kremenekd27f8162008-01-15 23:55:06 +0000444}
445
446//===----------------------------------------------------------------------===//
447// The Checker!
448//===----------------------------------------------------------------------===//
449
450namespace {
Ted Kremenekd27f8162008-01-15 23:55:06 +0000451
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000452class VISIBILITY_HIDDEN GRConstants {
Ted Kremenekd27f8162008-01-15 23:55:06 +0000453
454public:
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000455 typedef ValueMapTy StateTy;
Ted Kremenekd27f8162008-01-15 23:55:06 +0000456 typedef GRNodeBuilder<GRConstants> NodeBuilder;
457 typedef ExplodedNode<StateTy> NodeTy;
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000458
459 class NodeSet {
460 typedef llvm::SmallVector<NodeTy*,3> ImplTy;
461 ImplTy Impl;
462 public:
463
464 NodeSet() {}
465 NodeSet(NodeTy* N) { assert (N && !N->isInfeasible()); Impl.push_back(N); }
466
467 void Add(NodeTy* N) { if (N && !N->isInfeasible()) Impl.push_back(N); }
468
469 typedef ImplTy::iterator iterator;
470 typedef ImplTy::const_iterator const_iterator;
471
472 unsigned size() const { return Impl.size(); }
473
474 iterator begin() { return Impl.begin(); }
475 iterator end() { return Impl.end(); }
476
477 const_iterator begin() const { return Impl.begin(); }
478 const_iterator end() const { return Impl.end(); }
479 };
Ted Kremenekd27f8162008-01-15 23:55:06 +0000480
481protected:
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000482 /// Liveness - live-variables information the ValueDecl* and block-level
483 /// Expr* in the CFG. Used to prune out dead state.
Ted Kremenekd27f8162008-01-15 23:55:06 +0000484 LiveVariables* Liveness;
485
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000486 /// Builder - The current GRNodeBuilder which is used when building the nodes
487 /// for a given statement.
Ted Kremenekd27f8162008-01-15 23:55:06 +0000488 NodeBuilder* Builder;
489
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000490 /// StateMgr - Object that manages the data for all created states.
491 ValueMapTy::Factory StateMgr;
Ted Kremenekd27f8162008-01-15 23:55:06 +0000492
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000493 /// ValueMgr - Object that manages the data for all created ExprValues.
494 ValueManager ValMgr;
495
496 /// cfg - the current CFG.
Ted Kremenekd27f8162008-01-15 23:55:06 +0000497 CFG* cfg;
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000498
499 /// StmtEntryNode - The immediate predecessor node.
500 NodeTy* StmtEntryNode;
501
502 /// CurrentStmt - The current block-level statement.
503 Stmt* CurrentStmt;
504
505 bool StateCleaned;
Ted Kremenekd27f8162008-01-15 23:55:06 +0000506
Ted Kremenekd27f8162008-01-15 23:55:06 +0000507public:
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000508 GRConstants() : Liveness(NULL), Builder(NULL), cfg(NULL),
509 StmtEntryNode(NULL), CurrentStmt(NULL) {}
Ted Kremenekd27f8162008-01-15 23:55:06 +0000510
511 ~GRConstants() { delete Liveness; }
512
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000513 /// getCFG - Returns the CFG associated with this analysis.
Ted Kremenekd27f8162008-01-15 23:55:06 +0000514 CFG& getCFG() { assert (cfg); return *cfg; }
515
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000516 /// Initialize - Initialize the checker's state based on the specified
517 /// CFG. This results in liveness information being computed for
518 /// each block-level statement in the CFG.
Ted Kremenek874d63f2008-01-24 02:02:54 +0000519 void Initialize(CFG& c, ASTContext& ctx) {
520 cfg = &c;
521 ValMgr.setContext(&ctx);
Ted Kremenekd27f8162008-01-15 23:55:06 +0000522 Liveness = new LiveVariables(c);
523 Liveness->runOnCFG(c);
Ted Kremenek79649df2008-01-17 18:25:22 +0000524 Liveness->runOnAllBlocks(c, NULL, true);
Ted Kremenekd27f8162008-01-15 23:55:06 +0000525 }
526
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000527 /// getInitialState - Return the initial state used for the root vertex
528 /// in the ExplodedGraph.
Ted Kremenekd27f8162008-01-15 23:55:06 +0000529 StateTy getInitialState() {
Ted Kremenekcb448ca2008-01-16 00:53:15 +0000530 return StateMgr.GetEmptyMap();
Ted Kremenekd27f8162008-01-15 23:55:06 +0000531 }
Ted Kremenekd27f8162008-01-15 23:55:06 +0000532
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000533 /// ProcessStmt - Called by GREngine. Used to generate new successor
534 /// nodes by processing the 'effects' of a block-level statement.
535 void ProcessStmt(Stmt* S, NodeBuilder& builder);
536
537 /// RemoveDeadBindings - Return a new state that is the same as 'M' except
538 /// that all subexpression mappings are removed and that any
539 /// block-level expressions that are not live at 'S' also have their
540 /// mappings removed.
541 StateTy RemoveDeadBindings(Stmt* S, StateTy M);
542
543 StateTy SetValue(StateTy St, Stmt* S, const ExprValue& V,
544 bool isBlkExpr = false);
545
546 StateTy SetValue(StateTy St, const LValue& LV, const ExprValue& V);
Ted Kremenek1ccd31c2008-01-16 19:42:59 +0000547
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000548 ExprValue GetValue(const StateTy& St, Stmt* S);
549 ExprValue GetValue(const StateTy& St, const LValue& LV);
550 LValue GetLValue(const StateTy& St, Stmt* S);
Ted Kremenekd27f8162008-01-15 23:55:06 +0000551
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000552 void Nodify(NodeSet& Dst, Stmt* S, NodeTy* Pred, StateTy St);
Ted Kremenekd27f8162008-01-15 23:55:06 +0000553
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000554 /// Visit - Transfer function logic for all statements. Dispatches to
555 /// other functions that handle specific kinds of statements.
556 void Visit(Stmt* S, NodeTy* Pred, NodeSet& Dst);
Ted Kremenek874d63f2008-01-24 02:02:54 +0000557
558 /// VisitCast - Transfer function logic for all casts (implicit and explicit).
559 void VisitCast(Expr* CastE, Expr* E, NodeTy* Pred, NodeSet& Dst);
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000560
561 /// VisitBinaryOperator - Transfer function logic for binary operators.
562 void VisitBinaryOperator(BinaryOperator* B, NodeTy* Pred, NodeSet& Dst);
Ted Kremenekd27f8162008-01-15 23:55:06 +0000563};
564} // end anonymous namespace
565
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000566
Ted Kremenekd27f8162008-01-15 23:55:06 +0000567void GRConstants::ProcessStmt(Stmt* S, NodeBuilder& builder) {
568 Builder = &builder;
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000569
570 StmtEntryNode = builder.getLastNode();
571 CurrentStmt = S;
572 NodeSet Dst;
573 StateCleaned = false;
574
575 Visit(S, StmtEntryNode, Dst);
576
577 // If no nodes were generated, generate a new node that has all the
578 // dead mappings removed.
579 if (Dst.size() == 1 && *Dst.begin() == StmtEntryNode) {
580 StateTy St = RemoveDeadBindings(S, StmtEntryNode->getState());
581 builder.generateNode(S, St, StmtEntryNode);
582 }
Ted Kremenekf84469b2008-01-18 00:41:32 +0000583
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000584 CurrentStmt = NULL;
585 StmtEntryNode = NULL;
586 Builder = NULL;
Ted Kremenekd27f8162008-01-15 23:55:06 +0000587}
588
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000589
590ExprValue GRConstants::GetValue(const StateTy& St, const LValue& LV) {
591 switch (LV.getKind()) {
592 case ExprValue::LValueDeclKind: {
593 StateTy::TreeTy* T = St.SlimFind(cast<LValueDecl>(LV).getDecl());
594 return T ? T->getValue().second : InvalidValue();
595 }
596 default:
597 assert (false && "Invalid LValue.");
Ted Kremenekca3e8572008-01-16 22:28:08 +0000598 break;
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000599 }
600
601 return InvalidValue();
602}
603
604ExprValue GRConstants::GetValue(const StateTy& St, Stmt* S) {
Ted Kremenek671c9e82008-01-24 00:50:08 +0000605 for (;;) {
606 switch (S->getStmtClass()) {
607 case Stmt::ParenExprClass:
608 S = cast<ParenExpr>(S)->getSubExpr();
609 continue;
610
611 case Stmt::DeclRefExprClass:
612 return GetValue(St, LValueDecl(cast<DeclRefExpr>(S)->getDecl()));
Ted Kremenekca3e8572008-01-16 22:28:08 +0000613
Ted Kremenek671c9e82008-01-24 00:50:08 +0000614 case Stmt::IntegerLiteralClass:
615 return RValue::GetRValue(ValMgr, cast<IntegerLiteral>(S));
Ted Kremenek874d63f2008-01-24 02:02:54 +0000616
617 case Stmt::ImplicitCastExprClass: {
618 ImplicitCastExpr* C = cast<ImplicitCastExpr>(S);
619 if (C->getType() == C->getSubExpr()->getType()) {
620 S = C->getSubExpr();
621 continue;
622 }
623 break;
624 }
625
626 case Stmt::CastExprClass: {
627 CastExpr* C = cast<CastExpr>(S);
628 if (C->getType() == C->getSubExpr()->getType()) {
629 S = C->getSubExpr();
630 continue;
631 }
632 break;
633 }
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000634
Ted Kremenek671c9e82008-01-24 00:50:08 +0000635 default:
636 break;
637 };
638
639 break;
640 }
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000641
642 StateTy::TreeTy* T = St.SlimFind(ValueKey(S, getCFG().isBlkExpr(S)));
Ted Kremenek874d63f2008-01-24 02:02:54 +0000643
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000644 return T ? T->getValue().second : InvalidValue();
645}
646
647LValue GRConstants::GetLValue(const StateTy& St, Stmt* S) {
648 if (Expr* E = dyn_cast<Expr>(S))
649 S = E->IgnoreParens();
650
651 if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(S))
652 return LValueDecl(DR->getDecl());
653
654 return cast<LValue>(GetValue(St, S));
655}
656
657GRConstants::StateTy GRConstants::SetValue(StateTy St, Stmt* S,
658 const ExprValue& V, bool isBlkExpr) {
659
660 if (!StateCleaned) {
661 St = RemoveDeadBindings(CurrentStmt, St);
662 StateCleaned = true;
663 }
664
665 return V.isValid() ? StateMgr.Add(St, ValueKey(S,isBlkExpr), V)
666 : St;
667}
668
669GRConstants::StateTy GRConstants::SetValue(StateTy St, const LValue& LV,
670 const ExprValue& V) {
671 if (!LV.isValid())
672 return St;
673
674 if (!StateCleaned) {
675 St = RemoveDeadBindings(CurrentStmt, St);
676 StateCleaned = true;
Ted Kremenekca3e8572008-01-16 22:28:08 +0000677 }
Ted Kremenek0525a4f2008-01-16 19:47:19 +0000678
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000679 switch (LV.getKind()) {
680 case ExprValue::LValueDeclKind:
681 return V.isValid() ? StateMgr.Add(St, cast<LValueDecl>(LV).getDecl(), V)
682 : StateMgr.Remove(St, cast<LValueDecl>(LV).getDecl());
683
684 default:
685 assert ("SetValue for given LValue type not yet implemented.");
686 return St;
687 }
Ted Kremenekd27f8162008-01-15 23:55:06 +0000688}
689
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000690GRConstants::StateTy GRConstants::RemoveDeadBindings(Stmt* Loc, StateTy M) {
Ted Kremenekf84469b2008-01-18 00:41:32 +0000691 // Note: in the code below, we can assign a new map to M since the
692 // iterators are iterating over the tree of the *original* map.
Ted Kremenekf84469b2008-01-18 00:41:32 +0000693 StateTy::iterator I = M.begin(), E = M.end();
694
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000695 // Remove old bindings for subexpressions.
696 for (; I!=E && I.getKey().getKind() == ValueKey::IsSubExp; ++I)
Ted Kremeneke00fe3f2008-01-17 00:52:48 +0000697 M = StateMgr.Remove(M, I.getKey());
Ted Kremenekf84469b2008-01-18 00:41:32 +0000698
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000699 // Remove bindings for "dead" decls.
700 for (; I!=E && I.getKey().getKind() == ValueKey::IsDecl; ++I)
701 if (VarDecl* V = dyn_cast<VarDecl>(cast<ValueDecl>(I.getKey())))
702 if (!Liveness->isLive(Loc, V))
703 M = StateMgr.Remove(M, I.getKey());
704
705 // Remove bindings for "dead" block-level expressions.
706 for (; I!=E; ++I)
707 if (!Liveness->isLive(Loc, cast<Stmt>(I.getKey())))
708 M = StateMgr.Remove(M, I.getKey());
Ted Kremeneke00fe3f2008-01-17 00:52:48 +0000709
710 return M;
Ted Kremeneke00fe3f2008-01-17 00:52:48 +0000711}
712
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000713void GRConstants::Nodify(NodeSet& Dst, Stmt* S, GRConstants::NodeTy* Pred,
714 GRConstants::StateTy St) {
715
716 // If the state hasn't changed, don't generate a new node.
717 if (St == Pred->getState())
718 return;
Ted Kremenekcb448ca2008-01-16 00:53:15 +0000719
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000720 Dst.Add(Builder->generateNode(S, St, Pred));
Ted Kremenekcb448ca2008-01-16 00:53:15 +0000721}
Ted Kremenekd27f8162008-01-15 23:55:06 +0000722
Ted Kremenek874d63f2008-01-24 02:02:54 +0000723void GRConstants::VisitCast(Expr* CastE, Expr* E, GRConstants::NodeTy* Pred,
724 GRConstants::NodeSet& Dst) {
725
726 QualType T = CastE->getType();
727
728 // Check for redundant casts.
729 if (E->getType() == T) {
730 Dst.Add(Pred);
731 return;
732 }
733
734 NodeSet S1;
735 Visit(E, Pred, S1);
736
737 for (NodeSet::iterator I1=S1.begin(), E1=S1.end(); I1 != E1; ++I1) {
738 NodeTy* N = *I1;
739 StateTy St = N->getState();
740 const ExprValue& V = GetValue(St, E);
741 Nodify(Dst, CastE, N, SetValue(St, CastE, V.EvalCast(ValMgr, CastE)));
742 }
743 }
744
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000745void GRConstants::VisitBinaryOperator(BinaryOperator* B,
746 GRConstants::NodeTy* Pred,
747 GRConstants::NodeSet& Dst) {
748 NodeSet S1;
749 Visit(B->getLHS(), Pred, S1);
Ted Kremenekcb448ca2008-01-16 00:53:15 +0000750
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000751 for (NodeSet::iterator I1=S1.begin(), E1=S1.end(); I1 != E1; ++I1) {
752 NodeTy* N1 = *I1;
Ted Kremeneke00fe3f2008-01-17 00:52:48 +0000753
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000754 // When getting the value for the LHS, check if we are in an assignment.
755 // In such cases, we want to (initially) treat the LHS as an LValue,
756 // so we use GetLValue instead of GetValue so that DeclRefExpr's are
757 // evaluated to LValueDecl's instead of to an RValue.
758 const ExprValue& V1 =
759 B->isAssignmentOp() ? GetLValue(N1->getState(), B->getLHS())
760 : GetValue(N1->getState(), B->getLHS());
Ted Kremenekcb448ca2008-01-16 00:53:15 +0000761
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000762 NodeSet S2;
763 Visit(B->getRHS(), N1, S2);
764
765 for (NodeSet::iterator I2=S2.begin(), E2=S2.end(); I2 != E2; ++I2) {
766 NodeTy* N2 = *I2;
767 StateTy St = N2->getState();
768 const ExprValue& V2 = GetValue(St, B->getRHS());
769
770 switch (B->getOpcode()) {
771 case BinaryOperator::Add: {
772 const RValue& R1 = cast<RValue>(V1);
773 const RValue& R2 = cast<RValue>(V2);
774
Ted Kremenek874d63f2008-01-24 02:02:54 +0000775 Nodify(Dst, B, N2, SetValue(St, B, R1.EvalAdd(ValMgr, R2)));
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000776 break;
777 }
778
779 case BinaryOperator::Sub: {
780 const RValue& R1 = cast<RValue>(V1);
781 const RValue& R2 = cast<RValue>(V2);
Ted Kremenek874d63f2008-01-24 02:02:54 +0000782 Nodify(Dst, B, N2, SetValue(St, B, R1.EvalSub(ValMgr, R2)));
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000783 break;
784 }
785
Ted Kremenek2eafd0e2008-01-23 23:42:27 +0000786 case BinaryOperator::Mul: {
787 const RValue& R1 = cast<RValue>(V1);
788 const RValue& R2 = cast<RValue>(V2);
Ted Kremenek874d63f2008-01-24 02:02:54 +0000789 Nodify(Dst, B, N2, SetValue(St, B, R1.EvalMul(ValMgr, R2)));
Ted Kremenek2eafd0e2008-01-23 23:42:27 +0000790 break;
791 }
792
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000793 case BinaryOperator::Assign: {
794 const LValue& L1 = cast<LValue>(V1);
795 const RValue& R2 = cast<RValue>(V2);
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000796 Nodify(Dst, B, N2, SetValue(SetValue(St, B, R2), L1, R2));
797 break;
798 }
Ted Kremenekb4ae33f2008-01-23 23:38:00 +0000799
800 case BinaryOperator::AddAssign: {
801 const LValue& L1 = cast<LValue>(V1);
802 RValue R1 = cast<RValue>(GetValue(N1->getState(), L1));
Ted Kremenek874d63f2008-01-24 02:02:54 +0000803 RValue Result = R1.EvalAdd(ValMgr, cast<RValue>(V2));
Ted Kremenekb4ae33f2008-01-23 23:38:00 +0000804 Nodify(Dst, B, N2, SetValue(SetValue(St, B, Result), L1, Result));
805 break;
806 }
807
808 case BinaryOperator::SubAssign: {
809 const LValue& L1 = cast<LValue>(V1);
810 RValue R1 = cast<RValue>(GetValue(N1->getState(), L1));
Ted Kremenek874d63f2008-01-24 02:02:54 +0000811 RValue Result = R1.EvalSub(ValMgr, cast<RValue>(V2));
Ted Kremenekb4ae33f2008-01-23 23:38:00 +0000812 Nodify(Dst, B, N2, SetValue(SetValue(St, B, Result), L1, Result));
813 break;
814 }
Ted Kremenek2eafd0e2008-01-23 23:42:27 +0000815
816 case BinaryOperator::MulAssign: {
817 const LValue& L1 = cast<LValue>(V1);
818 RValue R1 = cast<RValue>(GetValue(N1->getState(), L1));
Ted Kremenek874d63f2008-01-24 02:02:54 +0000819 RValue Result = R1.EvalMul(ValMgr, cast<RValue>(V2));
Ted Kremenek2eafd0e2008-01-23 23:42:27 +0000820 Nodify(Dst, B, N2, SetValue(SetValue(St, B, Result), L1, Result));
821 break;
822 }
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000823
824 default:
825 Dst.Add(N2);
826 break;
827 }
Ted Kremenekcb448ca2008-01-16 00:53:15 +0000828 }
Ted Kremenekd27f8162008-01-15 23:55:06 +0000829 }
Ted Kremenekd27f8162008-01-15 23:55:06 +0000830}
Ted Kremenekee985462008-01-16 18:18:48 +0000831
Ted Kremenek1ccd31c2008-01-16 19:42:59 +0000832
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000833void GRConstants::Visit(Stmt* S, GRConstants::NodeTy* Pred,
834 GRConstants::NodeSet& Dst) {
835
836 // FIXME: add metadata to the CFG so that we can disable
837 // this check when we KNOW that there is no block-level subexpression.
838 // The motivation is that this check requires a hashtable lookup.
839
840 if (S != CurrentStmt && getCFG().isBlkExpr(S)) {
841 Dst.Add(Pred);
842 return;
843 }
844
845 switch (S->getStmtClass()) {
846 case Stmt::BinaryOperatorClass:
Ted Kremenekb4ae33f2008-01-23 23:38:00 +0000847 case Stmt::CompoundAssignOperatorClass:
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000848 VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Dst);
849 break;
850
851 case Stmt::ParenExprClass:
852 Visit(cast<ParenExpr>(S)->getSubExpr(), Pred, Dst);
853 break;
854
Ted Kremenek874d63f2008-01-24 02:02:54 +0000855 case Stmt::ImplicitCastExprClass: {
856 ImplicitCastExpr* C = cast<ImplicitCastExpr>(S);
857 VisitCast(C, C->getSubExpr(), Pred, Dst);
858 break;
859 }
860
861 case Stmt::CastExprClass: {
862 CastExpr* C = cast<CastExpr>(S);
863 VisitCast(C, C->getSubExpr(), Pred, Dst);
864 break;
865 }
866
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000867 default:
868 Dst.Add(Pred); // No-op. Simply propagate the current state unchanged.
869 break;
Ted Kremenek79649df2008-01-17 18:25:22 +0000870 }
Ted Kremenek1ccd31c2008-01-16 19:42:59 +0000871}
872
Ted Kremenekee985462008-01-16 18:18:48 +0000873//===----------------------------------------------------------------------===//
874// Driver.
875//===----------------------------------------------------------------------===//
876
Ted Kremenekaa66a322008-01-16 21:46:15 +0000877#ifndef NDEBUG
878namespace llvm {
879template<>
880struct VISIBILITY_HIDDEN DOTGraphTraits<GRConstants::NodeTy*> :
881 public DefaultDOTGraphTraits {
882
Ted Kremenek803c9ed2008-01-23 22:30:44 +0000883 static void PrintKind(std::ostringstream& Out, ValueKey::Kind kind) {
884 switch (kind) {
885 case ValueKey::IsSubExp: Out << "Sub-Expressions:\\l"; break;
886 case ValueKey::IsDecl: Out << "Variables:\\l"; break;
887 case ValueKey::IsBlkExpr: Out << "Block-level Expressions:\\l"; break;
888 default: assert (false && "Unknown ValueKey type.");
889 }
890 }
891
Ted Kremenekaa66a322008-01-16 21:46:15 +0000892 static std::string getNodeLabel(const GRConstants::NodeTy* N, void*) {
893 std::ostringstream Out;
Ted Kremenek803c9ed2008-01-23 22:30:44 +0000894
895 // Program Location.
Ted Kremenekaa66a322008-01-16 21:46:15 +0000896 ProgramPoint Loc = N->getLocation();
897
898 switch (Loc.getKind()) {
899 case ProgramPoint::BlockEntranceKind:
900 Out << "Block Entrance: B"
901 << cast<BlockEntrance>(Loc).getBlock()->getBlockID();
902 break;
903
904 case ProgramPoint::BlockExitKind:
905 assert (false);
906 break;
907
908 case ProgramPoint::PostStmtKind: {
909 const PostStmt& L = cast<PostStmt>(Loc);
Ted Kremenek803c9ed2008-01-23 22:30:44 +0000910 Out << "(" << (void*) L.getStmt() << ") ";
Ted Kremenekaa66a322008-01-16 21:46:15 +0000911 L.getStmt()->printPretty(Out);
912 break;
913 }
914
915 default: {
916 const BlockEdge& E = cast<BlockEdge>(Loc);
917 Out << "Edge: (B" << E.getSrc()->getBlockID() << ", B"
918 << E.getDst()->getBlockID() << ')';
919 }
920 }
921
Ted Kremenek803c9ed2008-01-23 22:30:44 +0000922 Out << "\\|";
Ted Kremenekaa66a322008-01-16 21:46:15 +0000923
924 GRConstants::StateTy M = N->getState();
925 bool isFirst = true;
Ted Kremenek803c9ed2008-01-23 22:30:44 +0000926 ValueKey::Kind kind;
Ted Kremenekaa66a322008-01-16 21:46:15 +0000927
928 for (GRConstants::StateTy::iterator I=M.begin(), E=M.end(); I!=E; ++I) {
Ted Kremenek803c9ed2008-01-23 22:30:44 +0000929 if (!isFirst) {
930 ValueKey::Kind newKind = I.getKey().getKind();
931
932 if (newKind != kind) {
933 Out << "\\l\\l";
934 PrintKind(Out, newKind);
935 }
936 else
937 Out << "\\l";
938
939 kind = newKind;
940 }
941 else {
942 kind = I.getKey().getKind();
943 PrintKind(Out, kind);
Ted Kremenekaa66a322008-01-16 21:46:15 +0000944 isFirst = false;
Ted Kremenek803c9ed2008-01-23 22:30:44 +0000945 }
946
947 Out << ' ';
Ted Kremenekaa66a322008-01-16 21:46:15 +0000948
949 if (ValueDecl* V = dyn_cast<ValueDecl>(I.getKey())) {
Ted Kremenek803c9ed2008-01-23 22:30:44 +0000950 Out << V->getName();
Ted Kremenekaa66a322008-01-16 21:46:15 +0000951 }
952 else {
953 Stmt* E = cast<Stmt>(I.getKey());
Ted Kremenek803c9ed2008-01-23 22:30:44 +0000954 Out << " (" << (void*) E << ") ";
955 E->printPretty(Out);
Ted Kremenekaa66a322008-01-16 21:46:15 +0000956 }
957
Ted Kremenek803c9ed2008-01-23 22:30:44 +0000958 Out << " : ";
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000959 I.getData().print(Out);
Ted Kremenekaa66a322008-01-16 21:46:15 +0000960 }
961
Ted Kremenek803c9ed2008-01-23 22:30:44 +0000962 Out << "\\l";
Ted Kremenekaa66a322008-01-16 21:46:15 +0000963 return Out.str();
964 }
965};
966} // end llvm namespace
967#endif
968
Ted Kremenekee985462008-01-16 18:18:48 +0000969namespace clang {
Ted Kremenek874d63f2008-01-24 02:02:54 +0000970void RunGRConstants(CFG& cfg, ASTContext& Ctx) {
971 GREngine<GRConstants> Engine(cfg, Ctx);
Ted Kremenekee985462008-01-16 18:18:48 +0000972 Engine.ExecuteWorkList();
Ted Kremenekaa66a322008-01-16 21:46:15 +0000973#ifndef NDEBUG
974 llvm::ViewGraph(*Engine.getGraph().roots_begin(),"GRConstants");
975#endif
Ted Kremenekee985462008-01-16 18:18:48 +0000976}
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000977} // end clang namespace