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