blob: 103e6a0d74bb6336fe042d2f5cda1d5ba4821275 [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 Kremenekcb48b9c2008-01-29 00:33:40 +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:
Ted Kremenekcb48b9c2008-01-29 00:33:40 +0000160 ValueManager(ASTContext& ctx) : Ctx(ctx) {}
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000161 ~ValueManager();
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000162
Ted Kremenekcb48b9c2008-01-29 00:33:40 +0000163 ASTContext& getContext() const { return Ctx; }
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000164 APSInt& getValue(const APSInt& X);
165
Ted Kremenekd27f8162008-01-15 23:55:06 +0000166};
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000167} // end anonymous namespace
168
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000169ValueManager::~ValueManager() {
170 // Note that the dstor for the contents of APSIntSet will never be called,
171 // so we iterate over the set and invoke the dstor for each APSInt. This
172 // frees an aux. memory allocated to represent very large constants.
173 for (APSIntSetTy::iterator I=APSIntSet.begin(), E=APSIntSet.end(); I!=E; ++I)
174 I->getValue().~APSInt();
175}
Ted Kremenek5ee4ff82008-01-25 22:55:56 +0000176
Ted Kremenek5ee4ff82008-01-25 22:55:56 +0000177
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000178
179APSInt& ValueManager::getValue(const APSInt& X) {
180 llvm::FoldingSetNodeID ID;
181 void* InsertPos;
182 typedef llvm::FoldingSetNodeWrapper<APSInt> FoldNodeTy;
Ted Kremenekcc1c3652008-01-25 23:43:12 +0000183
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000184 X.Profile(ID);
185 FoldNodeTy* P = APSIntSet.FindNodeOrInsertPos(ID, InsertPos);
Ted Kremenek5ee4ff82008-01-25 22:55:56 +0000186
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000187 if (!P) {
188 P = (FoldNodeTy*) BPAlloc.Allocate<FoldNodeTy>();
189 new (P) FoldNodeTy(X);
190 APSIntSet.InsertNode(P, InsertPos);
191 }
192
193 return *P;
Ted Kremenek5ee4ff82008-01-25 22:55:56 +0000194}
195
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000196//===----------------------------------------------------------------------===//
197// Expression Values.
198//===----------------------------------------------------------------------===//
Ted Kremenekf13794e2008-01-24 23:19:54 +0000199
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000200namespace {
201
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000202class VISIBILITY_HIDDEN RValue {
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000203public:
Ted Kremenek403c1812008-01-28 22:51:57 +0000204 enum BaseKind { LValueKind=0x0, NonLValueKind=0x1,
205 UninitializedKind=0x2, InvalidKind=0x3, BaseFlags = 0x3 };
Ted Kremenekf13794e2008-01-24 23:19:54 +0000206
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000207private:
Ted Kremenekf2645622008-01-28 22:25:21 +0000208 void* Data;
Ted Kremenekf13794e2008-01-24 23:19:54 +0000209 unsigned Kind;
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000210
211protected:
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000212 RValue(const void* d, bool isLValue, unsigned ValKind)
Ted Kremenekf2645622008-01-28 22:25:21 +0000213 : Data(const_cast<void*>(d)),
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000214 Kind((isLValue ? LValueKind : NonLValueKind) | (ValKind << 2)) {}
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000215
Ted Kremenek403c1812008-01-28 22:51:57 +0000216 explicit RValue(BaseKind k)
217 : Data(0), Kind(k) {}
Ted Kremenekf2645622008-01-28 22:25:21 +0000218
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000219 void* getRawPtr() const {
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000220 return reinterpret_cast<void*>(Data);
221 }
222
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000223public:
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000224 ~RValue() {};
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000225
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000226 RValue Cast(ValueManager& ValMgr, Expr* CastExpr) const;
Ted Kremenek874d63f2008-01-24 02:02:54 +0000227
Ted Kremenekf13794e2008-01-24 23:19:54 +0000228 unsigned getRawKind() const { return Kind; }
229 BaseKind getBaseKind() const { return (BaseKind) (Kind & 0x3); }
230 unsigned getSubKind() const { return (Kind & ~0x3) >> 2; }
231
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000232 void Profile(llvm::FoldingSetNodeID& ID) const {
Ted Kremenekf13794e2008-01-24 23:19:54 +0000233 ID.AddInteger((unsigned) getRawKind());
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000234 ID.AddPointer(reinterpret_cast<void*>(Data));
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000235 }
236
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000237 bool operator==(const RValue& RHS) const {
Ted Kremenekf13794e2008-01-24 23:19:54 +0000238 return getRawKind() == RHS.getRawKind() && Data == RHS.Data;
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000239 }
240
Ted Kremenekf13794e2008-01-24 23:19:54 +0000241 inline bool isValid() const { return getRawKind() != InvalidKind; }
242 inline bool isInvalid() const { return getRawKind() == InvalidKind; }
243
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000244 void print(std::ostream& OS) const;
245 void print() const { print(*llvm::cerr.stream()); }
246
247 // Implement isa<T> support.
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000248 static inline bool classof(const RValue*) { return true; }
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000249};
250
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000251class VISIBILITY_HIDDEN InvalidValue : public RValue {
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000252public:
Ted Kremenek403c1812008-01-28 22:51:57 +0000253 InvalidValue() : RValue(InvalidKind) {}
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000254
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000255 static inline bool classof(const RValue* V) {
Ted Kremenekf13794e2008-01-24 23:19:54 +0000256 return V->getBaseKind() == InvalidKind;
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000257 }
258};
Ted Kremenek403c1812008-01-28 22:51:57 +0000259
260class VISIBILITY_HIDDEN UninitializedValue : public RValue {
261public:
262 UninitializedValue() : RValue(UninitializedKind) {}
263
264 static inline bool classof(const RValue* V) {
265 return V->getBaseKind() == UninitializedKind;
266 }
267};
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000268
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000269class VISIBILITY_HIDDEN LValue : public RValue {
Ted Kremenekf13794e2008-01-24 23:19:54 +0000270protected:
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000271 LValue(unsigned SubKind, void* D) : RValue(D, true, SubKind) {}
Ted Kremenekf13794e2008-01-24 23:19:54 +0000272
273public:
274 // Implement isa<T> support.
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000275 static inline bool classof(const RValue* V) {
Ted Kremenekf13794e2008-01-24 23:19:54 +0000276 return V->getBaseKind() == LValueKind;
277 }
278};
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000279
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000280class VISIBILITY_HIDDEN NonLValue : public RValue {
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000281protected:
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000282 NonLValue(unsigned SubKind, const void* d) : RValue(d, false, SubKind) {}
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000283
284public:
Ted Kremenekf13794e2008-01-24 23:19:54 +0000285 void print(std::ostream& Out) const;
286
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000287 NonLValue Add(ValueManager& ValMgr, const NonLValue& RHS) const;
288 NonLValue Sub(ValueManager& ValMgr, const NonLValue& RHS) const;
289 NonLValue Mul(ValueManager& ValMgr, const NonLValue& RHS) const;
290 NonLValue Div(ValueManager& ValMgr, const NonLValue& RHS) const;
291 NonLValue Rem(ValueManager& ValMgr, const NonLValue& RHS) const;
292 NonLValue UnaryMinus(ValueManager& ValMgr, UnaryOperator* U) const;
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000293
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000294 static NonLValue GetValue(ValueManager& ValMgr, const APSInt& V);
295 static NonLValue GetValue(ValueManager& ValMgr, IntegerLiteral* I);
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000296
297 // Implement isa<T> support.
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000298 static inline bool classof(const RValue* V) {
Ted Kremenek403c1812008-01-28 22:51:57 +0000299 return V->getBaseKind() >= NonLValueKind;
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000300 }
301};
Ted Kremenekf13794e2008-01-24 23:19:54 +0000302
303} // end anonymous namespace
304
305//===----------------------------------------------------------------------===//
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000306// LValues.
Ted Kremenekf13794e2008-01-24 23:19:54 +0000307//===----------------------------------------------------------------------===//
308
309namespace {
310
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000311enum { LValueDeclKind, NumLValueKind };
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000312
313class VISIBILITY_HIDDEN LValueDecl : public LValue {
314public:
Ted Kremenek9de04c42008-01-24 20:55:43 +0000315 LValueDecl(const ValueDecl* vd)
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000316 : LValue(LValueDeclKind,const_cast<ValueDecl*>(vd)) {}
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000317
318 ValueDecl* getDecl() const {
319 return static_cast<ValueDecl*>(getRawPtr());
320 }
321
322 // Implement isa<T> support.
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000323 static inline bool classof(const RValue* V) {
Ted Kremenekf13794e2008-01-24 23:19:54 +0000324 return V->getSubKind() == LValueDeclKind;
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000325 }
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000326};
327
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000328} // end anonymous namespace
329
330//===----------------------------------------------------------------------===//
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000331// Non-LValues.
332//===----------------------------------------------------------------------===//
333
334namespace {
335
Ted Kremenekf2645622008-01-28 22:25:21 +0000336enum { SymbolicNonLValueKind, ConcreteIntKind, ConstrainedIntegerKind,
337 NumNonLValueKind };
338
339class VISIBILITY_HIDDEN SymbolicNonLValue : public NonLValue {
340public:
341 SymbolicNonLValue(unsigned SymID)
342 : NonLValue(SymbolicNonLValueKind,
343 reinterpret_cast<void*>((uintptr_t) SymID)) {}
344
345 SymbolID getSymbolID() const {
346 return (SymbolID) reinterpret_cast<uintptr_t>(getRawPtr());
347 }
348
349 static inline bool classof(const RValue* V) {
350 return V->getSubKind() == SymbolicNonLValueKind;
351 }
352};
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000353
354class VISIBILITY_HIDDEN ConcreteInt : public NonLValue {
355public:
356 ConcreteInt(const APSInt& V) : NonLValue(ConcreteIntKind, &V) {}
357
358 const APSInt& getValue() const {
359 return *static_cast<APSInt*>(getRawPtr());
360 }
361
362 ConcreteInt Add(ValueManager& ValMgr, const ConcreteInt& V) const {
363 return ValMgr.getValue(getValue() + V.getValue());
364 }
365
366 ConcreteInt Sub(ValueManager& ValMgr, const ConcreteInt& V) const {
367 return ValMgr.getValue(getValue() - V.getValue());
368 }
369
370 ConcreteInt Mul(ValueManager& ValMgr, const ConcreteInt& V) const {
371 return ValMgr.getValue(getValue() * V.getValue());
372 }
373
374 ConcreteInt Div(ValueManager& ValMgr, const ConcreteInt& V) const {
375 return ValMgr.getValue(getValue() / V.getValue());
376 }
377
378 ConcreteInt Rem(ValueManager& ValMgr, const ConcreteInt& V) const {
379 return ValMgr.getValue(getValue() % V.getValue());
380 }
381
382 ConcreteInt Cast(ValueManager& ValMgr, Expr* CastExpr) const {
383 assert (CastExpr->getType()->isIntegerType());
384
385 APSInt X(getValue());
Ted Kremenekcb48b9c2008-01-29 00:33:40 +0000386 X.extOrTrunc(ValMgr.getContext().getTypeSize(CastExpr->getType(),
387 CastExpr->getLocStart()));
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000388 return ValMgr.getValue(X);
389 }
390
391 ConcreteInt UnaryMinus(ValueManager& ValMgr, UnaryOperator* U) const {
392 assert (U->getType() == U->getSubExpr()->getType());
393 assert (U->getType()->isIntegerType());
394 return ValMgr.getValue(-getValue());
395 }
396
397 // Implement isa<T> support.
398 static inline bool classof(const RValue* V) {
399 return V->getSubKind() == ConcreteIntKind;
400 }
401};
402
403} // end anonymous namespace
404
405//===----------------------------------------------------------------------===//
406// Transfer function dispatch.
407//===----------------------------------------------------------------------===//
408
409RValue RValue::Cast(ValueManager& ValMgr, Expr* CastExpr) const {
410 switch (getSubKind()) {
411 case ConcreteIntKind:
412 return cast<ConcreteInt>(this)->Cast(ValMgr, CastExpr);
413 default:
414 return InvalidValue();
415 }
416}
417
418NonLValue NonLValue::UnaryMinus(ValueManager& ValMgr, UnaryOperator* U) const {
419 switch (getSubKind()) {
420 case ConcreteIntKind:
421 return cast<ConcreteInt>(this)->UnaryMinus(ValMgr, U);
422 default:
423 return cast<NonLValue>(InvalidValue());
424 }
425}
426
427#define RVALUE_DISPATCH_CASE(k1,k2,Op)\
428case (k1##Kind*NumNonLValueKind+k2##Kind):\
429 return cast<k1>(*this).Op(ValMgr,cast<k2>(RHS));
430
431#define RVALUE_DISPATCH(Op)\
432switch (getSubKind()*NumNonLValueKind+RHS.getSubKind()){\
433 RVALUE_DISPATCH_CASE(ConcreteInt,ConcreteInt,Op)\
434 default:\
Ted Kremenek403c1812008-01-28 22:51:57 +0000435 if (getBaseKind() == UninitializedKind ||\
436 RHS.getBaseKind() == UninitializedKind)\
437 return cast<NonLValue>(UninitializedValue());\
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000438 assert (!isValid() || !RHS.isValid() && "Missing case.");\
439 break;\
440}\
441return cast<NonLValue>(InvalidValue());
442
443NonLValue NonLValue::Add(ValueManager& ValMgr, const NonLValue& RHS) const {
444 RVALUE_DISPATCH(Add)
445}
446
447NonLValue NonLValue::Sub(ValueManager& ValMgr, const NonLValue& RHS) const {
448 RVALUE_DISPATCH(Sub)
449}
450
451NonLValue NonLValue::Mul(ValueManager& ValMgr, const NonLValue& RHS) const {
452 RVALUE_DISPATCH(Mul)
453}
454
455NonLValue NonLValue::Div(ValueManager& ValMgr, const NonLValue& RHS) const {
456 RVALUE_DISPATCH(Div)
457}
458
459NonLValue NonLValue::Rem(ValueManager& ValMgr, const NonLValue& RHS) const {
460 RVALUE_DISPATCH(Rem)
461}
462
463
464#undef RVALUE_DISPATCH_CASE
465#undef RVALUE_DISPATCH
466
467//===----------------------------------------------------------------------===//
468// Utility methods for constructing RValues.
469//===----------------------------------------------------------------------===//
470
471NonLValue NonLValue::GetValue(ValueManager& ValMgr, const APSInt& V) {
472 return ConcreteInt(ValMgr.getValue(V));
473}
474
475NonLValue NonLValue::GetValue(ValueManager& ValMgr, IntegerLiteral* I) {
476 return ConcreteInt(ValMgr.getValue(APSInt(I->getValue(),
477 I->getType()->isUnsignedIntegerType())));
478}
479
480//===----------------------------------------------------------------------===//
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000481// Pretty-Printing.
482//===----------------------------------------------------------------------===//
483
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000484void RValue::print(std::ostream& Out) const {
Ted Kremenekf13794e2008-01-24 23:19:54 +0000485 switch (getBaseKind()) {
486 case InvalidKind:
487 Out << "Invalid";
488 break;
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000489
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000490 case NonLValueKind:
491 cast<NonLValue>(this)->print(Out);
Ted Kremenekf13794e2008-01-24 23:19:54 +0000492 break;
493
494 case LValueKind:
495 assert (false && "FIXME: LValue printing not implemented.");
496 break;
497
Ted Kremenek403c1812008-01-28 22:51:57 +0000498 case UninitializedKind:
499 Out << "Uninitialized";
500 break;
501
Ted Kremenekf13794e2008-01-24 23:19:54 +0000502 default:
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000503 assert (false && "Invalid RValue.");
Ted Kremenekf13794e2008-01-24 23:19:54 +0000504 }
505}
506
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000507void NonLValue::print(std::ostream& Out) const {
Ted Kremenekf13794e2008-01-24 23:19:54 +0000508 switch (getSubKind()) {
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000509 case ConcreteIntKind:
510 Out << cast<ConcreteInt>(this)->getValue().toString();
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000511 break;
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000512
513 default:
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000514 assert (false && "Pretty-printed not implemented for this NonLValue.");
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000515 break;
516 }
517}
518
519//===----------------------------------------------------------------------===//
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000520// ValueMapTy - A ImmutableMap type Stmt*/Decl*/Symbols to RValues.
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000521//===----------------------------------------------------------------------===//
522
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000523typedef llvm::ImmutableMap<ValueKey,RValue> ValueMapTy;
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000524
525namespace clang {
526 template<>
527 struct VISIBILITY_HIDDEN GRTrait<ValueMapTy> {
528 static inline void* toPtr(ValueMapTy M) {
529 return reinterpret_cast<void*>(M.getRoot());
530 }
531 static inline ValueMapTy toState(void* P) {
532 return ValueMapTy(static_cast<ValueMapTy::TreeTy*>(P));
533 }
534 };
Ted Kremenekd27f8162008-01-15 23:55:06 +0000535}
536
537//===----------------------------------------------------------------------===//
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000538// The Checker.
Ted Kremenekd27f8162008-01-15 23:55:06 +0000539//===----------------------------------------------------------------------===//
540
541namespace {
Ted Kremenekd27f8162008-01-15 23:55:06 +0000542
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000543class VISIBILITY_HIDDEN GRConstants {
Ted Kremenekd27f8162008-01-15 23:55:06 +0000544
545public:
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000546 typedef ValueMapTy StateTy;
Ted Kremenekd27f8162008-01-15 23:55:06 +0000547 typedef GRNodeBuilder<GRConstants> NodeBuilder;
Ted Kremenekcb48b9c2008-01-29 00:33:40 +0000548 typedef ExplodedGraph<GRConstants> GraphTy;
549 typedef GraphTy::NodeTy NodeTy;
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000550
551 class NodeSet {
552 typedef llvm::SmallVector<NodeTy*,3> ImplTy;
553 ImplTy Impl;
554 public:
555
556 NodeSet() {}
557 NodeSet(NodeTy* N) { assert (N && !N->isInfeasible()); Impl.push_back(N); }
558
559 void Add(NodeTy* N) { if (N && !N->isInfeasible()) Impl.push_back(N); }
560
561 typedef ImplTy::iterator iterator;
562 typedef ImplTy::const_iterator const_iterator;
563
564 unsigned size() const { return Impl.size(); }
Ted Kremenek9de04c42008-01-24 20:55:43 +0000565 bool empty() const { return Impl.empty(); }
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000566
567 iterator begin() { return Impl.begin(); }
568 iterator end() { return Impl.end(); }
569
570 const_iterator begin() const { return Impl.begin(); }
571 const_iterator end() const { return Impl.end(); }
572 };
Ted Kremenekd27f8162008-01-15 23:55:06 +0000573
574protected:
Ted Kremenekcb48b9c2008-01-29 00:33:40 +0000575 /// G - the simulation graph.
576 GraphTy& G;
577
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000578 /// Liveness - live-variables information the ValueDecl* and block-level
579 /// Expr* in the CFG. Used to prune out dead state.
Ted Kremenekbffaa832008-01-29 05:13:23 +0000580 LiveVariables Liveness;
Ted Kremenekd27f8162008-01-15 23:55:06 +0000581
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000582 /// Builder - The current GRNodeBuilder which is used when building the nodes
583 /// for a given statement.
Ted Kremenekd27f8162008-01-15 23:55:06 +0000584 NodeBuilder* Builder;
585
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000586 /// StateMgr - Object that manages the data for all created states.
587 ValueMapTy::Factory StateMgr;
Ted Kremenekd27f8162008-01-15 23:55:06 +0000588
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000589 /// ValueMgr - Object that manages the data for all created RValues.
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000590 ValueManager ValMgr;
591
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000592 /// StmtEntryNode - The immediate predecessor node.
593 NodeTy* StmtEntryNode;
594
595 /// CurrentStmt - The current block-level statement.
596 Stmt* CurrentStmt;
597
598 bool StateCleaned;
Ted Kremenekd27f8162008-01-15 23:55:06 +0000599
Ted Kremenekcb48b9c2008-01-29 00:33:40 +0000600 ASTContext& getContext() const { return G.getContext(); }
Ted Kremenek7b8009a2008-01-24 02:28:56 +0000601
Ted Kremenekd27f8162008-01-15 23:55:06 +0000602public:
Ted Kremenekbffaa832008-01-29 05:13:23 +0000603 GRConstants(GraphTy& g) : G(g), Liveness(G.getCFG(), G.getFunctionDecl()),
604 Builder(NULL), ValMgr(G.getContext()), StmtEntryNode(NULL),
605 CurrentStmt(NULL) {
Ted Kremenekd27f8162008-01-15 23:55:06 +0000606
Ted Kremenekcb48b9c2008-01-29 00:33:40 +0000607 // Compute liveness information.
Ted Kremenekbffaa832008-01-29 05:13:23 +0000608 Liveness.runOnCFG(G.getCFG());
609 Liveness.runOnAllBlocks(G.getCFG(), NULL, true);
Ted Kremenekd27f8162008-01-15 23:55:06 +0000610 }
Ted Kremenekcb48b9c2008-01-29 00:33:40 +0000611
612 /// getCFG - Returns the CFG associated with this analysis.
613 CFG& getCFG() { return G.getCFG(); }
Ted Kremenekd27f8162008-01-15 23:55:06 +0000614
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000615 /// getInitialState - Return the initial state used for the root vertex
616 /// in the ExplodedGraph.
Ted Kremenekd27f8162008-01-15 23:55:06 +0000617 StateTy getInitialState() {
Ted Kremenekcb48b9c2008-01-29 00:33:40 +0000618 StateTy St = StateMgr.GetEmptyMap();
Ted Kremenekff6e3c52008-01-29 00:43:03 +0000619
620 // Iterate the parameters.
621 FunctionDecl& F = G.getFunctionDecl();
622
623 for (FunctionDecl::param_iterator I=F.param_begin(), E=F.param_end();
624 I!=E; ++I) {
625
626 // For now we only support symbolic values for non-pointer types.
627 if ((*I)->getType()->isPointerType() ||
628 (*I)->getType()->isReferenceType())
629 continue;
630
631 // FIXME: Set these values to a symbol, not Uninitialized.
632 St = SetValue(St, LValueDecl(*I), UninitializedValue());
633 }
634
Ted Kremenekcb48b9c2008-01-29 00:33:40 +0000635 return St;
Ted Kremenekd27f8162008-01-15 23:55:06 +0000636 }
Ted Kremenekd27f8162008-01-15 23:55:06 +0000637
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000638 /// ProcessStmt - Called by GREngine. Used to generate new successor
639 /// nodes by processing the 'effects' of a block-level statement.
640 void ProcessStmt(Stmt* S, NodeBuilder& builder);
641
642 /// RemoveDeadBindings - Return a new state that is the same as 'M' except
643 /// that all subexpression mappings are removed and that any
644 /// block-level expressions that are not live at 'S' also have their
645 /// mappings removed.
646 StateTy RemoveDeadBindings(Stmt* S, StateTy M);
647
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000648 StateTy SetValue(StateTy St, Stmt* S, const RValue& V);
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000649
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000650 StateTy SetValue(StateTy St, const Stmt* S, const RValue& V) {
Ted Kremenek9de04c42008-01-24 20:55:43 +0000651 return SetValue(St, const_cast<Stmt*>(S), V);
652 }
653
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000654 StateTy SetValue(StateTy St, const LValue& LV, const RValue& V);
Ted Kremenek1ccd31c2008-01-16 19:42:59 +0000655
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000656 RValue GetValue(const StateTy& St, Stmt* S);
657 inline RValue GetValue(const StateTy& St, const Stmt* S) {
Ted Kremenek9de04c42008-01-24 20:55:43 +0000658 return GetValue(St, const_cast<Stmt*>(S));
659 }
660
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000661 RValue GetValue(const StateTy& St, const LValue& LV);
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000662 LValue GetLValue(const StateTy& St, Stmt* S);
Ted Kremenekd27f8162008-01-15 23:55:06 +0000663
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000664 void Nodify(NodeSet& Dst, Stmt* S, NodeTy* Pred, StateTy St);
Ted Kremenekd27f8162008-01-15 23:55:06 +0000665
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000666 /// Visit - Transfer function logic for all statements. Dispatches to
667 /// other functions that handle specific kinds of statements.
668 void Visit(Stmt* S, NodeTy* Pred, NodeSet& Dst);
Ted Kremenek874d63f2008-01-24 02:02:54 +0000669
670 /// VisitCast - Transfer function logic for all casts (implicit and explicit).
671 void VisitCast(Expr* CastE, Expr* E, NodeTy* Pred, NodeSet& Dst);
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000672
Ted Kremenek7b8009a2008-01-24 02:28:56 +0000673 /// VisitUnaryOperator - Transfer function logic for unary operators.
674 void VisitUnaryOperator(UnaryOperator* B, NodeTy* Pred, NodeSet& Dst);
675
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000676 /// VisitBinaryOperator - Transfer function logic for binary operators.
Ted Kremenek9de04c42008-01-24 20:55:43 +0000677 void VisitBinaryOperator(BinaryOperator* B, NodeTy* Pred, NodeSet& Dst);
678
679 /// VisitDeclStmt - Transfer function logic for DeclStmts.
680 void VisitDeclStmt(DeclStmt* DS, NodeTy* Pred, NodeSet& Dst);
Ted Kremenekd27f8162008-01-15 23:55:06 +0000681};
682} // end anonymous namespace
683
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000684
Ted Kremenekd27f8162008-01-15 23:55:06 +0000685void GRConstants::ProcessStmt(Stmt* S, NodeBuilder& builder) {
686 Builder = &builder;
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000687
688 StmtEntryNode = builder.getLastNode();
689 CurrentStmt = S;
690 NodeSet Dst;
691 StateCleaned = false;
692
693 Visit(S, StmtEntryNode, Dst);
694
695 // If no nodes were generated, generate a new node that has all the
696 // dead mappings removed.
697 if (Dst.size() == 1 && *Dst.begin() == StmtEntryNode) {
698 StateTy St = RemoveDeadBindings(S, StmtEntryNode->getState());
699 builder.generateNode(S, St, StmtEntryNode);
700 }
Ted Kremenekf84469b2008-01-18 00:41:32 +0000701
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000702 CurrentStmt = NULL;
703 StmtEntryNode = NULL;
704 Builder = NULL;
Ted Kremenekd27f8162008-01-15 23:55:06 +0000705}
706
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000707
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000708RValue GRConstants::GetValue(const StateTy& St, const LValue& LV) {
Ted Kremenekf13794e2008-01-24 23:19:54 +0000709 switch (LV.getSubKind()) {
710 case LValueDeclKind: {
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000711 StateTy::TreeTy* T = St.SlimFind(cast<LValueDecl>(LV).getDecl());
712 return T ? T->getValue().second : InvalidValue();
713 }
714 default:
715 assert (false && "Invalid LValue.");
Ted Kremenekca3e8572008-01-16 22:28:08 +0000716 break;
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000717 }
718
719 return InvalidValue();
720}
721
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000722RValue GRConstants::GetValue(const StateTy& St, Stmt* S) {
Ted Kremenek671c9e82008-01-24 00:50:08 +0000723 for (;;) {
724 switch (S->getStmtClass()) {
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000725
726 // ParenExprs are no-ops.
727
Ted Kremenek671c9e82008-01-24 00:50:08 +0000728 case Stmt::ParenExprClass:
729 S = cast<ParenExpr>(S)->getSubExpr();
730 continue;
731
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000732 // DeclRefExprs can either evaluate to an LValue or a Non-LValue
733 // (assuming an implicit "load") depending on the context. In this
734 // context we assume that we are retrieving the value contained
735 // within the referenced variables.
736
Ted Kremenek671c9e82008-01-24 00:50:08 +0000737 case Stmt::DeclRefExprClass:
738 return GetValue(St, LValueDecl(cast<DeclRefExpr>(S)->getDecl()));
Ted Kremenekca3e8572008-01-16 22:28:08 +0000739
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000740 // Integer literals evaluate to an RValue. Simply retrieve the
741 // RValue for the literal.
742
Ted Kremenek671c9e82008-01-24 00:50:08 +0000743 case Stmt::IntegerLiteralClass:
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000744 return NonLValue::GetValue(ValMgr, cast<IntegerLiteral>(S));
745
746 // Casts where the source and target type are the same
747 // are no-ops. We blast through these to get the descendant
748 // subexpression that has a value.
749
Ted Kremenek874d63f2008-01-24 02:02:54 +0000750 case Stmt::ImplicitCastExprClass: {
751 ImplicitCastExpr* C = cast<ImplicitCastExpr>(S);
752 if (C->getType() == C->getSubExpr()->getType()) {
753 S = C->getSubExpr();
754 continue;
755 }
756 break;
757 }
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000758
Ted Kremenek874d63f2008-01-24 02:02:54 +0000759 case Stmt::CastExprClass: {
760 CastExpr* C = cast<CastExpr>(S);
761 if (C->getType() == C->getSubExpr()->getType()) {
762 S = C->getSubExpr();
763 continue;
764 }
765 break;
766 }
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000767
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000768 // Handle all other Stmt* using a lookup.
769
Ted Kremenek671c9e82008-01-24 00:50:08 +0000770 default:
771 break;
772 };
773
774 break;
775 }
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000776
Ted Kremenek5c1b9962008-01-24 19:43:37 +0000777 StateTy::TreeTy* T = St.SlimFind(S);
Ted Kremenek874d63f2008-01-24 02:02:54 +0000778
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000779 return T ? T->getValue().second : InvalidValue();
780}
781
782LValue GRConstants::GetLValue(const StateTy& St, Stmt* S) {
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000783 while (ParenExpr* P = dyn_cast<ParenExpr>(S))
784 S = P->getSubExpr();
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000785
786 if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(S))
787 return LValueDecl(DR->getDecl());
788
789 return cast<LValue>(GetValue(St, S));
790}
791
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000792
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000793GRConstants::StateTy GRConstants::SetValue(StateTy St, Stmt* S,
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000794 const RValue& V) {
Ted Kremenekcc1c3652008-01-25 23:43:12 +0000795 assert (S);
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000796
797 if (!StateCleaned) {
798 St = RemoveDeadBindings(CurrentStmt, St);
799 StateCleaned = true;
800 }
801
Ted Kremenek9ff731d2008-01-24 22:27:20 +0000802 bool isBlkExpr = false;
803
804 if (S == CurrentStmt) {
805 isBlkExpr = getCFG().isBlkExpr(S);
806
807 if (!isBlkExpr)
808 return St;
809 }
Ted Kremenekdaadf452008-01-24 19:28:01 +0000810
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000811 return V.isValid() ? StateMgr.Add(St, ValueKey(S,isBlkExpr), V)
812 : St;
813}
814
815GRConstants::StateTy GRConstants::SetValue(StateTy St, const LValue& LV,
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000816 const RValue& V) {
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000817 if (!LV.isValid())
818 return St;
819
820 if (!StateCleaned) {
821 St = RemoveDeadBindings(CurrentStmt, St);
822 StateCleaned = true;
Ted Kremenekca3e8572008-01-16 22:28:08 +0000823 }
Ted Kremenek0525a4f2008-01-16 19:47:19 +0000824
Ted Kremenekf13794e2008-01-24 23:19:54 +0000825 switch (LV.getSubKind()) {
826 case LValueDeclKind:
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000827 return V.isValid() ? StateMgr.Add(St, cast<LValueDecl>(LV).getDecl(), V)
828 : StateMgr.Remove(St, cast<LValueDecl>(LV).getDecl());
829
830 default:
831 assert ("SetValue for given LValue type not yet implemented.");
832 return St;
833 }
Ted Kremenekd27f8162008-01-15 23:55:06 +0000834}
835
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000836GRConstants::StateTy GRConstants::RemoveDeadBindings(Stmt* Loc, StateTy M) {
Ted Kremenekf84469b2008-01-18 00:41:32 +0000837 // Note: in the code below, we can assign a new map to M since the
838 // iterators are iterating over the tree of the *original* map.
Ted Kremenekf84469b2008-01-18 00:41:32 +0000839 StateTy::iterator I = M.begin(), E = M.end();
840
Ted Kremenek5c1b9962008-01-24 19:43:37 +0000841 // Remove old bindings for subexpressions and "dead" block-level expressions.
842 for (; I!=E && !I.getKey().isDecl(); ++I) {
Ted Kremenekbffaa832008-01-29 05:13:23 +0000843 if (I.getKey().isSubExpr() || !Liveness.isLive(Loc,cast<Stmt>(I.getKey())))
Ted Kremenek5c1b9962008-01-24 19:43:37 +0000844 M = StateMgr.Remove(M, I.getKey());
845 }
Ted Kremenekf84469b2008-01-18 00:41:32 +0000846
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000847 // Remove bindings for "dead" decls.
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000848 for (; I!=E && I.getKey().isDecl(); ++I)
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000849 if (VarDecl* V = dyn_cast<VarDecl>(cast<ValueDecl>(I.getKey())))
Ted Kremenekbffaa832008-01-29 05:13:23 +0000850 if (!Liveness.isLive(Loc, V))
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000851 M = StateMgr.Remove(M, I.getKey());
Ted Kremenek565256e2008-01-24 22:44:24 +0000852
Ted Kremeneke00fe3f2008-01-17 00:52:48 +0000853 return M;
Ted Kremeneke00fe3f2008-01-17 00:52:48 +0000854}
855
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000856void GRConstants::Nodify(NodeSet& Dst, Stmt* S, GRConstants::NodeTy* Pred,
857 GRConstants::StateTy St) {
858
859 // If the state hasn't changed, don't generate a new node.
860 if (St == Pred->getState())
861 return;
Ted Kremenekcb448ca2008-01-16 00:53:15 +0000862
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000863 Dst.Add(Builder->generateNode(S, St, Pred));
Ted Kremenekcb448ca2008-01-16 00:53:15 +0000864}
Ted Kremenekd27f8162008-01-15 23:55:06 +0000865
Ted Kremenek874d63f2008-01-24 02:02:54 +0000866void GRConstants::VisitCast(Expr* CastE, Expr* E, GRConstants::NodeTy* Pred,
867 GRConstants::NodeSet& Dst) {
868
869 QualType T = CastE->getType();
870
871 // Check for redundant casts.
872 if (E->getType() == T) {
873 Dst.Add(Pred);
874 return;
875 }
876
877 NodeSet S1;
878 Visit(E, Pred, S1);
879
880 for (NodeSet::iterator I1=S1.begin(), E1=S1.end(); I1 != E1; ++I1) {
881 NodeTy* N = *I1;
882 StateTy St = N->getState();
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000883 const RValue& V = GetValue(St, E);
884 Nodify(Dst, CastE, N, SetValue(St, CastE, V.Cast(ValMgr, CastE)));
Ted Kremenek874d63f2008-01-24 02:02:54 +0000885 }
Ted Kremenek9de04c42008-01-24 20:55:43 +0000886}
887
888void GRConstants::VisitDeclStmt(DeclStmt* DS, GRConstants::NodeTy* Pred,
889 GRConstants::NodeSet& Dst) {
890
891 StateTy St = Pred->getState();
892
893 for (const ScopedDecl* D = DS->getDecl(); D; D = D->getNextDeclarator())
Ted Kremenek403c1812008-01-28 22:51:57 +0000894 if (const VarDecl* VD = dyn_cast<VarDecl>(D)) {
895 const Expr* E = VD->getInit();
896 St = SetValue(St, LValueDecl(VD),
897 E ? GetValue(St, E) : UninitializedValue());
898 }
Ted Kremenek9de04c42008-01-24 20:55:43 +0000899
900 Nodify(Dst, DS, Pred, St);
901
902 if (Dst.empty())
903 Dst.Add(Pred);
904}
Ted Kremenek874d63f2008-01-24 02:02:54 +0000905
Ted Kremenek7b8009a2008-01-24 02:28:56 +0000906void GRConstants::VisitUnaryOperator(UnaryOperator* U,
907 GRConstants::NodeTy* Pred,
908 GRConstants::NodeSet& Dst) {
909 NodeSet S1;
910 Visit(U->getSubExpr(), Pred, S1);
911
912 for (NodeSet::iterator I1=S1.begin(), E1=S1.end(); I1 != E1; ++I1) {
913 NodeTy* N1 = *I1;
914 StateTy St = N1->getState();
915
916 switch (U->getOpcode()) {
917 case UnaryOperator::PostInc: {
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 Kremenekcb48b9c2008-01-29 00:33:40 +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 Kremeneke0cf9c82008-01-24 19:00:57 +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, R1), L1, Result));
928 break;
929 }
930
931 case UnaryOperator::PostDec: {
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 Kremenekcb48b9c2008-01-29 00:33:40 +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, R1), L1, Result));
942 break;
943 }
944
945 case UnaryOperator::PreInc: {
946 const LValue& L1 = GetLValue(St, U->getSubExpr());
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000947 NonLValue R1 = cast<NonLValue>(GetValue(St, L1));
Ted Kremenek7b8009a2008-01-24 02:28:56 +0000948
949 QualType T = U->getType();
Ted Kremenekcb48b9c2008-01-29 00:33:40 +0000950 unsigned bits = getContext().getTypeSize(T, U->getLocStart());
Ted Kremenek5ee4ff82008-01-25 22:55:56 +0000951 APSInt One(llvm::APInt(bits, 1), T->isUnsignedIntegerType());
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000952 NonLValue R2 = NonLValue::GetValue(ValMgr, One);
Ted Kremenek7b8009a2008-01-24 02:28:56 +0000953
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000954 NonLValue Result = R1.Add(ValMgr, R2);
Ted Kremenek7b8009a2008-01-24 02:28:56 +0000955 Nodify(Dst, U, N1, SetValue(SetValue(St, U, Result), L1, Result));
956 break;
957 }
958
959 case UnaryOperator::PreDec: {
960 const LValue& L1 = GetLValue(St, U->getSubExpr());
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000961 NonLValue R1 = cast<NonLValue>(GetValue(St, L1));
Ted Kremenek7b8009a2008-01-24 02:28:56 +0000962
963 QualType T = U->getType();
Ted Kremenekcb48b9c2008-01-29 00:33:40 +0000964 unsigned bits = getContext().getTypeSize(T, U->getLocStart());
Ted Kremenek5ee4ff82008-01-25 22:55:56 +0000965 APSInt One(llvm::APInt(bits, 1), T->isUnsignedIntegerType());
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000966 NonLValue R2 = NonLValue::GetValue(ValMgr, One);
Ted Kremenek7b8009a2008-01-24 02:28:56 +0000967
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000968 NonLValue Result = R1.Sub(ValMgr, R2);
Ted Kremenek7b8009a2008-01-24 02:28:56 +0000969 Nodify(Dst, U, N1, SetValue(SetValue(St, U, Result), L1, Result));
970 break;
971 }
972
Ted Kremenekdacbb4f2008-01-24 08:20:02 +0000973 case UnaryOperator::Minus: {
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000974 const NonLValue& R1 = cast<NonLValue>(GetValue(St, U->getSubExpr()));
975 Nodify(Dst, U, N1, SetValue(St, U, R1.UnaryMinus(ValMgr, U)));
Ted Kremenekdacbb4f2008-01-24 08:20:02 +0000976 break;
977 }
978
Ted Kremenek7b8009a2008-01-24 02:28:56 +0000979 default: ;
980 assert (false && "Not implemented.");
981 }
982 }
983}
984
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000985void GRConstants::VisitBinaryOperator(BinaryOperator* B,
986 GRConstants::NodeTy* Pred,
987 GRConstants::NodeSet& Dst) {
988 NodeSet S1;
989 Visit(B->getLHS(), Pred, S1);
Ted Kremenekcb448ca2008-01-16 00:53:15 +0000990
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000991 for (NodeSet::iterator I1=S1.begin(), E1=S1.end(); I1 != E1; ++I1) {
992 NodeTy* N1 = *I1;
Ted Kremeneke00fe3f2008-01-17 00:52:48 +0000993
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000994 // When getting the value for the LHS, check if we are in an assignment.
995 // In such cases, we want to (initially) treat the LHS as an LValue,
996 // so we use GetLValue instead of GetValue so that DeclRefExpr's are
Ted Kremenekbd03f1d2008-01-28 22:09:13 +0000997 // evaluated to LValueDecl's instead of to an NonLValue.
998 const RValue& V1 =
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000999 B->isAssignmentOp() ? GetLValue(N1->getState(), B->getLHS())
1000 : GetValue(N1->getState(), B->getLHS());
Ted Kremenekcb448ca2008-01-16 00:53:15 +00001001
Ted Kremenekab2b8c52008-01-23 19:59:44 +00001002 NodeSet S2;
1003 Visit(B->getRHS(), N1, S2);
1004
1005 for (NodeSet::iterator I2=S2.begin(), E2=S2.end(); I2 != E2; ++I2) {
1006 NodeTy* N2 = *I2;
1007 StateTy St = N2->getState();
Ted Kremenekbd03f1d2008-01-28 22:09:13 +00001008 const RValue& V2 = GetValue(St, B->getRHS());
Ted Kremenekab2b8c52008-01-23 19:59:44 +00001009
1010 switch (B->getOpcode()) {
1011 case BinaryOperator::Add: {
Ted Kremenekbd03f1d2008-01-28 22:09:13 +00001012 const NonLValue& R1 = cast<NonLValue>(V1);
1013 const NonLValue& R2 = cast<NonLValue>(V2);
Ted Kremenekab2b8c52008-01-23 19:59:44 +00001014
Ted Kremenekbd03f1d2008-01-28 22:09:13 +00001015 Nodify(Dst, B, N2, SetValue(St, B, R1.Add(ValMgr, R2)));
Ted Kremenekab2b8c52008-01-23 19:59:44 +00001016 break;
1017 }
1018
1019 case BinaryOperator::Sub: {
Ted Kremenekbd03f1d2008-01-28 22:09:13 +00001020 const NonLValue& R1 = cast<NonLValue>(V1);
1021 const NonLValue& R2 = cast<NonLValue>(V2);
1022 Nodify(Dst, B, N2, SetValue(St, B, R1.Sub(ValMgr, R2)));
Ted Kremenekab2b8c52008-01-23 19:59:44 +00001023 break;
1024 }
1025
Ted Kremenek2eafd0e2008-01-23 23:42:27 +00001026 case BinaryOperator::Mul: {
Ted Kremenekbd03f1d2008-01-28 22:09:13 +00001027 const NonLValue& R1 = cast<NonLValue>(V1);
1028 const NonLValue& R2 = cast<NonLValue>(V2);
1029 Nodify(Dst, B, N2, SetValue(St, B, R1.Mul(ValMgr, R2)));
Ted Kremenek2eafd0e2008-01-23 23:42:27 +00001030 break;
1031 }
1032
Ted Kremenek5ee4ff82008-01-25 22:55:56 +00001033 case BinaryOperator::Div: {
Ted Kremenekbd03f1d2008-01-28 22:09:13 +00001034 const NonLValue& R1 = cast<NonLValue>(V1);
1035 const NonLValue& R2 = cast<NonLValue>(V2);
1036 Nodify(Dst, B, N2, SetValue(St, B, R1.Div(ValMgr, R2)));
Ted Kremenek5ee4ff82008-01-25 22:55:56 +00001037 break;
1038 }
1039
Ted Kremenekcce207d2008-01-28 22:26:15 +00001040 case BinaryOperator::Rem: {
1041 const NonLValue& R1 = cast<NonLValue>(V1);
1042 const NonLValue& R2 = cast<NonLValue>(V2);
1043 Nodify(Dst, B, N2, SetValue(St, B, R1.Rem(ValMgr, R2)));
1044 break;
1045 }
1046
Ted Kremenekab2b8c52008-01-23 19:59:44 +00001047 case BinaryOperator::Assign: {
1048 const LValue& L1 = cast<LValue>(V1);
Ted Kremenekbd03f1d2008-01-28 22:09:13 +00001049 const NonLValue& R2 = cast<NonLValue>(V2);
Ted Kremenekab2b8c52008-01-23 19:59:44 +00001050 Nodify(Dst, B, N2, SetValue(SetValue(St, B, R2), L1, R2));
1051 break;
1052 }
Ted Kremenekb4ae33f2008-01-23 23:38:00 +00001053
1054 case BinaryOperator::AddAssign: {
1055 const LValue& L1 = cast<LValue>(V1);
Ted Kremenekbd03f1d2008-01-28 22:09:13 +00001056 NonLValue R1 = cast<NonLValue>(GetValue(N1->getState(), L1));
1057 NonLValue Result = R1.Add(ValMgr, cast<NonLValue>(V2));
Ted Kremenekb4ae33f2008-01-23 23:38:00 +00001058 Nodify(Dst, B, N2, SetValue(SetValue(St, B, Result), L1, Result));
1059 break;
1060 }
1061
1062 case BinaryOperator::SubAssign: {
1063 const LValue& L1 = cast<LValue>(V1);
Ted Kremenekbd03f1d2008-01-28 22:09:13 +00001064 NonLValue R1 = cast<NonLValue>(GetValue(N1->getState(), L1));
1065 NonLValue Result = R1.Sub(ValMgr, cast<NonLValue>(V2));
Ted Kremenekb4ae33f2008-01-23 23:38:00 +00001066 Nodify(Dst, B, N2, SetValue(SetValue(St, B, Result), L1, Result));
1067 break;
1068 }
Ted Kremenek2eafd0e2008-01-23 23:42:27 +00001069
1070 case BinaryOperator::MulAssign: {
1071 const LValue& L1 = cast<LValue>(V1);
Ted Kremenekbd03f1d2008-01-28 22:09:13 +00001072 NonLValue R1 = cast<NonLValue>(GetValue(N1->getState(), L1));
1073 NonLValue Result = R1.Mul(ValMgr, cast<NonLValue>(V2));
Ted Kremenek2eafd0e2008-01-23 23:42:27 +00001074 Nodify(Dst, B, N2, SetValue(SetValue(St, B, Result), L1, Result));
1075 break;
1076 }
Ted Kremenek5c1e2622008-01-25 23:45:34 +00001077
1078 case BinaryOperator::DivAssign: {
1079 const LValue& L1 = cast<LValue>(V1);
Ted Kremenekbd03f1d2008-01-28 22:09:13 +00001080 NonLValue R1 = cast<NonLValue>(GetValue(N1->getState(), L1));
1081 NonLValue Result = R1.Div(ValMgr, cast<NonLValue>(V2));
Ted Kremenek5c1e2622008-01-25 23:45:34 +00001082 Nodify(Dst, B, N2, SetValue(SetValue(St, B, Result), L1, Result));
1083 break;
1084 }
Ted Kremenek10099a62008-01-28 22:28:54 +00001085
1086 case BinaryOperator::RemAssign: {
1087 const LValue& L1 = cast<LValue>(V1);
1088 NonLValue R1 = cast<NonLValue>(GetValue(N1->getState(), L1));
1089 NonLValue Result = R1.Rem(ValMgr, cast<NonLValue>(V2));
1090 Nodify(Dst, B, N2, SetValue(SetValue(St, B, Result), L1, Result));
1091 break;
1092 }
Ted Kremenekab2b8c52008-01-23 19:59:44 +00001093
1094 default:
1095 Dst.Add(N2);
1096 break;
1097 }
Ted Kremenekcb448ca2008-01-16 00:53:15 +00001098 }
Ted Kremenekd27f8162008-01-15 23:55:06 +00001099 }
Ted Kremenekd27f8162008-01-15 23:55:06 +00001100}
Ted Kremenekee985462008-01-16 18:18:48 +00001101
Ted Kremenek1ccd31c2008-01-16 19:42:59 +00001102
Ted Kremenekab2b8c52008-01-23 19:59:44 +00001103void GRConstants::Visit(Stmt* S, GRConstants::NodeTy* Pred,
1104 GRConstants::NodeSet& Dst) {
1105
1106 // FIXME: add metadata to the CFG so that we can disable
1107 // this check when we KNOW that there is no block-level subexpression.
1108 // The motivation is that this check requires a hashtable lookup.
1109
1110 if (S != CurrentStmt && getCFG().isBlkExpr(S)) {
1111 Dst.Add(Pred);
1112 return;
1113 }
1114
1115 switch (S->getStmtClass()) {
1116 case Stmt::BinaryOperatorClass:
Ted Kremenekb4ae33f2008-01-23 23:38:00 +00001117 case Stmt::CompoundAssignOperatorClass:
Ted Kremenekab2b8c52008-01-23 19:59:44 +00001118 VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Dst);
1119 break;
1120
Ted Kremenek7b8009a2008-01-24 02:28:56 +00001121 case Stmt::UnaryOperatorClass:
1122 VisitUnaryOperator(cast<UnaryOperator>(S), Pred, Dst);
1123 break;
1124
Ted Kremenekab2b8c52008-01-23 19:59:44 +00001125 case Stmt::ParenExprClass:
1126 Visit(cast<ParenExpr>(S)->getSubExpr(), Pred, Dst);
1127 break;
1128
Ted Kremenek874d63f2008-01-24 02:02:54 +00001129 case Stmt::ImplicitCastExprClass: {
1130 ImplicitCastExpr* C = cast<ImplicitCastExpr>(S);
1131 VisitCast(C, C->getSubExpr(), Pred, Dst);
1132 break;
1133 }
1134
1135 case Stmt::CastExprClass: {
1136 CastExpr* C = cast<CastExpr>(S);
1137 VisitCast(C, C->getSubExpr(), Pred, Dst);
1138 break;
1139 }
1140
Ted Kremenek9de04c42008-01-24 20:55:43 +00001141 case Stmt::DeclStmtClass:
1142 VisitDeclStmt(cast<DeclStmt>(S), Pred, Dst);
1143 break;
1144
Ted Kremenekab2b8c52008-01-23 19:59:44 +00001145 default:
1146 Dst.Add(Pred); // No-op. Simply propagate the current state unchanged.
1147 break;
Ted Kremenek79649df2008-01-17 18:25:22 +00001148 }
Ted Kremenek1ccd31c2008-01-16 19:42:59 +00001149}
1150
Ted Kremenekee985462008-01-16 18:18:48 +00001151//===----------------------------------------------------------------------===//
1152// Driver.
1153//===----------------------------------------------------------------------===//
1154
Ted Kremenekaa66a322008-01-16 21:46:15 +00001155#ifndef NDEBUG
1156namespace llvm {
1157template<>
1158struct VISIBILITY_HIDDEN DOTGraphTraits<GRConstants::NodeTy*> :
1159 public DefaultDOTGraphTraits {
Ted Kremenek9ff731d2008-01-24 22:27:20 +00001160
1161 static void PrintKindLabel(std::ostream& Out, ValueKey::Kind kind) {
Ted Kremenek803c9ed2008-01-23 22:30:44 +00001162 switch (kind) {
Ted Kremenek565256e2008-01-24 22:44:24 +00001163 case ValueKey::IsSubExpr: Out << "Sub-Expressions:\\l"; break;
Ted Kremenek803c9ed2008-01-23 22:30:44 +00001164 case ValueKey::IsDecl: Out << "Variables:\\l"; break;
1165 case ValueKey::IsBlkExpr: Out << "Block-level Expressions:\\l"; break;
1166 default: assert (false && "Unknown ValueKey type.");
1167 }
1168 }
1169
Ted Kremenek9ff731d2008-01-24 22:27:20 +00001170 static void PrintKind(std::ostream& Out, GRConstants::StateTy M,
1171 ValueKey::Kind kind, bool isFirstGroup = false) {
1172 bool isFirst = true;
1173
1174 for (GRConstants::StateTy::iterator I=M.begin(), E=M.end();I!=E;++I) {
1175 if (I.getKey().getKind() != kind)
1176 continue;
1177
1178 if (isFirst) {
1179 if (!isFirstGroup) Out << "\\l\\l";
1180 PrintKindLabel(Out, kind);
1181 isFirst = false;
1182 }
1183 else
1184 Out << "\\l";
1185
1186 Out << ' ';
1187
1188 if (ValueDecl* V = dyn_cast<ValueDecl>(I.getKey()))
1189 Out << V->getName();
1190 else {
1191 Stmt* E = cast<Stmt>(I.getKey());
1192 Out << " (" << (void*) E << ") ";
1193 E->printPretty(Out);
1194 }
1195
1196 Out << " : ";
1197 I.getData().print(Out);
1198 }
1199 }
1200
Ted Kremenekaa66a322008-01-16 21:46:15 +00001201 static std::string getNodeLabel(const GRConstants::NodeTy* N, void*) {
1202 std::ostringstream Out;
Ted Kremenek803c9ed2008-01-23 22:30:44 +00001203
1204 // Program Location.
Ted Kremenekaa66a322008-01-16 21:46:15 +00001205 ProgramPoint Loc = N->getLocation();
1206
1207 switch (Loc.getKind()) {
1208 case ProgramPoint::BlockEntranceKind:
1209 Out << "Block Entrance: B"
1210 << cast<BlockEntrance>(Loc).getBlock()->getBlockID();
1211 break;
1212
1213 case ProgramPoint::BlockExitKind:
1214 assert (false);
1215 break;
1216
1217 case ProgramPoint::PostStmtKind: {
1218 const PostStmt& L = cast<PostStmt>(Loc);
Ted Kremenek9ff731d2008-01-24 22:27:20 +00001219 Out << L.getStmt()->getStmtClassName() << ':'
1220 << (void*) L.getStmt() << ' ';
1221
Ted Kremenekaa66a322008-01-16 21:46:15 +00001222 L.getStmt()->printPretty(Out);
1223 break;
1224 }
1225
1226 default: {
1227 const BlockEdge& E = cast<BlockEdge>(Loc);
1228 Out << "Edge: (B" << E.getSrc()->getBlockID() << ", B"
1229 << E.getDst()->getBlockID() << ')';
1230 }
1231 }
1232
Ted Kremenek803c9ed2008-01-23 22:30:44 +00001233 Out << "\\|";
Ted Kremenekaa66a322008-01-16 21:46:15 +00001234
Ted Kremenek9ff731d2008-01-24 22:27:20 +00001235 PrintKind(Out, N->getState(), ValueKey::IsDecl, true);
1236 PrintKind(Out, N->getState(), ValueKey::IsBlkExpr);
Ted Kremenek565256e2008-01-24 22:44:24 +00001237 PrintKind(Out, N->getState(), ValueKey::IsSubExpr);
Ted Kremenek803c9ed2008-01-23 22:30:44 +00001238
Ted Kremenek803c9ed2008-01-23 22:30:44 +00001239 Out << "\\l";
Ted Kremenekaa66a322008-01-16 21:46:15 +00001240 return Out.str();
1241 }
1242};
1243} // end llvm namespace
1244#endif
1245
Ted Kremenekee985462008-01-16 18:18:48 +00001246namespace clang {
Ted Kremenekcb48b9c2008-01-29 00:33:40 +00001247void RunGRConstants(CFG& cfg, FunctionDecl& FD, ASTContext& Ctx) {
1248 GREngine<GRConstants> Engine(cfg, FD, Ctx);
Ted Kremenekee985462008-01-16 18:18:48 +00001249 Engine.ExecuteWorkList();
Ted Kremenekaa66a322008-01-16 21:46:15 +00001250#ifndef NDEBUG
1251 llvm::ViewGraph(*Engine.getGraph().roots_begin(),"GRConstants");
1252#endif
Ted Kremenekee985462008-01-16 18:18:48 +00001253}
Ted Kremenekab2b8c52008-01-23 19:59:44 +00001254} // end clang namespace