don't use #pragma mark, it isn't portable.
[clang.git] / include / clang / StaticAnalyzer / EntoSA / PathSensitive / SymbolManager.h
blobad173bb43536b9ddca0b7b76123758771d18cecb
1 //== SymbolManager.h - Management of Symbolic Values ------------*- C++ -*--==//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file defines SymbolManager, a class that manages symbolic values
11 // created for use by ExprEngine and related classes.
13 //===----------------------------------------------------------------------===//
15 #ifndef LLVM_CLANG_GR_SYMMGR_H
16 #define LLVM_CLANG_GR_SYMMGR_H
18 #include "clang/AST/Decl.h"
19 #include "clang/AST/Expr.h"
20 #include "clang/Analysis/AnalysisContext.h"
21 #include "llvm/Support/DataTypes.h"
22 #include "llvm/ADT/FoldingSet.h"
23 #include "llvm/ADT/DenseSet.h"
25 namespace llvm {
26 class BumpPtrAllocator;
27 class raw_ostream;
30 namespace clang {
31 class ASTContext;
32 class StackFrameContext;
34 namespace ento {
35 class BasicValueFactory;
36 class MemRegion;
37 class SubRegion;
38 class TypedRegion;
39 class VarRegion;
41 class SymExpr : public llvm::FoldingSetNode {
42 public:
43 enum Kind { BEGIN_SYMBOLS,
44 RegionValueKind, ConjuredKind, DerivedKind, ExtentKind,
45 MetadataKind,
46 END_SYMBOLS,
47 SymIntKind, SymSymKind };
48 private:
49 Kind K;
51 protected:
52 SymExpr(Kind k) : K(k) {}
54 public:
55 virtual ~SymExpr() {}
57 Kind getKind() const { return K; }
59 void dump() const;
61 virtual void dumpToStream(llvm::raw_ostream &os) const = 0;
63 virtual QualType getType(ASTContext&) const = 0;
64 virtual void Profile(llvm::FoldingSetNodeID& profile) = 0;
66 // Implement isa<T> support.
67 static inline bool classof(const SymExpr*) { return true; }
70 typedef unsigned SymbolID;
72 class SymbolData : public SymExpr {
73 private:
74 const SymbolID Sym;
76 protected:
77 SymbolData(Kind k, SymbolID sym) : SymExpr(k), Sym(sym) {}
79 public:
80 virtual ~SymbolData() {}
82 SymbolID getSymbolID() const { return Sym; }
84 // Implement isa<T> support.
85 static inline bool classof(const SymExpr* SE) {
86 Kind k = SE->getKind();
87 return k > BEGIN_SYMBOLS && k < END_SYMBOLS;
91 typedef const SymbolData* SymbolRef;
93 // A symbol representing the value of a MemRegion.
94 class SymbolRegionValue : public SymbolData {
95 const TypedRegion *R;
97 public:
98 SymbolRegionValue(SymbolID sym, const TypedRegion *r)
99 : SymbolData(RegionValueKind, sym), R(r) {}
101 const TypedRegion* getRegion() const { return R; }
103 static void Profile(llvm::FoldingSetNodeID& profile, const TypedRegion* R) {
104 profile.AddInteger((unsigned) RegionValueKind);
105 profile.AddPointer(R);
108 virtual void Profile(llvm::FoldingSetNodeID& profile) {
109 Profile(profile, R);
112 void dumpToStream(llvm::raw_ostream &os) const;
114 QualType getType(ASTContext&) const;
116 // Implement isa<T> support.
117 static inline bool classof(const SymExpr* SE) {
118 return SE->getKind() == RegionValueKind;
122 // A symbol representing the result of an expression.
123 class SymbolConjured : public SymbolData {
124 const Stmt* S;
125 QualType T;
126 unsigned Count;
127 const void* SymbolTag;
129 public:
130 SymbolConjured(SymbolID sym, const Stmt* s, QualType t, unsigned count,
131 const void* symbolTag)
132 : SymbolData(ConjuredKind, sym), S(s), T(t), Count(count),
133 SymbolTag(symbolTag) {}
135 const Stmt* getStmt() const { return S; }
136 unsigned getCount() const { return Count; }
137 const void* getTag() const { return SymbolTag; }
139 QualType getType(ASTContext&) const;
141 void dumpToStream(llvm::raw_ostream &os) const;
143 static void Profile(llvm::FoldingSetNodeID& profile, const Stmt* S,
144 QualType T, unsigned Count, const void* SymbolTag) {
145 profile.AddInteger((unsigned) ConjuredKind);
146 profile.AddPointer(S);
147 profile.Add(T);
148 profile.AddInteger(Count);
149 profile.AddPointer(SymbolTag);
152 virtual void Profile(llvm::FoldingSetNodeID& profile) {
153 Profile(profile, S, T, Count, SymbolTag);
156 // Implement isa<T> support.
157 static inline bool classof(const SymExpr* SE) {
158 return SE->getKind() == ConjuredKind;
162 // A symbol representing the value of a MemRegion whose parent region has
163 // symbolic value.
164 class SymbolDerived : public SymbolData {
165 SymbolRef parentSymbol;
166 const TypedRegion *R;
168 public:
169 SymbolDerived(SymbolID sym, SymbolRef parent, const TypedRegion *r)
170 : SymbolData(DerivedKind, sym), parentSymbol(parent), R(r) {}
172 SymbolRef getParentSymbol() const { return parentSymbol; }
173 const TypedRegion *getRegion() const { return R; }
175 QualType getType(ASTContext&) const;
177 void dumpToStream(llvm::raw_ostream &os) const;
179 static void Profile(llvm::FoldingSetNodeID& profile, SymbolRef parent,
180 const TypedRegion *r) {
181 profile.AddInteger((unsigned) DerivedKind);
182 profile.AddPointer(r);
183 profile.AddPointer(parent);
186 virtual void Profile(llvm::FoldingSetNodeID& profile) {
187 Profile(profile, parentSymbol, R);
190 // Implement isa<T> support.
191 static inline bool classof(const SymExpr* SE) {
192 return SE->getKind() == DerivedKind;
196 /// SymbolExtent - Represents the extent (size in bytes) of a bounded region.
197 /// Clients should not ask the SymbolManager for a region's extent. Always use
198 /// SubRegion::getExtent instead -- the value returned may not be a symbol.
199 class SymbolExtent : public SymbolData {
200 const SubRegion *R;
202 public:
203 SymbolExtent(SymbolID sym, const SubRegion *r)
204 : SymbolData(ExtentKind, sym), R(r) {}
206 const SubRegion *getRegion() const { return R; }
208 QualType getType(ASTContext&) const;
210 void dumpToStream(llvm::raw_ostream &os) const;
212 static void Profile(llvm::FoldingSetNodeID& profile, const SubRegion *R) {
213 profile.AddInteger((unsigned) ExtentKind);
214 profile.AddPointer(R);
217 virtual void Profile(llvm::FoldingSetNodeID& profile) {
218 Profile(profile, R);
221 // Implement isa<T> support.
222 static inline bool classof(const SymExpr* SE) {
223 return SE->getKind() == ExtentKind;
227 /// SymbolMetadata - Represents path-dependent metadata about a specific region.
228 /// Metadata symbols remain live as long as they are marked as in use before
229 /// dead-symbol sweeping AND their associated regions are still alive.
230 /// Intended for use by checkers.
231 class SymbolMetadata : public SymbolData {
232 const MemRegion* R;
233 const Stmt* S;
234 QualType T;
235 unsigned Count;
236 const void* Tag;
237 public:
238 SymbolMetadata(SymbolID sym, const MemRegion* r, const Stmt* s, QualType t,
239 unsigned count, const void* tag)
240 : SymbolData(MetadataKind, sym), R(r), S(s), T(t), Count(count), Tag(tag) {}
242 const MemRegion *getRegion() const { return R; }
243 const Stmt* getStmt() const { return S; }
244 unsigned getCount() const { return Count; }
245 const void* getTag() const { return Tag; }
247 QualType getType(ASTContext&) const;
249 void dumpToStream(llvm::raw_ostream &os) const;
251 static void Profile(llvm::FoldingSetNodeID& profile, const MemRegion *R,
252 const Stmt *S, QualType T, unsigned Count,
253 const void *Tag) {
254 profile.AddInteger((unsigned) MetadataKind);
255 profile.AddPointer(R);
256 profile.AddPointer(S);
257 profile.Add(T);
258 profile.AddInteger(Count);
259 profile.AddPointer(Tag);
262 virtual void Profile(llvm::FoldingSetNodeID& profile) {
263 Profile(profile, R, S, T, Count, Tag);
266 // Implement isa<T> support.
267 static inline bool classof(const SymExpr* SE) {
268 return SE->getKind() == MetadataKind;
272 // SymIntExpr - Represents symbolic expression like 'x' + 3.
273 class SymIntExpr : public SymExpr {
274 const SymExpr *LHS;
275 BinaryOperator::Opcode Op;
276 const llvm::APSInt& RHS;
277 QualType T;
279 public:
280 SymIntExpr(const SymExpr *lhs, BinaryOperator::Opcode op,
281 const llvm::APSInt& rhs, QualType t)
282 : SymExpr(SymIntKind), LHS(lhs), Op(op), RHS(rhs), T(t) {}
284 // FIXME: We probably need to make this out-of-line to avoid redundant
285 // generation of virtual functions.
286 QualType getType(ASTContext& C) const { return T; }
288 BinaryOperator::Opcode getOpcode() const { return Op; }
290 void dumpToStream(llvm::raw_ostream &os) const;
292 const SymExpr *getLHS() const { return LHS; }
293 const llvm::APSInt &getRHS() const { return RHS; }
295 static void Profile(llvm::FoldingSetNodeID& ID, const SymExpr *lhs,
296 BinaryOperator::Opcode op, const llvm::APSInt& rhs,
297 QualType t) {
298 ID.AddInteger((unsigned) SymIntKind);
299 ID.AddPointer(lhs);
300 ID.AddInteger(op);
301 ID.AddPointer(&rhs);
302 ID.Add(t);
305 void Profile(llvm::FoldingSetNodeID& ID) {
306 Profile(ID, LHS, Op, RHS, T);
309 // Implement isa<T> support.
310 static inline bool classof(const SymExpr* SE) {
311 return SE->getKind() == SymIntKind;
315 // SymSymExpr - Represents symbolic expression like 'x' + 'y'.
316 class SymSymExpr : public SymExpr {
317 const SymExpr *LHS;
318 BinaryOperator::Opcode Op;
319 const SymExpr *RHS;
320 QualType T;
322 public:
323 SymSymExpr(const SymExpr *lhs, BinaryOperator::Opcode op, const SymExpr *rhs,
324 QualType t)
325 : SymExpr(SymSymKind), LHS(lhs), Op(op), RHS(rhs), T(t) {}
327 BinaryOperator::Opcode getOpcode() const { return Op; }
328 const SymExpr *getLHS() const { return LHS; }
329 const SymExpr *getRHS() const { return RHS; }
331 // FIXME: We probably need to make this out-of-line to avoid redundant
332 // generation of virtual functions.
333 QualType getType(ASTContext& C) const { return T; }
335 void dumpToStream(llvm::raw_ostream &os) const;
337 static void Profile(llvm::FoldingSetNodeID& ID, const SymExpr *lhs,
338 BinaryOperator::Opcode op, const SymExpr *rhs, QualType t) {
339 ID.AddInteger((unsigned) SymSymKind);
340 ID.AddPointer(lhs);
341 ID.AddInteger(op);
342 ID.AddPointer(rhs);
343 ID.Add(t);
346 void Profile(llvm::FoldingSetNodeID& ID) {
347 Profile(ID, LHS, Op, RHS, T);
350 // Implement isa<T> support.
351 static inline bool classof(const SymExpr* SE) {
352 return SE->getKind() == SymSymKind;
356 class SymbolManager {
357 typedef llvm::FoldingSet<SymExpr> DataSetTy;
358 DataSetTy DataSet;
359 unsigned SymbolCounter;
360 llvm::BumpPtrAllocator& BPAlloc;
361 BasicValueFactory &BV;
362 ASTContext& Ctx;
364 public:
365 SymbolManager(ASTContext& ctx, BasicValueFactory &bv,
366 llvm::BumpPtrAllocator& bpalloc)
367 : SymbolCounter(0), BPAlloc(bpalloc), BV(bv), Ctx(ctx) {}
369 ~SymbolManager();
371 static bool canSymbolicate(QualType T);
373 /// Make a unique symbol for MemRegion R according to its kind.
374 const SymbolRegionValue* getRegionValueSymbol(const TypedRegion* R);
376 const SymbolConjured* getConjuredSymbol(const Stmt* E, QualType T,
377 unsigned VisitCount,
378 const void* SymbolTag = 0);
380 const SymbolConjured* getConjuredSymbol(const Expr* E, unsigned VisitCount,
381 const void* SymbolTag = 0) {
382 return getConjuredSymbol(E, E->getType(), VisitCount, SymbolTag);
385 const SymbolDerived *getDerivedSymbol(SymbolRef parentSymbol,
386 const TypedRegion *R);
388 const SymbolExtent *getExtentSymbol(const SubRegion *R);
390 const SymbolMetadata* getMetadataSymbol(const MemRegion* R, const Stmt* S,
391 QualType T, unsigned VisitCount,
392 const void* SymbolTag = 0);
394 const SymIntExpr *getSymIntExpr(const SymExpr *lhs, BinaryOperator::Opcode op,
395 const llvm::APSInt& rhs, QualType t);
397 const SymIntExpr *getSymIntExpr(const SymExpr &lhs, BinaryOperator::Opcode op,
398 const llvm::APSInt& rhs, QualType t) {
399 return getSymIntExpr(&lhs, op, rhs, t);
402 const SymSymExpr *getSymSymExpr(const SymExpr *lhs, BinaryOperator::Opcode op,
403 const SymExpr *rhs, QualType t);
405 QualType getType(const SymExpr *SE) const {
406 return SE->getType(Ctx);
409 ASTContext &getContext() { return Ctx; }
410 BasicValueFactory &getBasicVals() { return BV; }
413 class SymbolReaper {
414 typedef llvm::DenseSet<SymbolRef> SetTy;
416 SetTy TheLiving;
417 SetTy MetadataInUse;
418 SetTy TheDead;
419 const LocationContext *LCtx;
420 const Stmt *Loc;
421 SymbolManager& SymMgr;
423 public:
424 SymbolReaper(const LocationContext *ctx, const Stmt *s, SymbolManager& symmgr)
425 : LCtx(ctx), Loc(s), SymMgr(symmgr) {}
427 ~SymbolReaper() {}
429 const LocationContext *getLocationContext() const { return LCtx; }
430 const Stmt *getCurrentStatement() const { return Loc; }
432 bool isLive(SymbolRef sym);
433 bool isLive(const Stmt *ExprVal) const;
434 bool isLive(const VarRegion *VR) const;
436 // markLive - Unconditionally marks a symbol as live. This should never be
437 // used by checkers, only by the state infrastructure such as the store and
438 // environment. Checkers should instead use metadata symbols and markInUse.
439 void markLive(SymbolRef sym);
441 // markInUse - Marks a symbol as important to a checker. For metadata symbols,
442 // this will keep the symbol alive as long as its associated region is also
443 // live. For other symbols, this has no effect; checkers are not permitted
444 // to influence the life of other symbols. This should be used before any
445 // symbol marking has occurred, i.e. in the MarkLiveSymbols callback.
446 void markInUse(SymbolRef sym);
448 // maybeDead - If a symbol is known to be live, marks the symbol as live.
449 // Otherwise, if the symbol cannot be proven live, it is marked as dead.
450 // Returns true if the symbol is dead, false if live.
451 bool maybeDead(SymbolRef sym);
453 typedef SetTy::const_iterator dead_iterator;
454 dead_iterator dead_begin() const { return TheDead.begin(); }
455 dead_iterator dead_end() const { return TheDead.end(); }
457 bool hasDeadSymbols() const {
458 return !TheDead.empty();
461 /// isDead - Returns whether or not a symbol has been confirmed dead. This
462 /// should only be called once all marking of dead symbols has completed.
463 /// (For checkers, this means only in the evalDeadSymbols callback.)
464 bool isDead(SymbolRef sym) const {
465 return TheDead.count(sym);
469 class SymbolVisitor {
470 public:
471 // VisitSymbol - A visitor method invoked by
472 // GRStateManager::scanReachableSymbols. The method returns \c true if
473 // symbols should continue be scanned and \c false otherwise.
474 virtual bool VisitSymbol(SymbolRef sym) = 0;
475 virtual ~SymbolVisitor();
478 } // end GR namespace
480 } // end clang namespace
482 namespace llvm {
483 static inline llvm::raw_ostream& operator<<(llvm::raw_ostream& os,
484 const clang::ento::SymExpr *SE) {
485 SE->dumpToStream(os);
486 return os;
488 } // end llvm namespace
489 #endif