Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. //===- SymbolManager.h - Management of Symbolic Values ----------*- C++ -*-===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. //  This file defines SymbolManager, a class that manages symbolic values
  10. //  created for use by ExprEngine and related classes.
  11. //
  12. //===----------------------------------------------------------------------===//
  13.  
  14. #ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SYMBOLMANAGER_H
  15. #define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SYMBOLMANAGER_H
  16.  
  17. #include "clang/AST/Expr.h"
  18. #include "clang/AST/Type.h"
  19. #include "clang/Analysis/AnalysisDeclContext.h"
  20. #include "clang/Basic/LLVM.h"
  21. #include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
  22. #include "clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h"
  23. #include "clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h"
  24. #include "llvm/ADT/DenseMap.h"
  25. #include "llvm/ADT/DenseSet.h"
  26. #include "llvm/ADT/FoldingSet.h"
  27. #include "llvm/Support/Allocator.h"
  28. #include <cassert>
  29.  
  30. namespace clang {
  31.  
  32. class ASTContext;
  33. class Stmt;
  34.  
  35. namespace ento {
  36.  
  37. class BasicValueFactory;
  38. class StoreManager;
  39.  
  40. ///A symbol representing the value stored at a MemRegion.
  41. class SymbolRegionValue : public SymbolData {
  42.   const TypedValueRegion *R;
  43.  
  44. public:
  45.   SymbolRegionValue(SymbolID sym, const TypedValueRegion *r)
  46.       : SymbolData(SymbolRegionValueKind, sym), R(r) {
  47.     assert(r);
  48.     assert(isValidTypeForSymbol(r->getValueType()));
  49.   }
  50.  
  51.   LLVM_ATTRIBUTE_RETURNS_NONNULL
  52.   const TypedValueRegion* getRegion() const { return R; }
  53.  
  54.   static void Profile(llvm::FoldingSetNodeID& profile, const TypedValueRegion* R) {
  55.     profile.AddInteger((unsigned) SymbolRegionValueKind);
  56.     profile.AddPointer(R);
  57.   }
  58.  
  59.   void Profile(llvm::FoldingSetNodeID& profile) override {
  60.     Profile(profile, R);
  61.   }
  62.  
  63.   StringRef getKindStr() const override;
  64.  
  65.   void dumpToStream(raw_ostream &os) const override;
  66.   const MemRegion *getOriginRegion() const override { return getRegion(); }
  67.  
  68.   QualType getType() const override;
  69.  
  70.   // Implement isa<T> support.
  71.   static bool classof(const SymExpr *SE) {
  72.     return SE->getKind() == SymbolRegionValueKind;
  73.   }
  74. };
  75.  
  76. /// A symbol representing the result of an expression in the case when we do
  77. /// not know anything about what the expression is.
  78. class SymbolConjured : public SymbolData {
  79.   const Stmt *S;
  80.   QualType T;
  81.   unsigned Count;
  82.   const LocationContext *LCtx;
  83.   const void *SymbolTag;
  84.  
  85. public:
  86.   SymbolConjured(SymbolID sym, const Stmt *s, const LocationContext *lctx,
  87.                  QualType t, unsigned count, const void *symbolTag)
  88.       : SymbolData(SymbolConjuredKind, sym), S(s), T(t), Count(count),
  89.         LCtx(lctx), SymbolTag(symbolTag) {
  90.     // FIXME: 's' might be a nullptr if we're conducting invalidation
  91.     // that was caused by a destructor call on a temporary object,
  92.     // which has no statement associated with it.
  93.     // Due to this, we might be creating the same invalidation symbol for
  94.     // two different invalidation passes (for two different temporaries).
  95.     assert(lctx);
  96.     assert(isValidTypeForSymbol(t));
  97.   }
  98.  
  99.   /// It might return null.
  100.   const Stmt *getStmt() const { return S; }
  101.   unsigned getCount() const { return Count; }
  102.   /// It might return null.
  103.   const void *getTag() const { return SymbolTag; }
  104.  
  105.   QualType getType() const override;
  106.  
  107.   StringRef getKindStr() const override;
  108.  
  109.   void dumpToStream(raw_ostream &os) const override;
  110.  
  111.   static void Profile(llvm::FoldingSetNodeID& profile, const Stmt *S,
  112.                       QualType T, unsigned Count, const LocationContext *LCtx,
  113.                       const void *SymbolTag) {
  114.     profile.AddInteger((unsigned) SymbolConjuredKind);
  115.     profile.AddPointer(S);
  116.     profile.AddPointer(LCtx);
  117.     profile.Add(T);
  118.     profile.AddInteger(Count);
  119.     profile.AddPointer(SymbolTag);
  120.   }
  121.  
  122.   void Profile(llvm::FoldingSetNodeID& profile) override {
  123.     Profile(profile, S, T, Count, LCtx, SymbolTag);
  124.   }
  125.  
  126.   // Implement isa<T> support.
  127.   static bool classof(const SymExpr *SE) {
  128.     return SE->getKind() == SymbolConjuredKind;
  129.   }
  130. };
  131.  
  132. /// A symbol representing the value of a MemRegion whose parent region has
  133. /// symbolic value.
  134. class SymbolDerived : public SymbolData {
  135.   SymbolRef parentSymbol;
  136.   const TypedValueRegion *R;
  137.  
  138. public:
  139.   SymbolDerived(SymbolID sym, SymbolRef parent, const TypedValueRegion *r)
  140.       : SymbolData(SymbolDerivedKind, sym), parentSymbol(parent), R(r) {
  141.     assert(parent);
  142.     assert(r);
  143.     assert(isValidTypeForSymbol(r->getValueType()));
  144.   }
  145.  
  146.   LLVM_ATTRIBUTE_RETURNS_NONNULL
  147.   SymbolRef getParentSymbol() const { return parentSymbol; }
  148.   LLVM_ATTRIBUTE_RETURNS_NONNULL
  149.   const TypedValueRegion *getRegion() const { return R; }
  150.  
  151.   QualType getType() const override;
  152.  
  153.   StringRef getKindStr() const override;
  154.  
  155.   void dumpToStream(raw_ostream &os) const override;
  156.   const MemRegion *getOriginRegion() const override { return getRegion(); }
  157.  
  158.   static void Profile(llvm::FoldingSetNodeID& profile, SymbolRef parent,
  159.                       const TypedValueRegion *r) {
  160.     profile.AddInteger((unsigned) SymbolDerivedKind);
  161.     profile.AddPointer(r);
  162.     profile.AddPointer(parent);
  163.   }
  164.  
  165.   void Profile(llvm::FoldingSetNodeID& profile) override {
  166.     Profile(profile, parentSymbol, R);
  167.   }
  168.  
  169.   // Implement isa<T> support.
  170.   static bool classof(const SymExpr *SE) {
  171.     return SE->getKind() == SymbolDerivedKind;
  172.   }
  173. };
  174.  
  175. /// SymbolExtent - Represents the extent (size in bytes) of a bounded region.
  176. ///  Clients should not ask the SymbolManager for a region's extent. Always use
  177. ///  SubRegion::getExtent instead -- the value returned may not be a symbol.
  178. class SymbolExtent : public SymbolData {
  179.   const SubRegion *R;
  180.  
  181. public:
  182.   SymbolExtent(SymbolID sym, const SubRegion *r)
  183.       : SymbolData(SymbolExtentKind, sym), R(r) {
  184.     assert(r);
  185.   }
  186.  
  187.   LLVM_ATTRIBUTE_RETURNS_NONNULL
  188.   const SubRegion *getRegion() const { return R; }
  189.  
  190.   QualType getType() const override;
  191.  
  192.   StringRef getKindStr() const override;
  193.  
  194.   void dumpToStream(raw_ostream &os) const override;
  195.  
  196.   static void Profile(llvm::FoldingSetNodeID& profile, const SubRegion *R) {
  197.     profile.AddInteger((unsigned) SymbolExtentKind);
  198.     profile.AddPointer(R);
  199.   }
  200.  
  201.   void Profile(llvm::FoldingSetNodeID& profile) override {
  202.     Profile(profile, R);
  203.   }
  204.  
  205.   // Implement isa<T> support.
  206.   static bool classof(const SymExpr *SE) {
  207.     return SE->getKind() == SymbolExtentKind;
  208.   }
  209. };
  210.  
  211. /// SymbolMetadata - Represents path-dependent metadata about a specific region.
  212. ///  Metadata symbols remain live as long as they are marked as in use before
  213. ///  dead-symbol sweeping AND their associated regions are still alive.
  214. ///  Intended for use by checkers.
  215. class SymbolMetadata : public SymbolData {
  216.   const MemRegion* R;
  217.   const Stmt *S;
  218.   QualType T;
  219.   const LocationContext *LCtx;
  220.   unsigned Count;
  221.   const void *Tag;
  222.  
  223. public:
  224.   SymbolMetadata(SymbolID sym, const MemRegion* r, const Stmt *s, QualType t,
  225.                  const LocationContext *LCtx, unsigned count, const void *tag)
  226.       : SymbolData(SymbolMetadataKind, sym), R(r), S(s), T(t), LCtx(LCtx),
  227.         Count(count), Tag(tag) {
  228.       assert(r);
  229.       assert(s);
  230.       assert(isValidTypeForSymbol(t));
  231.       assert(LCtx);
  232.       assert(tag);
  233.     }
  234.  
  235.     LLVM_ATTRIBUTE_RETURNS_NONNULL
  236.     const MemRegion *getRegion() const { return R; }
  237.  
  238.     LLVM_ATTRIBUTE_RETURNS_NONNULL
  239.     const Stmt *getStmt() const { return S; }
  240.  
  241.     LLVM_ATTRIBUTE_RETURNS_NONNULL
  242.     const LocationContext *getLocationContext() const { return LCtx; }
  243.  
  244.     unsigned getCount() const { return Count; }
  245.  
  246.     LLVM_ATTRIBUTE_RETURNS_NONNULL
  247.     const void *getTag() const { return Tag; }
  248.  
  249.     QualType getType() const override;
  250.  
  251.     StringRef getKindStr() const override;
  252.  
  253.     void dumpToStream(raw_ostream &os) const override;
  254.  
  255.     static void Profile(llvm::FoldingSetNodeID &profile, const MemRegion *R,
  256.                         const Stmt *S, QualType T, const LocationContext *LCtx,
  257.                         unsigned Count, const void *Tag) {
  258.       profile.AddInteger((unsigned)SymbolMetadataKind);
  259.       profile.AddPointer(R);
  260.       profile.AddPointer(S);
  261.       profile.Add(T);
  262.       profile.AddPointer(LCtx);
  263.       profile.AddInteger(Count);
  264.       profile.AddPointer(Tag);
  265.     }
  266.  
  267.   void Profile(llvm::FoldingSetNodeID& profile) override {
  268.     Profile(profile, R, S, T, LCtx, Count, Tag);
  269.   }
  270.  
  271.   // Implement isa<T> support.
  272.   static bool classof(const SymExpr *SE) {
  273.     return SE->getKind() == SymbolMetadataKind;
  274.   }
  275. };
  276.  
  277. /// Represents a cast expression.
  278. class SymbolCast : public SymExpr {
  279.   const SymExpr *Operand;
  280.  
  281.   /// Type of the operand.
  282.   QualType FromTy;
  283.  
  284.   /// The type of the result.
  285.   QualType ToTy;
  286.  
  287. public:
  288.   SymbolCast(const SymExpr *In, QualType From, QualType To)
  289.       : SymExpr(SymbolCastKind), Operand(In), FromTy(From), ToTy(To) {
  290.     assert(In);
  291.     assert(isValidTypeForSymbol(From));
  292.     // FIXME: GenericTaintChecker creates symbols of void type.
  293.     // Otherwise, 'To' should also be a valid type.
  294.   }
  295.  
  296.   unsigned computeComplexity() const override {
  297.     if (Complexity == 0)
  298.       Complexity = 1 + Operand->computeComplexity();
  299.     return Complexity;
  300.   }
  301.  
  302.   QualType getType() const override { return ToTy; }
  303.  
  304.   LLVM_ATTRIBUTE_RETURNS_NONNULL
  305.   const SymExpr *getOperand() const { return Operand; }
  306.  
  307.   void dumpToStream(raw_ostream &os) const override;
  308.  
  309.   static void Profile(llvm::FoldingSetNodeID& ID,
  310.                       const SymExpr *In, QualType From, QualType To) {
  311.     ID.AddInteger((unsigned) SymbolCastKind);
  312.     ID.AddPointer(In);
  313.     ID.Add(From);
  314.     ID.Add(To);
  315.   }
  316.  
  317.   void Profile(llvm::FoldingSetNodeID& ID) override {
  318.     Profile(ID, Operand, FromTy, ToTy);
  319.   }
  320.  
  321.   // Implement isa<T> support.
  322.   static bool classof(const SymExpr *SE) {
  323.     return SE->getKind() == SymbolCastKind;
  324.   }
  325. };
  326.  
  327. /// Represents a symbolic expression involving a unary operator.
  328. class UnarySymExpr : public SymExpr {
  329.   const SymExpr *Operand;
  330.   UnaryOperator::Opcode Op;
  331.   QualType T;
  332.  
  333. public:
  334.   UnarySymExpr(const SymExpr *In, UnaryOperator::Opcode Op, QualType T)
  335.       : SymExpr(UnarySymExprKind), Operand(In), Op(Op), T(T) {
  336.     // Note, some unary operators are modeled as a binary operator. E.g. ++x is
  337.     // modeled as x + 1.
  338.     assert((Op == UO_Minus || Op == UO_Not) && "non-supported unary expression");
  339.     // Unary expressions are results of arithmetic. Pointer arithmetic is not
  340.     // handled by unary expressions, but it is instead handled by applying
  341.     // sub-regions to regions.
  342.     assert(isValidTypeForSymbol(T) && "non-valid type for unary symbol");
  343.     assert(!Loc::isLocType(T) && "unary symbol should be nonloc");
  344.   }
  345.  
  346.   unsigned computeComplexity() const override {
  347.     if (Complexity == 0)
  348.       Complexity = 1 + Operand->computeComplexity();
  349.     return Complexity;
  350.   }
  351.  
  352.   const SymExpr *getOperand() const { return Operand; }
  353.   UnaryOperator::Opcode getOpcode() const { return Op; }
  354.   QualType getType() const override { return T; }
  355.  
  356.   void dumpToStream(raw_ostream &os) const override;
  357.  
  358.   static void Profile(llvm::FoldingSetNodeID &ID, const SymExpr *In,
  359.                       UnaryOperator::Opcode Op, QualType T) {
  360.     ID.AddInteger((unsigned)UnarySymExprKind);
  361.     ID.AddPointer(In);
  362.     ID.AddInteger(Op);
  363.     ID.Add(T);
  364.   }
  365.  
  366.   void Profile(llvm::FoldingSetNodeID &ID) override {
  367.     Profile(ID, Operand, Op, T);
  368.   }
  369.  
  370.   // Implement isa<T> support.
  371.   static bool classof(const SymExpr *SE) {
  372.     return SE->getKind() == UnarySymExprKind;
  373.   }
  374. };
  375.  
  376. /// Represents a symbolic expression involving a binary operator
  377. class BinarySymExpr : public SymExpr {
  378.   BinaryOperator::Opcode Op;
  379.   QualType T;
  380.  
  381. protected:
  382.   BinarySymExpr(Kind k, BinaryOperator::Opcode op, QualType t)
  383.       : SymExpr(k), Op(op), T(t) {
  384.     assert(classof(this));
  385.     // Binary expressions are results of arithmetic. Pointer arithmetic is not
  386.     // handled by binary expressions, but it is instead handled by applying
  387.     // sub-regions to regions.
  388.     assert(isValidTypeForSymbol(t) && !Loc::isLocType(t));
  389.   }
  390.  
  391. public:
  392.   // FIXME: We probably need to make this out-of-line to avoid redundant
  393.   // generation of virtual functions.
  394.   QualType getType() const override { return T; }
  395.  
  396.   BinaryOperator::Opcode getOpcode() const { return Op; }
  397.  
  398.   // Implement isa<T> support.
  399.   static bool classof(const SymExpr *SE) {
  400.     Kind k = SE->getKind();
  401.     return k >= BEGIN_BINARYSYMEXPRS && k <= END_BINARYSYMEXPRS;
  402.   }
  403.  
  404. protected:
  405.   static unsigned computeOperandComplexity(const SymExpr *Value) {
  406.     return Value->computeComplexity();
  407.   }
  408.   static unsigned computeOperandComplexity(const llvm::APSInt &Value) {
  409.     return 1;
  410.   }
  411.  
  412.   static const llvm::APSInt *getPointer(const llvm::APSInt &Value) {
  413.     return &Value;
  414.   }
  415.   static const SymExpr *getPointer(const SymExpr *Value) { return Value; }
  416.  
  417.   static void dumpToStreamImpl(raw_ostream &os, const SymExpr *Value);
  418.   static void dumpToStreamImpl(raw_ostream &os, const llvm::APSInt &Value);
  419.   static void dumpToStreamImpl(raw_ostream &os, BinaryOperator::Opcode op);
  420. };
  421.  
  422. /// Template implementation for all binary symbolic expressions
  423. template <class LHSTYPE, class RHSTYPE, SymExpr::Kind ClassKind>
  424. class BinarySymExprImpl : public BinarySymExpr {
  425.   LHSTYPE LHS;
  426.   RHSTYPE RHS;
  427.  
  428. public:
  429.   BinarySymExprImpl(LHSTYPE lhs, BinaryOperator::Opcode op, RHSTYPE rhs,
  430.                     QualType t)
  431.       : BinarySymExpr(ClassKind, op, t), LHS(lhs), RHS(rhs) {
  432.     assert(getPointer(lhs));
  433.     assert(getPointer(rhs));
  434.   }
  435.  
  436.   void dumpToStream(raw_ostream &os) const override {
  437.     dumpToStreamImpl(os, LHS);
  438.     dumpToStreamImpl(os, getOpcode());
  439.     dumpToStreamImpl(os, RHS);
  440.   }
  441.  
  442.   LHSTYPE getLHS() const { return LHS; }
  443.   RHSTYPE getRHS() const { return RHS; }
  444.  
  445.   unsigned computeComplexity() const override {
  446.     if (Complexity == 0)
  447.       Complexity =
  448.           computeOperandComplexity(RHS) + computeOperandComplexity(LHS);
  449.     return Complexity;
  450.   }
  451.  
  452.   static void Profile(llvm::FoldingSetNodeID &ID, LHSTYPE lhs,
  453.                       BinaryOperator::Opcode op, RHSTYPE rhs, QualType t) {
  454.     ID.AddInteger((unsigned)ClassKind);
  455.     ID.AddPointer(getPointer(lhs));
  456.     ID.AddInteger(op);
  457.     ID.AddPointer(getPointer(rhs));
  458.     ID.Add(t);
  459.   }
  460.  
  461.   void Profile(llvm::FoldingSetNodeID &ID) override {
  462.     Profile(ID, LHS, getOpcode(), RHS, getType());
  463.   }
  464.  
  465.   // Implement isa<T> support.
  466.   static bool classof(const SymExpr *SE) { return SE->getKind() == ClassKind; }
  467. };
  468.  
  469. /// Represents a symbolic expression like 'x' + 3.
  470. using SymIntExpr = BinarySymExprImpl<const SymExpr *, const llvm::APSInt &,
  471.                                      SymExpr::Kind::SymIntExprKind>;
  472.  
  473. /// Represents a symbolic expression like 3 - 'x'.
  474. using IntSymExpr = BinarySymExprImpl<const llvm::APSInt &, const SymExpr *,
  475.                                      SymExpr::Kind::IntSymExprKind>;
  476.  
  477. /// Represents a symbolic expression like 'x' + 'y'.
  478. using SymSymExpr = BinarySymExprImpl<const SymExpr *, const SymExpr *,
  479.                                      SymExpr::Kind::SymSymExprKind>;
  480.  
  481. class SymbolManager {
  482.   using DataSetTy = llvm::FoldingSet<SymExpr>;
  483.   using SymbolDependTy =
  484.       llvm::DenseMap<SymbolRef, std::unique_ptr<SymbolRefSmallVectorTy>>;
  485.  
  486.   DataSetTy DataSet;
  487.  
  488.   /// Stores the extra dependencies between symbols: the data should be kept
  489.   /// alive as long as the key is live.
  490.   SymbolDependTy SymbolDependencies;
  491.  
  492.   unsigned SymbolCounter = 0;
  493.   llvm::BumpPtrAllocator& BPAlloc;
  494.   BasicValueFactory &BV;
  495.   ASTContext &Ctx;
  496.  
  497. public:
  498.   SymbolManager(ASTContext &ctx, BasicValueFactory &bv,
  499.                 llvm::BumpPtrAllocator& bpalloc)
  500.       : SymbolDependencies(16), BPAlloc(bpalloc), BV(bv), Ctx(ctx) {}
  501.  
  502.   static bool canSymbolicate(QualType T);
  503.  
  504.   /// Make a unique symbol for MemRegion R according to its kind.
  505.   const SymbolRegionValue* getRegionValueSymbol(const TypedValueRegion* R);
  506.  
  507.   const SymbolConjured* conjureSymbol(const Stmt *E,
  508.                                       const LocationContext *LCtx,
  509.                                       QualType T,
  510.                                       unsigned VisitCount,
  511.                                       const void *SymbolTag = nullptr);
  512.  
  513.   const SymbolConjured* conjureSymbol(const Expr *E,
  514.                                       const LocationContext *LCtx,
  515.                                       unsigned VisitCount,
  516.                                       const void *SymbolTag = nullptr) {
  517.     return conjureSymbol(E, LCtx, E->getType(), VisitCount, SymbolTag);
  518.   }
  519.  
  520.   const SymbolDerived *getDerivedSymbol(SymbolRef parentSymbol,
  521.                                         const TypedValueRegion *R);
  522.  
  523.   const SymbolExtent *getExtentSymbol(const SubRegion *R);
  524.  
  525.   /// Creates a metadata symbol associated with a specific region.
  526.   ///
  527.   /// VisitCount can be used to differentiate regions corresponding to
  528.   /// different loop iterations, thus, making the symbol path-dependent.
  529.   const SymbolMetadata *getMetadataSymbol(const MemRegion *R, const Stmt *S,
  530.                                           QualType T,
  531.                                           const LocationContext *LCtx,
  532.                                           unsigned VisitCount,
  533.                                           const void *SymbolTag = nullptr);
  534.  
  535.   const SymbolCast* getCastSymbol(const SymExpr *Operand,
  536.                                   QualType From, QualType To);
  537.  
  538.   const SymIntExpr *getSymIntExpr(const SymExpr *lhs, BinaryOperator::Opcode op,
  539.                                   const llvm::APSInt& rhs, QualType t);
  540.  
  541.   const SymIntExpr *getSymIntExpr(const SymExpr &lhs, BinaryOperator::Opcode op,
  542.                                   const llvm::APSInt& rhs, QualType t) {
  543.     return getSymIntExpr(&lhs, op, rhs, t);
  544.   }
  545.  
  546.   const IntSymExpr *getIntSymExpr(const llvm::APSInt& lhs,
  547.                                   BinaryOperator::Opcode op,
  548.                                   const SymExpr *rhs, QualType t);
  549.  
  550.   const SymSymExpr *getSymSymExpr(const SymExpr *lhs, BinaryOperator::Opcode op,
  551.                                   const SymExpr *rhs, QualType t);
  552.  
  553.   const UnarySymExpr *getUnarySymExpr(const SymExpr *operand,
  554.                                       UnaryOperator::Opcode op, QualType t);
  555.  
  556.   QualType getType(const SymExpr *SE) const {
  557.     return SE->getType();
  558.   }
  559.  
  560.   /// Add artificial symbol dependency.
  561.   ///
  562.   /// The dependent symbol should stay alive as long as the primary is alive.
  563.   void addSymbolDependency(const SymbolRef Primary, const SymbolRef Dependent);
  564.  
  565.   const SymbolRefSmallVectorTy *getDependentSymbols(const SymbolRef Primary);
  566.  
  567.   ASTContext &getContext() { return Ctx; }
  568.   BasicValueFactory &getBasicVals() { return BV; }
  569. };
  570.  
  571. /// A class responsible for cleaning up unused symbols.
  572. class SymbolReaper {
  573.   enum SymbolStatus {
  574.     NotProcessed,
  575.     HaveMarkedDependents
  576.   };
  577.  
  578.   using SymbolSetTy = llvm::DenseSet<SymbolRef>;
  579.   using SymbolMapTy = llvm::DenseMap<SymbolRef, SymbolStatus>;
  580.   using RegionSetTy = llvm::DenseSet<const MemRegion *>;
  581.  
  582.   SymbolMapTy TheLiving;
  583.   SymbolSetTy MetadataInUse;
  584.  
  585.   RegionSetTy LiveRegionRoots;
  586.   // The lazily copied regions are locations for which a program
  587.   // can access the value stored at that location, but not its address.
  588.   // These regions are constructed as a set of regions referred to by
  589.   // lazyCompoundVal.
  590.   RegionSetTy LazilyCopiedRegionRoots;
  591.  
  592.   const StackFrameContext *LCtx;
  593.   const Stmt *Loc;
  594.   SymbolManager& SymMgr;
  595.   StoreRef reapedStore;
  596.   llvm::DenseMap<const MemRegion *, unsigned> includedRegionCache;
  597.  
  598. public:
  599.   /// Construct a reaper object, which removes everything which is not
  600.   /// live before we execute statement s in the given location context.
  601.   ///
  602.   /// If the statement is NULL, everything is this and parent contexts is
  603.   /// considered live.
  604.   /// If the stack frame context is NULL, everything on stack is considered
  605.   /// dead.
  606.   SymbolReaper(const StackFrameContext *Ctx, const Stmt *s,
  607.                SymbolManager &symmgr, StoreManager &storeMgr)
  608.       : LCtx(Ctx), Loc(s), SymMgr(symmgr), reapedStore(nullptr, storeMgr) {}
  609.  
  610.   /// It might return null.
  611.   const LocationContext *getLocationContext() const { return LCtx; }
  612.  
  613.   bool isLive(SymbolRef sym);
  614.   bool isLiveRegion(const MemRegion *region);
  615.   bool isLive(const Expr *ExprVal, const LocationContext *LCtx) const;
  616.   bool isLive(const VarRegion *VR, bool includeStoreBindings = false) const;
  617.  
  618.   /// Unconditionally marks a symbol as live.
  619.   ///
  620.   /// This should never be
  621.   /// used by checkers, only by the state infrastructure such as the store and
  622.   /// environment. Checkers should instead use metadata symbols and markInUse.
  623.   void markLive(SymbolRef sym);
  624.  
  625.   /// Marks a symbol as important to a checker.
  626.   ///
  627.   /// For metadata symbols,
  628.   /// this will keep the symbol alive as long as its associated region is also
  629.   /// live. For other symbols, this has no effect; checkers are not permitted
  630.   /// to influence the life of other symbols. This should be used before any
  631.   /// symbol marking has occurred, i.e. in the MarkLiveSymbols callback.
  632.   void markInUse(SymbolRef sym);
  633.  
  634.   using region_iterator = RegionSetTy::const_iterator;
  635.  
  636.   region_iterator region_begin() const { return LiveRegionRoots.begin(); }
  637.   region_iterator region_end() const { return LiveRegionRoots.end(); }
  638.  
  639.   /// Returns whether or not a symbol has been confirmed dead.
  640.   ///
  641.   /// This should only be called once all marking of dead symbols has completed.
  642.   /// (For checkers, this means only in the checkDeadSymbols callback.)
  643.   bool isDead(SymbolRef sym) {
  644.     return !isLive(sym);
  645.   }
  646.  
  647.   void markLive(const MemRegion *region);
  648.   void markLazilyCopied(const MemRegion *region);
  649.   void markElementIndicesLive(const MemRegion *region);
  650.  
  651.   /// Set to the value of the symbolic store after
  652.   /// StoreManager::removeDeadBindings has been called.
  653.   void setReapedStore(StoreRef st) { reapedStore = st; }
  654.  
  655. private:
  656.   bool isLazilyCopiedRegion(const MemRegion *region) const;
  657.   // A readable region is a region that live or lazily copied.
  658.   // Any symbols that refer to values in regions are alive if the region
  659.   // is readable.
  660.   bool isReadableRegion(const MemRegion *region);
  661.  
  662.   /// Mark the symbols dependent on the input symbol as live.
  663.   void markDependentsLive(SymbolRef sym);
  664. };
  665.  
  666. class SymbolVisitor {
  667. protected:
  668.   ~SymbolVisitor() = default;
  669.  
  670. public:
  671.   SymbolVisitor() = default;
  672.   SymbolVisitor(const SymbolVisitor &) = default;
  673.   SymbolVisitor(SymbolVisitor &&) {}
  674.  
  675.   /// A visitor method invoked by ProgramStateManager::scanReachableSymbols.
  676.   ///
  677.   /// The method returns \c true if symbols should continue be scanned and \c
  678.   /// false otherwise.
  679.   virtual bool VisitSymbol(SymbolRef sym) = 0;
  680.   virtual bool VisitMemRegion(const MemRegion *) { return true; }
  681. };
  682.  
  683. } // namespace ento
  684.  
  685. } // namespace clang
  686.  
  687. #endif // LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SYMBOLMANAGER_H
  688.