blob: 9e71d336c7f41fa6c20bdf72a57ff289f4898a8a [file] [log] [blame]
Ted Kremenekd27f8162008-01-15 23:55:06 +00001//===-- GRConstants.cpp - Simple, Path-Sens. Constant Prop. ------*- C++ -*-==//
2//
Ted Kremenekab2b8c52008-01-23 19:59:44 +00003// The LLValM Compiler Infrastructure
Ted Kremenekd27f8162008-01-15 23:55:06 +00004//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// Constant Propagation via Graph Reachability
11//
12// This files defines a simple analysis that performs path-sensitive
13// constant propagation within a function. An example use of this analysis
14// is to perform simple checks for NULL dereferences.
15//
16//===----------------------------------------------------------------------===//
17
18#include "clang/Analysis/PathSensitive/GREngine.h"
19#include "clang/AST/Expr.h"
Ted Kremenek874d63f2008-01-24 02:02:54 +000020#include "clang/AST/ASTContext.h"
Ted Kremenekd27f8162008-01-15 23:55:06 +000021#include "clang/Analysis/Analyses/LiveVariables.h"
Ted Kremenekd27f8162008-01-15 23:55:06 +000022
23#include "llvm/Support/Casting.h"
24#include "llvm/Support/DataTypes.h"
25#include "llvm/ADT/APSInt.h"
26#include "llvm/ADT/FoldingSet.h"
27#include "llvm/ADT/ImmutableMap.h"
Ted Kremenek3c6c6722008-01-16 17:56:25 +000028#include "llvm/ADT/SmallVector.h"
Ted Kremenekab2b8c52008-01-23 19:59:44 +000029#include "llvm/Support/Allocator.h"
Ted Kremenekd27f8162008-01-15 23:55:06 +000030#include "llvm/Support/Compiler.h"
Ted Kremenekab2b8c52008-01-23 19:59:44 +000031#include "llvm/Support/Streams.h"
32
Ted Kremenek5ee4ff82008-01-25 22:55:56 +000033#include <functional>
34
Ted Kremenekaa66a322008-01-16 21:46:15 +000035#ifndef NDEBUG
36#include "llvm/Support/GraphWriter.h"
37#include <sstream>
38#endif
39
Ted Kremenekd27f8162008-01-15 23:55:06 +000040using namespace clang;
Ted Kremenekd27f8162008-01-15 23:55:06 +000041using llvm::dyn_cast;
42using llvm::cast;
Ted Kremenek5ee4ff82008-01-25 22:55:56 +000043using llvm::APSInt;
Ted Kremenekd27f8162008-01-15 23:55:06 +000044
45//===----------------------------------------------------------------------===//
Ted Kremenekab2b8c52008-01-23 19:59:44 +000046/// ValueKey - A variant smart pointer that wraps either a ValueDecl* or a
Ted Kremenekd27f8162008-01-15 23:55:06 +000047/// Stmt*. Use cast<> or dyn_cast<> to get actual pointer type
48//===----------------------------------------------------------------------===//
49namespace {
Ted Kremenekbd03f1d2008-01-28 22:09:13 +000050
Ted Kremenekf2645622008-01-28 22:25:21 +000051typedef unsigned SymbolID;
Ted Kremenekab2b8c52008-01-23 19:59:44 +000052
53class VISIBILITY_HIDDEN ValueKey {
Ted Kremenekbd03f1d2008-01-28 22:09:13 +000054 uintptr_t Raw;
Ted Kremenekcc1c3652008-01-25 23:43:12 +000055 void operator=(const ValueKey& RHS); // Do not implement.
Ted Kremenekbd03f1d2008-01-28 22:09:13 +000056
Ted Kremenekd27f8162008-01-15 23:55:06 +000057public:
Ted Kremenekbd03f1d2008-01-28 22:09:13 +000058 enum Kind { IsSubExpr=0x0, IsBlkExpr=0x1, IsDecl=0x2, // L-Value Bindings.
59 IsSymbol=0x3, // Symbol Bindings.
60 Flags=0x3 };
61
62 inline Kind getKind() const {
63 return (Kind) (Raw & Flags);
64 }
65
66 inline void* getPtr() const {
67 assert (getKind() != IsSymbol);
68 return reinterpret_cast<void*>(Raw & ~Flags);
69 }
70
71 inline SymbolID getSymbolID() const {
72 assert (getKind() == IsSymbol);
Ted Kremenekf2645622008-01-28 22:25:21 +000073 return (SymbolID) (Raw >> 2);
Ted Kremenekbd03f1d2008-01-28 22:09:13 +000074 }
Ted Kremenekd27f8162008-01-15 23:55:06 +000075
Ted Kremenekab2b8c52008-01-23 19:59:44 +000076 ValueKey(const ValueDecl* VD)
Ted Kremenekbd03f1d2008-01-28 22:09:13 +000077 : Raw(reinterpret_cast<uintptr_t>(VD) | IsDecl) {
78 assert(VD && "ValueDecl cannot be NULL.");
79 }
Ted Kremenekab2b8c52008-01-23 19:59:44 +000080
Ted Kremenek5c1b9962008-01-24 19:43:37 +000081 ValueKey(Stmt* S, bool isBlkExpr = false)
Ted Kremenekcc1c3652008-01-25 23:43:12 +000082 : Raw(reinterpret_cast<uintptr_t>(S) | (isBlkExpr ? IsBlkExpr : IsSubExpr)){
Ted Kremenekbd03f1d2008-01-28 22:09:13 +000083 assert(S && "Tracked statement cannot be NULL.");
Ted Kremenekcc1c3652008-01-25 23:43:12 +000084 }
Ted Kremenekd27f8162008-01-15 23:55:06 +000085
Ted Kremenekbd03f1d2008-01-28 22:09:13 +000086 ValueKey(SymbolID V)
87 : Raw((V << 2) | IsSymbol) {}
88
89 bool isSymbol() const { return getKind() == IsSymbol; }
Ted Kremenek565256e2008-01-24 22:44:24 +000090 bool isSubExpr() const { return getKind() == IsSubExpr; }
Ted Kremenekbd03f1d2008-01-28 22:09:13 +000091 bool isDecl() const { return getKind() == IsDecl; }
Ted Kremenekd27f8162008-01-15 23:55:06 +000092
93 inline void Profile(llvm::FoldingSetNodeID& ID) const {
Ted Kremenekbd03f1d2008-01-28 22:09:13 +000094 ID.AddInteger(isSymbol() ? 1 : 0);
95
96 if (isSymbol())
Ted Kremenekf2645622008-01-28 22:25:21 +000097 ID.AddInteger(getSymbolID());
Ted Kremenekbd03f1d2008-01-28 22:09:13 +000098 else
99 ID.AddPointer(getPtr());
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000100 }
101
102 inline bool operator==(const ValueKey& X) const {
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000103 return isSymbol() ? getSymbolID() == X.getSymbolID()
104 : getPtr() == X.getPtr();
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000105 }
106
107 inline bool operator!=(const ValueKey& X) const {
108 return !operator==(X);
109 }
110
111 inline bool operator<(const ValueKey& X) const {
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000112 if (isSymbol())
113 return X.isSymbol() ? getSymbolID() < X.getSymbolID() : false;
Ted Kremenek5c1b9962008-01-24 19:43:37 +0000114
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000115 return getPtr() < X.getPtr();
Ted Kremenekb3d2dca2008-01-16 23:33:44 +0000116 }
Ted Kremenekd27f8162008-01-15 23:55:06 +0000117};
118} // end anonymous namespace
119
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000120// Machinery to get cast<> and dyn_cast<> working with ValueKey.
Ted Kremenekd27f8162008-01-15 23:55:06 +0000121namespace llvm {
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000122 template<> inline bool isa<ValueDecl,ValueKey>(const ValueKey& V) {
123 return V.getKind() == ValueKey::IsDecl;
Ted Kremenekd27f8162008-01-15 23:55:06 +0000124 }
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000125 template<> inline bool isa<Stmt,ValueKey>(const ValueKey& V) {
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000126 return ((unsigned) V.getKind()) < ValueKey::IsDecl;
Ted Kremenekd27f8162008-01-15 23:55:06 +0000127 }
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000128 template<> struct VISIBILITY_HIDDEN cast_retty_impl<ValueDecl,ValueKey> {
Ted Kremenekaa66a322008-01-16 21:46:15 +0000129 typedef const ValueDecl* ret_type;
Ted Kremenekd27f8162008-01-15 23:55:06 +0000130 };
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000131 template<> struct VISIBILITY_HIDDEN cast_retty_impl<Stmt,ValueKey> {
Ted Kremenekd27f8162008-01-15 23:55:06 +0000132 typedef const Stmt* ret_type;
133 };
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000134 template<> struct VISIBILITY_HIDDEN simplify_type<ValueKey> {
Ted Kremenekd27f8162008-01-15 23:55:06 +0000135 typedef void* SimpleType;
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000136 static inline SimpleType getSimplifiedValue(const ValueKey &V) {
Ted Kremenekd27f8162008-01-15 23:55:06 +0000137 return V.getPtr();
138 }
139 };
140} // end llvm namespace
141
142//===----------------------------------------------------------------------===//
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000143// ValueManager.
Ted Kremenekd27f8162008-01-15 23:55:06 +0000144//===----------------------------------------------------------------------===//
145
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000146namespace {
147
Ted Kremenek5ee4ff82008-01-25 22:55:56 +0000148typedef llvm::ImmutableSet<APSInt > APSIntSetTy;
149
150
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000151class VISIBILITY_HIDDEN ValueManager {
Ted Kremenek874d63f2008-01-24 02:02:54 +0000152 ASTContext* Ctx;
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000153
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000154 typedef llvm::FoldingSet<llvm::FoldingSetNodeWrapper<APSInt> > APSIntSetTy;
155 APSIntSetTy APSIntSet;
156
157 llvm::BumpPtrAllocator BPAlloc;
158
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000159public:
160 ValueManager() {}
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000161 ~ValueManager();
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000162
Ted Kremenek874d63f2008-01-24 02:02:54 +0000163 void setContext(ASTContext* ctx) { Ctx = ctx; }
164 ASTContext* getContext() const { return Ctx; }
165
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000166 APSInt& getValue(const APSInt& X);
167
Ted Kremenekd27f8162008-01-15 23:55:06 +0000168};
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000169} // end anonymous namespace
170
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000171ValueManager::~ValueManager() {
172 // Note that the dstor for the contents of APSIntSet will never be called,
173 // so we iterate over the set and invoke the dstor for each APSInt. This
174 // frees an aux. memory allocated to represent very large constants.
175 for (APSIntSetTy::iterator I=APSIntSet.begin(), E=APSIntSet.end(); I!=E; ++I)
176 I->getValue().~APSInt();
177}
Ted Kremenek5ee4ff82008-01-25 22:55:56 +0000178
Ted Kremenek5ee4ff82008-01-25 22:55:56 +0000179
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000180
181APSInt& ValueManager::getValue(const APSInt& X) {
182 llvm::FoldingSetNodeID ID;
183 void* InsertPos;
184 typedef llvm::FoldingSetNodeWrapper<APSInt> FoldNodeTy;
Ted Kremenekcc1c3652008-01-25 23:43:12 +0000185
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000186 X.Profile(ID);
187 FoldNodeTy* P = APSIntSet.FindNodeOrInsertPos(ID, InsertPos);
Ted Kremenek5ee4ff82008-01-25 22:55:56 +0000188
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000189 if (!P) {
190 P = (FoldNodeTy*) BPAlloc.Allocate<FoldNodeTy>();
191 new (P) FoldNodeTy(X);
192 APSIntSet.InsertNode(P, InsertPos);
193 }
194
195 return *P;
Ted Kremenek5ee4ff82008-01-25 22:55:56 +0000196}
197
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000198//===----------------------------------------------------------------------===//
199// Expression Values.
200//===----------------------------------------------------------------------===//
Ted Kremenekf13794e2008-01-24 23:19:54 +0000201
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000202namespace {
203
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000204class VISIBILITY_HIDDEN RValue {
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000205public:
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000206 enum BaseKind { InvalidKind=0x0, LValueKind=0x1, NonLValueKind=0x2,
Ted Kremenekf2645622008-01-28 22:25:21 +0000207 BaseFlags = 0x3 };
Ted Kremenekf13794e2008-01-24 23:19:54 +0000208
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000209private:
Ted Kremenekf2645622008-01-28 22:25:21 +0000210 void* Data;
Ted Kremenekf13794e2008-01-24 23:19:54 +0000211 unsigned Kind;
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000212
213protected:
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000214 RValue(const void* d, bool isLValue, unsigned ValKind)
Ted Kremenekf2645622008-01-28 22:25:21 +0000215 : Data(const_cast<void*>(d)),
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000216 Kind((isLValue ? LValueKind : NonLValueKind) | (ValKind << 2)) {}
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000217
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000218 explicit RValue()
219 : Data(0), Kind(InvalidKind) {}
Ted Kremenekf2645622008-01-28 22:25:21 +0000220
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000221 void* getRawPtr() const {
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000222 return reinterpret_cast<void*>(Data);
223 }
224
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000225public:
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000226 ~RValue() {};
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000227
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000228 RValue Cast(ValueManager& ValMgr, Expr* CastExpr) const;
Ted Kremenek874d63f2008-01-24 02:02:54 +0000229
Ted Kremenekf13794e2008-01-24 23:19:54 +0000230 unsigned getRawKind() const { return Kind; }
231 BaseKind getBaseKind() const { return (BaseKind) (Kind & 0x3); }
232 unsigned getSubKind() const { return (Kind & ~0x3) >> 2; }
233
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000234 void Profile(llvm::FoldingSetNodeID& ID) const {
Ted Kremenekf13794e2008-01-24 23:19:54 +0000235 ID.AddInteger((unsigned) getRawKind());
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000236 ID.AddPointer(reinterpret_cast<void*>(Data));
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000237 }
238
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000239 bool operator==(const RValue& RHS) const {
Ted Kremenekf13794e2008-01-24 23:19:54 +0000240 return getRawKind() == RHS.getRawKind() && Data == RHS.Data;
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000241 }
242
Ted Kremenekf13794e2008-01-24 23:19:54 +0000243 inline bool isValid() const { return getRawKind() != InvalidKind; }
244 inline bool isInvalid() const { return getRawKind() == InvalidKind; }
245
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000246 void print(std::ostream& OS) const;
247 void print() const { print(*llvm::cerr.stream()); }
248
249 // Implement isa<T> support.
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000250 static inline bool classof(const RValue*) { return true; }
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000251};
252
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000253class VISIBILITY_HIDDEN InvalidValue : public RValue {
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000254public:
Ted Kremenekf13794e2008-01-24 23:19:54 +0000255 InvalidValue() {}
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000256
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000257 static inline bool classof(const RValue* V) {
Ted Kremenekf13794e2008-01-24 23:19:54 +0000258 return V->getBaseKind() == InvalidKind;
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000259 }
260};
261
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000262class VISIBILITY_HIDDEN LValue : public RValue {
Ted Kremenekf13794e2008-01-24 23:19:54 +0000263protected:
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000264 LValue(unsigned SubKind, void* D) : RValue(D, true, SubKind) {}
Ted Kremenekf13794e2008-01-24 23:19:54 +0000265
266public:
267 // Implement isa<T> support.
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000268 static inline bool classof(const RValue* V) {
Ted Kremenekf13794e2008-01-24 23:19:54 +0000269 return V->getBaseKind() == LValueKind;
270 }
271};
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000272
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000273class VISIBILITY_HIDDEN NonLValue : public RValue {
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000274protected:
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000275 NonLValue(unsigned SubKind, const void* d) : RValue(d, false, SubKind) {}
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000276
277public:
Ted Kremenekf13794e2008-01-24 23:19:54 +0000278 void print(std::ostream& Out) const;
279
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000280 NonLValue Add(ValueManager& ValMgr, const NonLValue& RHS) const;
281 NonLValue Sub(ValueManager& ValMgr, const NonLValue& RHS) const;
282 NonLValue Mul(ValueManager& ValMgr, const NonLValue& RHS) const;
283 NonLValue Div(ValueManager& ValMgr, const NonLValue& RHS) const;
284 NonLValue Rem(ValueManager& ValMgr, const NonLValue& RHS) const;
285 NonLValue UnaryMinus(ValueManager& ValMgr, UnaryOperator* U) const;
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000286
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000287 static NonLValue GetValue(ValueManager& ValMgr, const APSInt& V);
288 static NonLValue GetValue(ValueManager& ValMgr, IntegerLiteral* I);
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000289
290 // Implement isa<T> support.
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000291 static inline bool classof(const RValue* V) {
292 return V->getBaseKind() == NonLValueKind;
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000293 }
294};
Ted Kremenekf13794e2008-01-24 23:19:54 +0000295
296} // end anonymous namespace
297
298//===----------------------------------------------------------------------===//
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000299// LValues.
Ted Kremenekf13794e2008-01-24 23:19:54 +0000300//===----------------------------------------------------------------------===//
301
302namespace {
303
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000304enum { LValueDeclKind, NumLValueKind };
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000305
306class VISIBILITY_HIDDEN LValueDecl : public LValue {
307public:
Ted Kremenek9de04c42008-01-24 20:55:43 +0000308 LValueDecl(const ValueDecl* vd)
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000309 : LValue(LValueDeclKind,const_cast<ValueDecl*>(vd)) {}
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000310
311 ValueDecl* getDecl() const {
312 return static_cast<ValueDecl*>(getRawPtr());
313 }
314
315 // Implement isa<T> support.
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000316 static inline bool classof(const RValue* V) {
Ted Kremenekf13794e2008-01-24 23:19:54 +0000317 return V->getSubKind() == LValueDeclKind;
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000318 }
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000319};
320
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000321} // end anonymous namespace
322
323//===----------------------------------------------------------------------===//
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000324// Non-LValues.
325//===----------------------------------------------------------------------===//
326
327namespace {
328
Ted Kremenekf2645622008-01-28 22:25:21 +0000329enum { SymbolicNonLValueKind, ConcreteIntKind, ConstrainedIntegerKind,
330 NumNonLValueKind };
331
332class VISIBILITY_HIDDEN SymbolicNonLValue : public NonLValue {
333public:
334 SymbolicNonLValue(unsigned SymID)
335 : NonLValue(SymbolicNonLValueKind,
336 reinterpret_cast<void*>((uintptr_t) SymID)) {}
337
338 SymbolID getSymbolID() const {
339 return (SymbolID) reinterpret_cast<uintptr_t>(getRawPtr());
340 }
341
342 static inline bool classof(const RValue* V) {
343 return V->getSubKind() == SymbolicNonLValueKind;
344 }
345};
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000346
347class VISIBILITY_HIDDEN ConcreteInt : public NonLValue {
348public:
349 ConcreteInt(const APSInt& V) : NonLValue(ConcreteIntKind, &V) {}
350
351 const APSInt& getValue() const {
352 return *static_cast<APSInt*>(getRawPtr());
353 }
354
355 ConcreteInt Add(ValueManager& ValMgr, const ConcreteInt& V) const {
356 return ValMgr.getValue(getValue() + V.getValue());
357 }
358
359 ConcreteInt Sub(ValueManager& ValMgr, const ConcreteInt& V) const {
360 return ValMgr.getValue(getValue() - V.getValue());
361 }
362
363 ConcreteInt Mul(ValueManager& ValMgr, const ConcreteInt& V) const {
364 return ValMgr.getValue(getValue() * V.getValue());
365 }
366
367 ConcreteInt Div(ValueManager& ValMgr, const ConcreteInt& V) const {
368 return ValMgr.getValue(getValue() / V.getValue());
369 }
370
371 ConcreteInt Rem(ValueManager& ValMgr, const ConcreteInt& V) const {
372 return ValMgr.getValue(getValue() % V.getValue());
373 }
374
375 ConcreteInt Cast(ValueManager& ValMgr, Expr* CastExpr) const {
376 assert (CastExpr->getType()->isIntegerType());
377
378 APSInt X(getValue());
379 X.extOrTrunc(ValMgr.getContext()->getTypeSize(CastExpr->getType(),
380 CastExpr->getLocStart()));
381 return ValMgr.getValue(X);
382 }
383
384 ConcreteInt UnaryMinus(ValueManager& ValMgr, UnaryOperator* U) const {
385 assert (U->getType() == U->getSubExpr()->getType());
386 assert (U->getType()->isIntegerType());
387 return ValMgr.getValue(-getValue());
388 }
389
390 // Implement isa<T> support.
391 static inline bool classof(const RValue* V) {
392 return V->getSubKind() == ConcreteIntKind;
393 }
394};
395
396} // end anonymous namespace
397
398//===----------------------------------------------------------------------===//
399// Transfer function dispatch.
400//===----------------------------------------------------------------------===//
401
402RValue RValue::Cast(ValueManager& ValMgr, Expr* CastExpr) const {
403 switch (getSubKind()) {
404 case ConcreteIntKind:
405 return cast<ConcreteInt>(this)->Cast(ValMgr, CastExpr);
406 default:
407 return InvalidValue();
408 }
409}
410
411NonLValue NonLValue::UnaryMinus(ValueManager& ValMgr, UnaryOperator* U) const {
412 switch (getSubKind()) {
413 case ConcreteIntKind:
414 return cast<ConcreteInt>(this)->UnaryMinus(ValMgr, U);
415 default:
416 return cast<NonLValue>(InvalidValue());
417 }
418}
419
420#define RVALUE_DISPATCH_CASE(k1,k2,Op)\
421case (k1##Kind*NumNonLValueKind+k2##Kind):\
422 return cast<k1>(*this).Op(ValMgr,cast<k2>(RHS));
423
424#define RVALUE_DISPATCH(Op)\
425switch (getSubKind()*NumNonLValueKind+RHS.getSubKind()){\
426 RVALUE_DISPATCH_CASE(ConcreteInt,ConcreteInt,Op)\
427 default:\
428 assert (!isValid() || !RHS.isValid() && "Missing case.");\
429 break;\
430}\
431return cast<NonLValue>(InvalidValue());
432
433NonLValue NonLValue::Add(ValueManager& ValMgr, const NonLValue& RHS) const {
434 RVALUE_DISPATCH(Add)
435}
436
437NonLValue NonLValue::Sub(ValueManager& ValMgr, const NonLValue& RHS) const {
438 RVALUE_DISPATCH(Sub)
439}
440
441NonLValue NonLValue::Mul(ValueManager& ValMgr, const NonLValue& RHS) const {
442 RVALUE_DISPATCH(Mul)
443}
444
445NonLValue NonLValue::Div(ValueManager& ValMgr, const NonLValue& RHS) const {
446 RVALUE_DISPATCH(Div)
447}
448
449NonLValue NonLValue::Rem(ValueManager& ValMgr, const NonLValue& RHS) const {
450 RVALUE_DISPATCH(Rem)
451}
452
453
454#undef RVALUE_DISPATCH_CASE
455#undef RVALUE_DISPATCH
456
457//===----------------------------------------------------------------------===//
458// Utility methods for constructing RValues.
459//===----------------------------------------------------------------------===//
460
461NonLValue NonLValue::GetValue(ValueManager& ValMgr, const APSInt& V) {
462 return ConcreteInt(ValMgr.getValue(V));
463}
464
465NonLValue NonLValue::GetValue(ValueManager& ValMgr, IntegerLiteral* I) {
466 return ConcreteInt(ValMgr.getValue(APSInt(I->getValue(),
467 I->getType()->isUnsignedIntegerType())));
468}
469
470//===----------------------------------------------------------------------===//
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000471// Pretty-Printing.
472//===----------------------------------------------------------------------===//
473
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000474void RValue::print(std::ostream& Out) const {
Ted Kremenekf13794e2008-01-24 23:19:54 +0000475 switch (getBaseKind()) {
476 case InvalidKind:
477 Out << "Invalid";
478 break;
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000479
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000480 case NonLValueKind:
481 cast<NonLValue>(this)->print(Out);
Ted Kremenekf13794e2008-01-24 23:19:54 +0000482 break;
483
484 case LValueKind:
485 assert (false && "FIXME: LValue printing not implemented.");
486 break;
487
488 default:
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000489 assert (false && "Invalid RValue.");
Ted Kremenekf13794e2008-01-24 23:19:54 +0000490 }
491}
492
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000493void NonLValue::print(std::ostream& Out) const {
Ted Kremenekf13794e2008-01-24 23:19:54 +0000494 switch (getSubKind()) {
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000495 case ConcreteIntKind:
496 Out << cast<ConcreteInt>(this)->getValue().toString();
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000497 break;
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000498
499 default:
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000500 assert (false && "Pretty-printed not implemented for this NonLValue.");
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000501 break;
502 }
503}
504
505//===----------------------------------------------------------------------===//
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000506// ValueMapTy - A ImmutableMap type Stmt*/Decl*/Symbols to RValues.
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000507//===----------------------------------------------------------------------===//
508
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000509typedef llvm::ImmutableMap<ValueKey,RValue> ValueMapTy;
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000510
511namespace clang {
512 template<>
513 struct VISIBILITY_HIDDEN GRTrait<ValueMapTy> {
514 static inline void* toPtr(ValueMapTy M) {
515 return reinterpret_cast<void*>(M.getRoot());
516 }
517 static inline ValueMapTy toState(void* P) {
518 return ValueMapTy(static_cast<ValueMapTy::TreeTy*>(P));
519 }
520 };
Ted Kremenekd27f8162008-01-15 23:55:06 +0000521}
522
523//===----------------------------------------------------------------------===//
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000524// The Checker.
Ted Kremenekd27f8162008-01-15 23:55:06 +0000525//===----------------------------------------------------------------------===//
526
527namespace {
Ted Kremenekd27f8162008-01-15 23:55:06 +0000528
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000529class VISIBILITY_HIDDEN GRConstants {
Ted Kremenekd27f8162008-01-15 23:55:06 +0000530
531public:
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000532 typedef ValueMapTy StateTy;
Ted Kremenekd27f8162008-01-15 23:55:06 +0000533 typedef GRNodeBuilder<GRConstants> NodeBuilder;
534 typedef ExplodedNode<StateTy> NodeTy;
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000535
536 class NodeSet {
537 typedef llvm::SmallVector<NodeTy*,3> ImplTy;
538 ImplTy Impl;
539 public:
540
541 NodeSet() {}
542 NodeSet(NodeTy* N) { assert (N && !N->isInfeasible()); Impl.push_back(N); }
543
544 void Add(NodeTy* N) { if (N && !N->isInfeasible()) Impl.push_back(N); }
545
546 typedef ImplTy::iterator iterator;
547 typedef ImplTy::const_iterator const_iterator;
548
549 unsigned size() const { return Impl.size(); }
Ted Kremenek9de04c42008-01-24 20:55:43 +0000550 bool empty() const { return Impl.empty(); }
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000551
552 iterator begin() { return Impl.begin(); }
553 iterator end() { return Impl.end(); }
554
555 const_iterator begin() const { return Impl.begin(); }
556 const_iterator end() const { return Impl.end(); }
557 };
Ted Kremenekd27f8162008-01-15 23:55:06 +0000558
559protected:
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000560 /// Liveness - live-variables information the ValueDecl* and block-level
561 /// Expr* in the CFG. Used to prune out dead state.
Ted Kremenekd27f8162008-01-15 23:55:06 +0000562 LiveVariables* Liveness;
563
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000564 /// Builder - The current GRNodeBuilder which is used when building the nodes
565 /// for a given statement.
Ted Kremenekd27f8162008-01-15 23:55:06 +0000566 NodeBuilder* Builder;
567
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000568 /// StateMgr - Object that manages the data for all created states.
569 ValueMapTy::Factory StateMgr;
Ted Kremenekd27f8162008-01-15 23:55:06 +0000570
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000571 /// ValueMgr - Object that manages the data for all created RValues.
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000572 ValueManager ValMgr;
573
574 /// cfg - the current CFG.
Ted Kremenekd27f8162008-01-15 23:55:06 +0000575 CFG* cfg;
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000576
577 /// StmtEntryNode - The immediate predecessor node.
578 NodeTy* StmtEntryNode;
579
580 /// CurrentStmt - The current block-level statement.
581 Stmt* CurrentStmt;
582
583 bool StateCleaned;
Ted Kremenekd27f8162008-01-15 23:55:06 +0000584
Ted Kremenek7b8009a2008-01-24 02:28:56 +0000585 ASTContext* getContext() const { return ValMgr.getContext(); }
586
Ted Kremenekd27f8162008-01-15 23:55:06 +0000587public:
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000588 GRConstants() : Liveness(NULL), Builder(NULL), cfg(NULL),
589 StmtEntryNode(NULL), CurrentStmt(NULL) {}
Ted Kremenekd27f8162008-01-15 23:55:06 +0000590
591 ~GRConstants() { delete Liveness; }
592
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000593 /// getCFG - Returns the CFG associated with this analysis.
Ted Kremenekd27f8162008-01-15 23:55:06 +0000594 CFG& getCFG() { assert (cfg); return *cfg; }
595
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000596 /// Initialize - Initialize the checker's state based on the specified
597 /// CFG. This results in liveness information being computed for
598 /// each block-level statement in the CFG.
Ted Kremenek874d63f2008-01-24 02:02:54 +0000599 void Initialize(CFG& c, ASTContext& ctx) {
600 cfg = &c;
601 ValMgr.setContext(&ctx);
Ted Kremenekd27f8162008-01-15 23:55:06 +0000602 Liveness = new LiveVariables(c);
603 Liveness->runOnCFG(c);
Ted Kremenek79649df2008-01-17 18:25:22 +0000604 Liveness->runOnAllBlocks(c, NULL, true);
Ted Kremenekd27f8162008-01-15 23:55:06 +0000605 }
606
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000607 /// getInitialState - Return the initial state used for the root vertex
608 /// in the ExplodedGraph.
Ted Kremenekd27f8162008-01-15 23:55:06 +0000609 StateTy getInitialState() {
Ted Kremenekcb448ca2008-01-16 00:53:15 +0000610 return StateMgr.GetEmptyMap();
Ted Kremenekd27f8162008-01-15 23:55:06 +0000611 }
Ted Kremenekd27f8162008-01-15 23:55:06 +0000612
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000613 /// ProcessStmt - Called by GREngine. Used to generate new successor
614 /// nodes by processing the 'effects' of a block-level statement.
615 void ProcessStmt(Stmt* S, NodeBuilder& builder);
616
617 /// RemoveDeadBindings - Return a new state that is the same as 'M' except
618 /// that all subexpression mappings are removed and that any
619 /// block-level expressions that are not live at 'S' also have their
620 /// mappings removed.
621 StateTy RemoveDeadBindings(Stmt* S, StateTy M);
622
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000623 StateTy SetValue(StateTy St, Stmt* S, const RValue& V);
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000624
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000625 StateTy SetValue(StateTy St, const Stmt* S, const RValue& V) {
Ted Kremenek9de04c42008-01-24 20:55:43 +0000626 return SetValue(St, const_cast<Stmt*>(S), V);
627 }
628
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000629 StateTy SetValue(StateTy St, const LValue& LV, const RValue& V);
Ted Kremenek1ccd31c2008-01-16 19:42:59 +0000630
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000631 RValue GetValue(const StateTy& St, Stmt* S);
632 inline RValue GetValue(const StateTy& St, const Stmt* S) {
Ted Kremenek9de04c42008-01-24 20:55:43 +0000633 return GetValue(St, const_cast<Stmt*>(S));
634 }
635
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000636 RValue GetValue(const StateTy& St, const LValue& LV);
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000637 LValue GetLValue(const StateTy& St, Stmt* S);
Ted Kremenekd27f8162008-01-15 23:55:06 +0000638
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000639 void Nodify(NodeSet& Dst, Stmt* S, NodeTy* Pred, StateTy St);
Ted Kremenekd27f8162008-01-15 23:55:06 +0000640
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000641 /// Visit - Transfer function logic for all statements. Dispatches to
642 /// other functions that handle specific kinds of statements.
643 void Visit(Stmt* S, NodeTy* Pred, NodeSet& Dst);
Ted Kremenek874d63f2008-01-24 02:02:54 +0000644
645 /// VisitCast - Transfer function logic for all casts (implicit and explicit).
646 void VisitCast(Expr* CastE, Expr* E, NodeTy* Pred, NodeSet& Dst);
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000647
Ted Kremenek7b8009a2008-01-24 02:28:56 +0000648 /// VisitUnaryOperator - Transfer function logic for unary operators.
649 void VisitUnaryOperator(UnaryOperator* B, NodeTy* Pred, NodeSet& Dst);
650
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000651 /// VisitBinaryOperator - Transfer function logic for binary operators.
Ted Kremenek9de04c42008-01-24 20:55:43 +0000652 void VisitBinaryOperator(BinaryOperator* B, NodeTy* Pred, NodeSet& Dst);
653
654 /// VisitDeclStmt - Transfer function logic for DeclStmts.
655 void VisitDeclStmt(DeclStmt* DS, NodeTy* Pred, NodeSet& Dst);
Ted Kremenekd27f8162008-01-15 23:55:06 +0000656};
657} // end anonymous namespace
658
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000659
Ted Kremenekd27f8162008-01-15 23:55:06 +0000660void GRConstants::ProcessStmt(Stmt* S, NodeBuilder& builder) {
661 Builder = &builder;
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000662
663 StmtEntryNode = builder.getLastNode();
664 CurrentStmt = S;
665 NodeSet Dst;
666 StateCleaned = false;
667
668 Visit(S, StmtEntryNode, Dst);
669
670 // If no nodes were generated, generate a new node that has all the
671 // dead mappings removed.
672 if (Dst.size() == 1 && *Dst.begin() == StmtEntryNode) {
673 StateTy St = RemoveDeadBindings(S, StmtEntryNode->getState());
674 builder.generateNode(S, St, StmtEntryNode);
675 }
Ted Kremenekf84469b2008-01-18 00:41:32 +0000676
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000677 CurrentStmt = NULL;
678 StmtEntryNode = NULL;
679 Builder = NULL;
Ted Kremenekd27f8162008-01-15 23:55:06 +0000680}
681
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000682
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000683RValue GRConstants::GetValue(const StateTy& St, const LValue& LV) {
Ted Kremenekf13794e2008-01-24 23:19:54 +0000684 switch (LV.getSubKind()) {
685 case LValueDeclKind: {
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000686 StateTy::TreeTy* T = St.SlimFind(cast<LValueDecl>(LV).getDecl());
687 return T ? T->getValue().second : InvalidValue();
688 }
689 default:
690 assert (false && "Invalid LValue.");
Ted Kremenekca3e8572008-01-16 22:28:08 +0000691 break;
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000692 }
693
694 return InvalidValue();
695}
696
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000697RValue GRConstants::GetValue(const StateTy& St, Stmt* S) {
Ted Kremenek671c9e82008-01-24 00:50:08 +0000698 for (;;) {
699 switch (S->getStmtClass()) {
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000700
701 // ParenExprs are no-ops.
702
Ted Kremenek671c9e82008-01-24 00:50:08 +0000703 case Stmt::ParenExprClass:
704 S = cast<ParenExpr>(S)->getSubExpr();
705 continue;
706
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000707 // DeclRefExprs can either evaluate to an LValue or a Non-LValue
708 // (assuming an implicit "load") depending on the context. In this
709 // context we assume that we are retrieving the value contained
710 // within the referenced variables.
711
Ted Kremenek671c9e82008-01-24 00:50:08 +0000712 case Stmt::DeclRefExprClass:
713 return GetValue(St, LValueDecl(cast<DeclRefExpr>(S)->getDecl()));
Ted Kremenekca3e8572008-01-16 22:28:08 +0000714
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000715 // Integer literals evaluate to an RValue. Simply retrieve the
716 // RValue for the literal.
717
Ted Kremenek671c9e82008-01-24 00:50:08 +0000718 case Stmt::IntegerLiteralClass:
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000719 return NonLValue::GetValue(ValMgr, cast<IntegerLiteral>(S));
720
721 // Casts where the source and target type are the same
722 // are no-ops. We blast through these to get the descendant
723 // subexpression that has a value.
724
Ted Kremenek874d63f2008-01-24 02:02:54 +0000725 case Stmt::ImplicitCastExprClass: {
726 ImplicitCastExpr* C = cast<ImplicitCastExpr>(S);
727 if (C->getType() == C->getSubExpr()->getType()) {
728 S = C->getSubExpr();
729 continue;
730 }
731 break;
732 }
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000733
Ted Kremenek874d63f2008-01-24 02:02:54 +0000734 case Stmt::CastExprClass: {
735 CastExpr* C = cast<CastExpr>(S);
736 if (C->getType() == C->getSubExpr()->getType()) {
737 S = C->getSubExpr();
738 continue;
739 }
740 break;
741 }
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000742
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000743 // Handle all other Stmt* using a lookup.
744
Ted Kremenek671c9e82008-01-24 00:50:08 +0000745 default:
746 break;
747 };
748
749 break;
750 }
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000751
Ted Kremenek5c1b9962008-01-24 19:43:37 +0000752 StateTy::TreeTy* T = St.SlimFind(S);
Ted Kremenek874d63f2008-01-24 02:02:54 +0000753
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000754 return T ? T->getValue().second : InvalidValue();
755}
756
757LValue GRConstants::GetLValue(const StateTy& St, Stmt* S) {
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000758 while (ParenExpr* P = dyn_cast<ParenExpr>(S))
759 S = P->getSubExpr();
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000760
761 if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(S))
762 return LValueDecl(DR->getDecl());
763
764 return cast<LValue>(GetValue(St, S));
765}
766
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000767
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000768GRConstants::StateTy GRConstants::SetValue(StateTy St, Stmt* S,
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000769 const RValue& V) {
Ted Kremenekcc1c3652008-01-25 23:43:12 +0000770 assert (S);
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000771
772 if (!StateCleaned) {
773 St = RemoveDeadBindings(CurrentStmt, St);
774 StateCleaned = true;
775 }
776
Ted Kremenek9ff731d2008-01-24 22:27:20 +0000777 bool isBlkExpr = false;
778
779 if (S == CurrentStmt) {
780 isBlkExpr = getCFG().isBlkExpr(S);
781
782 if (!isBlkExpr)
783 return St;
784 }
Ted Kremenekdaadf452008-01-24 19:28:01 +0000785
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000786 return V.isValid() ? StateMgr.Add(St, ValueKey(S,isBlkExpr), V)
787 : St;
788}
789
790GRConstants::StateTy GRConstants::SetValue(StateTy St, const LValue& LV,
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000791 const RValue& V) {
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000792 if (!LV.isValid())
793 return St;
794
795 if (!StateCleaned) {
796 St = RemoveDeadBindings(CurrentStmt, St);
797 StateCleaned = true;
Ted Kremenekca3e8572008-01-16 22:28:08 +0000798 }
Ted Kremenek0525a4f2008-01-16 19:47:19 +0000799
Ted Kremenekf13794e2008-01-24 23:19:54 +0000800 switch (LV.getSubKind()) {
801 case LValueDeclKind:
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000802 return V.isValid() ? StateMgr.Add(St, cast<LValueDecl>(LV).getDecl(), V)
803 : StateMgr.Remove(St, cast<LValueDecl>(LV).getDecl());
804
805 default:
806 assert ("SetValue for given LValue type not yet implemented.");
807 return St;
808 }
Ted Kremenekd27f8162008-01-15 23:55:06 +0000809}
810
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000811GRConstants::StateTy GRConstants::RemoveDeadBindings(Stmt* Loc, StateTy M) {
Ted Kremenekf84469b2008-01-18 00:41:32 +0000812 // Note: in the code below, we can assign a new map to M since the
813 // iterators are iterating over the tree of the *original* map.
Ted Kremenekf84469b2008-01-18 00:41:32 +0000814 StateTy::iterator I = M.begin(), E = M.end();
815
Ted Kremenek5c1b9962008-01-24 19:43:37 +0000816 // Remove old bindings for subexpressions and "dead" block-level expressions.
817 for (; I!=E && !I.getKey().isDecl(); ++I) {
818 if (I.getKey().isSubExpr() || !Liveness->isLive(Loc,cast<Stmt>(I.getKey())))
819 M = StateMgr.Remove(M, I.getKey());
820 }
Ted Kremenekf84469b2008-01-18 00:41:32 +0000821
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000822 // Remove bindings for "dead" decls.
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000823 for (; I!=E && I.getKey().isDecl(); ++I)
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000824 if (VarDecl* V = dyn_cast<VarDecl>(cast<ValueDecl>(I.getKey())))
825 if (!Liveness->isLive(Loc, V))
826 M = StateMgr.Remove(M, I.getKey());
Ted Kremenek565256e2008-01-24 22:44:24 +0000827
Ted Kremeneke00fe3f2008-01-17 00:52:48 +0000828 return M;
Ted Kremeneke00fe3f2008-01-17 00:52:48 +0000829}
830
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000831void GRConstants::Nodify(NodeSet& Dst, Stmt* S, GRConstants::NodeTy* Pred,
832 GRConstants::StateTy St) {
833
834 // If the state hasn't changed, don't generate a new node.
835 if (St == Pred->getState())
836 return;
Ted Kremenekcb448ca2008-01-16 00:53:15 +0000837
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000838 Dst.Add(Builder->generateNode(S, St, Pred));
Ted Kremenekcb448ca2008-01-16 00:53:15 +0000839}
Ted Kremenekd27f8162008-01-15 23:55:06 +0000840
Ted Kremenek874d63f2008-01-24 02:02:54 +0000841void GRConstants::VisitCast(Expr* CastE, Expr* E, GRConstants::NodeTy* Pred,
842 GRConstants::NodeSet& Dst) {
843
844 QualType T = CastE->getType();
845
846 // Check for redundant casts.
847 if (E->getType() == T) {
848 Dst.Add(Pred);
849 return;
850 }
851
852 NodeSet S1;
853 Visit(E, Pred, S1);
854
855 for (NodeSet::iterator I1=S1.begin(), E1=S1.end(); I1 != E1; ++I1) {
856 NodeTy* N = *I1;
857 StateTy St = N->getState();
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000858 const RValue& V = GetValue(St, E);
859 Nodify(Dst, CastE, N, SetValue(St, CastE, V.Cast(ValMgr, CastE)));
Ted Kremenek874d63f2008-01-24 02:02:54 +0000860 }
Ted Kremenek9de04c42008-01-24 20:55:43 +0000861}
862
863void GRConstants::VisitDeclStmt(DeclStmt* DS, GRConstants::NodeTy* Pred,
864 GRConstants::NodeSet& Dst) {
865
866 StateTy St = Pred->getState();
867
868 for (const ScopedDecl* D = DS->getDecl(); D; D = D->getNextDeclarator())
869 if (const VarDecl* VD = dyn_cast<VarDecl>(D))
870 St = SetValue(St, LValueDecl(VD), GetValue(St, VD->getInit()));
871
872 Nodify(Dst, DS, Pred, St);
873
874 if (Dst.empty())
875 Dst.Add(Pred);
876}
Ted Kremenek874d63f2008-01-24 02:02:54 +0000877
Ted Kremenek7b8009a2008-01-24 02:28:56 +0000878void GRConstants::VisitUnaryOperator(UnaryOperator* U,
879 GRConstants::NodeTy* Pred,
880 GRConstants::NodeSet& Dst) {
881 NodeSet S1;
882 Visit(U->getSubExpr(), Pred, S1);
883
884 for (NodeSet::iterator I1=S1.begin(), E1=S1.end(); I1 != E1; ++I1) {
885 NodeTy* N1 = *I1;
886 StateTy St = N1->getState();
887
888 switch (U->getOpcode()) {
889 case UnaryOperator::PostInc: {
890 const LValue& L1 = GetLValue(St, U->getSubExpr());
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000891 NonLValue R1 = cast<NonLValue>(GetValue(St, L1));
Ted Kremenek7b8009a2008-01-24 02:28:56 +0000892
893 QualType T = U->getType();
Ted Kremeneke0cf9c82008-01-24 19:00:57 +0000894 unsigned bits = getContext()->getTypeSize(T, U->getLocStart());
Ted Kremenek5ee4ff82008-01-25 22:55:56 +0000895 APSInt One(llvm::APInt(bits, 1), T->isUnsignedIntegerType());
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000896 NonLValue R2 = NonLValue::GetValue(ValMgr, One);
Ted Kremeneke0cf9c82008-01-24 19:00:57 +0000897
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000898 NonLValue Result = R1.Add(ValMgr, R2);
Ted Kremenek7b8009a2008-01-24 02:28:56 +0000899 Nodify(Dst, U, N1, SetValue(SetValue(St, U, R1), L1, Result));
900 break;
901 }
902
903 case UnaryOperator::PostDec: {
904 const LValue& L1 = GetLValue(St, U->getSubExpr());
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000905 NonLValue R1 = cast<NonLValue>(GetValue(St, L1));
Ted Kremenek7b8009a2008-01-24 02:28:56 +0000906
907 QualType T = U->getType();
Ted Kremeneke0cf9c82008-01-24 19:00:57 +0000908 unsigned bits = getContext()->getTypeSize(T, U->getLocStart());
Ted Kremenek5ee4ff82008-01-25 22:55:56 +0000909 APSInt One(llvm::APInt(bits, 1), T->isUnsignedIntegerType());
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000910 NonLValue R2 = NonLValue::GetValue(ValMgr, One);
Ted Kremenek7b8009a2008-01-24 02:28:56 +0000911
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000912 NonLValue Result = R1.Sub(ValMgr, R2);
Ted Kremenek7b8009a2008-01-24 02:28:56 +0000913 Nodify(Dst, U, N1, SetValue(SetValue(St, U, R1), L1, Result));
914 break;
915 }
916
917 case UnaryOperator::PreInc: {
918 const LValue& L1 = GetLValue(St, U->getSubExpr());
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000919 NonLValue R1 = cast<NonLValue>(GetValue(St, L1));
Ted Kremenek7b8009a2008-01-24 02:28:56 +0000920
921 QualType T = U->getType();
Ted Kremeneke0cf9c82008-01-24 19:00:57 +0000922 unsigned bits = getContext()->getTypeSize(T, U->getLocStart());
Ted Kremenek5ee4ff82008-01-25 22:55:56 +0000923 APSInt One(llvm::APInt(bits, 1), T->isUnsignedIntegerType());
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000924 NonLValue R2 = NonLValue::GetValue(ValMgr, One);
Ted Kremenek7b8009a2008-01-24 02:28:56 +0000925
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000926 NonLValue Result = R1.Add(ValMgr, R2);
Ted Kremenek7b8009a2008-01-24 02:28:56 +0000927 Nodify(Dst, U, N1, SetValue(SetValue(St, U, Result), L1, Result));
928 break;
929 }
930
931 case UnaryOperator::PreDec: {
932 const LValue& L1 = GetLValue(St, U->getSubExpr());
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000933 NonLValue R1 = cast<NonLValue>(GetValue(St, L1));
Ted Kremenek7b8009a2008-01-24 02:28:56 +0000934
935 QualType T = U->getType();
Ted Kremeneke0cf9c82008-01-24 19:00:57 +0000936 unsigned bits = getContext()->getTypeSize(T, U->getLocStart());
Ted Kremenek5ee4ff82008-01-25 22:55:56 +0000937 APSInt One(llvm::APInt(bits, 1), T->isUnsignedIntegerType());
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000938 NonLValue R2 = NonLValue::GetValue(ValMgr, One);
Ted Kremenek7b8009a2008-01-24 02:28:56 +0000939
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000940 NonLValue Result = R1.Sub(ValMgr, R2);
Ted Kremenek7b8009a2008-01-24 02:28:56 +0000941 Nodify(Dst, U, N1, SetValue(SetValue(St, U, Result), L1, Result));
942 break;
943 }
944
Ted Kremenekdacbb4f2008-01-24 08:20:02 +0000945 case UnaryOperator::Minus: {
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000946 const NonLValue& R1 = cast<NonLValue>(GetValue(St, U->getSubExpr()));
947 Nodify(Dst, U, N1, SetValue(St, U, R1.UnaryMinus(ValMgr, U)));
Ted Kremenekdacbb4f2008-01-24 08:20:02 +0000948 break;
949 }
950
Ted Kremenek7b8009a2008-01-24 02:28:56 +0000951 default: ;
952 assert (false && "Not implemented.");
953 }
954 }
955}
956
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000957void GRConstants::VisitBinaryOperator(BinaryOperator* B,
958 GRConstants::NodeTy* Pred,
959 GRConstants::NodeSet& Dst) {
960 NodeSet S1;
961 Visit(B->getLHS(), Pred, S1);
Ted Kremenekcb448ca2008-01-16 00:53:15 +0000962
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000963 for (NodeSet::iterator I1=S1.begin(), E1=S1.end(); I1 != E1; ++I1) {
964 NodeTy* N1 = *I1;
Ted Kremeneke00fe3f2008-01-17 00:52:48 +0000965
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000966 // When getting the value for the LHS, check if we are in an assignment.
967 // In such cases, we want to (initially) treat the LHS as an LValue,
968 // so we use GetLValue instead of GetValue so that DeclRefExpr's are
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000969 // evaluated to LValueDecl's instead of to an NonLValue.
970 const RValue& V1 =
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000971 B->isAssignmentOp() ? GetLValue(N1->getState(), B->getLHS())
972 : GetValue(N1->getState(), B->getLHS());
Ted Kremenekcb448ca2008-01-16 00:53:15 +0000973
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000974 NodeSet S2;
975 Visit(B->getRHS(), N1, S2);
976
977 for (NodeSet::iterator I2=S2.begin(), E2=S2.end(); I2 != E2; ++I2) {
978 NodeTy* N2 = *I2;
979 StateTy St = N2->getState();
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000980 const RValue& V2 = GetValue(St, B->getRHS());
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000981
982 switch (B->getOpcode()) {
983 case BinaryOperator::Add: {
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000984 const NonLValue& R1 = cast<NonLValue>(V1);
985 const NonLValue& R2 = cast<NonLValue>(V2);
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000986
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000987 Nodify(Dst, B, N2, SetValue(St, B, R1.Add(ValMgr, R2)));
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000988 break;
989 }
990
991 case BinaryOperator::Sub: {
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000992 const NonLValue& R1 = cast<NonLValue>(V1);
993 const NonLValue& R2 = cast<NonLValue>(V2);
994 Nodify(Dst, B, N2, SetValue(St, B, R1.Sub(ValMgr, R2)));
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000995 break;
996 }
997
Ted Kremenek2eafd0e2008-01-23 23:42:27 +0000998 case BinaryOperator::Mul: {
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000999 const NonLValue& R1 = cast<NonLValue>(V1);
1000 const NonLValue& R2 = cast<NonLValue>(V2);
1001 Nodify(Dst, B, N2, SetValue(St, B, R1.Mul(ValMgr, R2)));
Ted Kremenek2eafd0e2008-01-23 23:42:27 +00001002 break;
1003 }
1004
Ted Kremenek5ee4ff82008-01-25 22:55:56 +00001005 case BinaryOperator::Div: {
Ted Kremenekbd03f1d2008-01-28 22:09:13 +00001006 const NonLValue& R1 = cast<NonLValue>(V1);
1007 const NonLValue& R2 = cast<NonLValue>(V2);
1008 Nodify(Dst, B, N2, SetValue(St, B, R1.Div(ValMgr, R2)));
Ted Kremenek5ee4ff82008-01-25 22:55:56 +00001009 break;
1010 }
1011
Ted Kremenekcce207d2008-01-28 22:26:15 +00001012 case BinaryOperator::Rem: {
1013 const NonLValue& R1 = cast<NonLValue>(V1);
1014 const NonLValue& R2 = cast<NonLValue>(V2);
1015 Nodify(Dst, B, N2, SetValue(St, B, R1.Rem(ValMgr, R2)));
1016 break;
1017 }
1018
Ted Kremenekab2b8c52008-01-23 19:59:44 +00001019 case BinaryOperator::Assign: {
1020 const LValue& L1 = cast<LValue>(V1);
Ted Kremenekbd03f1d2008-01-28 22:09:13 +00001021 const NonLValue& R2 = cast<NonLValue>(V2);
Ted Kremenekab2b8c52008-01-23 19:59:44 +00001022 Nodify(Dst, B, N2, SetValue(SetValue(St, B, R2), L1, R2));
1023 break;
1024 }
Ted Kremenekb4ae33f2008-01-23 23:38:00 +00001025
1026 case BinaryOperator::AddAssign: {
1027 const LValue& L1 = cast<LValue>(V1);
Ted Kremenekbd03f1d2008-01-28 22:09:13 +00001028 NonLValue R1 = cast<NonLValue>(GetValue(N1->getState(), L1));
1029 NonLValue Result = R1.Add(ValMgr, cast<NonLValue>(V2));
Ted Kremenekb4ae33f2008-01-23 23:38:00 +00001030 Nodify(Dst, B, N2, SetValue(SetValue(St, B, Result), L1, Result));
1031 break;
1032 }
1033
1034 case BinaryOperator::SubAssign: {
1035 const LValue& L1 = cast<LValue>(V1);
Ted Kremenekbd03f1d2008-01-28 22:09:13 +00001036 NonLValue R1 = cast<NonLValue>(GetValue(N1->getState(), L1));
1037 NonLValue Result = R1.Sub(ValMgr, cast<NonLValue>(V2));
Ted Kremenekb4ae33f2008-01-23 23:38:00 +00001038 Nodify(Dst, B, N2, SetValue(SetValue(St, B, Result), L1, Result));
1039 break;
1040 }
Ted Kremenek2eafd0e2008-01-23 23:42:27 +00001041
1042 case BinaryOperator::MulAssign: {
1043 const LValue& L1 = cast<LValue>(V1);
Ted Kremenekbd03f1d2008-01-28 22:09:13 +00001044 NonLValue R1 = cast<NonLValue>(GetValue(N1->getState(), L1));
1045 NonLValue Result = R1.Mul(ValMgr, cast<NonLValue>(V2));
Ted Kremenek2eafd0e2008-01-23 23:42:27 +00001046 Nodify(Dst, B, N2, SetValue(SetValue(St, B, Result), L1, Result));
1047 break;
1048 }
Ted Kremenek5c1e2622008-01-25 23:45:34 +00001049
1050 case BinaryOperator::DivAssign: {
1051 const LValue& L1 = cast<LValue>(V1);
Ted Kremenekbd03f1d2008-01-28 22:09:13 +00001052 NonLValue R1 = cast<NonLValue>(GetValue(N1->getState(), L1));
1053 NonLValue Result = R1.Div(ValMgr, cast<NonLValue>(V2));
Ted Kremenek5c1e2622008-01-25 23:45:34 +00001054 Nodify(Dst, B, N2, SetValue(SetValue(St, B, Result), L1, Result));
1055 break;
1056 }
Ted Kremenek10099a62008-01-28 22:28:54 +00001057
1058 case BinaryOperator::RemAssign: {
1059 const LValue& L1 = cast<LValue>(V1);
1060 NonLValue R1 = cast<NonLValue>(GetValue(N1->getState(), L1));
1061 NonLValue Result = R1.Rem(ValMgr, cast<NonLValue>(V2));
1062 Nodify(Dst, B, N2, SetValue(SetValue(St, B, Result), L1, Result));
1063 break;
1064 }
Ted Kremenekab2b8c52008-01-23 19:59:44 +00001065
1066 default:
1067 Dst.Add(N2);
1068 break;
1069 }
Ted Kremenekcb448ca2008-01-16 00:53:15 +00001070 }
Ted Kremenekd27f8162008-01-15 23:55:06 +00001071 }
Ted Kremenekd27f8162008-01-15 23:55:06 +00001072}
Ted Kremenekee985462008-01-16 18:18:48 +00001073
Ted Kremenek1ccd31c2008-01-16 19:42:59 +00001074
Ted Kremenekab2b8c52008-01-23 19:59:44 +00001075void GRConstants::Visit(Stmt* S, GRConstants::NodeTy* Pred,
1076 GRConstants::NodeSet& Dst) {
1077
1078 // FIXME: add metadata to the CFG so that we can disable
1079 // this check when we KNOW that there is no block-level subexpression.
1080 // The motivation is that this check requires a hashtable lookup.
1081
1082 if (S != CurrentStmt && getCFG().isBlkExpr(S)) {
1083 Dst.Add(Pred);
1084 return;
1085 }
1086
1087 switch (S->getStmtClass()) {
1088 case Stmt::BinaryOperatorClass:
Ted Kremenekb4ae33f2008-01-23 23:38:00 +00001089 case Stmt::CompoundAssignOperatorClass:
Ted Kremenekab2b8c52008-01-23 19:59:44 +00001090 VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Dst);
1091 break;
1092
Ted Kremenek7b8009a2008-01-24 02:28:56 +00001093 case Stmt::UnaryOperatorClass:
1094 VisitUnaryOperator(cast<UnaryOperator>(S), Pred, Dst);
1095 break;
1096
Ted Kremenekab2b8c52008-01-23 19:59:44 +00001097 case Stmt::ParenExprClass:
1098 Visit(cast<ParenExpr>(S)->getSubExpr(), Pred, Dst);
1099 break;
1100
Ted Kremenek874d63f2008-01-24 02:02:54 +00001101 case Stmt::ImplicitCastExprClass: {
1102 ImplicitCastExpr* C = cast<ImplicitCastExpr>(S);
1103 VisitCast(C, C->getSubExpr(), Pred, Dst);
1104 break;
1105 }
1106
1107 case Stmt::CastExprClass: {
1108 CastExpr* C = cast<CastExpr>(S);
1109 VisitCast(C, C->getSubExpr(), Pred, Dst);
1110 break;
1111 }
1112
Ted Kremenek9de04c42008-01-24 20:55:43 +00001113 case Stmt::DeclStmtClass:
1114 VisitDeclStmt(cast<DeclStmt>(S), Pred, Dst);
1115 break;
1116
Ted Kremenekab2b8c52008-01-23 19:59:44 +00001117 default:
1118 Dst.Add(Pred); // No-op. Simply propagate the current state unchanged.
1119 break;
Ted Kremenek79649df2008-01-17 18:25:22 +00001120 }
Ted Kremenek1ccd31c2008-01-16 19:42:59 +00001121}
1122
Ted Kremenekee985462008-01-16 18:18:48 +00001123//===----------------------------------------------------------------------===//
1124// Driver.
1125//===----------------------------------------------------------------------===//
1126
Ted Kremenekaa66a322008-01-16 21:46:15 +00001127#ifndef NDEBUG
1128namespace llvm {
1129template<>
1130struct VISIBILITY_HIDDEN DOTGraphTraits<GRConstants::NodeTy*> :
1131 public DefaultDOTGraphTraits {
Ted Kremenek9ff731d2008-01-24 22:27:20 +00001132
1133 static void PrintKindLabel(std::ostream& Out, ValueKey::Kind kind) {
Ted Kremenek803c9ed2008-01-23 22:30:44 +00001134 switch (kind) {
Ted Kremenek565256e2008-01-24 22:44:24 +00001135 case ValueKey::IsSubExpr: Out << "Sub-Expressions:\\l"; break;
Ted Kremenek803c9ed2008-01-23 22:30:44 +00001136 case ValueKey::IsDecl: Out << "Variables:\\l"; break;
1137 case ValueKey::IsBlkExpr: Out << "Block-level Expressions:\\l"; break;
1138 default: assert (false && "Unknown ValueKey type.");
1139 }
1140 }
1141
Ted Kremenek9ff731d2008-01-24 22:27:20 +00001142 static void PrintKind(std::ostream& Out, GRConstants::StateTy M,
1143 ValueKey::Kind kind, bool isFirstGroup = false) {
1144 bool isFirst = true;
1145
1146 for (GRConstants::StateTy::iterator I=M.begin(), E=M.end();I!=E;++I) {
1147 if (I.getKey().getKind() != kind)
1148 continue;
1149
1150 if (isFirst) {
1151 if (!isFirstGroup) Out << "\\l\\l";
1152 PrintKindLabel(Out, kind);
1153 isFirst = false;
1154 }
1155 else
1156 Out << "\\l";
1157
1158 Out << ' ';
1159
1160 if (ValueDecl* V = dyn_cast<ValueDecl>(I.getKey()))
1161 Out << V->getName();
1162 else {
1163 Stmt* E = cast<Stmt>(I.getKey());
1164 Out << " (" << (void*) E << ") ";
1165 E->printPretty(Out);
1166 }
1167
1168 Out << " : ";
1169 I.getData().print(Out);
1170 }
1171 }
1172
Ted Kremenekaa66a322008-01-16 21:46:15 +00001173 static std::string getNodeLabel(const GRConstants::NodeTy* N, void*) {
1174 std::ostringstream Out;
Ted Kremenek803c9ed2008-01-23 22:30:44 +00001175
1176 // Program Location.
Ted Kremenekaa66a322008-01-16 21:46:15 +00001177 ProgramPoint Loc = N->getLocation();
1178
1179 switch (Loc.getKind()) {
1180 case ProgramPoint::BlockEntranceKind:
1181 Out << "Block Entrance: B"
1182 << cast<BlockEntrance>(Loc).getBlock()->getBlockID();
1183 break;
1184
1185 case ProgramPoint::BlockExitKind:
1186 assert (false);
1187 break;
1188
1189 case ProgramPoint::PostStmtKind: {
1190 const PostStmt& L = cast<PostStmt>(Loc);
Ted Kremenek9ff731d2008-01-24 22:27:20 +00001191 Out << L.getStmt()->getStmtClassName() << ':'
1192 << (void*) L.getStmt() << ' ';
1193
Ted Kremenekaa66a322008-01-16 21:46:15 +00001194 L.getStmt()->printPretty(Out);
1195 break;
1196 }
1197
1198 default: {
1199 const BlockEdge& E = cast<BlockEdge>(Loc);
1200 Out << "Edge: (B" << E.getSrc()->getBlockID() << ", B"
1201 << E.getDst()->getBlockID() << ')';
1202 }
1203 }
1204
Ted Kremenek803c9ed2008-01-23 22:30:44 +00001205 Out << "\\|";
Ted Kremenekaa66a322008-01-16 21:46:15 +00001206
Ted Kremenek9ff731d2008-01-24 22:27:20 +00001207 PrintKind(Out, N->getState(), ValueKey::IsDecl, true);
1208 PrintKind(Out, N->getState(), ValueKey::IsBlkExpr);
Ted Kremenek565256e2008-01-24 22:44:24 +00001209 PrintKind(Out, N->getState(), ValueKey::IsSubExpr);
Ted Kremenek803c9ed2008-01-23 22:30:44 +00001210
Ted Kremenek803c9ed2008-01-23 22:30:44 +00001211 Out << "\\l";
Ted Kremenekaa66a322008-01-16 21:46:15 +00001212 return Out.str();
1213 }
1214};
1215} // end llvm namespace
1216#endif
1217
Ted Kremenekee985462008-01-16 18:18:48 +00001218namespace clang {
Ted Kremenek874d63f2008-01-24 02:02:54 +00001219void RunGRConstants(CFG& cfg, ASTContext& Ctx) {
1220 GREngine<GRConstants> Engine(cfg, Ctx);
Ted Kremenekee985462008-01-16 18:18:48 +00001221 Engine.ExecuteWorkList();
Ted Kremenekaa66a322008-01-16 21:46:15 +00001222#ifndef NDEBUG
1223 llvm::ViewGraph(*Engine.getGraph().roots_begin(),"GRConstants");
1224#endif
Ted Kremenekee985462008-01-16 18:18:48 +00001225}
Ted Kremenekab2b8c52008-01-23 19:59:44 +00001226} // end clang namespace