Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:37:10

0001 //===- SymbolManager.h - Management of Symbolic Values ----------*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 //
0009 //  This file defines SymbolManager, a class that manages symbolic values
0010 //  created for use by ExprEngine and related classes.
0011 //
0012 //===----------------------------------------------------------------------===//
0013 
0014 #ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SYMBOLMANAGER_H
0015 #define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SYMBOLMANAGER_H
0016 
0017 #include "clang/AST/Expr.h"
0018 #include "clang/AST/Type.h"
0019 #include "clang/Analysis/AnalysisDeclContext.h"
0020 #include "clang/Basic/LLVM.h"
0021 #include "clang/StaticAnalyzer/Core/PathSensitive/APSIntPtr.h"
0022 #include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
0023 #include "clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h"
0024 #include "clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h"
0025 #include "llvm/ADT/DenseMap.h"
0026 #include "llvm/ADT/DenseSet.h"
0027 #include "llvm/ADT/FoldingSet.h"
0028 #include "llvm/ADT/ImmutableSet.h"
0029 #include "llvm/ADT/iterator_range.h"
0030 #include "llvm/Support/Allocator.h"
0031 #include <cassert>
0032 
0033 namespace clang {
0034 
0035 class ASTContext;
0036 class Stmt;
0037 
0038 namespace ento {
0039 
0040 class BasicValueFactory;
0041 class StoreManager;
0042 
0043 ///A symbol representing the value stored at a MemRegion.
0044 class SymbolRegionValue : public SymbolData {
0045   const TypedValueRegion *R;
0046 
0047   friend class SymExprAllocator;
0048   SymbolRegionValue(SymbolID sym, const TypedValueRegion *r)
0049       : SymbolData(SymbolRegionValueKind, sym), R(r) {
0050     assert(r);
0051     assert(isValidTypeForSymbol(r->getValueType()));
0052   }
0053 
0054 public:
0055   LLVM_ATTRIBUTE_RETURNS_NONNULL
0056   const TypedValueRegion *getRegion() const { return R; }
0057 
0058   static void Profile(llvm::FoldingSetNodeID& profile, const TypedValueRegion* R) {
0059     profile.AddInteger((unsigned) SymbolRegionValueKind);
0060     profile.AddPointer(R);
0061   }
0062 
0063   void Profile(llvm::FoldingSetNodeID& profile) override {
0064     Profile(profile, R);
0065   }
0066 
0067   StringRef getKindStr() const override;
0068 
0069   void dumpToStream(raw_ostream &os) const override;
0070   const MemRegion *getOriginRegion() const override { return getRegion(); }
0071 
0072   QualType getType() const override;
0073 
0074   // Implement isa<T> support.
0075   static bool classof(const SymExpr *SE) {
0076     return SE->getKind() == SymbolRegionValueKind;
0077   }
0078 };
0079 
0080 /// A symbol representing the result of an expression in the case when we do
0081 /// not know anything about what the expression is.
0082 class SymbolConjured : public SymbolData {
0083   const Stmt *S;
0084   QualType T;
0085   unsigned Count;
0086   const LocationContext *LCtx;
0087   const void *SymbolTag;
0088 
0089   friend class SymExprAllocator;
0090   SymbolConjured(SymbolID sym, const Stmt *s, const LocationContext *lctx,
0091                  QualType t, unsigned count, const void *symbolTag)
0092       : SymbolData(SymbolConjuredKind, sym), S(s), T(t), Count(count),
0093         LCtx(lctx), SymbolTag(symbolTag) {
0094     // FIXME: 's' might be a nullptr if we're conducting invalidation
0095     // that was caused by a destructor call on a temporary object,
0096     // which has no statement associated with it.
0097     // Due to this, we might be creating the same invalidation symbol for
0098     // two different invalidation passes (for two different temporaries).
0099     assert(lctx);
0100     assert(isValidTypeForSymbol(t));
0101   }
0102 
0103 public:
0104   /// It might return null.
0105   const Stmt *getStmt() const { return S; }
0106   unsigned getCount() const { return Count; }
0107   /// It might return null.
0108   const void *getTag() const { return SymbolTag; }
0109 
0110   QualType getType() const override;
0111 
0112   StringRef getKindStr() const override;
0113 
0114   void dumpToStream(raw_ostream &os) const override;
0115 
0116   static void Profile(llvm::FoldingSetNodeID &profile, const Stmt *S,
0117                       const LocationContext *LCtx, QualType T, unsigned Count,
0118                       const void *SymbolTag) {
0119     profile.AddInteger((unsigned)SymbolConjuredKind);
0120     profile.AddPointer(S);
0121     profile.AddPointer(LCtx);
0122     profile.Add(T);
0123     profile.AddInteger(Count);
0124     profile.AddPointer(SymbolTag);
0125   }
0126 
0127   void Profile(llvm::FoldingSetNodeID& profile) override {
0128     Profile(profile, S, LCtx, T, Count, SymbolTag);
0129   }
0130 
0131   // Implement isa<T> support.
0132   static bool classof(const SymExpr *SE) {
0133     return SE->getKind() == SymbolConjuredKind;
0134   }
0135 };
0136 
0137 /// A symbol representing the value of a MemRegion whose parent region has
0138 /// symbolic value.
0139 class SymbolDerived : public SymbolData {
0140   SymbolRef parentSymbol;
0141   const TypedValueRegion *R;
0142 
0143   friend class SymExprAllocator;
0144   SymbolDerived(SymbolID sym, SymbolRef parent, const TypedValueRegion *r)
0145       : SymbolData(SymbolDerivedKind, sym), parentSymbol(parent), R(r) {
0146     assert(parent);
0147     assert(r);
0148     assert(isValidTypeForSymbol(r->getValueType()));
0149   }
0150 
0151 public:
0152   LLVM_ATTRIBUTE_RETURNS_NONNULL
0153   SymbolRef getParentSymbol() const { return parentSymbol; }
0154   LLVM_ATTRIBUTE_RETURNS_NONNULL
0155   const TypedValueRegion *getRegion() const { return R; }
0156 
0157   QualType getType() const override;
0158 
0159   StringRef getKindStr() const override;
0160 
0161   void dumpToStream(raw_ostream &os) const override;
0162   const MemRegion *getOriginRegion() const override { return getRegion(); }
0163 
0164   static void Profile(llvm::FoldingSetNodeID& profile, SymbolRef parent,
0165                       const TypedValueRegion *r) {
0166     profile.AddInteger((unsigned) SymbolDerivedKind);
0167     profile.AddPointer(r);
0168     profile.AddPointer(parent);
0169   }
0170 
0171   void Profile(llvm::FoldingSetNodeID& profile) override {
0172     Profile(profile, parentSymbol, R);
0173   }
0174 
0175   // Implement isa<T> support.
0176   static bool classof(const SymExpr *SE) {
0177     return SE->getKind() == SymbolDerivedKind;
0178   }
0179 };
0180 
0181 /// SymbolExtent - Represents the extent (size in bytes) of a bounded region.
0182 ///  Clients should not ask the SymbolManager for a region's extent. Always use
0183 ///  SubRegion::getExtent instead -- the value returned may not be a symbol.
0184 class SymbolExtent : public SymbolData {
0185   const SubRegion *R;
0186 
0187   friend class SymExprAllocator;
0188   SymbolExtent(SymbolID sym, const SubRegion *r)
0189       : SymbolData(SymbolExtentKind, sym), R(r) {
0190     assert(r);
0191   }
0192 
0193 public:
0194   LLVM_ATTRIBUTE_RETURNS_NONNULL
0195   const SubRegion *getRegion() const { return R; }
0196 
0197   QualType getType() const override;
0198 
0199   StringRef getKindStr() const override;
0200 
0201   void dumpToStream(raw_ostream &os) const override;
0202 
0203   static void Profile(llvm::FoldingSetNodeID& profile, const SubRegion *R) {
0204     profile.AddInteger((unsigned) SymbolExtentKind);
0205     profile.AddPointer(R);
0206   }
0207 
0208   void Profile(llvm::FoldingSetNodeID& profile) override {
0209     Profile(profile, R);
0210   }
0211 
0212   // Implement isa<T> support.
0213   static bool classof(const SymExpr *SE) {
0214     return SE->getKind() == SymbolExtentKind;
0215   }
0216 };
0217 
0218 /// SymbolMetadata - Represents path-dependent metadata about a specific region.
0219 ///  Metadata symbols remain live as long as they are marked as in use before
0220 ///  dead-symbol sweeping AND their associated regions are still alive.
0221 ///  Intended for use by checkers.
0222 class SymbolMetadata : public SymbolData {
0223   const MemRegion* R;
0224   const Stmt *S;
0225   QualType T;
0226   const LocationContext *LCtx;
0227   /// Count can be used to differentiate regions corresponding to
0228   /// different loop iterations, thus, making the symbol path-dependent.
0229   unsigned Count;
0230   const void *Tag;
0231 
0232   friend class SymExprAllocator;
0233   SymbolMetadata(SymbolID sym, const MemRegion* r, const Stmt *s, QualType t,
0234                  const LocationContext *LCtx, unsigned count, const void *tag)
0235       : SymbolData(SymbolMetadataKind, sym), R(r), S(s), T(t), LCtx(LCtx),
0236         Count(count), Tag(tag) {
0237       assert(r);
0238       assert(s);
0239       assert(isValidTypeForSymbol(t));
0240       assert(LCtx);
0241       assert(tag);
0242     }
0243 
0244   public:
0245     LLVM_ATTRIBUTE_RETURNS_NONNULL
0246     const MemRegion *getRegion() const { return R; }
0247 
0248     LLVM_ATTRIBUTE_RETURNS_NONNULL
0249     const Stmt *getStmt() const { return S; }
0250 
0251     LLVM_ATTRIBUTE_RETURNS_NONNULL
0252     const LocationContext *getLocationContext() const { return LCtx; }
0253 
0254     unsigned getCount() const { return Count; }
0255 
0256     LLVM_ATTRIBUTE_RETURNS_NONNULL
0257     const void *getTag() const { return Tag; }
0258 
0259     QualType getType() const override;
0260 
0261     StringRef getKindStr() const override;
0262 
0263     void dumpToStream(raw_ostream &os) const override;
0264 
0265     static void Profile(llvm::FoldingSetNodeID &profile, const MemRegion *R,
0266                         const Stmt *S, QualType T, const LocationContext *LCtx,
0267                         unsigned Count, const void *Tag) {
0268       profile.AddInteger((unsigned)SymbolMetadataKind);
0269       profile.AddPointer(R);
0270       profile.AddPointer(S);
0271       profile.Add(T);
0272       profile.AddPointer(LCtx);
0273       profile.AddInteger(Count);
0274       profile.AddPointer(Tag);
0275     }
0276 
0277   void Profile(llvm::FoldingSetNodeID& profile) override {
0278     Profile(profile, R, S, T, LCtx, Count, Tag);
0279   }
0280 
0281   // Implement isa<T> support.
0282   static bool classof(const SymExpr *SE) {
0283     return SE->getKind() == SymbolMetadataKind;
0284   }
0285 };
0286 
0287 /// Represents a cast expression.
0288 class SymbolCast : public SymExpr {
0289   const SymExpr *Operand;
0290 
0291   /// Type of the operand.
0292   QualType FromTy;
0293 
0294   /// The type of the result.
0295   QualType ToTy;
0296 
0297   friend class SymExprAllocator;
0298   SymbolCast(SymbolID Sym, const SymExpr *In, QualType From, QualType To)
0299       : SymExpr(SymbolCastKind, Sym), Operand(In), FromTy(From), ToTy(To) {
0300     assert(In);
0301     assert(isValidTypeForSymbol(From));
0302     // FIXME: GenericTaintChecker creates symbols of void type.
0303     // Otherwise, 'To' should also be a valid type.
0304   }
0305 
0306 public:
0307   unsigned computeComplexity() const override {
0308     if (Complexity == 0)
0309       Complexity = 1 + Operand->computeComplexity();
0310     return Complexity;
0311   }
0312 
0313   QualType getType() const override { return ToTy; }
0314 
0315   LLVM_ATTRIBUTE_RETURNS_NONNULL
0316   const SymExpr *getOperand() const { return Operand; }
0317 
0318   void dumpToStream(raw_ostream &os) const override;
0319 
0320   static void Profile(llvm::FoldingSetNodeID& ID,
0321                       const SymExpr *In, QualType From, QualType To) {
0322     ID.AddInteger((unsigned) SymbolCastKind);
0323     ID.AddPointer(In);
0324     ID.Add(From);
0325     ID.Add(To);
0326   }
0327 
0328   void Profile(llvm::FoldingSetNodeID& ID) override {
0329     Profile(ID, Operand, FromTy, ToTy);
0330   }
0331 
0332   // Implement isa<T> support.
0333   static bool classof(const SymExpr *SE) {
0334     return SE->getKind() == SymbolCastKind;
0335   }
0336 };
0337 
0338 /// Represents a symbolic expression involving a unary operator.
0339 class UnarySymExpr : public SymExpr {
0340   const SymExpr *Operand;
0341   UnaryOperator::Opcode Op;
0342   QualType T;
0343 
0344   friend class SymExprAllocator;
0345   UnarySymExpr(SymbolID Sym, const SymExpr *In, UnaryOperator::Opcode Op,
0346                QualType T)
0347       : SymExpr(UnarySymExprKind, Sym), Operand(In), Op(Op), T(T) {
0348     // Note, some unary operators are modeled as a binary operator. E.g. ++x is
0349     // modeled as x + 1.
0350     assert((Op == UO_Minus || Op == UO_Not) && "non-supported unary expression");
0351     // Unary expressions are results of arithmetic. Pointer arithmetic is not
0352     // handled by unary expressions, but it is instead handled by applying
0353     // sub-regions to regions.
0354     assert(isValidTypeForSymbol(T) && "non-valid type for unary symbol");
0355     assert(!Loc::isLocType(T) && "unary symbol should be nonloc");
0356   }
0357 
0358 public:
0359   unsigned computeComplexity() const override {
0360     if (Complexity == 0)
0361       Complexity = 1 + Operand->computeComplexity();
0362     return Complexity;
0363   }
0364 
0365   const SymExpr *getOperand() const { return Operand; }
0366   UnaryOperator::Opcode getOpcode() const { return Op; }
0367   QualType getType() const override { return T; }
0368 
0369   void dumpToStream(raw_ostream &os) const override;
0370 
0371   static void Profile(llvm::FoldingSetNodeID &ID, const SymExpr *In,
0372                       UnaryOperator::Opcode Op, QualType T) {
0373     ID.AddInteger((unsigned)UnarySymExprKind);
0374     ID.AddPointer(In);
0375     ID.AddInteger(Op);
0376     ID.Add(T);
0377   }
0378 
0379   void Profile(llvm::FoldingSetNodeID &ID) override {
0380     Profile(ID, Operand, Op, T);
0381   }
0382 
0383   // Implement isa<T> support.
0384   static bool classof(const SymExpr *SE) {
0385     return SE->getKind() == UnarySymExprKind;
0386   }
0387 };
0388 
0389 /// Represents a symbolic expression involving a binary operator
0390 class BinarySymExpr : public SymExpr {
0391   BinaryOperator::Opcode Op;
0392   QualType T;
0393 
0394 protected:
0395   BinarySymExpr(SymbolID Sym, Kind k, BinaryOperator::Opcode op, QualType t)
0396       : SymExpr(k, Sym), Op(op), T(t) {
0397     assert(classof(this));
0398     // Binary expressions are results of arithmetic. Pointer arithmetic is not
0399     // handled by binary expressions, but it is instead handled by applying
0400     // sub-regions to regions.
0401     assert(isValidTypeForSymbol(t) && !Loc::isLocType(t));
0402   }
0403 
0404 public:
0405   // FIXME: We probably need to make this out-of-line to avoid redundant
0406   // generation of virtual functions.
0407   QualType getType() const override { return T; }
0408 
0409   BinaryOperator::Opcode getOpcode() const { return Op; }
0410 
0411   // Implement isa<T> support.
0412   static bool classof(const SymExpr *SE) {
0413     Kind k = SE->getKind();
0414     return k >= BEGIN_BINARYSYMEXPRS && k <= END_BINARYSYMEXPRS;
0415   }
0416 
0417 protected:
0418   static unsigned computeOperandComplexity(const SymExpr *Value) {
0419     return Value->computeComplexity();
0420   }
0421   static unsigned computeOperandComplexity(const llvm::APSInt &Value) {
0422     return 1;
0423   }
0424 
0425   static const llvm::APSInt *getPointer(APSIntPtr Value) { return Value.get(); }
0426   static const SymExpr *getPointer(const SymExpr *Value) { return Value; }
0427 
0428   static void dumpToStreamImpl(raw_ostream &os, const SymExpr *Value);
0429   static void dumpToStreamImpl(raw_ostream &os, const llvm::APSInt &Value);
0430   static void dumpToStreamImpl(raw_ostream &os, BinaryOperator::Opcode op);
0431 };
0432 
0433 /// Template implementation for all binary symbolic expressions
0434 template <class LHSTYPE, class RHSTYPE, SymExpr::Kind ClassKind>
0435 class BinarySymExprImpl : public BinarySymExpr {
0436   LHSTYPE LHS;
0437   RHSTYPE RHS;
0438 
0439   friend class SymExprAllocator;
0440   BinarySymExprImpl(SymbolID Sym, LHSTYPE lhs, BinaryOperator::Opcode op,
0441                     RHSTYPE rhs, QualType t)
0442       : BinarySymExpr(Sym, ClassKind, op, t), LHS(lhs), RHS(rhs) {
0443     assert(getPointer(lhs));
0444     assert(getPointer(rhs));
0445   }
0446 
0447 public:
0448   void dumpToStream(raw_ostream &os) const override {
0449     dumpToStreamImpl(os, LHS);
0450     dumpToStreamImpl(os, getOpcode());
0451     dumpToStreamImpl(os, RHS);
0452   }
0453 
0454   LHSTYPE getLHS() const { return LHS; }
0455   RHSTYPE getRHS() const { return RHS; }
0456 
0457   unsigned computeComplexity() const override {
0458     if (Complexity == 0)
0459       Complexity =
0460           computeOperandComplexity(RHS) + computeOperandComplexity(LHS);
0461     return Complexity;
0462   }
0463 
0464   static void Profile(llvm::FoldingSetNodeID &ID, LHSTYPE lhs,
0465                       BinaryOperator::Opcode op, RHSTYPE rhs, QualType t) {
0466     ID.AddInteger((unsigned)ClassKind);
0467     ID.AddPointer(getPointer(lhs));
0468     ID.AddInteger(op);
0469     ID.AddPointer(getPointer(rhs));
0470     ID.Add(t);
0471   }
0472 
0473   void Profile(llvm::FoldingSetNodeID &ID) override {
0474     Profile(ID, LHS, getOpcode(), RHS, getType());
0475   }
0476 
0477   // Implement isa<T> support.
0478   static bool classof(const SymExpr *SE) { return SE->getKind() == ClassKind; }
0479 };
0480 
0481 /// Represents a symbolic expression like 'x' + 3.
0482 using SymIntExpr = BinarySymExprImpl<const SymExpr *, APSIntPtr,
0483                                      SymExpr::Kind::SymIntExprKind>;
0484 
0485 /// Represents a symbolic expression like 3 - 'x'.
0486 using IntSymExpr = BinarySymExprImpl<APSIntPtr, const SymExpr *,
0487                                      SymExpr::Kind::IntSymExprKind>;
0488 
0489 /// Represents a symbolic expression like 'x' + 'y'.
0490 using SymSymExpr = BinarySymExprImpl<const SymExpr *, const SymExpr *,
0491                                      SymExpr::Kind::SymSymExprKind>;
0492 
0493 class SymExprAllocator {
0494   SymbolID NextSymbolID = 0;
0495   llvm::BumpPtrAllocator &Alloc;
0496 
0497 public:
0498   explicit SymExprAllocator(llvm::BumpPtrAllocator &Alloc) : Alloc(Alloc) {}
0499 
0500   template <class SymT, typename... ArgsT> SymT *make(ArgsT &&...Args) {
0501     return new (Alloc) SymT(nextID(), std::forward<ArgsT>(Args)...);
0502   }
0503 
0504 private:
0505   SymbolID nextID() { return NextSymbolID++; }
0506 };
0507 
0508 class SymbolManager {
0509   using DataSetTy = llvm::FoldingSet<SymExpr>;
0510   using SymbolDependTy =
0511       llvm::DenseMap<SymbolRef, std::unique_ptr<SymbolRefSmallVectorTy>>;
0512 
0513   DataSetTy DataSet;
0514 
0515   /// Stores the extra dependencies between symbols: the data should be kept
0516   /// alive as long as the key is live.
0517   SymbolDependTy SymbolDependencies;
0518 
0519   SymExprAllocator Alloc;
0520   BasicValueFactory &BV;
0521   ASTContext &Ctx;
0522 
0523 public:
0524   SymbolManager(ASTContext &ctx, BasicValueFactory &bv,
0525                 llvm::BumpPtrAllocator &bpalloc)
0526       : SymbolDependencies(16), Alloc(bpalloc), BV(bv), Ctx(ctx) {}
0527 
0528   static bool canSymbolicate(QualType T);
0529 
0530   /// Create or retrieve a SymExpr of type \p SymExprT for the given arguments.
0531   /// Use the arguments to check for an existing SymExpr and return it,
0532   /// otherwise, create a new one and keep a pointer to it to avoid duplicates.
0533   template <typename SymExprT, typename... Args>
0534   const SymExprT *acquire(Args &&...args);
0535 
0536   const SymbolConjured *conjureSymbol(const Stmt *E,
0537                                       const LocationContext *LCtx, QualType T,
0538                                       unsigned VisitCount,
0539                                       const void *SymbolTag = nullptr) {
0540     return acquire<SymbolConjured>(E, LCtx, T, VisitCount, SymbolTag);
0541   }
0542 
0543   const SymbolConjured* conjureSymbol(const Expr *E,
0544                                       const LocationContext *LCtx,
0545                                       unsigned VisitCount,
0546                                       const void *SymbolTag = nullptr) {
0547     return conjureSymbol(E, LCtx, E->getType(), VisitCount, SymbolTag);
0548   }
0549 
0550   QualType getType(const SymExpr *SE) const {
0551     return SE->getType();
0552   }
0553 
0554   /// Add artificial symbol dependency.
0555   ///
0556   /// The dependent symbol should stay alive as long as the primary is alive.
0557   void addSymbolDependency(const SymbolRef Primary, const SymbolRef Dependent);
0558 
0559   const SymbolRefSmallVectorTy *getDependentSymbols(const SymbolRef Primary);
0560 
0561   ASTContext &getContext() { return Ctx; }
0562   BasicValueFactory &getBasicVals() { return BV; }
0563 };
0564 
0565 /// A class responsible for cleaning up unused symbols.
0566 class SymbolReaper {
0567   enum SymbolStatus {
0568     NotProcessed,
0569     HaveMarkedDependents
0570   };
0571 
0572   using SymbolSetTy = llvm::DenseSet<SymbolRef>;
0573   using SymbolMapTy = llvm::DenseMap<SymbolRef, SymbolStatus>;
0574   using RegionSetTy = llvm::DenseSet<const MemRegion *>;
0575 
0576   SymbolMapTy TheLiving;
0577   SymbolSetTy MetadataInUse;
0578 
0579   RegionSetTy LiveRegionRoots;
0580   // The lazily copied regions are locations for which a program
0581   // can access the value stored at that location, but not its address.
0582   // These regions are constructed as a set of regions referred to by
0583   // lazyCompoundVal.
0584   RegionSetTy LazilyCopiedRegionRoots;
0585 
0586   const StackFrameContext *LCtx;
0587   const Stmt *Loc;
0588   SymbolManager& SymMgr;
0589   StoreRef reapedStore;
0590   llvm::DenseMap<const MemRegion *, unsigned> includedRegionCache;
0591 
0592 public:
0593   /// Construct a reaper object, which removes everything which is not
0594   /// live before we execute statement s in the given location context.
0595   ///
0596   /// If the statement is NULL, everything is this and parent contexts is
0597   /// considered live.
0598   /// If the stack frame context is NULL, everything on stack is considered
0599   /// dead.
0600   SymbolReaper(const StackFrameContext *Ctx, const Stmt *s,
0601                SymbolManager &symmgr, StoreManager &storeMgr)
0602       : LCtx(Ctx), Loc(s), SymMgr(symmgr), reapedStore(nullptr, storeMgr) {}
0603 
0604   /// It might return null.
0605   const LocationContext *getLocationContext() const { return LCtx; }
0606 
0607   bool isLive(SymbolRef sym);
0608   bool isLiveRegion(const MemRegion *region);
0609   bool isLive(const Expr *ExprVal, const LocationContext *LCtx) const;
0610   bool isLive(const VarRegion *VR, bool includeStoreBindings = false) const;
0611 
0612   /// Unconditionally marks a symbol as live.
0613   ///
0614   /// This should never be
0615   /// used by checkers, only by the state infrastructure such as the store and
0616   /// environment. Checkers should instead use metadata symbols and markInUse.
0617   void markLive(SymbolRef sym);
0618 
0619   /// Marks a symbol as important to a checker.
0620   ///
0621   /// For metadata symbols,
0622   /// this will keep the symbol alive as long as its associated region is also
0623   /// live. For other symbols, this has no effect; checkers are not permitted
0624   /// to influence the life of other symbols. This should be used before any
0625   /// symbol marking has occurred, i.e. in the MarkLiveSymbols callback.
0626   void markInUse(SymbolRef sym);
0627 
0628   llvm::iterator_range<RegionSetTy::const_iterator> regions() const {
0629     return LiveRegionRoots;
0630   }
0631 
0632   /// Returns whether or not a symbol has been confirmed dead.
0633   ///
0634   /// This should only be called once all marking of dead symbols has completed.
0635   /// (For checkers, this means only in the checkDeadSymbols callback.)
0636   bool isDead(SymbolRef sym) {
0637     return !isLive(sym);
0638   }
0639 
0640   void markLive(const MemRegion *region);
0641   void markLazilyCopied(const MemRegion *region);
0642   void markElementIndicesLive(const MemRegion *region);
0643 
0644   /// Set to the value of the symbolic store after
0645   /// StoreManager::removeDeadBindings has been called.
0646   void setReapedStore(StoreRef st) { reapedStore = st; }
0647 
0648 private:
0649   bool isLazilyCopiedRegion(const MemRegion *region) const;
0650   // A readable region is a region that live or lazily copied.
0651   // Any symbols that refer to values in regions are alive if the region
0652   // is readable.
0653   bool isReadableRegion(const MemRegion *region);
0654 
0655   /// Mark the symbols dependent on the input symbol as live.
0656   void markDependentsLive(SymbolRef sym);
0657 };
0658 
0659 class SymbolVisitor {
0660 protected:
0661   ~SymbolVisitor() = default;
0662 
0663 public:
0664   SymbolVisitor() = default;
0665   SymbolVisitor(const SymbolVisitor &) = default;
0666   SymbolVisitor(SymbolVisitor &&) {}
0667 
0668   // The copy and move assignment operator is defined as deleted pending further
0669   // motivation.
0670   SymbolVisitor &operator=(const SymbolVisitor &) = delete;
0671   SymbolVisitor &operator=(SymbolVisitor &&) = delete;
0672 
0673   /// A visitor method invoked by ProgramStateManager::scanReachableSymbols.
0674   ///
0675   /// The method returns \c true if symbols should continue be scanned and \c
0676   /// false otherwise.
0677   virtual bool VisitSymbol(SymbolRef sym) = 0;
0678   virtual bool VisitMemRegion(const MemRegion *) { return true; }
0679 };
0680 
0681 template <typename T, typename... Args>
0682 const T *SymbolManager::acquire(Args &&...args) {
0683   llvm::FoldingSetNodeID profile;
0684   T::Profile(profile, args...);
0685   void *InsertPos;
0686   SymExpr *SD = DataSet.FindNodeOrInsertPos(profile, InsertPos);
0687   if (!SD) {
0688     SD = Alloc.make<T>(std::forward<Args>(args)...);
0689     DataSet.InsertNode(SD, InsertPos);
0690   }
0691   return cast<T>(SD);
0692 }
0693 
0694 } // namespace ento
0695 
0696 } // namespace clang
0697 
0698 // Override the default definition that would use pointer values of SymbolRefs
0699 // to order them, which is unstable due to ASLR.
0700 // Use the SymbolID instead which reflect the order in which the symbols were
0701 // allocated. This is usually stable across runs leading to the stability of
0702 // ConstraintMap and other containers using SymbolRef as keys.
0703 template <>
0704 struct llvm::ImutContainerInfo<clang::ento::SymbolRef>
0705     : public ImutProfileInfo<clang::ento::SymbolRef> {
0706   using value_type = clang::ento::SymbolRef;
0707   using value_type_ref = clang::ento::SymbolRef;
0708   using key_type = value_type;
0709   using key_type_ref = value_type_ref;
0710   using data_type = bool;
0711   using data_type_ref = bool;
0712 
0713   static key_type_ref KeyOfValue(value_type_ref D) { return D; }
0714   static data_type_ref DataOfValue(value_type_ref) { return true; }
0715 
0716   static bool isEqual(clang::ento::SymbolRef LHS, clang::ento::SymbolRef RHS) {
0717     return LHS->getSymbolID() == RHS->getSymbolID();
0718   }
0719 
0720   static bool isLess(clang::ento::SymbolRef LHS, clang::ento::SymbolRef RHS) {
0721     return LHS->getSymbolID() < RHS->getSymbolID();
0722   }
0723 
0724   // This might seem redundant, but it is required because of the way
0725   // ImmutableSet is implemented through AVLTree:
0726   // same as ImmutableMap, but with a non-informative "data".
0727   static bool isDataEqual(data_type_ref, data_type_ref) { return true; }
0728 };
0729 
0730 #endif // LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SYMBOLMANAGER_H