blob: e1e664edb12496c0e4c55b225ec3aebc2af11a40 [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) {
Ted Kremenek671c9e82008-01-24 00:50:08 +0000558 for (;;) {
559 switch (S->getStmtClass()) {
560 case Stmt::ParenExprClass:
561 S = cast<ParenExpr>(S)->getSubExpr();
562 continue;
563
564 case Stmt::DeclRefExprClass:
565 return GetValue(St, LValueDecl(cast<DeclRefExpr>(S)->getDecl()));
Ted Kremenekca3e8572008-01-16 22:28:08 +0000566
Ted Kremenek671c9e82008-01-24 00:50:08 +0000567 case Stmt::IntegerLiteralClass:
568 return RValue::GetRValue(ValMgr, cast<IntegerLiteral>(S));
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000569
Ted Kremenek671c9e82008-01-24 00:50:08 +0000570 default:
571 break;
572 };
573
574 break;
575 }
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000576
577 StateTy::TreeTy* T = St.SlimFind(ValueKey(S, getCFG().isBlkExpr(S)));
578 return T ? T->getValue().second : InvalidValue();
579}
580
581LValue GRConstants::GetLValue(const StateTy& St, Stmt* S) {
582 if (Expr* E = dyn_cast<Expr>(S))
583 S = E->IgnoreParens();
584
585 if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(S))
586 return LValueDecl(DR->getDecl());
587
588 return cast<LValue>(GetValue(St, S));
589}
590
591GRConstants::StateTy GRConstants::SetValue(StateTy St, Stmt* S,
592 const ExprValue& V, bool isBlkExpr) {
593
594 if (!StateCleaned) {
595 St = RemoveDeadBindings(CurrentStmt, St);
596 StateCleaned = true;
597 }
598
599 return V.isValid() ? StateMgr.Add(St, ValueKey(S,isBlkExpr), V)
600 : St;
601}
602
603GRConstants::StateTy GRConstants::SetValue(StateTy St, const LValue& LV,
604 const ExprValue& V) {
605 if (!LV.isValid())
606 return St;
607
608 if (!StateCleaned) {
609 St = RemoveDeadBindings(CurrentStmt, St);
610 StateCleaned = true;
Ted Kremenekca3e8572008-01-16 22:28:08 +0000611 }
Ted Kremenek0525a4f2008-01-16 19:47:19 +0000612
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000613 switch (LV.getKind()) {
614 case ExprValue::LValueDeclKind:
615 return V.isValid() ? StateMgr.Add(St, cast<LValueDecl>(LV).getDecl(), V)
616 : StateMgr.Remove(St, cast<LValueDecl>(LV).getDecl());
617
618 default:
619 assert ("SetValue for given LValue type not yet implemented.");
620 return St;
621 }
Ted Kremenekd27f8162008-01-15 23:55:06 +0000622}
623
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000624GRConstants::StateTy GRConstants::RemoveDeadBindings(Stmt* Loc, StateTy M) {
Ted Kremenekf84469b2008-01-18 00:41:32 +0000625 // Note: in the code below, we can assign a new map to M since the
626 // iterators are iterating over the tree of the *original* map.
Ted Kremenekf84469b2008-01-18 00:41:32 +0000627 StateTy::iterator I = M.begin(), E = M.end();
628
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000629 // Remove old bindings for subexpressions.
630 for (; I!=E && I.getKey().getKind() == ValueKey::IsSubExp; ++I)
Ted Kremeneke00fe3f2008-01-17 00:52:48 +0000631 M = StateMgr.Remove(M, I.getKey());
Ted Kremenekf84469b2008-01-18 00:41:32 +0000632
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000633 // Remove bindings for "dead" decls.
634 for (; I!=E && I.getKey().getKind() == ValueKey::IsDecl; ++I)
635 if (VarDecl* V = dyn_cast<VarDecl>(cast<ValueDecl>(I.getKey())))
636 if (!Liveness->isLive(Loc, V))
637 M = StateMgr.Remove(M, I.getKey());
638
639 // Remove bindings for "dead" block-level expressions.
640 for (; I!=E; ++I)
641 if (!Liveness->isLive(Loc, cast<Stmt>(I.getKey())))
642 M = StateMgr.Remove(M, I.getKey());
Ted Kremeneke00fe3f2008-01-17 00:52:48 +0000643
644 return M;
Ted Kremeneke00fe3f2008-01-17 00:52:48 +0000645}
646
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000647void GRConstants::Nodify(NodeSet& Dst, Stmt* S, GRConstants::NodeTy* Pred,
648 GRConstants::StateTy St) {
649
650 // If the state hasn't changed, don't generate a new node.
651 if (St == Pred->getState())
652 return;
Ted Kremenekcb448ca2008-01-16 00:53:15 +0000653
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000654 Dst.Add(Builder->generateNode(S, St, Pred));
Ted Kremenekcb448ca2008-01-16 00:53:15 +0000655}
Ted Kremenekd27f8162008-01-15 23:55:06 +0000656
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000657void GRConstants::VisitBinaryOperator(BinaryOperator* B,
658 GRConstants::NodeTy* Pred,
659 GRConstants::NodeSet& Dst) {
660 NodeSet S1;
661 Visit(B->getLHS(), Pred, S1);
Ted Kremenekcb448ca2008-01-16 00:53:15 +0000662
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000663 for (NodeSet::iterator I1=S1.begin(), E1=S1.end(); I1 != E1; ++I1) {
664 NodeTy* N1 = *I1;
Ted Kremeneke00fe3f2008-01-17 00:52:48 +0000665
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000666 // When getting the value for the LHS, check if we are in an assignment.
667 // In such cases, we want to (initially) treat the LHS as an LValue,
668 // so we use GetLValue instead of GetValue so that DeclRefExpr's are
669 // evaluated to LValueDecl's instead of to an RValue.
670 const ExprValue& V1 =
671 B->isAssignmentOp() ? GetLValue(N1->getState(), B->getLHS())
672 : GetValue(N1->getState(), B->getLHS());
Ted Kremenekcb448ca2008-01-16 00:53:15 +0000673
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000674 NodeSet S2;
675 Visit(B->getRHS(), N1, S2);
676
677 for (NodeSet::iterator I2=S2.begin(), E2=S2.end(); I2 != E2; ++I2) {
678 NodeTy* N2 = *I2;
679 StateTy St = N2->getState();
680 const ExprValue& V2 = GetValue(St, B->getRHS());
681
682 switch (B->getOpcode()) {
683 case BinaryOperator::Add: {
684 const RValue& R1 = cast<RValue>(V1);
685 const RValue& R2 = cast<RValue>(V2);
686
687 Nodify(Dst, B, N2, SetValue(St, B, R1.Add(ValMgr, R2)));
688 break;
689 }
690
691 case BinaryOperator::Sub: {
692 const RValue& R1 = cast<RValue>(V1);
693 const RValue& R2 = cast<RValue>(V2);
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000694 Nodify(Dst, B, N2, SetValue(St, B, R1.Sub(ValMgr, R2)));
695 break;
696 }
697
Ted Kremenek2eafd0e2008-01-23 23:42:27 +0000698 case BinaryOperator::Mul: {
699 const RValue& R1 = cast<RValue>(V1);
700 const RValue& R2 = cast<RValue>(V2);
701 Nodify(Dst, B, N2, SetValue(St, B, R1.Mul(ValMgr, R2)));
702 break;
703 }
704
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000705 case BinaryOperator::Assign: {
706 const LValue& L1 = cast<LValue>(V1);
707 const RValue& R2 = cast<RValue>(V2);
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000708 Nodify(Dst, B, N2, SetValue(SetValue(St, B, R2), L1, R2));
709 break;
710 }
Ted Kremenekb4ae33f2008-01-23 23:38:00 +0000711
712 case BinaryOperator::AddAssign: {
713 const LValue& L1 = cast<LValue>(V1);
714 RValue R1 = cast<RValue>(GetValue(N1->getState(), L1));
715 RValue Result = R1.Add(ValMgr, cast<RValue>(V2));
716 Nodify(Dst, B, N2, SetValue(SetValue(St, B, Result), L1, Result));
717 break;
718 }
719
720 case BinaryOperator::SubAssign: {
721 const LValue& L1 = cast<LValue>(V1);
722 RValue R1 = cast<RValue>(GetValue(N1->getState(), L1));
723 RValue Result = R1.Sub(ValMgr, cast<RValue>(V2));
724 Nodify(Dst, B, N2, SetValue(SetValue(St, B, Result), L1, Result));
725 break;
726 }
Ted Kremenek2eafd0e2008-01-23 23:42:27 +0000727
728 case BinaryOperator::MulAssign: {
729 const LValue& L1 = cast<LValue>(V1);
730 RValue R1 = cast<RValue>(GetValue(N1->getState(), L1));
731 RValue Result = R1.Mul(ValMgr, cast<RValue>(V2));
732 Nodify(Dst, B, N2, SetValue(SetValue(St, B, Result), L1, Result));
733 break;
734 }
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000735
736 default:
737 Dst.Add(N2);
738 break;
739 }
Ted Kremenekcb448ca2008-01-16 00:53:15 +0000740 }
Ted Kremenekd27f8162008-01-15 23:55:06 +0000741 }
Ted Kremenekd27f8162008-01-15 23:55:06 +0000742}
Ted Kremenekee985462008-01-16 18:18:48 +0000743
Ted Kremenek1ccd31c2008-01-16 19:42:59 +0000744
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000745void GRConstants::Visit(Stmt* S, GRConstants::NodeTy* Pred,
746 GRConstants::NodeSet& Dst) {
747
748 // FIXME: add metadata to the CFG so that we can disable
749 // this check when we KNOW that there is no block-level subexpression.
750 // The motivation is that this check requires a hashtable lookup.
751
752 if (S != CurrentStmt && getCFG().isBlkExpr(S)) {
753 Dst.Add(Pred);
754 return;
755 }
756
757 switch (S->getStmtClass()) {
758 case Stmt::BinaryOperatorClass:
Ted Kremenekb4ae33f2008-01-23 23:38:00 +0000759 case Stmt::CompoundAssignOperatorClass:
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000760 VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Dst);
761 break;
762
763 case Stmt::ParenExprClass:
764 Visit(cast<ParenExpr>(S)->getSubExpr(), Pred, Dst);
765 break;
766
767 default:
768 Dst.Add(Pred); // No-op. Simply propagate the current state unchanged.
769 break;
Ted Kremenek79649df2008-01-17 18:25:22 +0000770 }
Ted Kremenek1ccd31c2008-01-16 19:42:59 +0000771}
772
Ted Kremenekee985462008-01-16 18:18:48 +0000773//===----------------------------------------------------------------------===//
774// Driver.
775//===----------------------------------------------------------------------===//
776
Ted Kremenekaa66a322008-01-16 21:46:15 +0000777#ifndef NDEBUG
778namespace llvm {
779template<>
780struct VISIBILITY_HIDDEN DOTGraphTraits<GRConstants::NodeTy*> :
781 public DefaultDOTGraphTraits {
782
Ted Kremenek803c9ed2008-01-23 22:30:44 +0000783 static void PrintKind(std::ostringstream& Out, ValueKey::Kind kind) {
784 switch (kind) {
785 case ValueKey::IsSubExp: Out << "Sub-Expressions:\\l"; break;
786 case ValueKey::IsDecl: Out << "Variables:\\l"; break;
787 case ValueKey::IsBlkExpr: Out << "Block-level Expressions:\\l"; break;
788 default: assert (false && "Unknown ValueKey type.");
789 }
790 }
791
Ted Kremenekaa66a322008-01-16 21:46:15 +0000792 static std::string getNodeLabel(const GRConstants::NodeTy* N, void*) {
793 std::ostringstream Out;
Ted Kremenek803c9ed2008-01-23 22:30:44 +0000794
795 // Program Location.
Ted Kremenekaa66a322008-01-16 21:46:15 +0000796 ProgramPoint Loc = N->getLocation();
797
798 switch (Loc.getKind()) {
799 case ProgramPoint::BlockEntranceKind:
800 Out << "Block Entrance: B"
801 << cast<BlockEntrance>(Loc).getBlock()->getBlockID();
802 break;
803
804 case ProgramPoint::BlockExitKind:
805 assert (false);
806 break;
807
808 case ProgramPoint::PostStmtKind: {
809 const PostStmt& L = cast<PostStmt>(Loc);
Ted Kremenek803c9ed2008-01-23 22:30:44 +0000810 Out << "(" << (void*) L.getStmt() << ") ";
Ted Kremenekaa66a322008-01-16 21:46:15 +0000811 L.getStmt()->printPretty(Out);
812 break;
813 }
814
815 default: {
816 const BlockEdge& E = cast<BlockEdge>(Loc);
817 Out << "Edge: (B" << E.getSrc()->getBlockID() << ", B"
818 << E.getDst()->getBlockID() << ')';
819 }
820 }
821
Ted Kremenek803c9ed2008-01-23 22:30:44 +0000822 Out << "\\|";
Ted Kremenekaa66a322008-01-16 21:46:15 +0000823
824 GRConstants::StateTy M = N->getState();
825 bool isFirst = true;
Ted Kremenek803c9ed2008-01-23 22:30:44 +0000826 ValueKey::Kind kind;
Ted Kremenekaa66a322008-01-16 21:46:15 +0000827
828 for (GRConstants::StateTy::iterator I=M.begin(), E=M.end(); I!=E; ++I) {
Ted Kremenek803c9ed2008-01-23 22:30:44 +0000829 if (!isFirst) {
830 ValueKey::Kind newKind = I.getKey().getKind();
831
832 if (newKind != kind) {
833 Out << "\\l\\l";
834 PrintKind(Out, newKind);
835 }
836 else
837 Out << "\\l";
838
839 kind = newKind;
840 }
841 else {
842 kind = I.getKey().getKind();
843 PrintKind(Out, kind);
Ted Kremenekaa66a322008-01-16 21:46:15 +0000844 isFirst = false;
Ted Kremenek803c9ed2008-01-23 22:30:44 +0000845 }
846
847 Out << ' ';
Ted Kremenekaa66a322008-01-16 21:46:15 +0000848
849 if (ValueDecl* V = dyn_cast<ValueDecl>(I.getKey())) {
Ted Kremenek803c9ed2008-01-23 22:30:44 +0000850 Out << V->getName();
Ted Kremenekaa66a322008-01-16 21:46:15 +0000851 }
852 else {
853 Stmt* E = cast<Stmt>(I.getKey());
Ted Kremenek803c9ed2008-01-23 22:30:44 +0000854 Out << " (" << (void*) E << ") ";
855 E->printPretty(Out);
Ted Kremenekaa66a322008-01-16 21:46:15 +0000856 }
857
Ted Kremenek803c9ed2008-01-23 22:30:44 +0000858 Out << " : ";
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000859 I.getData().print(Out);
Ted Kremenekaa66a322008-01-16 21:46:15 +0000860 }
861
Ted Kremenek803c9ed2008-01-23 22:30:44 +0000862 Out << "\\l";
Ted Kremenekaa66a322008-01-16 21:46:15 +0000863 return Out.str();
864 }
865};
866} // end llvm namespace
867#endif
868
Ted Kremenekee985462008-01-16 18:18:48 +0000869namespace clang {
870void RunGRConstants(CFG& cfg) {
871 GREngine<GRConstants> Engine(cfg);
872 Engine.ExecuteWorkList();
Ted Kremenekaa66a322008-01-16 21:46:15 +0000873#ifndef NDEBUG
874 llvm::ViewGraph(*Engine.getGraph().roots_begin(),"GRConstants");
875#endif
Ted Kremenekee985462008-01-16 18:18:48 +0000876}
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000877} // end clang namespace