blob: 9385d28c67902f96a2a22ae9b55dae76f1358c34 [file] [log] [blame]
Ted Kremenekd27f8162008-01-15 23:55:06 +00001//===-- GRConstants.cpp - Simple, Path-Sens. Constant Prop. ------*- C++ -*-==//
2//
3// The LLVM Compiler Infrastructure
4//
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"
20#include "clang/Analysis/Analyses/LiveVariables.h"
21#include "clang/Analysis/Visitors/CFGStmtVisitor.h"
22
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 Kremenekd27f8162008-01-15 23:55:06 +000029#include "llvm/Support/Compiler.h"
30
Ted Kremenekaa66a322008-01-16 21:46:15 +000031#ifndef NDEBUG
32#include "llvm/Support/GraphWriter.h"
33#include <sstream>
34#endif
35
Ted Kremenekd27f8162008-01-15 23:55:06 +000036using namespace clang;
37using llvm::APInt;
38using llvm::APFloat;
39using llvm::dyn_cast;
40using llvm::cast;
41
42//===----------------------------------------------------------------------===//
Ted Kremenekaa66a322008-01-16 21:46:15 +000043/// DSPtr - A variant smart pointer that wraps either a ValueDecl* or a
Ted Kremenekd27f8162008-01-15 23:55:06 +000044/// Stmt*. Use cast<> or dyn_cast<> to get actual pointer type
45//===----------------------------------------------------------------------===//
46namespace {
Ted Kremenekcb448ca2008-01-16 00:53:15 +000047class VISIBILITY_HIDDEN DSPtr {
Ted Kremenek0525a4f2008-01-16 19:47:19 +000048 uintptr_t Raw;
Ted Kremenekd27f8162008-01-15 23:55:06 +000049public:
Ted Kremeneke3d7c242008-01-16 23:35:31 +000050 enum VariantKind { IsSubExp=0x0, IsValueDecl=0x1, IsBlkLvl=0x2, Flags=0x3 };
Ted Kremenekd27f8162008-01-15 23:55:06 +000051 inline void* getPtr() const { return reinterpret_cast<void*>(Raw & ~Flags); }
52 inline VariantKind getKind() const { return (VariantKind) (Raw & Flags); }
53
Ted Kremenekaa66a322008-01-16 21:46:15 +000054 DSPtr(ValueDecl* D) : Raw(reinterpret_cast<uintptr_t>(D) | IsValueDecl) {}
Ted Kremenekcb448ca2008-01-16 00:53:15 +000055 DSPtr(Stmt* S, bool isBlkLvl)
Ted Kremenekd27f8162008-01-15 23:55:06 +000056 : Raw(reinterpret_cast<uintptr_t>(S) | (isBlkLvl ? IsBlkLvl : IsSubExp)) {}
57
58 bool isSubExpr() const { return getKind() == IsSubExp; }
59
60 inline void Profile(llvm::FoldingSetNodeID& ID) const {
Ted Kremenek98491852008-01-16 05:51:13 +000061 ID.AddPointer(getPtr());
62 ID.AddInteger((unsigned) getKind());
Ted Kremenekd27f8162008-01-15 23:55:06 +000063 }
Ted Kremenekcb448ca2008-01-16 00:53:15 +000064 inline bool operator==(const DSPtr& X) const { return Raw == X.Raw; }
65 inline bool operator!=(const DSPtr& X) const { return Raw != X.Raw; }
Ted Kremenekb3d2dca2008-01-16 23:33:44 +000066 inline bool operator<(const DSPtr& X) const {
67 VariantKind k = getKind(), Xk = X.getKind();
Ted Kremeneke00fe3f2008-01-17 00:52:48 +000068 return k == Xk ? getPtr() < X.getPtr() : ((unsigned) k) < ((unsigned) Xk);
Ted Kremenekb3d2dca2008-01-16 23:33:44 +000069 }
Ted Kremenekd27f8162008-01-15 23:55:06 +000070};
71} // end anonymous namespace
72
Ted Kremenekcb448ca2008-01-16 00:53:15 +000073// Machinery to get cast<> and dyn_cast<> working with DSPtr.
Ted Kremenekd27f8162008-01-15 23:55:06 +000074namespace llvm {
Ted Kremenekaa66a322008-01-16 21:46:15 +000075 template<> inline bool isa<ValueDecl,DSPtr>(const DSPtr& V) {
76 return V.getKind() == DSPtr::IsValueDecl;
Ted Kremenekd27f8162008-01-15 23:55:06 +000077 }
Ted Kremenekcb448ca2008-01-16 00:53:15 +000078 template<> inline bool isa<Stmt,DSPtr>(const DSPtr& V) {
Ted Kremeneke00fe3f2008-01-17 00:52:48 +000079 return ((unsigned) V.getKind()) != DSPtr::IsValueDecl;
Ted Kremenekd27f8162008-01-15 23:55:06 +000080 }
Ted Kremenekaa66a322008-01-16 21:46:15 +000081 template<> struct VISIBILITY_HIDDEN cast_retty_impl<ValueDecl,DSPtr> {
82 typedef const ValueDecl* ret_type;
Ted Kremenekd27f8162008-01-15 23:55:06 +000083 };
Ted Kremenekcb448ca2008-01-16 00:53:15 +000084 template<> struct VISIBILITY_HIDDEN cast_retty_impl<Stmt,DSPtr> {
Ted Kremenekd27f8162008-01-15 23:55:06 +000085 typedef const Stmt* ret_type;
86 };
Ted Kremenekcb448ca2008-01-16 00:53:15 +000087 template<> struct VISIBILITY_HIDDEN simplify_type<DSPtr> {
Ted Kremenekd27f8162008-01-15 23:55:06 +000088 typedef void* SimpleType;
Ted Kremenekcb448ca2008-01-16 00:53:15 +000089 static inline SimpleType getSimplifiedValue(const DSPtr &V) {
Ted Kremenekd27f8162008-01-15 23:55:06 +000090 return V.getPtr();
91 }
92 };
93} // end llvm namespace
94
95//===----------------------------------------------------------------------===//
96// DeclStmtMapTy - A ImmutableMap type from Decl*/Stmt* to integers.
97//
98// FIXME: We may eventually use APSInt, or a mixture of APSInt and
99// integer primitives to do this right; this will handle both
100// different bit-widths and allow us to detect integer overflows, etc.
101//
102//===----------------------------------------------------------------------===//
103
Ted Kremenekcb448ca2008-01-16 00:53:15 +0000104typedef llvm::ImmutableMap<DSPtr,uint64_t> DeclStmtMapTy;
Ted Kremenekd27f8162008-01-15 23:55:06 +0000105
106namespace clang {
107template<>
108struct VISIBILITY_HIDDEN GRTrait<DeclStmtMapTy> {
109 static inline void* toPtr(DeclStmtMapTy M) {
110 return reinterpret_cast<void*>(M.getRoot());
111 }
112 static inline DeclStmtMapTy toState(void* P) {
113 return DeclStmtMapTy(static_cast<DeclStmtMapTy::TreeTy*>(P));
114 }
115};
116}
117
118//===----------------------------------------------------------------------===//
119// The Checker!
120//===----------------------------------------------------------------------===//
121
122namespace {
123class VISIBILITY_HIDDEN ExprVariantTy {
124 const uint64_t val;
125 const bool isConstant;
126public:
127 ExprVariantTy() : val(0), isConstant(false) {}
128 ExprVariantTy(uint64_t v) : val(v), isConstant(true) {}
129
130 operator bool() const { return isConstant; }
131 uint64_t getVal() const { assert (isConstant); return val; }
132
133 ExprVariantTy operator+(const ExprVariantTy& X) const {
Ted Kremenekf84469b2008-01-18 00:41:32 +0000134 return (isConstant && X.isConstant) ? ExprVariantTy(val + X.val)
135 : ExprVariantTy();
Ted Kremenekd27f8162008-01-15 23:55:06 +0000136 }
137
138 ExprVariantTy operator-(const ExprVariantTy& X) const {
Ted Kremenekf84469b2008-01-18 00:41:32 +0000139 return (isConstant && X.isConstant) ? ExprVariantTy(val - X.val)
140 : ExprVariantTy();
Ted Kremenekd27f8162008-01-15 23:55:06 +0000141 }
142};
143} // end anonymous namespace
144
145//===----------------------------------------------------------------------===//
146// The Checker!
147//===----------------------------------------------------------------------===//
148
149namespace {
150class VISIBILITY_HIDDEN GRConstants : public CFGStmtVisitor<GRConstants> {
151
152public:
153 typedef DeclStmtMapTy StateTy;
154 typedef GRNodeBuilder<GRConstants> NodeBuilder;
155 typedef ExplodedNode<StateTy> NodeTy;
156
157protected:
Ted Kremenekaa66a322008-01-16 21:46:15 +0000158 // Liveness - live-variables information the ValueDecl* and Expr* (block-level)
Ted Kremenekd27f8162008-01-15 23:55:06 +0000159 // in the CFG. Used to prune out dead state.
160 LiveVariables* Liveness;
161
162 // Builder - The current GRNodeBuilder which is used when building the nodes
163 // for a given statement.
164 NodeBuilder* Builder;
165
Ted Kremenekcb448ca2008-01-16 00:53:15 +0000166 DeclStmtMapTy::Factory StateMgr;
Ted Kremenekd27f8162008-01-15 23:55:06 +0000167
168 // cfg - the current CFG.
169 CFG* cfg;
170
Ted Kremenek3c6c6722008-01-16 17:56:25 +0000171 typedef llvm::SmallVector<NodeTy*,8> NodeSetTy;
Ted Kremenekd27f8162008-01-15 23:55:06 +0000172 NodeSetTy NodeSetA;
173 NodeSetTy NodeSetB;
174 NodeSetTy* Nodes;
175 NodeSetTy* OldNodes;
Ted Kremenekcb448ca2008-01-16 00:53:15 +0000176 StateTy CurrentState;
Ted Kremeneke00fe3f2008-01-17 00:52:48 +0000177 NodeTy* InitialPred;
Ted Kremenekd27f8162008-01-15 23:55:06 +0000178
Ted Kremenekd27f8162008-01-15 23:55:06 +0000179public:
180 GRConstants() : Liveness(NULL), Builder(NULL), cfg(NULL),
Ted Kremenek3c6c6722008-01-16 17:56:25 +0000181 Nodes(&NodeSetA), OldNodes(&NodeSetB),
Ted Kremeneke00fe3f2008-01-17 00:52:48 +0000182 CurrentState(StateMgr.GetEmptyMap()), InitialPred(NULL) {}
Ted Kremenekd27f8162008-01-15 23:55:06 +0000183
184 ~GRConstants() { delete Liveness; }
185
186 CFG& getCFG() { assert (cfg); return *cfg; }
187
188 void Initialize(CFG& c) {
189 cfg = &c;
190 Liveness = new LiveVariables(c);
191 Liveness->runOnCFG(c);
Ted Kremenek79649df2008-01-17 18:25:22 +0000192 Liveness->runOnAllBlocks(c, NULL, true);
Ted Kremenekd27f8162008-01-15 23:55:06 +0000193 }
194
195 StateTy getInitialState() {
Ted Kremenekcb448ca2008-01-16 00:53:15 +0000196 return StateMgr.GetEmptyMap();
Ted Kremenekd27f8162008-01-15 23:55:06 +0000197 }
198
199 void ProcessStmt(Stmt* S, NodeBuilder& builder);
Ted Kremenekcb448ca2008-01-16 00:53:15 +0000200 void SwitchNodeSets();
Ted Kremenekd27f8162008-01-15 23:55:06 +0000201 void DoStmt(Stmt* S);
Ted Kremeneke00fe3f2008-01-17 00:52:48 +0000202
203 StateTy RemoveDescendantMappings(Stmt* S, StateTy M, unsigned Levels=2);
Ted Kremenekf84469b2008-01-18 00:41:32 +0000204 StateTy RemoveDeadMappings(Stmt* S, StateTy M);
Ted Kremenekd27f8162008-01-15 23:55:06 +0000205
206 void AddBinding(Expr* E, ExprVariantTy V, bool isBlkLvl = false);
Ted Kremenekaa66a322008-01-16 21:46:15 +0000207 void AddBinding(ValueDecl* D, ExprVariantTy V);
Ted Kremenek1ccd31c2008-01-16 19:42:59 +0000208
Ted Kremenekd27f8162008-01-15 23:55:06 +0000209 ExprVariantTy GetBinding(Expr* E);
210
211 void BlockStmt_VisitStmt(Stmt* S) { DoStmt(S); }
Ted Kremenekd27f8162008-01-15 23:55:06 +0000212
213 void VisitAssign(BinaryOperator* O);
Ted Kremenekd27f8162008-01-15 23:55:06 +0000214 void VisitBinAdd(BinaryOperator* O);
215 void VisitBinSub(BinaryOperator* O);
Ted Kremenek1ccd31c2008-01-16 19:42:59 +0000216 void VisitBinAssign(BinaryOperator* D);
Ted Kremenekd27f8162008-01-15 23:55:06 +0000217};
218} // end anonymous namespace
219
220void GRConstants::ProcessStmt(Stmt* S, NodeBuilder& builder) {
221 Builder = &builder;
Ted Kremenekf84469b2008-01-18 00:41:32 +0000222
Ted Kremenekd27f8162008-01-15 23:55:06 +0000223 Nodes->clear();
224 OldNodes->clear();
Ted Kremenekf84469b2008-01-18 00:41:32 +0000225
Ted Kremeneke00fe3f2008-01-17 00:52:48 +0000226 InitialPred = Builder->getLastNode();
227 assert (InitialPred);
228 OldNodes->push_back(InitialPred);
Ted Kremenekf84469b2008-01-18 00:41:32 +0000229
230 CurrentState = RemoveDeadMappings(S, InitialPred->getState());
231
Ted Kremenekd27f8162008-01-15 23:55:06 +0000232 BlockStmt_Visit(S);
Ted Kremenekf84469b2008-01-18 00:41:32 +0000233
Ted Kremenekd27f8162008-01-15 23:55:06 +0000234 Builder = NULL;
235}
236
237ExprVariantTy GRConstants::GetBinding(Expr* E) {
Ted Kremenek0525a4f2008-01-16 19:47:19 +0000238 DSPtr P(NULL);
Ted Kremenek4e99a5f2008-01-17 16:57:34 +0000239 E = E->IgnoreParens();
Ted Kremenek0525a4f2008-01-16 19:47:19 +0000240
Ted Kremenekca3e8572008-01-16 22:28:08 +0000241 switch (E->getStmtClass()) {
242 case Stmt::DeclRefExprClass:
243 P = DSPtr(cast<DeclRefExpr>(E)->getDecl());
244 break;
245
246 case Stmt::IntegerLiteralClass:
247 return cast<IntegerLiteral>(E)->getValue().getZExtValue();
248
249 default:
250 P = DSPtr(E, getCFG().isBlkExpr(E));
251 break;
252 }
Ted Kremenek0525a4f2008-01-16 19:47:19 +0000253
Ted Kremenekf84469b2008-01-18 00:41:32 +0000254 StateTy::TreeTy* T = CurrentState.SlimFind(P);
Ted Kremenekd27f8162008-01-15 23:55:06 +0000255
Ted Kremenekf84469b2008-01-18 00:41:32 +0000256 if (!T)
Ted Kremenekd27f8162008-01-15 23:55:06 +0000257 return ExprVariantTy();
258
Ted Kremenekf84469b2008-01-18 00:41:32 +0000259 return T->getValue().second;
Ted Kremenekd27f8162008-01-15 23:55:06 +0000260}
261
262void GRConstants::AddBinding(Expr* E, ExprVariantTy V, bool isBlkLvl) {
Ted Kremenekf84469b2008-01-18 00:41:32 +0000263 if (V) CurrentState = StateMgr.Add(CurrentState, DSPtr(E,isBlkLvl), V.getVal());
Ted Kremenekd27f8162008-01-15 23:55:06 +0000264}
265
Ted Kremenekaa66a322008-01-16 21:46:15 +0000266void GRConstants::AddBinding(ValueDecl* D, ExprVariantTy V) {
Ted Kremenekf84469b2008-01-18 00:41:32 +0000267 if (V) CurrentState = StateMgr.Add(CurrentState, DSPtr(D), V.getVal());
268 else CurrentState = StateMgr.Remove(CurrentState, DSPtr(D));
Ted Kremenek1ccd31c2008-01-16 19:42:59 +0000269}
270
Ted Kremenekd27f8162008-01-15 23:55:06 +0000271void GRConstants::SwitchNodeSets() {
272 NodeSetTy* Tmp = OldNodes;
273 OldNodes = Nodes;
274 Nodes = Tmp;
275 Nodes->clear();
276}
277
Ted Kremenekf84469b2008-01-18 00:41:32 +0000278GRConstants::StateTy GRConstants::RemoveDeadMappings(Stmt* Loc, StateTy M) {
279#if 0
280 return M;
281#else
282 // Note: in the code below, we can assign a new map to M since the
283 // iterators are iterating over the tree of the *original* map.
284
285 StateTy::iterator I = M.begin(), E = M.end();
286
287 // First remove mappings for subexpressions, since they are not needed.
288 for (; I!=E && I.getKey().getKind() == DSPtr::IsSubExp; ++I)
Ted Kremeneke00fe3f2008-01-17 00:52:48 +0000289 M = StateMgr.Remove(M, I.getKey());
Ted Kremenekf84469b2008-01-18 00:41:32 +0000290
291 // Next, remove any decls or block-level expressions whose mappings are dead.
292 for (; I != E; ++I) {
293 if (ValueDecl* VD = dyn_cast<ValueDecl>(I.getKey())) {
294 if (VarDecl* V = dyn_cast<VarDecl>(VD)) {
295 if (!Liveness->isLive(Loc, V)) M = StateMgr.Remove(M, I.getKey());
296 }
297 }
298 else {
299 Stmt* S = cast<Stmt>(I.getKey());
300 assert (I.getKey().getKind() == DSPtr::IsBlkLvl);
301 if (!Liveness->isLive(Loc, S)) M = StateMgr.Remove(M, I.getKey());
302 }
Ted Kremeneke00fe3f2008-01-17 00:52:48 +0000303 }
304
305 return M;
Ted Kremenekf84469b2008-01-18 00:41:32 +0000306#endif
Ted Kremeneke00fe3f2008-01-17 00:52:48 +0000307}
308
309
310GRConstants::StateTy
311GRConstants::RemoveDescendantMappings(Stmt* S, GRConstants::StateTy State,
312 unsigned Levels) {
Ted Kremenekcb448ca2008-01-16 00:53:15 +0000313 typedef Stmt::child_iterator iterator;
314
315 for (iterator I=S->child_begin(), E=S->child_end(); I!=E; ++I)
Ted Kremeneke00fe3f2008-01-17 00:52:48 +0000316 if (Stmt* C = *I) {
317 if (Levels == 1) {
Ted Kremenekcb448ca2008-01-16 00:53:15 +0000318 // Observe that this will only remove mappings to non-block level
319 // expressions. This is valid even if *CI is a block-level expression,
320 // since it simply won't be in the map in the first place.
Ted Kremenek3c6c6722008-01-16 17:56:25 +0000321 // Note: This should also work if 'C' is a block-level expression,
322 // although ideally we would want to skip processing C's children.
Ted Kremeneke00fe3f2008-01-17 00:52:48 +0000323 State = StateMgr.Remove(State, DSPtr(C,false));
Ted Kremenekcb448ca2008-01-16 00:53:15 +0000324 }
Ted Kremeneke00fe3f2008-01-17 00:52:48 +0000325 else {
326 if (ParenExpr* P = dyn_cast<ParenExpr>(C))
327 State = RemoveDescendantMappings(P, State, Levels);
328 else
329 State = RemoveDescendantMappings(C, State, Levels-1);
330 }
331 }
Ted Kremenekcb448ca2008-01-16 00:53:15 +0000332
333 return State;
334}
Ted Kremenekd27f8162008-01-15 23:55:06 +0000335
336void GRConstants::DoStmt(Stmt* S) {
337 for (Stmt::child_iterator I=S->child_begin(), E=S->child_end(); I!=E; ++I)
Ted Kremenekcb448ca2008-01-16 00:53:15 +0000338 if (*I) DoStmt(*I);
Ted Kremenekd27f8162008-01-15 23:55:06 +0000339
Ted Kremenekd27f8162008-01-15 23:55:06 +0000340 for (NodeSetTy::iterator I=OldNodes->begin(), E=OldNodes->end(); I!=E; ++I) {
Ted Kremenekcb448ca2008-01-16 00:53:15 +0000341 NodeTy* Pred = *I;
Ted Kremeneke00fe3f2008-01-17 00:52:48 +0000342
343 if (Pred != InitialPred)
344 CurrentState = Pred->getState();
Ted Kremenekcb448ca2008-01-16 00:53:15 +0000345
Ted Kremenek3c6c6722008-01-16 17:56:25 +0000346 StateTy OldState = CurrentState;
Ted Kremeneke00fe3f2008-01-17 00:52:48 +0000347
348 if (Pred != InitialPred)
349 CurrentState = RemoveDescendantMappings(S, CurrentState);
Ted Kremenekcb448ca2008-01-16 00:53:15 +0000350
Ted Kremenekd27f8162008-01-15 23:55:06 +0000351 Visit(S);
Ted Kremenekcb448ca2008-01-16 00:53:15 +0000352
Ted Kremenek3c6c6722008-01-16 17:56:25 +0000353 if (CurrentState != OldState) {
Ted Kremenekcb448ca2008-01-16 00:53:15 +0000354 NodeTy* N = Builder->generateNode(S, CurrentState, Pred);
Ted Kremenek3c6c6722008-01-16 17:56:25 +0000355 if (N) Nodes->push_back(N);
Ted Kremenekcb448ca2008-01-16 00:53:15 +0000356 }
Ted Kremenek3c6c6722008-01-16 17:56:25 +0000357 else Nodes->push_back(Pred);
Ted Kremenekd27f8162008-01-15 23:55:06 +0000358 }
Ted Kremenek3c6c6722008-01-16 17:56:25 +0000359
360 SwitchNodeSets();
Ted Kremenekd27f8162008-01-15 23:55:06 +0000361}
362
Ted Kremenekf84469b2008-01-18 00:41:32 +0000363void GRConstants::VisitBinAdd(BinaryOperator* B) {
Ted Kremenekd27f8162008-01-15 23:55:06 +0000364 AddBinding(B, GetBinding(B->getLHS()) + GetBinding(B->getRHS()));
365}
366
367void GRConstants::VisitBinSub(BinaryOperator* B) {
Ted Kremenekf84469b2008-01-18 00:41:32 +0000368 ExprVariantTy V1 = GetBinding(B->getLHS());
369 ExprVariantTy V2 = GetBinding(B->getRHS());
370
371 AddBinding(B, V1 - V2 );
Ted Kremenekd27f8162008-01-15 23:55:06 +0000372}
Ted Kremenekee985462008-01-16 18:18:48 +0000373
Ted Kremenek1ccd31c2008-01-16 19:42:59 +0000374
Ted Kremenek1ccd31c2008-01-16 19:42:59 +0000375void GRConstants::VisitBinAssign(BinaryOperator* B) {
Ted Kremenek79649df2008-01-17 18:25:22 +0000376 if (DeclRefExpr* D = dyn_cast<DeclRefExpr>(B->getLHS()->IgnoreParens())) {
377 ExprVariantTy V = GetBinding(B->getRHS());
378 AddBinding(D->getDecl(), V);
379 AddBinding(B, V);
380 }
Ted Kremenek1ccd31c2008-01-16 19:42:59 +0000381}
382
Ted Kremenekee985462008-01-16 18:18:48 +0000383//===----------------------------------------------------------------------===//
384// Driver.
385//===----------------------------------------------------------------------===//
386
Ted Kremenekaa66a322008-01-16 21:46:15 +0000387#ifndef NDEBUG
388namespace llvm {
389template<>
390struct VISIBILITY_HIDDEN DOTGraphTraits<GRConstants::NodeTy*> :
391 public DefaultDOTGraphTraits {
392
393 static std::string getNodeLabel(const GRConstants::NodeTy* N, void*) {
394 std::ostringstream Out;
395
396 Out << "Vertex: " << (void*) N << '\n';
397 ProgramPoint Loc = N->getLocation();
398
399 switch (Loc.getKind()) {
400 case ProgramPoint::BlockEntranceKind:
401 Out << "Block Entrance: B"
402 << cast<BlockEntrance>(Loc).getBlock()->getBlockID();
403 break;
404
405 case ProgramPoint::BlockExitKind:
406 assert (false);
407 break;
408
409 case ProgramPoint::PostStmtKind: {
410 const PostStmt& L = cast<PostStmt>(Loc);
411 Out << "Stmt: " << (void*) L.getStmt() << '\n';
412 L.getStmt()->printPretty(Out);
413 break;
414 }
415
416 default: {
417 const BlockEdge& E = cast<BlockEdge>(Loc);
418 Out << "Edge: (B" << E.getSrc()->getBlockID() << ", B"
419 << E.getDst()->getBlockID() << ')';
420 }
421 }
422
423 Out << "\n{";
424
425 GRConstants::StateTy M = N->getState();
426 bool isFirst = true;
427
428 for (GRConstants::StateTy::iterator I=M.begin(), E=M.end(); I!=E; ++I) {
429 if (!isFirst)
430 Out << '\n';
431 else
432 isFirst = false;
433
434 if (ValueDecl* V = dyn_cast<ValueDecl>(I.getKey())) {
435 Out << "Decl: " << (void*) V << ", " << V->getName();
436 }
437 else {
438 Stmt* E = cast<Stmt>(I.getKey());
439 Out << "Stmt: " << (void*) E;
440 }
441
442 Out << " => " << I.getData();
443 }
444
445 Out << " }";
446
447 return Out.str();
448 }
449};
450} // end llvm namespace
451#endif
452
Ted Kremenekee985462008-01-16 18:18:48 +0000453namespace clang {
454void RunGRConstants(CFG& cfg) {
455 GREngine<GRConstants> Engine(cfg);
456 Engine.ExecuteWorkList();
Ted Kremenekaa66a322008-01-16 21:46:15 +0000457#ifndef NDEBUG
458 llvm::ViewGraph(*Engine.getGraph().roots_begin(),"GRConstants");
459#endif
Ted Kremenekee985462008-01-16 18:18:48 +0000460}
461}