blob: 62b007ab30b3e6f4f0770262a6e75efaeaac7248 [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;
Ted Kremenek2eafd0e2008-01-23 23:42:27 +0000209 RValue Mul(ValueManager& ValMgr, const RValue& RHS) const;
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000210
211 static RValue GetRValue(ValueManager& ValMgr, IntegerLiteral* S);
212
213 // Implement isa<T> support.
214 static inline bool classof(const ExprValue* V) {
215 return V->getKind() >= MinRValueKind;
216 }
217};
218
219class VISIBILITY_HIDDEN RValueMayEqualSet : public RValue {
220public:
221 RValueMayEqualSet(const APSIntSetTy& S)
222 : RValue(RValueMayEqualSetKind, S.getRoot()) {}
223
224 APSIntSetTy GetValues() const {
225 return APSIntSetTy(reinterpret_cast<APSIntSetTy::TreeTy*>(getRawPtr()));
226 }
227
228 RValueMayEqualSet Add(ValueManager& ValMgr, const RValueMayEqualSet& V) const;
Ted Kremenek2eafd0e2008-01-23 23:42:27 +0000229 RValueMayEqualSet Sub(ValueManager& ValMgr, const RValueMayEqualSet& V) const;
230 RValueMayEqualSet Mul(ValueManager& ValMgr, const RValueMayEqualSet& V) const;
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000231
232 // Implement isa<T> support.
233 static inline bool classof(const ExprValue* V) {
234 return V->getKind() == RValueMayEqualSetKind;
235 }
236};
237} // end anonymous namespace
238
239//===----------------------------------------------------------------------===//
240// "R-Values": Implementation.
241//===----------------------------------------------------------------------===//
242
243#define RVALUE_DISPATCH_CASE(k1,k2,Op)\
244case ((k1##Kind+(MaxRValueKind-MinRValueKind))+(k2##Kind - MinRValueKind)):\
245 return cast<k1>(*this).Op(ValMgr,cast<k2>(RHS));
246
247#define RVALUE_DISPATCH(Op)\
248switch (getKind()+(MaxRValueKind-MinRValueKind)+(RHS.getKind()-MinRValueKind)){\
249 RVALUE_DISPATCH_CASE(RValueMayEqualSet,RValueMayEqualSet,Op)\
250 default:\
251 assert (!isValid() || !RHS.isValid() && "Missing case.");\
252 break;\
253}\
254return cast<RValue>(InvalidValue());
255
256RValue RValue::Add(ValueManager& ValMgr, const RValue& RHS) const {
257 RVALUE_DISPATCH(Add)
258}
259
260RValue RValue::Sub(ValueManager& ValMgr, const RValue& RHS) const {
261 RVALUE_DISPATCH(Sub)
262}
263
Ted Kremenek2eafd0e2008-01-23 23:42:27 +0000264RValue RValue::Mul(ValueManager& ValMgr, const RValue& RHS) const {
265 RVALUE_DISPATCH(Mul)
266}
267
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000268#undef RVALUE_DISPATCH_CASE
269#undef RVALUE_DISPATCH
270
271RValueMayEqualSet
272RValueMayEqualSet::Add(ValueManager& ValMgr,
273 const RValueMayEqualSet& RHS) const {
274
275 APSIntSetTy S1 = GetValues();
276 APSIntSetTy S2 = RHS.GetValues();
277
278 APSIntSetTy M = ValMgr.GetEmptyAPSIntSet();
279
280 for (APSIntSetTy::iterator I1=S1.begin(), E1=S2.end(); I1!=E1; ++I1)
281 for (APSIntSetTy::iterator I2=S2.begin(), E2=S2.end(); I2!=E2; ++I2)
282 M = ValMgr.AddToSet(M, *I1 + *I2);
283
284 return M;
285}
286
287RValueMayEqualSet
288RValueMayEqualSet::Sub(ValueManager& ValMgr,
289 const RValueMayEqualSet& RHS) const {
290
291 APSIntSetTy S1 = GetValues();
292 APSIntSetTy S2 = RHS.GetValues();
293
294 APSIntSetTy M = ValMgr.GetEmptyAPSIntSet();
295
296 for (APSIntSetTy::iterator I1=S1.begin(), E1=S2.end(); I1!=E1; ++I1)
297 for (APSIntSetTy::iterator I2=S2.begin(), E2=S2.end(); I2!=E2; ++I2)
298 M = ValMgr.AddToSet(M, *I1 - *I2);
299
300 return M;
301}
302
Ted Kremenek2eafd0e2008-01-23 23:42:27 +0000303RValueMayEqualSet
304RValueMayEqualSet::Mul(ValueManager& ValMgr,
305 const RValueMayEqualSet& RHS) const {
306
307 APSIntSetTy S1 = GetValues();
308 APSIntSetTy S2 = RHS.GetValues();
309
310 APSIntSetTy M = ValMgr.GetEmptyAPSIntSet();
311
312 for (APSIntSetTy::iterator I1=S1.begin(), E1=S2.end(); I1!=E1; ++I1)
313 for (APSIntSetTy::iterator I2=S2.begin(), E2=S2.end(); I2!=E2; ++I2)
314 M = ValMgr.AddToSet(M, *I1 * *I2);
315
316 return M;
317}
318
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000319RValue RValue::GetRValue(ValueManager& ValMgr, IntegerLiteral* S) {
320 return RValueMayEqualSet(ValMgr.AddToSet(ValMgr.GetEmptyAPSIntSet(),
321 S->getValue()));
322}
323
324//===----------------------------------------------------------------------===//
325// "L-Values".
326//===----------------------------------------------------------------------===//
327
328namespace {
329
330class VISIBILITY_HIDDEN LValue : public ExprValue {
331protected:
332 LValue(Kind k, void* D) : ExprValue(k, D) {}
333
334public:
335 // Implement isa<T> support.
336 static inline bool classof(const ExprValue* V) {
337 return V->getKind() <= MaxLValueKind;
338 }
339};
340
341class VISIBILITY_HIDDEN LValueDecl : public LValue {
342public:
343 LValueDecl(ValueDecl* vd) : LValue(LValueDeclKind,vd) {}
344
345 ValueDecl* getDecl() const {
346 return static_cast<ValueDecl*>(getRawPtr());
347 }
348
349 // Implement isa<T> support.
350 static inline bool classof(const ExprValue* V) {
351 return V->getKind() == LValueDeclKind;
352 }
353};
354} // end anonymous namespace
355
356//===----------------------------------------------------------------------===//
357// Pretty-Printing.
358//===----------------------------------------------------------------------===//
359
360void ExprValue::print(std::ostream& Out) const {
361 switch (getKind()) {
362 case InvalidValueKind:
363 Out << "Invalid"; break;
364
365 case RValueMayEqualSetKind: {
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000366 APSIntSetTy S = cast<RValueMayEqualSet>(this)->GetValues();
Ted Kremenek803c9ed2008-01-23 22:30:44 +0000367 bool first = true;
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000368
Ted Kremenek803c9ed2008-01-23 22:30:44 +0000369 for (APSIntSetTy::iterator I=S.begin(), E=S.end(); I!=E; ++I) {
370 if (first) first = false;
371 else Out << " | ";
372
373 Out << (*I).toString();
374 }
375
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000376 break;
377 }
378
379 default:
380 assert (false && "Pretty-printed not implemented for this ExprValue.");
381 break;
382 }
383}
384
385//===----------------------------------------------------------------------===//
386// ValueMapTy - A ImmutableMap type Stmt*/Decl* to ExprValues.
387//===----------------------------------------------------------------------===//
388
389typedef llvm::ImmutableMap<ValueKey,ExprValue> ValueMapTy;
390
391namespace clang {
392 template<>
393 struct VISIBILITY_HIDDEN GRTrait<ValueMapTy> {
394 static inline void* toPtr(ValueMapTy M) {
395 return reinterpret_cast<void*>(M.getRoot());
396 }
397 static inline ValueMapTy toState(void* P) {
398 return ValueMapTy(static_cast<ValueMapTy::TreeTy*>(P));
399 }
400 };
Ted Kremenekd27f8162008-01-15 23:55:06 +0000401}
402
403//===----------------------------------------------------------------------===//
404// The Checker!
405//===----------------------------------------------------------------------===//
406
407namespace {
Ted Kremenekd27f8162008-01-15 23:55:06 +0000408
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000409class VISIBILITY_HIDDEN GRConstants {
Ted Kremenekd27f8162008-01-15 23:55:06 +0000410
411public:
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000412 typedef ValueMapTy StateTy;
Ted Kremenekd27f8162008-01-15 23:55:06 +0000413 typedef GRNodeBuilder<GRConstants> NodeBuilder;
414 typedef ExplodedNode<StateTy> NodeTy;
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000415
416 class NodeSet {
417 typedef llvm::SmallVector<NodeTy*,3> ImplTy;
418 ImplTy Impl;
419 public:
420
421 NodeSet() {}
422 NodeSet(NodeTy* N) { assert (N && !N->isInfeasible()); Impl.push_back(N); }
423
424 void Add(NodeTy* N) { if (N && !N->isInfeasible()) Impl.push_back(N); }
425
426 typedef ImplTy::iterator iterator;
427 typedef ImplTy::const_iterator const_iterator;
428
429 unsigned size() const { return Impl.size(); }
430
431 iterator begin() { return Impl.begin(); }
432 iterator end() { return Impl.end(); }
433
434 const_iterator begin() const { return Impl.begin(); }
435 const_iterator end() const { return Impl.end(); }
436 };
Ted Kremenekd27f8162008-01-15 23:55:06 +0000437
438protected:
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000439 /// Liveness - live-variables information the ValueDecl* and block-level
440 /// Expr* in the CFG. Used to prune out dead state.
Ted Kremenekd27f8162008-01-15 23:55:06 +0000441 LiveVariables* Liveness;
442
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000443 /// Builder - The current GRNodeBuilder which is used when building the nodes
444 /// for a given statement.
Ted Kremenekd27f8162008-01-15 23:55:06 +0000445 NodeBuilder* Builder;
446
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000447 /// StateMgr - Object that manages the data for all created states.
448 ValueMapTy::Factory StateMgr;
Ted Kremenekd27f8162008-01-15 23:55:06 +0000449
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000450 /// ValueMgr - Object that manages the data for all created ExprValues.
451 ValueManager ValMgr;
452
453 /// cfg - the current CFG.
Ted Kremenekd27f8162008-01-15 23:55:06 +0000454 CFG* cfg;
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000455
456 /// StmtEntryNode - The immediate predecessor node.
457 NodeTy* StmtEntryNode;
458
459 /// CurrentStmt - The current block-level statement.
460 Stmt* CurrentStmt;
461
462 bool StateCleaned;
Ted Kremenekd27f8162008-01-15 23:55:06 +0000463
Ted Kremenekd27f8162008-01-15 23:55:06 +0000464public:
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000465 GRConstants() : Liveness(NULL), Builder(NULL), cfg(NULL),
466 StmtEntryNode(NULL), CurrentStmt(NULL) {}
Ted Kremenekd27f8162008-01-15 23:55:06 +0000467
468 ~GRConstants() { delete Liveness; }
469
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000470 /// getCFG - Returns the CFG associated with this analysis.
Ted Kremenekd27f8162008-01-15 23:55:06 +0000471 CFG& getCFG() { assert (cfg); return *cfg; }
472
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000473 /// Initialize - Initialize the checker's state based on the specified
474 /// CFG. This results in liveness information being computed for
475 /// each block-level statement in the CFG.
Ted Kremenekd27f8162008-01-15 23:55:06 +0000476 void Initialize(CFG& c) {
477 cfg = &c;
478 Liveness = new LiveVariables(c);
479 Liveness->runOnCFG(c);
Ted Kremenek79649df2008-01-17 18:25:22 +0000480 Liveness->runOnAllBlocks(c, NULL, true);
Ted Kremenekd27f8162008-01-15 23:55:06 +0000481 }
482
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000483 /// getInitialState - Return the initial state used for the root vertex
484 /// in the ExplodedGraph.
Ted Kremenekd27f8162008-01-15 23:55:06 +0000485 StateTy getInitialState() {
Ted Kremenekcb448ca2008-01-16 00:53:15 +0000486 return StateMgr.GetEmptyMap();
Ted Kremenekd27f8162008-01-15 23:55:06 +0000487 }
Ted Kremenekd27f8162008-01-15 23:55:06 +0000488
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000489 /// ProcessStmt - Called by GREngine. Used to generate new successor
490 /// nodes by processing the 'effects' of a block-level statement.
491 void ProcessStmt(Stmt* S, NodeBuilder& builder);
492
493 /// RemoveDeadBindings - Return a new state that is the same as 'M' except
494 /// that all subexpression mappings are removed and that any
495 /// block-level expressions that are not live at 'S' also have their
496 /// mappings removed.
497 StateTy RemoveDeadBindings(Stmt* S, StateTy M);
498
499 StateTy SetValue(StateTy St, Stmt* S, const ExprValue& V,
500 bool isBlkExpr = false);
501
502 StateTy SetValue(StateTy St, const LValue& LV, const ExprValue& V);
Ted Kremenek1ccd31c2008-01-16 19:42:59 +0000503
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000504 ExprValue GetValue(const StateTy& St, Stmt* S);
505 ExprValue GetValue(const StateTy& St, const LValue& LV);
506 LValue GetLValue(const StateTy& St, Stmt* S);
Ted Kremenekd27f8162008-01-15 23:55:06 +0000507
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000508 void Nodify(NodeSet& Dst, Stmt* S, NodeTy* Pred, StateTy St);
Ted Kremenekd27f8162008-01-15 23:55:06 +0000509
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000510 /// Visit - Transfer function logic for all statements. Dispatches to
511 /// other functions that handle specific kinds of statements.
512 void Visit(Stmt* S, NodeTy* Pred, NodeSet& Dst);
513
514 /// VisitBinaryOperator - Transfer function logic for binary operators.
515 void VisitBinaryOperator(BinaryOperator* B, NodeTy* Pred, NodeSet& Dst);
Ted Kremenekd27f8162008-01-15 23:55:06 +0000516};
517} // end anonymous namespace
518
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000519
Ted Kremenekd27f8162008-01-15 23:55:06 +0000520void GRConstants::ProcessStmt(Stmt* S, NodeBuilder& builder) {
521 Builder = &builder;
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000522
523 StmtEntryNode = builder.getLastNode();
524 CurrentStmt = S;
525 NodeSet Dst;
526 StateCleaned = false;
527
528 Visit(S, StmtEntryNode, Dst);
529
530 // If no nodes were generated, generate a new node that has all the
531 // dead mappings removed.
532 if (Dst.size() == 1 && *Dst.begin() == StmtEntryNode) {
533 StateTy St = RemoveDeadBindings(S, StmtEntryNode->getState());
534 builder.generateNode(S, St, StmtEntryNode);
535 }
Ted Kremenekf84469b2008-01-18 00:41:32 +0000536
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000537 CurrentStmt = NULL;
538 StmtEntryNode = NULL;
539 Builder = NULL;
Ted Kremenekd27f8162008-01-15 23:55:06 +0000540}
541
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000542
543ExprValue GRConstants::GetValue(const StateTy& St, const LValue& LV) {
544 switch (LV.getKind()) {
545 case ExprValue::LValueDeclKind: {
546 StateTy::TreeTy* T = St.SlimFind(cast<LValueDecl>(LV).getDecl());
547 return T ? T->getValue().second : InvalidValue();
548 }
549 default:
550 assert (false && "Invalid LValue.");
Ted Kremenekca3e8572008-01-16 22:28:08 +0000551 break;
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000552 }
553
554 return InvalidValue();
555}
556
557ExprValue GRConstants::GetValue(const StateTy& St, Stmt* S) {
558 if (Expr* E = dyn_cast<Expr>(S))
559 S = E->IgnoreParens();
560
561 switch (S->getStmtClass()) {
562 case Stmt::DeclRefExprClass:
563 return GetValue(St, LValueDecl(cast<DeclRefExpr>(S)->getDecl()));
Ted Kremenekca3e8572008-01-16 22:28:08 +0000564
565 case Stmt::IntegerLiteralClass:
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000566 return RValue::GetRValue(ValMgr, cast<IntegerLiteral>(S));
567
568 default:
Ted Kremenekca3e8572008-01-16 22:28:08 +0000569 break;
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000570 };
571
572 StateTy::TreeTy* T = St.SlimFind(ValueKey(S, getCFG().isBlkExpr(S)));
573 return T ? T->getValue().second : InvalidValue();
574}
575
576LValue GRConstants::GetLValue(const StateTy& St, Stmt* S) {
577 if (Expr* E = dyn_cast<Expr>(S))
578 S = E->IgnoreParens();
579
580 if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(S))
581 return LValueDecl(DR->getDecl());
582
583 return cast<LValue>(GetValue(St, S));
584}
585
586GRConstants::StateTy GRConstants::SetValue(StateTy St, Stmt* S,
587 const ExprValue& V, bool isBlkExpr) {
588
589 if (!StateCleaned) {
590 St = RemoveDeadBindings(CurrentStmt, St);
591 StateCleaned = true;
592 }
593
594 return V.isValid() ? StateMgr.Add(St, ValueKey(S,isBlkExpr), V)
595 : St;
596}
597
598GRConstants::StateTy GRConstants::SetValue(StateTy St, const LValue& LV,
599 const ExprValue& V) {
600 if (!LV.isValid())
601 return St;
602
603 if (!StateCleaned) {
604 St = RemoveDeadBindings(CurrentStmt, St);
605 StateCleaned = true;
Ted Kremenekca3e8572008-01-16 22:28:08 +0000606 }
Ted Kremenek0525a4f2008-01-16 19:47:19 +0000607
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000608 switch (LV.getKind()) {
609 case ExprValue::LValueDeclKind:
610 return V.isValid() ? StateMgr.Add(St, cast<LValueDecl>(LV).getDecl(), V)
611 : StateMgr.Remove(St, cast<LValueDecl>(LV).getDecl());
612
613 default:
614 assert ("SetValue for given LValue type not yet implemented.");
615 return St;
616 }
Ted Kremenekd27f8162008-01-15 23:55:06 +0000617}
618
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000619GRConstants::StateTy GRConstants::RemoveDeadBindings(Stmt* Loc, StateTy M) {
Ted Kremenekf84469b2008-01-18 00:41:32 +0000620 // Note: in the code below, we can assign a new map to M since the
621 // iterators are iterating over the tree of the *original* map.
Ted Kremenekf84469b2008-01-18 00:41:32 +0000622 StateTy::iterator I = M.begin(), E = M.end();
623
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000624 // Remove old bindings for subexpressions.
625 for (; I!=E && I.getKey().getKind() == ValueKey::IsSubExp; ++I)
Ted Kremeneke00fe3f2008-01-17 00:52:48 +0000626 M = StateMgr.Remove(M, I.getKey());
Ted Kremenekf84469b2008-01-18 00:41:32 +0000627
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000628 // Remove bindings for "dead" decls.
629 for (; I!=E && I.getKey().getKind() == ValueKey::IsDecl; ++I)
630 if (VarDecl* V = dyn_cast<VarDecl>(cast<ValueDecl>(I.getKey())))
631 if (!Liveness->isLive(Loc, V))
632 M = StateMgr.Remove(M, I.getKey());
633
634 // Remove bindings for "dead" block-level expressions.
635 for (; I!=E; ++I)
636 if (!Liveness->isLive(Loc, cast<Stmt>(I.getKey())))
637 M = StateMgr.Remove(M, I.getKey());
Ted Kremeneke00fe3f2008-01-17 00:52:48 +0000638
639 return M;
Ted Kremeneke00fe3f2008-01-17 00:52:48 +0000640}
641
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000642void GRConstants::Nodify(NodeSet& Dst, Stmt* S, GRConstants::NodeTy* Pred,
643 GRConstants::StateTy St) {
644
645 // If the state hasn't changed, don't generate a new node.
646 if (St == Pred->getState())
647 return;
Ted Kremenekcb448ca2008-01-16 00:53:15 +0000648
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000649 Dst.Add(Builder->generateNode(S, St, Pred));
Ted Kremenekcb448ca2008-01-16 00:53:15 +0000650}
Ted Kremenekd27f8162008-01-15 23:55:06 +0000651
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000652void GRConstants::VisitBinaryOperator(BinaryOperator* B,
653 GRConstants::NodeTy* Pred,
654 GRConstants::NodeSet& Dst) {
655 NodeSet S1;
656 Visit(B->getLHS(), Pred, S1);
Ted Kremenekcb448ca2008-01-16 00:53:15 +0000657
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000658 for (NodeSet::iterator I1=S1.begin(), E1=S1.end(); I1 != E1; ++I1) {
659 NodeTy* N1 = *I1;
Ted Kremeneke00fe3f2008-01-17 00:52:48 +0000660
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000661 // When getting the value for the LHS, check if we are in an assignment.
662 // In such cases, we want to (initially) treat the LHS as an LValue,
663 // so we use GetLValue instead of GetValue so that DeclRefExpr's are
664 // evaluated to LValueDecl's instead of to an RValue.
665 const ExprValue& V1 =
666 B->isAssignmentOp() ? GetLValue(N1->getState(), B->getLHS())
667 : GetValue(N1->getState(), B->getLHS());
Ted Kremenekcb448ca2008-01-16 00:53:15 +0000668
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000669 NodeSet S2;
670 Visit(B->getRHS(), N1, S2);
671
672 for (NodeSet::iterator I2=S2.begin(), E2=S2.end(); I2 != E2; ++I2) {
673 NodeTy* N2 = *I2;
674 StateTy St = N2->getState();
675 const ExprValue& V2 = GetValue(St, B->getRHS());
676
677 switch (B->getOpcode()) {
678 case BinaryOperator::Add: {
679 const RValue& R1 = cast<RValue>(V1);
680 const RValue& R2 = cast<RValue>(V2);
681
682 Nodify(Dst, B, N2, SetValue(St, B, R1.Add(ValMgr, R2)));
683 break;
684 }
685
686 case BinaryOperator::Sub: {
687 const RValue& R1 = cast<RValue>(V1);
688 const RValue& R2 = cast<RValue>(V2);
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000689 Nodify(Dst, B, N2, SetValue(St, B, R1.Sub(ValMgr, R2)));
690 break;
691 }
692
Ted Kremenek2eafd0e2008-01-23 23:42:27 +0000693 case BinaryOperator::Mul: {
694 const RValue& R1 = cast<RValue>(V1);
695 const RValue& R2 = cast<RValue>(V2);
696 Nodify(Dst, B, N2, SetValue(St, B, R1.Mul(ValMgr, R2)));
697 break;
698 }
699
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000700 case BinaryOperator::Assign: {
701 const LValue& L1 = cast<LValue>(V1);
702 const RValue& R2 = cast<RValue>(V2);
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000703 Nodify(Dst, B, N2, SetValue(SetValue(St, B, R2), L1, R2));
704 break;
705 }
Ted Kremenekb4ae33f2008-01-23 23:38:00 +0000706
707 case BinaryOperator::AddAssign: {
708 const LValue& L1 = cast<LValue>(V1);
709 RValue R1 = cast<RValue>(GetValue(N1->getState(), L1));
710 RValue Result = R1.Add(ValMgr, cast<RValue>(V2));
711 Nodify(Dst, B, N2, SetValue(SetValue(St, B, Result), L1, Result));
712 break;
713 }
714
715 case BinaryOperator::SubAssign: {
716 const LValue& L1 = cast<LValue>(V1);
717 RValue R1 = cast<RValue>(GetValue(N1->getState(), L1));
718 RValue Result = R1.Sub(ValMgr, cast<RValue>(V2));
719 Nodify(Dst, B, N2, SetValue(SetValue(St, B, Result), L1, Result));
720 break;
721 }
Ted Kremenek2eafd0e2008-01-23 23:42:27 +0000722
723 case BinaryOperator::MulAssign: {
724 const LValue& L1 = cast<LValue>(V1);
725 RValue R1 = cast<RValue>(GetValue(N1->getState(), L1));
726 RValue Result = R1.Mul(ValMgr, cast<RValue>(V2));
727 Nodify(Dst, B, N2, SetValue(SetValue(St, B, Result), L1, Result));
728 break;
729 }
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000730
731 default:
732 Dst.Add(N2);
733 break;
734 }
Ted Kremenekcb448ca2008-01-16 00:53:15 +0000735 }
Ted Kremenekd27f8162008-01-15 23:55:06 +0000736 }
Ted Kremenekd27f8162008-01-15 23:55:06 +0000737}
Ted Kremenekee985462008-01-16 18:18:48 +0000738
Ted Kremenek1ccd31c2008-01-16 19:42:59 +0000739
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000740void GRConstants::Visit(Stmt* S, GRConstants::NodeTy* Pred,
741 GRConstants::NodeSet& Dst) {
742
743 // FIXME: add metadata to the CFG so that we can disable
744 // this check when we KNOW that there is no block-level subexpression.
745 // The motivation is that this check requires a hashtable lookup.
746
747 if (S != CurrentStmt && getCFG().isBlkExpr(S)) {
748 Dst.Add(Pred);
749 return;
750 }
751
752 switch (S->getStmtClass()) {
753 case Stmt::BinaryOperatorClass:
Ted Kremenekb4ae33f2008-01-23 23:38:00 +0000754 case Stmt::CompoundAssignOperatorClass:
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000755 VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Dst);
756 break;
757
758 case Stmt::ParenExprClass:
759 Visit(cast<ParenExpr>(S)->getSubExpr(), Pred, Dst);
760 break;
761
762 default:
763 Dst.Add(Pred); // No-op. Simply propagate the current state unchanged.
764 break;
Ted Kremenek79649df2008-01-17 18:25:22 +0000765 }
Ted Kremenek1ccd31c2008-01-16 19:42:59 +0000766}
767
Ted Kremenekee985462008-01-16 18:18:48 +0000768//===----------------------------------------------------------------------===//
769// Driver.
770//===----------------------------------------------------------------------===//
771
Ted Kremenekaa66a322008-01-16 21:46:15 +0000772#ifndef NDEBUG
773namespace llvm {
774template<>
775struct VISIBILITY_HIDDEN DOTGraphTraits<GRConstants::NodeTy*> :
776 public DefaultDOTGraphTraits {
777
Ted Kremenek803c9ed2008-01-23 22:30:44 +0000778 static void PrintKind(std::ostringstream& Out, ValueKey::Kind kind) {
779 switch (kind) {
780 case ValueKey::IsSubExp: Out << "Sub-Expressions:\\l"; break;
781 case ValueKey::IsDecl: Out << "Variables:\\l"; break;
782 case ValueKey::IsBlkExpr: Out << "Block-level Expressions:\\l"; break;
783 default: assert (false && "Unknown ValueKey type.");
784 }
785 }
786
Ted Kremenekaa66a322008-01-16 21:46:15 +0000787 static std::string getNodeLabel(const GRConstants::NodeTy* N, void*) {
788 std::ostringstream Out;
Ted Kremenek803c9ed2008-01-23 22:30:44 +0000789
790 // Program Location.
Ted Kremenekaa66a322008-01-16 21:46:15 +0000791 ProgramPoint Loc = N->getLocation();
792
793 switch (Loc.getKind()) {
794 case ProgramPoint::BlockEntranceKind:
795 Out << "Block Entrance: B"
796 << cast<BlockEntrance>(Loc).getBlock()->getBlockID();
797 break;
798
799 case ProgramPoint::BlockExitKind:
800 assert (false);
801 break;
802
803 case ProgramPoint::PostStmtKind: {
804 const PostStmt& L = cast<PostStmt>(Loc);
Ted Kremenek803c9ed2008-01-23 22:30:44 +0000805 Out << "(" << (void*) L.getStmt() << ") ";
Ted Kremenekaa66a322008-01-16 21:46:15 +0000806 L.getStmt()->printPretty(Out);
807 break;
808 }
809
810 default: {
811 const BlockEdge& E = cast<BlockEdge>(Loc);
812 Out << "Edge: (B" << E.getSrc()->getBlockID() << ", B"
813 << E.getDst()->getBlockID() << ')';
814 }
815 }
816
Ted Kremenek803c9ed2008-01-23 22:30:44 +0000817 Out << "\\|";
Ted Kremenekaa66a322008-01-16 21:46:15 +0000818
819 GRConstants::StateTy M = N->getState();
820 bool isFirst = true;
Ted Kremenek803c9ed2008-01-23 22:30:44 +0000821 ValueKey::Kind kind;
Ted Kremenekaa66a322008-01-16 21:46:15 +0000822
823 for (GRConstants::StateTy::iterator I=M.begin(), E=M.end(); I!=E; ++I) {
Ted Kremenek803c9ed2008-01-23 22:30:44 +0000824 if (!isFirst) {
825 ValueKey::Kind newKind = I.getKey().getKind();
826
827 if (newKind != kind) {
828 Out << "\\l\\l";
829 PrintKind(Out, newKind);
830 }
831 else
832 Out << "\\l";
833
834 kind = newKind;
835 }
836 else {
837 kind = I.getKey().getKind();
838 PrintKind(Out, kind);
Ted Kremenekaa66a322008-01-16 21:46:15 +0000839 isFirst = false;
Ted Kremenek803c9ed2008-01-23 22:30:44 +0000840 }
841
842 Out << ' ';
Ted Kremenekaa66a322008-01-16 21:46:15 +0000843
844 if (ValueDecl* V = dyn_cast<ValueDecl>(I.getKey())) {
Ted Kremenek803c9ed2008-01-23 22:30:44 +0000845 Out << V->getName();
Ted Kremenekaa66a322008-01-16 21:46:15 +0000846 }
847 else {
848 Stmt* E = cast<Stmt>(I.getKey());
Ted Kremenek803c9ed2008-01-23 22:30:44 +0000849 Out << " (" << (void*) E << ") ";
850 E->printPretty(Out);
Ted Kremenekaa66a322008-01-16 21:46:15 +0000851 }
852
Ted Kremenek803c9ed2008-01-23 22:30:44 +0000853 Out << " : ";
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000854 I.getData().print(Out);
Ted Kremenekaa66a322008-01-16 21:46:15 +0000855 }
856
Ted Kremenek803c9ed2008-01-23 22:30:44 +0000857 Out << "\\l";
Ted Kremenekaa66a322008-01-16 21:46:15 +0000858 return Out.str();
859 }
860};
861} // end llvm namespace
862#endif
863
Ted Kremenekee985462008-01-16 18:18:48 +0000864namespace clang {
865void RunGRConstants(CFG& cfg) {
866 GREngine<GRConstants> Engine(cfg);
867 Engine.ExecuteWorkList();
Ted Kremenekaa66a322008-01-16 21:46:15 +0000868#ifndef NDEBUG
869 llvm::ViewGraph(*Engine.getGraph().roots_begin(),"GRConstants");
870#endif
Ted Kremenekee985462008-01-16 18:18:48 +0000871}
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000872} // end clang namespace