clang API Documentation
00001 //== SymbolManager.h - Management of Symbolic Values ------------*- C++ -*--==// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file defines SymbolManager, a class that manages symbolic values 00011 // created for use by ExprEngine and related classes. 00012 // 00013 //===----------------------------------------------------------------------===// 00014 00015 #ifndef LLVM_CLANG_GR_SYMMGR_H 00016 #define LLVM_CLANG_GR_SYMMGR_H 00017 00018 #include "clang/AST/Decl.h" 00019 #include "clang/AST/Expr.h" 00020 #include "clang/Analysis/AnalysisContext.h" 00021 #include "clang/Basic/LLVM.h" 00022 #include "clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h" 00023 #include "llvm/Support/DataTypes.h" 00024 #include "llvm/ADT/FoldingSet.h" 00025 #include "llvm/ADT/DenseSet.h" 00026 #include "llvm/ADT/DenseMap.h" 00027 00028 namespace llvm { 00029 class BumpPtrAllocator; 00030 } 00031 00032 namespace clang { 00033 class ASTContext; 00034 class StackFrameContext; 00035 00036 namespace ento { 00037 class BasicValueFactory; 00038 class MemRegion; 00039 class SubRegion; 00040 class TypedValueRegion; 00041 class VarRegion; 00042 00043 /// \brief Symbolic value. These values used to capture symbolic execution of 00044 /// the program. 00045 class SymExpr : public llvm::FoldingSetNode { 00046 virtual void anchor(); 00047 public: 00048 enum Kind { RegionValueKind, ConjuredKind, DerivedKind, ExtentKind, 00049 MetadataKind, 00050 BEGIN_SYMBOLS = RegionValueKind, 00051 END_SYMBOLS = MetadataKind, 00052 SymIntKind, IntSymKind, SymSymKind, CastSymbolKind }; 00053 private: 00054 Kind K; 00055 00056 protected: 00057 SymExpr(Kind k) : K(k) {} 00058 00059 public: 00060 virtual ~SymExpr() {} 00061 00062 Kind getKind() const { return K; } 00063 00064 virtual void dump() const; 00065 00066 virtual void dumpToStream(raw_ostream &os) const {} 00067 00068 virtual QualType getType(ASTContext&) const = 0; 00069 virtual void Profile(llvm::FoldingSetNodeID& profile) = 0; 00070 00071 // Implement isa<T> support. 00072 static inline bool classof(const SymExpr*) { return true; } 00073 00074 /// \brief Iterator over symbols that the current symbol depends on. 00075 /// 00076 /// For SymbolData, it's the symbol itself; for expressions, it's the 00077 /// expression symbol and all the operands in it. Note, SymbolDerived is 00078 /// treated as SymbolData - the iterator will NOT visit the parent region. 00079 class symbol_iterator { 00080 SmallVector<const SymExpr*, 5> itr; 00081 void expand(); 00082 public: 00083 symbol_iterator() {} 00084 symbol_iterator(const SymExpr *SE); 00085 00086 symbol_iterator &operator++(); 00087 const SymExpr* operator*(); 00088 00089 bool operator==(const symbol_iterator &X) const; 00090 bool operator!=(const symbol_iterator &X) const; 00091 }; 00092 00093 symbol_iterator symbol_begin() const { 00094 return symbol_iterator(this); 00095 } 00096 static symbol_iterator symbol_end() { return symbol_iterator(); } 00097 00098 unsigned computeComplexity() const; 00099 }; 00100 00101 typedef const SymExpr* SymbolRef; 00102 typedef llvm::SmallVector<SymbolRef, 2> SymbolRefSmallVectorTy; 00103 00104 typedef unsigned SymbolID; 00105 /// \brief A symbol representing data which can be stored in a memory location 00106 /// (region). 00107 class SymbolData : public SymExpr { 00108 virtual void anchor(); 00109 const SymbolID Sym; 00110 00111 protected: 00112 SymbolData(Kind k, SymbolID sym) : SymExpr(k), Sym(sym) {} 00113 00114 public: 00115 virtual ~SymbolData() {} 00116 00117 SymbolID getSymbolID() const { return Sym; } 00118 00119 // Implement isa<T> support. 00120 static inline bool classof(const SymExpr *SE) { 00121 Kind k = SE->getKind(); 00122 return k >= BEGIN_SYMBOLS && k <= END_SYMBOLS; 00123 } 00124 }; 00125 00126 ///\brief A symbol representing the value stored at a MemRegion. 00127 class SymbolRegionValue : public SymbolData { 00128 const TypedValueRegion *R; 00129 00130 public: 00131 SymbolRegionValue(SymbolID sym, const TypedValueRegion *r) 00132 : SymbolData(RegionValueKind, sym), R(r) {} 00133 00134 const TypedValueRegion* getRegion() const { return R; } 00135 00136 static void Profile(llvm::FoldingSetNodeID& profile, const TypedValueRegion* R) { 00137 profile.AddInteger((unsigned) RegionValueKind); 00138 profile.AddPointer(R); 00139 } 00140 00141 virtual void Profile(llvm::FoldingSetNodeID& profile) { 00142 Profile(profile, R); 00143 } 00144 00145 virtual void dumpToStream(raw_ostream &os) const; 00146 00147 QualType getType(ASTContext&) const; 00148 00149 // Implement isa<T> support. 00150 static inline bool classof(const SymExpr *SE) { 00151 return SE->getKind() == RegionValueKind; 00152 } 00153 }; 00154 00155 /// A symbol representing the result of an expression in the case when we do 00156 /// not know anything about what the expression is. 00157 class SymbolConjured : public SymbolData { 00158 const Stmt *S; 00159 QualType T; 00160 unsigned Count; 00161 const LocationContext *LCtx; 00162 const void *SymbolTag; 00163 00164 public: 00165 SymbolConjured(SymbolID sym, const Stmt *s, const LocationContext *lctx, 00166 QualType t, unsigned count, 00167 const void *symbolTag) 00168 : SymbolData(ConjuredKind, sym), S(s), T(t), Count(count), 00169 LCtx(lctx), 00170 SymbolTag(symbolTag) {} 00171 00172 const Stmt *getStmt() const { return S; } 00173 unsigned getCount() const { return Count; } 00174 const void *getTag() const { return SymbolTag; } 00175 00176 QualType getType(ASTContext&) const; 00177 00178 virtual void dumpToStream(raw_ostream &os) const; 00179 00180 static void Profile(llvm::FoldingSetNodeID& profile, const Stmt *S, 00181 QualType T, unsigned Count, const LocationContext *LCtx, 00182 const void *SymbolTag) { 00183 profile.AddInteger((unsigned) ConjuredKind); 00184 profile.AddPointer(S); 00185 profile.AddPointer(LCtx); 00186 profile.Add(T); 00187 profile.AddInteger(Count); 00188 profile.AddPointer(SymbolTag); 00189 } 00190 00191 virtual void Profile(llvm::FoldingSetNodeID& profile) { 00192 Profile(profile, S, T, Count, LCtx, SymbolTag); 00193 } 00194 00195 // Implement isa<T> support. 00196 static inline bool classof(const SymExpr *SE) { 00197 return SE->getKind() == ConjuredKind; 00198 } 00199 }; 00200 00201 /// A symbol representing the value of a MemRegion whose parent region has 00202 /// symbolic value. 00203 class SymbolDerived : public SymbolData { 00204 SymbolRef parentSymbol; 00205 const TypedValueRegion *R; 00206 00207 public: 00208 SymbolDerived(SymbolID sym, SymbolRef parent, const TypedValueRegion *r) 00209 : SymbolData(DerivedKind, sym), parentSymbol(parent), R(r) {} 00210 00211 SymbolRef getParentSymbol() const { return parentSymbol; } 00212 const TypedValueRegion *getRegion() const { return R; } 00213 00214 QualType getType(ASTContext&) const; 00215 00216 virtual void dumpToStream(raw_ostream &os) const; 00217 00218 static void Profile(llvm::FoldingSetNodeID& profile, SymbolRef parent, 00219 const TypedValueRegion *r) { 00220 profile.AddInteger((unsigned) DerivedKind); 00221 profile.AddPointer(r); 00222 profile.AddPointer(parent); 00223 } 00224 00225 virtual void Profile(llvm::FoldingSetNodeID& profile) { 00226 Profile(profile, parentSymbol, R); 00227 } 00228 00229 // Implement isa<T> support. 00230 static inline bool classof(const SymExpr *SE) { 00231 return SE->getKind() == DerivedKind; 00232 } 00233 }; 00234 00235 /// SymbolExtent - Represents the extent (size in bytes) of a bounded region. 00236 /// Clients should not ask the SymbolManager for a region's extent. Always use 00237 /// SubRegion::getExtent instead -- the value returned may not be a symbol. 00238 class SymbolExtent : public SymbolData { 00239 const SubRegion *R; 00240 00241 public: 00242 SymbolExtent(SymbolID sym, const SubRegion *r) 00243 : SymbolData(ExtentKind, sym), R(r) {} 00244 00245 const SubRegion *getRegion() const { return R; } 00246 00247 QualType getType(ASTContext&) const; 00248 00249 virtual void dumpToStream(raw_ostream &os) const; 00250 00251 static void Profile(llvm::FoldingSetNodeID& profile, const SubRegion *R) { 00252 profile.AddInteger((unsigned) ExtentKind); 00253 profile.AddPointer(R); 00254 } 00255 00256 virtual void Profile(llvm::FoldingSetNodeID& profile) { 00257 Profile(profile, R); 00258 } 00259 00260 // Implement isa<T> support. 00261 static inline bool classof(const SymExpr *SE) { 00262 return SE->getKind() == ExtentKind; 00263 } 00264 }; 00265 00266 /// SymbolMetadata - Represents path-dependent metadata about a specific region. 00267 /// Metadata symbols remain live as long as they are marked as in use before 00268 /// dead-symbol sweeping AND their associated regions are still alive. 00269 /// Intended for use by checkers. 00270 class SymbolMetadata : public SymbolData { 00271 const MemRegion* R; 00272 const Stmt *S; 00273 QualType T; 00274 unsigned Count; 00275 const void *Tag; 00276 public: 00277 SymbolMetadata(SymbolID sym, const MemRegion* r, const Stmt *s, QualType t, 00278 unsigned count, const void *tag) 00279 : SymbolData(MetadataKind, sym), R(r), S(s), T(t), Count(count), Tag(tag) {} 00280 00281 const MemRegion *getRegion() const { return R; } 00282 const Stmt *getStmt() const { return S; } 00283 unsigned getCount() const { return Count; } 00284 const void *getTag() const { return Tag; } 00285 00286 QualType getType(ASTContext&) const; 00287 00288 virtual void dumpToStream(raw_ostream &os) const; 00289 00290 static void Profile(llvm::FoldingSetNodeID& profile, const MemRegion *R, 00291 const Stmt *S, QualType T, unsigned Count, 00292 const void *Tag) { 00293 profile.AddInteger((unsigned) MetadataKind); 00294 profile.AddPointer(R); 00295 profile.AddPointer(S); 00296 profile.Add(T); 00297 profile.AddInteger(Count); 00298 profile.AddPointer(Tag); 00299 } 00300 00301 virtual void Profile(llvm::FoldingSetNodeID& profile) { 00302 Profile(profile, R, S, T, Count, Tag); 00303 } 00304 00305 // Implement isa<T> support. 00306 static inline bool classof(const SymExpr *SE) { 00307 return SE->getKind() == MetadataKind; 00308 } 00309 }; 00310 00311 /// \brief Represents a cast expression. 00312 class SymbolCast : public SymExpr { 00313 const SymExpr *Operand; 00314 /// Type of the operand. 00315 QualType FromTy; 00316 /// The type of the result. 00317 QualType ToTy; 00318 00319 public: 00320 SymbolCast(const SymExpr *In, QualType From, QualType To) : 00321 SymExpr(CastSymbolKind), Operand(In), FromTy(From), ToTy(To) { } 00322 00323 QualType getType(ASTContext &C) const { return ToTy; } 00324 00325 const SymExpr *getOperand() const { return Operand; } 00326 00327 virtual void dumpToStream(raw_ostream &os) const; 00328 00329 static void Profile(llvm::FoldingSetNodeID& ID, 00330 const SymExpr *In, QualType From, QualType To) { 00331 ID.AddInteger((unsigned) CastSymbolKind); 00332 ID.AddPointer(In); 00333 ID.Add(From); 00334 ID.Add(To); 00335 } 00336 00337 void Profile(llvm::FoldingSetNodeID& ID) { 00338 Profile(ID, Operand, FromTy, ToTy); 00339 } 00340 00341 // Implement isa<T> support. 00342 static inline bool classof(const SymExpr *SE) { 00343 return SE->getKind() == CastSymbolKind; 00344 } 00345 }; 00346 00347 /// SymIntExpr - Represents symbolic expression like 'x' + 3. 00348 class SymIntExpr : public SymExpr { 00349 const SymExpr *LHS; 00350 BinaryOperator::Opcode Op; 00351 const llvm::APSInt& RHS; 00352 QualType T; 00353 00354 public: 00355 SymIntExpr(const SymExpr *lhs, BinaryOperator::Opcode op, 00356 const llvm::APSInt& rhs, QualType t) 00357 : SymExpr(SymIntKind), LHS(lhs), Op(op), RHS(rhs), T(t) {} 00358 00359 // FIXME: We probably need to make this out-of-line to avoid redundant 00360 // generation of virtual functions. 00361 QualType getType(ASTContext &C) const { return T; } 00362 00363 BinaryOperator::Opcode getOpcode() const { return Op; } 00364 00365 virtual void dumpToStream(raw_ostream &os) const; 00366 00367 const SymExpr *getLHS() const { return LHS; } 00368 const llvm::APSInt &getRHS() const { return RHS; } 00369 00370 static void Profile(llvm::FoldingSetNodeID& ID, const SymExpr *lhs, 00371 BinaryOperator::Opcode op, const llvm::APSInt& rhs, 00372 QualType t) { 00373 ID.AddInteger((unsigned) SymIntKind); 00374 ID.AddPointer(lhs); 00375 ID.AddInteger(op); 00376 ID.AddPointer(&rhs); 00377 ID.Add(t); 00378 } 00379 00380 void Profile(llvm::FoldingSetNodeID& ID) { 00381 Profile(ID, LHS, Op, RHS, T); 00382 } 00383 00384 // Implement isa<T> support. 00385 static inline bool classof(const SymExpr *SE) { 00386 return SE->getKind() == SymIntKind; 00387 } 00388 }; 00389 00390 /// IntSymExpr - Represents symbolic expression like 3 - 'x'. 00391 class IntSymExpr : public SymExpr { 00392 const llvm::APSInt& LHS; 00393 BinaryOperator::Opcode Op; 00394 const SymExpr *RHS; 00395 QualType T; 00396 00397 public: 00398 IntSymExpr(const llvm::APSInt& lhs, BinaryOperator::Opcode op, 00399 const SymExpr *rhs, QualType t) 00400 : SymExpr(IntSymKind), LHS(lhs), Op(op), RHS(rhs), T(t) {} 00401 00402 QualType getType(ASTContext &C) const { return T; } 00403 00404 BinaryOperator::Opcode getOpcode() const { return Op; } 00405 00406 virtual void dumpToStream(raw_ostream &os) const; 00407 00408 const SymExpr *getRHS() const { return RHS; } 00409 const llvm::APSInt &getLHS() const { return LHS; } 00410 00411 static void Profile(llvm::FoldingSetNodeID& ID, const llvm::APSInt& lhs, 00412 BinaryOperator::Opcode op, const SymExpr *rhs, 00413 QualType t) { 00414 ID.AddInteger((unsigned) IntSymKind); 00415 ID.AddPointer(&lhs); 00416 ID.AddInteger(op); 00417 ID.AddPointer(rhs); 00418 ID.Add(t); 00419 } 00420 00421 void Profile(llvm::FoldingSetNodeID& ID) { 00422 Profile(ID, LHS, Op, RHS, T); 00423 } 00424 00425 // Implement isa<T> support. 00426 static inline bool classof(const SymExpr *SE) { 00427 return SE->getKind() == IntSymKind; 00428 } 00429 }; 00430 00431 /// SymSymExpr - Represents symbolic expression like 'x' + 'y'. 00432 class SymSymExpr : public SymExpr { 00433 const SymExpr *LHS; 00434 BinaryOperator::Opcode Op; 00435 const SymExpr *RHS; 00436 QualType T; 00437 00438 public: 00439 SymSymExpr(const SymExpr *lhs, BinaryOperator::Opcode op, const SymExpr *rhs, 00440 QualType t) 00441 : SymExpr(SymSymKind), LHS(lhs), Op(op), RHS(rhs), T(t) {} 00442 00443 BinaryOperator::Opcode getOpcode() const { return Op; } 00444 const SymExpr *getLHS() const { return LHS; } 00445 const SymExpr *getRHS() const { return RHS; } 00446 00447 // FIXME: We probably need to make this out-of-line to avoid redundant 00448 // generation of virtual functions. 00449 QualType getType(ASTContext &C) const { return T; } 00450 00451 virtual void dumpToStream(raw_ostream &os) const; 00452 00453 static void Profile(llvm::FoldingSetNodeID& ID, const SymExpr *lhs, 00454 BinaryOperator::Opcode op, const SymExpr *rhs, QualType t) { 00455 ID.AddInteger((unsigned) SymSymKind); 00456 ID.AddPointer(lhs); 00457 ID.AddInteger(op); 00458 ID.AddPointer(rhs); 00459 ID.Add(t); 00460 } 00461 00462 void Profile(llvm::FoldingSetNodeID& ID) { 00463 Profile(ID, LHS, Op, RHS, T); 00464 } 00465 00466 // Implement isa<T> support. 00467 static inline bool classof(const SymExpr *SE) { 00468 return SE->getKind() == SymSymKind; 00469 } 00470 }; 00471 00472 class SymbolManager { 00473 typedef llvm::FoldingSet<SymExpr> DataSetTy; 00474 typedef llvm::DenseMap<SymbolRef, SymbolRefSmallVectorTy*> SymbolDependTy; 00475 00476 DataSetTy DataSet; 00477 /// Stores the extra dependencies between symbols: the data should be kept 00478 /// alive as long as the key is live. 00479 SymbolDependTy SymbolDependencies; 00480 unsigned SymbolCounter; 00481 llvm::BumpPtrAllocator& BPAlloc; 00482 BasicValueFactory &BV; 00483 ASTContext &Ctx; 00484 00485 public: 00486 SymbolManager(ASTContext &ctx, BasicValueFactory &bv, 00487 llvm::BumpPtrAllocator& bpalloc) 00488 : SymbolDependencies(16), SymbolCounter(0), 00489 BPAlloc(bpalloc), BV(bv), Ctx(ctx) {} 00490 00491 ~SymbolManager(); 00492 00493 static bool canSymbolicate(QualType T); 00494 00495 /// \brief Make a unique symbol for MemRegion R according to its kind. 00496 const SymbolRegionValue* getRegionValueSymbol(const TypedValueRegion* R); 00497 00498 const SymbolConjured* getConjuredSymbol(const Stmt *E, 00499 const LocationContext *LCtx, 00500 QualType T, 00501 unsigned VisitCount, 00502 const void *SymbolTag = 0); 00503 00504 const SymbolConjured* getConjuredSymbol(const Expr *E, 00505 const LocationContext *LCtx, 00506 unsigned VisitCount, 00507 const void *SymbolTag = 0) { 00508 return getConjuredSymbol(E, LCtx, E->getType(), 00509 VisitCount, SymbolTag); 00510 } 00511 00512 const SymbolDerived *getDerivedSymbol(SymbolRef parentSymbol, 00513 const TypedValueRegion *R); 00514 00515 const SymbolExtent *getExtentSymbol(const SubRegion *R); 00516 00517 /// \brief Creates a metadata symbol associated with a specific region. 00518 /// 00519 /// VisitCount can be used to differentiate regions corresponding to 00520 /// different loop iterations, thus, making the symbol path-dependent. 00521 const SymbolMetadata* getMetadataSymbol(const MemRegion* R, const Stmt *S, 00522 QualType T, unsigned VisitCount, 00523 const void *SymbolTag = 0); 00524 00525 const SymbolCast* getCastSymbol(const SymExpr *Operand, 00526 QualType From, QualType To); 00527 00528 const SymIntExpr *getSymIntExpr(const SymExpr *lhs, BinaryOperator::Opcode op, 00529 const llvm::APSInt& rhs, QualType t); 00530 00531 const SymIntExpr *getSymIntExpr(const SymExpr &lhs, BinaryOperator::Opcode op, 00532 const llvm::APSInt& rhs, QualType t) { 00533 return getSymIntExpr(&lhs, op, rhs, t); 00534 } 00535 00536 const IntSymExpr *getIntSymExpr(const llvm::APSInt& lhs, 00537 BinaryOperator::Opcode op, 00538 const SymExpr *rhs, QualType t); 00539 00540 const SymSymExpr *getSymSymExpr(const SymExpr *lhs, BinaryOperator::Opcode op, 00541 const SymExpr *rhs, QualType t); 00542 00543 QualType getType(const SymExpr *SE) const { 00544 return SE->getType(Ctx); 00545 } 00546 00547 /// \brief Add artificial symbol dependency. 00548 /// 00549 /// The dependent symbol should stay alive as long as the primary is alive. 00550 void addSymbolDependency(const SymbolRef Primary, const SymbolRef Dependent); 00551 00552 const SymbolRefSmallVectorTy *getDependentSymbols(const SymbolRef Primary); 00553 00554 ASTContext &getContext() { return Ctx; } 00555 BasicValueFactory &getBasicVals() { return BV; } 00556 }; 00557 00558 /// \brief A class responsible for cleaning up unused symbols. 00559 class SymbolReaper { 00560 enum SymbolStatus { 00561 NotProcessed, 00562 HaveMarkedDependents 00563 }; 00564 00565 typedef llvm::DenseSet<SymbolRef> SymbolSetTy; 00566 typedef llvm::DenseMap<SymbolRef, SymbolStatus> SymbolMapTy; 00567 typedef llvm::DenseSet<const MemRegion *> RegionSetTy; 00568 00569 SymbolMapTy TheLiving; 00570 SymbolSetTy MetadataInUse; 00571 SymbolSetTy TheDead; 00572 00573 RegionSetTy RegionRoots; 00574 00575 const LocationContext *LCtx; 00576 const Stmt *Loc; 00577 SymbolManager& SymMgr; 00578 StoreRef reapedStore; 00579 llvm::DenseMap<const MemRegion *, unsigned> includedRegionCache; 00580 00581 public: 00582 /// \brief Construct a reaper object, which removes everything which is not 00583 /// live before we execute statement s in the given location context. 00584 /// 00585 /// If the statement is NULL, everything is this and parent contexts is 00586 /// considered live. 00587 SymbolReaper(const LocationContext *ctx, const Stmt *s, SymbolManager& symmgr, 00588 StoreManager &storeMgr) 00589 : LCtx(ctx), Loc(s), SymMgr(symmgr), reapedStore(0, storeMgr) {} 00590 00591 ~SymbolReaper() {} 00592 00593 const LocationContext *getLocationContext() const { return LCtx; } 00594 00595 bool isLive(SymbolRef sym); 00596 bool isLiveRegion(const MemRegion *region); 00597 bool isLive(const Stmt *ExprVal, const LocationContext *LCtx) const; 00598 bool isLive(const VarRegion *VR, bool includeStoreBindings = false) const; 00599 00600 /// \brief Unconditionally marks a symbol as live. 00601 /// 00602 /// This should never be 00603 /// used by checkers, only by the state infrastructure such as the store and 00604 /// environment. Checkers should instead use metadata symbols and markInUse. 00605 void markLive(SymbolRef sym); 00606 00607 /// \brief Marks a symbol as important to a checker. 00608 /// 00609 /// For metadata symbols, 00610 /// this will keep the symbol alive as long as its associated region is also 00611 /// live. For other symbols, this has no effect; checkers are not permitted 00612 /// to influence the life of other symbols. This should be used before any 00613 /// symbol marking has occurred, i.e. in the MarkLiveSymbols callback. 00614 void markInUse(SymbolRef sym); 00615 00616 /// \brief If a symbol is known to be live, marks the symbol as live. 00617 /// 00618 /// Otherwise, if the symbol cannot be proven live, it is marked as dead. 00619 /// Returns true if the symbol is dead, false if live. 00620 bool maybeDead(SymbolRef sym); 00621 00622 typedef SymbolSetTy::const_iterator dead_iterator; 00623 dead_iterator dead_begin() const { return TheDead.begin(); } 00624 dead_iterator dead_end() const { return TheDead.end(); } 00625 00626 bool hasDeadSymbols() const { 00627 return !TheDead.empty(); 00628 } 00629 00630 typedef RegionSetTy::const_iterator region_iterator; 00631 region_iterator region_begin() const { return RegionRoots.begin(); } 00632 region_iterator region_end() const { return RegionRoots.end(); } 00633 00634 /// \brief Returns whether or not a symbol has been confirmed dead. 00635 /// 00636 /// This should only be called once all marking of dead symbols has completed. 00637 /// (For checkers, this means only in the evalDeadSymbols callback.) 00638 bool isDead(SymbolRef sym) const { 00639 return TheDead.count(sym); 00640 } 00641 00642 void markLive(const MemRegion *region); 00643 00644 /// \brief Set to the value of the symbolic store after 00645 /// StoreManager::removeDeadBindings has been called. 00646 void setReapedStore(StoreRef st) { reapedStore = st; } 00647 00648 private: 00649 /// Mark the symbols dependent on the input symbol as live. 00650 void markDependentsLive(SymbolRef sym); 00651 }; 00652 00653 class SymbolVisitor { 00654 public: 00655 /// \brief A visitor method invoked by ProgramStateManager::scanReachableSymbols. 00656 /// 00657 /// The method returns \c true if symbols should continue be scanned and \c 00658 /// false otherwise. 00659 virtual bool VisitSymbol(SymbolRef sym) = 0; 00660 virtual bool VisitMemRegion(const MemRegion *region) { return true; } 00661 virtual ~SymbolVisitor(); 00662 }; 00663 00664 } // end GR namespace 00665 00666 } // end clang namespace 00667 00668 namespace llvm { 00669 static inline raw_ostream &operator<<(raw_ostream &os, 00670 const clang::ento::SymExpr *SE) { 00671 SE->dumpToStream(os); 00672 return os; 00673 } 00674 } // end llvm namespace 00675 #endif