blob: 84a8f048a8aa627f3f62d031b2624eaa56494de8 [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"
20#include "clang/Analysis/Analyses/LiveVariables.h"
Ted Kremenekd27f8162008-01-15 23:55:06 +000021
22#include "llvm/Support/Casting.h"
23#include "llvm/Support/DataTypes.h"
24#include "llvm/ADT/APSInt.h"
25#include "llvm/ADT/FoldingSet.h"
26#include "llvm/ADT/ImmutableMap.h"
Ted Kremenek3c6c6722008-01-16 17:56:25 +000027#include "llvm/ADT/SmallVector.h"
Ted Kremenekab2b8c52008-01-23 19:59:44 +000028#include "llvm/Support/Allocator.h"
Ted Kremenekd27f8162008-01-15 23:55:06 +000029#include "llvm/Support/Compiler.h"
30
Ted Kremenekab2b8c52008-01-23 19:59:44 +000031#include "llvm/Support/Streams.h"
32
Ted Kremenekaa66a322008-01-16 21:46:15 +000033#ifndef NDEBUG
34#include "llvm/Support/GraphWriter.h"
35#include <sstream>
36#endif
37
Ted Kremenekd27f8162008-01-15 23:55:06 +000038using namespace clang;
Ted Kremenekd27f8162008-01-15 23:55:06 +000039using llvm::dyn_cast;
40using llvm::cast;
41
42//===----------------------------------------------------------------------===//
Ted Kremenekab2b8c52008-01-23 19:59:44 +000043/// ValueKey - 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 Kremenekab2b8c52008-01-23 19:59:44 +000047
48class VISIBILITY_HIDDEN ValueKey {
Ted Kremenek0525a4f2008-01-16 19:47:19 +000049 uintptr_t Raw;
Ted Kremenekd27f8162008-01-15 23:55:06 +000050public:
Ted Kremenekab2b8c52008-01-23 19:59:44 +000051 enum Kind { IsSubExp=0x0, IsDecl=0x1, IsBlkExpr=0x2, Flags=0x3 };
Ted Kremenekd27f8162008-01-15 23:55:06 +000052 inline void* getPtr() const { return reinterpret_cast<void*>(Raw & ~Flags); }
Ted Kremenekab2b8c52008-01-23 19:59:44 +000053 inline Kind getKind() const { return (Kind) (Raw & Flags); }
Ted Kremenekd27f8162008-01-15 23:55:06 +000054
Ted Kremenekab2b8c52008-01-23 19:59:44 +000055 ValueKey(const ValueDecl* VD)
56 : Raw(reinterpret_cast<uintptr_t>(VD) | IsDecl) {}
57
58 ValueKey(Stmt* S, bool isBlkExpr)
59 : Raw(reinterpret_cast<uintptr_t>(S) | (isBlkExpr ? IsBlkExpr : IsSubExp)){}
Ted Kremenekd27f8162008-01-15 23:55:06 +000060
61 bool isSubExpr() const { return getKind() == IsSubExp; }
Ted Kremenekab2b8c52008-01-23 19:59:44 +000062 bool isDecl() const { return getKind() == IsDecl; }
Ted Kremenekd27f8162008-01-15 23:55:06 +000063
64 inline void Profile(llvm::FoldingSetNodeID& ID) const {
Ted Kremenek98491852008-01-16 05:51:13 +000065 ID.AddPointer(getPtr());
66 ID.AddInteger((unsigned) getKind());
Ted Kremenekab2b8c52008-01-23 19:59:44 +000067 }
68
69 inline bool operator==(const ValueKey& X) const {
70 return Raw == X.Raw;
71 }
72
73 inline bool operator!=(const ValueKey& X) const {
74 return !operator==(X);
75 }
76
77 inline bool operator<(const ValueKey& X) const {
78 Kind k = getKind(), Xk = X.getKind();
79
80 return k == Xk ? getPtr() < X.getPtr()
81 : ((unsigned) k) < ((unsigned) Xk);
Ted Kremenekb3d2dca2008-01-16 23:33:44 +000082 }
Ted Kremenekd27f8162008-01-15 23:55:06 +000083};
84} // end anonymous namespace
85
Ted Kremenekab2b8c52008-01-23 19:59:44 +000086// Machinery to get cast<> and dyn_cast<> working with ValueKey.
Ted Kremenekd27f8162008-01-15 23:55:06 +000087namespace llvm {
Ted Kremenekab2b8c52008-01-23 19:59:44 +000088 template<> inline bool isa<ValueDecl,ValueKey>(const ValueKey& V) {
89 return V.getKind() == ValueKey::IsDecl;
Ted Kremenekd27f8162008-01-15 23:55:06 +000090 }
Ted Kremenekab2b8c52008-01-23 19:59:44 +000091 template<> inline bool isa<Stmt,ValueKey>(const ValueKey& V) {
92 return ((unsigned) V.getKind()) != ValueKey::IsDecl;
Ted Kremenekd27f8162008-01-15 23:55:06 +000093 }
Ted Kremenekab2b8c52008-01-23 19:59:44 +000094 template<> struct VISIBILITY_HIDDEN cast_retty_impl<ValueDecl,ValueKey> {
Ted Kremenekaa66a322008-01-16 21:46:15 +000095 typedef const ValueDecl* ret_type;
Ted Kremenekd27f8162008-01-15 23:55:06 +000096 };
Ted Kremenekab2b8c52008-01-23 19:59:44 +000097 template<> struct VISIBILITY_HIDDEN cast_retty_impl<Stmt,ValueKey> {
Ted Kremenekd27f8162008-01-15 23:55:06 +000098 typedef const Stmt* ret_type;
99 };
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000100 template<> struct VISIBILITY_HIDDEN simplify_type<ValueKey> {
Ted Kremenekd27f8162008-01-15 23:55:06 +0000101 typedef void* SimpleType;
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000102 static inline SimpleType getSimplifiedValue(const ValueKey &V) {
Ted Kremenekd27f8162008-01-15 23:55:06 +0000103 return V.getPtr();
104 }
105 };
106} // end llvm namespace
107
108//===----------------------------------------------------------------------===//
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000109// ValueManager.
Ted Kremenekd27f8162008-01-15 23:55:06 +0000110//===----------------------------------------------------------------------===//
111
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000112namespace {
113
114typedef llvm::ImmutableSet<llvm::APSInt > APSIntSetTy;
115
116class VISIBILITY_HIDDEN ValueManager {
117
118
119 APSIntSetTy::Factory APSIntSetFactory;
120
121public:
122 ValueManager() {}
123 ~ValueManager() {}
124
125 APSIntSetTy GetEmptyAPSIntSet() {
126 return APSIntSetFactory.GetEmptySet();
127 }
128
129 APSIntSetTy AddToSet(const APSIntSetTy& Set, const llvm::APSInt& Val) {
130 return APSIntSetFactory.Add(Set, Val);
Ted Kremenekd27f8162008-01-15 23:55:06 +0000131 }
132};
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000133} // end anonymous namespace
134
135//===----------------------------------------------------------------------===//
136// Expression Values.
137//===----------------------------------------------------------------------===//
138
139namespace {
140
141class VISIBILITY_HIDDEN ExprValue {
142public:
143 enum Kind { // L-Values.
144 LValueDeclKind = 0x0,
145 // Special "Invalid" value.
146 InvalidValueKind = 0x1,
147 // R-Values.
148 RValueMayEqualSetKind = 0x2,
149 // Note that the Lvalue and RValue "kinds" overlap;
150 // the "InvalidValue" class can be used either as
151 // an LValue or RValue.
152 MinLValueKind = 0x0, MaxLValueKind = 0x1,
153 MinRValueKind = 0x1, MaxRValueKind = 0x2 };
154
155private:
156 enum Kind kind;
157 void* Data;
158
159protected:
160 ExprValue(Kind k, void* d) : kind(k), Data(d) {}
161
162 void* getRawPtr() const { return Data; }
163
164public:
165 ~ExprValue() {};
166
167 void Profile(llvm::FoldingSetNodeID& ID) const {
168 ID.AddInteger((unsigned) getKind());
169 ID.AddPointer(Data);
170 }
171
172 bool operator==(const ExprValue& RHS) const {
173 return kind == RHS.kind && Data == RHS.Data;
174 }
175
176 Kind getKind() const { return kind; }
177 bool isValid() const { return getKind() != InvalidValueKind; }
178
179 void print(std::ostream& OS) const;
180 void print() const { print(*llvm::cerr.stream()); }
181
182 // Implement isa<T> support.
183 static inline bool classof(const ExprValue*) { return true; }
184};
185
186class VISIBILITY_HIDDEN InvalidValue : public ExprValue {
187public:
188 InvalidValue() : ExprValue(InvalidValueKind, NULL) {}
189
190 static inline bool classof(const ExprValue* V) {
191 return V->getKind() == InvalidValueKind;
192 }
193};
194
195} // end anonymous namespace
196
197//===----------------------------------------------------------------------===//
198// "R-Values": Interface.
199//===----------------------------------------------------------------------===//
200
201namespace {
202class VISIBILITY_HIDDEN RValue : public ExprValue {
203protected:
204 RValue(Kind k, void* d) : ExprValue(k,d) {}
205
206public:
207 RValue Add(ValueManager& ValMgr, const RValue& RHS) const;
208 RValue Sub(ValueManager& ValMgr, const RValue& RHS) const;
209
210 static RValue GetRValue(ValueManager& ValMgr, IntegerLiteral* S);
211
212 // Implement isa<T> support.
213 static inline bool classof(const ExprValue* V) {
214 return V->getKind() >= MinRValueKind;
215 }
216};
217
218class VISIBILITY_HIDDEN RValueMayEqualSet : public RValue {
219public:
220 RValueMayEqualSet(const APSIntSetTy& S)
221 : RValue(RValueMayEqualSetKind, S.getRoot()) {}
222
223 APSIntSetTy GetValues() const {
224 return APSIntSetTy(reinterpret_cast<APSIntSetTy::TreeTy*>(getRawPtr()));
225 }
226
227 RValueMayEqualSet Add(ValueManager& ValMgr, const RValueMayEqualSet& V) const;
228 RValueMayEqualSet Sub(ValueManager& ValMgr, const RValueMayEqualSet& V) const;
229
230 // Implement isa<T> support.
231 static inline bool classof(const ExprValue* V) {
232 return V->getKind() == RValueMayEqualSetKind;
233 }
234};
235} // end anonymous namespace
236
237//===----------------------------------------------------------------------===//
238// "R-Values": Implementation.
239//===----------------------------------------------------------------------===//
240
241#define RVALUE_DISPATCH_CASE(k1,k2,Op)\
242case ((k1##Kind+(MaxRValueKind-MinRValueKind))+(k2##Kind - MinRValueKind)):\
243 return cast<k1>(*this).Op(ValMgr,cast<k2>(RHS));
244
245#define RVALUE_DISPATCH(Op)\
246switch (getKind()+(MaxRValueKind-MinRValueKind)+(RHS.getKind()-MinRValueKind)){\
247 RVALUE_DISPATCH_CASE(RValueMayEqualSet,RValueMayEqualSet,Op)\
248 default:\
249 assert (!isValid() || !RHS.isValid() && "Missing case.");\
250 break;\
251}\
252return cast<RValue>(InvalidValue());
253
254RValue RValue::Add(ValueManager& ValMgr, const RValue& RHS) const {
255 RVALUE_DISPATCH(Add)
256}
257
258RValue RValue::Sub(ValueManager& ValMgr, const RValue& RHS) const {
259 RVALUE_DISPATCH(Sub)
260}
261
262#undef RVALUE_DISPATCH_CASE
263#undef RVALUE_DISPATCH
264
265RValueMayEqualSet
266RValueMayEqualSet::Add(ValueManager& ValMgr,
267 const RValueMayEqualSet& RHS) const {
268
269 APSIntSetTy S1 = GetValues();
270 APSIntSetTy S2 = RHS.GetValues();
271
272 APSIntSetTy M = ValMgr.GetEmptyAPSIntSet();
273
274 for (APSIntSetTy::iterator I1=S1.begin(), E1=S2.end(); I1!=E1; ++I1)
275 for (APSIntSetTy::iterator I2=S2.begin(), E2=S2.end(); I2!=E2; ++I2)
276 M = ValMgr.AddToSet(M, *I1 + *I2);
277
278 return M;
279}
280
281RValueMayEqualSet
282RValueMayEqualSet::Sub(ValueManager& ValMgr,
283 const RValueMayEqualSet& RHS) const {
284
285 APSIntSetTy S1 = GetValues();
286 APSIntSetTy S2 = RHS.GetValues();
287
288 APSIntSetTy M = ValMgr.GetEmptyAPSIntSet();
289
290 for (APSIntSetTy::iterator I1=S1.begin(), E1=S2.end(); I1!=E1; ++I1)
291 for (APSIntSetTy::iterator I2=S2.begin(), E2=S2.end(); I2!=E2; ++I2)
292 M = ValMgr.AddToSet(M, *I1 - *I2);
293
294 return M;
295}
296
297RValue RValue::GetRValue(ValueManager& ValMgr, IntegerLiteral* S) {
298 return RValueMayEqualSet(ValMgr.AddToSet(ValMgr.GetEmptyAPSIntSet(),
299 S->getValue()));
300}
301
302//===----------------------------------------------------------------------===//
303// "L-Values".
304//===----------------------------------------------------------------------===//
305
306namespace {
307
308class VISIBILITY_HIDDEN LValue : public ExprValue {
309protected:
310 LValue(Kind k, void* D) : ExprValue(k, D) {}
311
312public:
313 // Implement isa<T> support.
314 static inline bool classof(const ExprValue* V) {
315 return V->getKind() <= MaxLValueKind;
316 }
317};
318
319class VISIBILITY_HIDDEN LValueDecl : public LValue {
320public:
321 LValueDecl(ValueDecl* vd) : LValue(LValueDeclKind,vd) {}
322
323 ValueDecl* getDecl() const {
324 return static_cast<ValueDecl*>(getRawPtr());
325 }
326
327 // Implement isa<T> support.
328 static inline bool classof(const ExprValue* V) {
329 return V->getKind() == LValueDeclKind;
330 }
331};
332} // end anonymous namespace
333
334//===----------------------------------------------------------------------===//
335// Pretty-Printing.
336//===----------------------------------------------------------------------===//
337
338void ExprValue::print(std::ostream& Out) const {
339 switch (getKind()) {
340 case InvalidValueKind:
341 Out << "Invalid"; break;
342
343 case RValueMayEqualSetKind: {
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000344 APSIntSetTy S = cast<RValueMayEqualSet>(this)->GetValues();
Ted Kremenek803c9ed2008-01-23 22:30:44 +0000345 bool first = true;
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000346
Ted Kremenek803c9ed2008-01-23 22:30:44 +0000347 for (APSIntSetTy::iterator I=S.begin(), E=S.end(); I!=E; ++I) {
348 if (first) first = false;
349 else Out << " | ";
350
351 Out << (*I).toString();
352 }
353
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000354 break;
355 }
356
357 default:
358 assert (false && "Pretty-printed not implemented for this ExprValue.");
359 break;
360 }
361}
362
363//===----------------------------------------------------------------------===//
364// ValueMapTy - A ImmutableMap type Stmt*/Decl* to ExprValues.
365//===----------------------------------------------------------------------===//
366
367typedef llvm::ImmutableMap<ValueKey,ExprValue> ValueMapTy;
368
369namespace clang {
370 template<>
371 struct VISIBILITY_HIDDEN GRTrait<ValueMapTy> {
372 static inline void* toPtr(ValueMapTy M) {
373 return reinterpret_cast<void*>(M.getRoot());
374 }
375 static inline ValueMapTy toState(void* P) {
376 return ValueMapTy(static_cast<ValueMapTy::TreeTy*>(P));
377 }
378 };
Ted Kremenekd27f8162008-01-15 23:55:06 +0000379}
380
381//===----------------------------------------------------------------------===//
382// The Checker!
383//===----------------------------------------------------------------------===//
384
385namespace {
Ted Kremenekd27f8162008-01-15 23:55:06 +0000386
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000387class VISIBILITY_HIDDEN GRConstants {
Ted Kremenekd27f8162008-01-15 23:55:06 +0000388
389public:
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000390 typedef ValueMapTy StateTy;
Ted Kremenekd27f8162008-01-15 23:55:06 +0000391 typedef GRNodeBuilder<GRConstants> NodeBuilder;
392 typedef ExplodedNode<StateTy> NodeTy;
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000393
394 class NodeSet {
395 typedef llvm::SmallVector<NodeTy*,3> ImplTy;
396 ImplTy Impl;
397 public:
398
399 NodeSet() {}
400 NodeSet(NodeTy* N) { assert (N && !N->isInfeasible()); Impl.push_back(N); }
401
402 void Add(NodeTy* N) { if (N && !N->isInfeasible()) Impl.push_back(N); }
403
404 typedef ImplTy::iterator iterator;
405 typedef ImplTy::const_iterator const_iterator;
406
407 unsigned size() const { return Impl.size(); }
408
409 iterator begin() { return Impl.begin(); }
410 iterator end() { return Impl.end(); }
411
412 const_iterator begin() const { return Impl.begin(); }
413 const_iterator end() const { return Impl.end(); }
414 };
Ted Kremenekd27f8162008-01-15 23:55:06 +0000415
416protected:
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000417 /// Liveness - live-variables information the ValueDecl* and block-level
418 /// Expr* in the CFG. Used to prune out dead state.
Ted Kremenekd27f8162008-01-15 23:55:06 +0000419 LiveVariables* Liveness;
420
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000421 /// Builder - The current GRNodeBuilder which is used when building the nodes
422 /// for a given statement.
Ted Kremenekd27f8162008-01-15 23:55:06 +0000423 NodeBuilder* Builder;
424
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000425 /// StateMgr - Object that manages the data for all created states.
426 ValueMapTy::Factory StateMgr;
Ted Kremenekd27f8162008-01-15 23:55:06 +0000427
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000428 /// ValueMgr - Object that manages the data for all created ExprValues.
429 ValueManager ValMgr;
430
431 /// cfg - the current CFG.
Ted Kremenekd27f8162008-01-15 23:55:06 +0000432 CFG* cfg;
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000433
434 /// StmtEntryNode - The immediate predecessor node.
435 NodeTy* StmtEntryNode;
436
437 /// CurrentStmt - The current block-level statement.
438 Stmt* CurrentStmt;
439
440 bool StateCleaned;
Ted Kremenekd27f8162008-01-15 23:55:06 +0000441
Ted Kremenekd27f8162008-01-15 23:55:06 +0000442public:
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000443 GRConstants() : Liveness(NULL), Builder(NULL), cfg(NULL),
444 StmtEntryNode(NULL), CurrentStmt(NULL) {}
Ted Kremenekd27f8162008-01-15 23:55:06 +0000445
446 ~GRConstants() { delete Liveness; }
447
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000448 /// getCFG - Returns the CFG associated with this analysis.
Ted Kremenekd27f8162008-01-15 23:55:06 +0000449 CFG& getCFG() { assert (cfg); return *cfg; }
450
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000451 /// Initialize - Initialize the checker's state based on the specified
452 /// CFG. This results in liveness information being computed for
453 /// each block-level statement in the CFG.
Ted Kremenekd27f8162008-01-15 23:55:06 +0000454 void Initialize(CFG& c) {
455 cfg = &c;
456 Liveness = new LiveVariables(c);
457 Liveness->runOnCFG(c);
Ted Kremenek79649df2008-01-17 18:25:22 +0000458 Liveness->runOnAllBlocks(c, NULL, true);
Ted Kremenekd27f8162008-01-15 23:55:06 +0000459 }
460
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000461 /// getInitialState - Return the initial state used for the root vertex
462 /// in the ExplodedGraph.
Ted Kremenekd27f8162008-01-15 23:55:06 +0000463 StateTy getInitialState() {
Ted Kremenekcb448ca2008-01-16 00:53:15 +0000464 return StateMgr.GetEmptyMap();
Ted Kremenekd27f8162008-01-15 23:55:06 +0000465 }
Ted Kremenekd27f8162008-01-15 23:55:06 +0000466
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000467 /// ProcessStmt - Called by GREngine. Used to generate new successor
468 /// nodes by processing the 'effects' of a block-level statement.
469 void ProcessStmt(Stmt* S, NodeBuilder& builder);
470
471 /// RemoveDeadBindings - Return a new state that is the same as 'M' except
472 /// that all subexpression mappings are removed and that any
473 /// block-level expressions that are not live at 'S' also have their
474 /// mappings removed.
475 StateTy RemoveDeadBindings(Stmt* S, StateTy M);
476
477 StateTy SetValue(StateTy St, Stmt* S, const ExprValue& V,
478 bool isBlkExpr = false);
479
480 StateTy SetValue(StateTy St, const LValue& LV, const ExprValue& V);
Ted Kremenek1ccd31c2008-01-16 19:42:59 +0000481
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000482 ExprValue GetValue(const StateTy& St, Stmt* S);
483 ExprValue GetValue(const StateTy& St, const LValue& LV);
484 LValue GetLValue(const StateTy& St, Stmt* S);
Ted Kremenekd27f8162008-01-15 23:55:06 +0000485
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000486 void Nodify(NodeSet& Dst, Stmt* S, NodeTy* Pred, StateTy St);
Ted Kremenekd27f8162008-01-15 23:55:06 +0000487
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000488 /// Visit - Transfer function logic for all statements. Dispatches to
489 /// other functions that handle specific kinds of statements.
490 void Visit(Stmt* S, NodeTy* Pred, NodeSet& Dst);
491
492 /// VisitBinaryOperator - Transfer function logic for binary operators.
493 void VisitBinaryOperator(BinaryOperator* B, NodeTy* Pred, NodeSet& Dst);
Ted Kremenekd27f8162008-01-15 23:55:06 +0000494};
495} // end anonymous namespace
496
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000497
Ted Kremenekd27f8162008-01-15 23:55:06 +0000498void GRConstants::ProcessStmt(Stmt* S, NodeBuilder& builder) {
499 Builder = &builder;
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000500
501 StmtEntryNode = builder.getLastNode();
502 CurrentStmt = S;
503 NodeSet Dst;
504 StateCleaned = false;
505
506 Visit(S, StmtEntryNode, Dst);
507
508 // If no nodes were generated, generate a new node that has all the
509 // dead mappings removed.
510 if (Dst.size() == 1 && *Dst.begin() == StmtEntryNode) {
511 StateTy St = RemoveDeadBindings(S, StmtEntryNode->getState());
512 builder.generateNode(S, St, StmtEntryNode);
513 }
Ted Kremenekf84469b2008-01-18 00:41:32 +0000514
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000515 CurrentStmt = NULL;
516 StmtEntryNode = NULL;
517 Builder = NULL;
Ted Kremenekd27f8162008-01-15 23:55:06 +0000518}
519
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000520
521ExprValue GRConstants::GetValue(const StateTy& St, const LValue& LV) {
522 switch (LV.getKind()) {
523 case ExprValue::LValueDeclKind: {
524 StateTy::TreeTy* T = St.SlimFind(cast<LValueDecl>(LV).getDecl());
525 return T ? T->getValue().second : InvalidValue();
526 }
527 default:
528 assert (false && "Invalid LValue.");
Ted Kremenekca3e8572008-01-16 22:28:08 +0000529 break;
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000530 }
531
532 return InvalidValue();
533}
534
535ExprValue GRConstants::GetValue(const StateTy& St, Stmt* S) {
536 if (Expr* E = dyn_cast<Expr>(S))
537 S = E->IgnoreParens();
538
539 switch (S->getStmtClass()) {
540 case Stmt::DeclRefExprClass:
541 return GetValue(St, LValueDecl(cast<DeclRefExpr>(S)->getDecl()));
Ted Kremenekca3e8572008-01-16 22:28:08 +0000542
543 case Stmt::IntegerLiteralClass:
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000544 return RValue::GetRValue(ValMgr, cast<IntegerLiteral>(S));
545
546 default:
Ted Kremenekca3e8572008-01-16 22:28:08 +0000547 break;
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000548 };
549
550 StateTy::TreeTy* T = St.SlimFind(ValueKey(S, getCFG().isBlkExpr(S)));
551 return T ? T->getValue().second : InvalidValue();
552}
553
554LValue GRConstants::GetLValue(const StateTy& St, Stmt* S) {
555 if (Expr* E = dyn_cast<Expr>(S))
556 S = E->IgnoreParens();
557
558 if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(S))
559 return LValueDecl(DR->getDecl());
560
561 return cast<LValue>(GetValue(St, S));
562}
563
564GRConstants::StateTy GRConstants::SetValue(StateTy St, Stmt* S,
565 const ExprValue& V, bool isBlkExpr) {
566
567 if (!StateCleaned) {
568 St = RemoveDeadBindings(CurrentStmt, St);
569 StateCleaned = true;
570 }
571
572 return V.isValid() ? StateMgr.Add(St, ValueKey(S,isBlkExpr), V)
573 : St;
574}
575
576GRConstants::StateTy GRConstants::SetValue(StateTy St, const LValue& LV,
577 const ExprValue& V) {
578 if (!LV.isValid())
579 return St;
580
581 if (!StateCleaned) {
582 St = RemoveDeadBindings(CurrentStmt, St);
583 StateCleaned = true;
Ted Kremenekca3e8572008-01-16 22:28:08 +0000584 }
Ted Kremenek0525a4f2008-01-16 19:47:19 +0000585
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000586 switch (LV.getKind()) {
587 case ExprValue::LValueDeclKind:
588 return V.isValid() ? StateMgr.Add(St, cast<LValueDecl>(LV).getDecl(), V)
589 : StateMgr.Remove(St, cast<LValueDecl>(LV).getDecl());
590
591 default:
592 assert ("SetValue for given LValue type not yet implemented.");
593 return St;
594 }
Ted Kremenekd27f8162008-01-15 23:55:06 +0000595}
596
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000597GRConstants::StateTy GRConstants::RemoveDeadBindings(Stmt* Loc, StateTy M) {
Ted Kremenekf84469b2008-01-18 00:41:32 +0000598 // Note: in the code below, we can assign a new map to M since the
599 // iterators are iterating over the tree of the *original* map.
Ted Kremenekf84469b2008-01-18 00:41:32 +0000600 StateTy::iterator I = M.begin(), E = M.end();
601
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000602 // Remove old bindings for subexpressions.
603 for (; I!=E && I.getKey().getKind() == ValueKey::IsSubExp; ++I)
Ted Kremeneke00fe3f2008-01-17 00:52:48 +0000604 M = StateMgr.Remove(M, I.getKey());
Ted Kremenekf84469b2008-01-18 00:41:32 +0000605
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000606 // Remove bindings for "dead" decls.
607 for (; I!=E && I.getKey().getKind() == ValueKey::IsDecl; ++I)
608 if (VarDecl* V = dyn_cast<VarDecl>(cast<ValueDecl>(I.getKey())))
609 if (!Liveness->isLive(Loc, V))
610 M = StateMgr.Remove(M, I.getKey());
611
612 // Remove bindings for "dead" block-level expressions.
613 for (; I!=E; ++I)
614 if (!Liveness->isLive(Loc, cast<Stmt>(I.getKey())))
615 M = StateMgr.Remove(M, I.getKey());
Ted Kremeneke00fe3f2008-01-17 00:52:48 +0000616
617 return M;
Ted Kremeneke00fe3f2008-01-17 00:52:48 +0000618}
619
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000620void GRConstants::Nodify(NodeSet& Dst, Stmt* S, GRConstants::NodeTy* Pred,
621 GRConstants::StateTy St) {
622
623 // If the state hasn't changed, don't generate a new node.
624 if (St == Pred->getState())
625 return;
Ted Kremenekcb448ca2008-01-16 00:53:15 +0000626
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000627 Dst.Add(Builder->generateNode(S, St, Pred));
Ted Kremenekcb448ca2008-01-16 00:53:15 +0000628}
Ted Kremenekd27f8162008-01-15 23:55:06 +0000629
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000630void GRConstants::VisitBinaryOperator(BinaryOperator* B,
631 GRConstants::NodeTy* Pred,
632 GRConstants::NodeSet& Dst) {
633 NodeSet S1;
634 Visit(B->getLHS(), Pred, S1);
Ted Kremenekcb448ca2008-01-16 00:53:15 +0000635
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000636 for (NodeSet::iterator I1=S1.begin(), E1=S1.end(); I1 != E1; ++I1) {
637 NodeTy* N1 = *I1;
Ted Kremeneke00fe3f2008-01-17 00:52:48 +0000638
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000639 // When getting the value for the LHS, check if we are in an assignment.
640 // In such cases, we want to (initially) treat the LHS as an LValue,
641 // so we use GetLValue instead of GetValue so that DeclRefExpr's are
642 // evaluated to LValueDecl's instead of to an RValue.
643 const ExprValue& V1 =
644 B->isAssignmentOp() ? GetLValue(N1->getState(), B->getLHS())
645 : GetValue(N1->getState(), B->getLHS());
Ted Kremenekcb448ca2008-01-16 00:53:15 +0000646
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000647 NodeSet S2;
648 Visit(B->getRHS(), N1, S2);
649
650 for (NodeSet::iterator I2=S2.begin(), E2=S2.end(); I2 != E2; ++I2) {
651 NodeTy* N2 = *I2;
652 StateTy St = N2->getState();
653 const ExprValue& V2 = GetValue(St, B->getRHS());
654
655 switch (B->getOpcode()) {
656 case BinaryOperator::Add: {
657 const RValue& R1 = cast<RValue>(V1);
658 const RValue& R2 = cast<RValue>(V2);
659
660 Nodify(Dst, B, N2, SetValue(St, B, R1.Add(ValMgr, R2)));
661 break;
662 }
663
664 case BinaryOperator::Sub: {
665 const RValue& R1 = cast<RValue>(V1);
666 const RValue& R2 = cast<RValue>(V2);
667
668 Nodify(Dst, B, N2, SetValue(St, B, R1.Sub(ValMgr, R2)));
669 break;
670 }
671
672 case BinaryOperator::Assign: {
673 const LValue& L1 = cast<LValue>(V1);
674 const RValue& R2 = cast<RValue>(V2);
675
676 Nodify(Dst, B, N2, SetValue(SetValue(St, B, R2), L1, R2));
677 break;
678 }
679
680 default:
681 Dst.Add(N2);
682 break;
683 }
Ted Kremenekcb448ca2008-01-16 00:53:15 +0000684 }
Ted Kremenekd27f8162008-01-15 23:55:06 +0000685 }
Ted Kremenekd27f8162008-01-15 23:55:06 +0000686}
Ted Kremenekee985462008-01-16 18:18:48 +0000687
Ted Kremenek1ccd31c2008-01-16 19:42:59 +0000688
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000689void GRConstants::Visit(Stmt* S, GRConstants::NodeTy* Pred,
690 GRConstants::NodeSet& Dst) {
691
692 // FIXME: add metadata to the CFG so that we can disable
693 // this check when we KNOW that there is no block-level subexpression.
694 // The motivation is that this check requires a hashtable lookup.
695
696 if (S != CurrentStmt && getCFG().isBlkExpr(S)) {
697 Dst.Add(Pred);
698 return;
699 }
700
701 switch (S->getStmtClass()) {
702 case Stmt::BinaryOperatorClass:
703 VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Dst);
704 break;
705
706 case Stmt::ParenExprClass:
707 Visit(cast<ParenExpr>(S)->getSubExpr(), Pred, Dst);
708 break;
709
710 default:
711 Dst.Add(Pred); // No-op. Simply propagate the current state unchanged.
712 break;
Ted Kremenek79649df2008-01-17 18:25:22 +0000713 }
Ted Kremenek1ccd31c2008-01-16 19:42:59 +0000714}
715
Ted Kremenekee985462008-01-16 18:18:48 +0000716//===----------------------------------------------------------------------===//
717// Driver.
718//===----------------------------------------------------------------------===//
719
Ted Kremenekaa66a322008-01-16 21:46:15 +0000720#ifndef NDEBUG
721namespace llvm {
722template<>
723struct VISIBILITY_HIDDEN DOTGraphTraits<GRConstants::NodeTy*> :
724 public DefaultDOTGraphTraits {
725
Ted Kremenek803c9ed2008-01-23 22:30:44 +0000726 static void PrintKind(std::ostringstream& Out, ValueKey::Kind kind) {
727 switch (kind) {
728 case ValueKey::IsSubExp: Out << "Sub-Expressions:\\l"; break;
729 case ValueKey::IsDecl: Out << "Variables:\\l"; break;
730 case ValueKey::IsBlkExpr: Out << "Block-level Expressions:\\l"; break;
731 default: assert (false && "Unknown ValueKey type.");
732 }
733 }
734
Ted Kremenekaa66a322008-01-16 21:46:15 +0000735 static std::string getNodeLabel(const GRConstants::NodeTy* N, void*) {
736 std::ostringstream Out;
Ted Kremenek803c9ed2008-01-23 22:30:44 +0000737
738 // Program Location.
Ted Kremenekaa66a322008-01-16 21:46:15 +0000739 ProgramPoint Loc = N->getLocation();
740
741 switch (Loc.getKind()) {
742 case ProgramPoint::BlockEntranceKind:
743 Out << "Block Entrance: B"
744 << cast<BlockEntrance>(Loc).getBlock()->getBlockID();
745 break;
746
747 case ProgramPoint::BlockExitKind:
748 assert (false);
749 break;
750
751 case ProgramPoint::PostStmtKind: {
752 const PostStmt& L = cast<PostStmt>(Loc);
Ted Kremenek803c9ed2008-01-23 22:30:44 +0000753 Out << "(" << (void*) L.getStmt() << ") ";
Ted Kremenekaa66a322008-01-16 21:46:15 +0000754 L.getStmt()->printPretty(Out);
755 break;
756 }
757
758 default: {
759 const BlockEdge& E = cast<BlockEdge>(Loc);
760 Out << "Edge: (B" << E.getSrc()->getBlockID() << ", B"
761 << E.getDst()->getBlockID() << ')';
762 }
763 }
764
Ted Kremenek803c9ed2008-01-23 22:30:44 +0000765 Out << "\\|";
Ted Kremenekaa66a322008-01-16 21:46:15 +0000766
767 GRConstants::StateTy M = N->getState();
768 bool isFirst = true;
Ted Kremenek803c9ed2008-01-23 22:30:44 +0000769 ValueKey::Kind kind;
Ted Kremenekaa66a322008-01-16 21:46:15 +0000770
771 for (GRConstants::StateTy::iterator I=M.begin(), E=M.end(); I!=E; ++I) {
Ted Kremenek803c9ed2008-01-23 22:30:44 +0000772 if (!isFirst) {
773 ValueKey::Kind newKind = I.getKey().getKind();
774
775 if (newKind != kind) {
776 Out << "\\l\\l";
777 PrintKind(Out, newKind);
778 }
779 else
780 Out << "\\l";
781
782 kind = newKind;
783 }
784 else {
785 kind = I.getKey().getKind();
786 PrintKind(Out, kind);
Ted Kremenekaa66a322008-01-16 21:46:15 +0000787 isFirst = false;
Ted Kremenek803c9ed2008-01-23 22:30:44 +0000788 }
789
790 Out << ' ';
Ted Kremenekaa66a322008-01-16 21:46:15 +0000791
792 if (ValueDecl* V = dyn_cast<ValueDecl>(I.getKey())) {
Ted Kremenek803c9ed2008-01-23 22:30:44 +0000793 Out << V->getName();
Ted Kremenekaa66a322008-01-16 21:46:15 +0000794 }
795 else {
796 Stmt* E = cast<Stmt>(I.getKey());
Ted Kremenek803c9ed2008-01-23 22:30:44 +0000797 Out << " (" << (void*) E << ") ";
798 E->printPretty(Out);
Ted Kremenekaa66a322008-01-16 21:46:15 +0000799 }
800
Ted Kremenek803c9ed2008-01-23 22:30:44 +0000801 Out << " : ";
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000802 I.getData().print(Out);
Ted Kremenekaa66a322008-01-16 21:46:15 +0000803 }
804
Ted Kremenek803c9ed2008-01-23 22:30:44 +0000805 Out << "\\l";
Ted Kremenekaa66a322008-01-16 21:46:15 +0000806 return Out.str();
807 }
808};
809} // end llvm namespace
810#endif
811
Ted Kremenekee985462008-01-16 18:18:48 +0000812namespace clang {
813void RunGRConstants(CFG& cfg) {
814 GREngine<GRConstants> Engine(cfg);
815 Engine.ExecuteWorkList();
Ted Kremenekaa66a322008-01-16 21:46:15 +0000816#ifndef NDEBUG
817 llvm::ViewGraph(*Engine.getGraph().roots_begin(),"GRConstants");
818#endif
Ted Kremenekee985462008-01-16 18:18:48 +0000819}
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000820} // end clang namespace