]> granicus.if.org Git - clang/blobdiff - include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h
Revert "[analyzer] Provide .def-files and visitors for SVal/SymExpr/MemRegion."
[clang] / include / clang / StaticAnalyzer / Core / PathSensitive / SymbolManager.h
index 1ed16ac311176b527a0b81741330ad87ccd43550..77d12e5ba666e734f9b73616dc41e0f655a3925b 100644 (file)
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_CLANG_GR_SYMMGR_H
-#define LLVM_CLANG_GR_SYMMGR_H
+#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SYMBOLMANAGER_H
+#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SYMBOLMANAGER_H
 
 #include "clang/AST/Decl.h"
 #include "clang/AST/Expr.h"
 #include "clang/Analysis/AnalysisContext.h"
 #include "clang/Basic/LLVM.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h"
-#include "llvm/Support/DataTypes.h"
-#include "llvm/ADT/FoldingSet.h"
-#include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/DenseMap.h"
-
-namespace llvm {
-class BumpPtrAllocator;
-}
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/DataTypes.h"
 
 namespace clang {
   class ASTContext;
@@ -40,13 +37,27 @@ namespace ento {
   class TypedValueRegion;
   class VarRegion;
 
+/// \brief Symbolic value. These values used to capture symbolic execution of
+/// the program.
 class SymExpr : public llvm::FoldingSetNode {
+  virtual void anchor();
 public:
-  enum Kind { RegionValueKind, ConjuredKind, DerivedKind, ExtentKind,
-              MetadataKind,
-              BEGIN_SYMBOLS = RegionValueKind,
-              END_SYMBOLS = MetadataKind,
-              SymIntKind, SymSymKind };
+  enum Kind {
+    SymbolRegionValueKind,
+    SymbolConjuredKind,
+    SymbolDerivedKind,
+    SymbolExtentKind,
+    SymbolMetadataKind,
+    BEGIN_SYMBOLS = SymbolRegionValueKind,
+    END_SYMBOLS = SymbolMetadataKind,
+    SymIntExprKind,
+    IntSymExprKind,
+    SymSymExprKind,
+    BEGIN_BINARYSYMEXPRS = SymIntExprKind,
+    END_BINARYSYMEXPRS = SymSymExprKind,
+    SymbolCastKind
+  };
+
 private:
   Kind K;
 
@@ -58,107 +69,135 @@ public:
 
   Kind getKind() const { return K; }
 
-  void dump() const;
+  virtual void dump() const;
 
-  virtual void dumpToStream(raw_ostream &os) const = 0;
+  virtual void dumpToStream(raw_ostream &os) const {}
 
-  virtual QualType getType(ASTContext&) const = 0;
+  virtual QualType getType() const = 0;
   virtual void Profile(llvm::FoldingSetNodeID& profile) = 0;
 
-  // Implement isa<T> support.
-  static inline bool classof(const SymExpr*) { return true; }
+  /// \brief Iterator over symbols that the current symbol depends on.
+  ///
+  /// For SymbolData, it's the symbol itself; for expressions, it's the
+  /// expression symbol and all the operands in it. Note, SymbolDerived is
+  /// treated as SymbolData - the iterator will NOT visit the parent region.
+  class symbol_iterator {
+    SmallVector<const SymExpr*, 5> itr;
+    void expand();
+  public:
+    symbol_iterator() {}
+    symbol_iterator(const SymExpr *SE);
+
+    symbol_iterator &operator++();
+    const SymExpr* operator*();
+
+    bool operator==(const symbol_iterator &X) const;
+    bool operator!=(const symbol_iterator &X) const;
+  };
+
+  symbol_iterator symbol_begin() const {
+    return symbol_iterator(this);
+  }
+  static symbol_iterator symbol_end() { return symbol_iterator(); }
+
+  unsigned computeComplexity() const;
 };
 
-typedef unsigned SymbolID;
+typedef const SymExpr* SymbolRef;
+typedef SmallVector<SymbolRef, 2> SymbolRefSmallVectorTy;
 
+typedef unsigned SymbolID;
+/// \brief A symbol representing data which can be stored in a memory location
+/// (region).
 class SymbolData : public SymExpr {
-private:
+  void anchor() override;
   const SymbolID Sym;
 
 protected:
   SymbolData(Kind k, SymbolID sym) : SymExpr(k), Sym(sym) {}
 
 public:
-  virtual ~SymbolData() {}
+  ~SymbolData() override {}
 
   SymbolID getSymbolID() const { return Sym; }
 
   // Implement isa<T> support.
-  static inline bool classof(const SymExprSE) {
+  static inline bool classof(const SymExpr *SE) {
     Kind k = SE->getKind();
     return k >= BEGIN_SYMBOLS && k <= END_SYMBOLS;
   }
 };
 
-typedef const SymbolData* SymbolRef;
-typedef llvm::SmallVector<SymbolRef, 2> SymbolRefSmallVectorTy;
-
-/// A symbol representing the value of a MemRegion.
+///\brief A symbol representing the value stored at a MemRegion.
 class SymbolRegionValue : public SymbolData {
   const TypedValueRegion *R;
 
 public:
   SymbolRegionValue(SymbolID sym, const TypedValueRegion *r)
-    : SymbolData(RegionValueKind, sym), R(r) {}
+    : SymbolData(SymbolRegionValueKind, sym), R(r) {}
 
   const TypedValueRegion* getRegion() const { return R; }
 
   static void Profile(llvm::FoldingSetNodeID& profile, const TypedValueRegion* R) {
-    profile.AddInteger((unsigned) RegionValueKind);
+    profile.AddInteger((unsigned) SymbolRegionValueKind);
     profile.AddPointer(R);
   }
 
-  virtual void Profile(llvm::FoldingSetNodeID& profile) {
+  void Profile(llvm::FoldingSetNodeID& profile) override {
     Profile(profile, R);
   }
 
-  void dumpToStream(raw_ostream &os) const;
+  void dumpToStream(raw_ostream &os) const override;
 
-  QualType getType(ASTContext&) const;
+  QualType getType() const override;
 
   // Implement isa<T> support.
-  static inline bool classof(const SymExprSE) {
-    return SE->getKind() == RegionValueKind;
+  static inline bool classof(const SymExpr *SE) {
+    return SE->getKind() == SymbolRegionValueKind;
   }
 };
 
-/// A symbol representing the result of an expression.
+/// A symbol representing the result of an expression in the case when we do
+/// not know anything about what the expression is.
 class SymbolConjured : public SymbolData {
-  const StmtS;
+  const Stmt *S;
   QualType T;
   unsigned Count;
-  const void* SymbolTag;
+  const LocationContext *LCtx;
+  const void *SymbolTag;
 
 public:
-  SymbolConjured(SymbolID sym, const Stmt* s, QualType t, unsigned count,
-                 const void* symbolTag)
-    : SymbolData(ConjuredKind, sym), S(s), T(t), Count(count),
-      SymbolTag(symbolTag) {}
+  SymbolConjured(SymbolID sym, const Stmt *s, const LocationContext *lctx,
+                 QualType t, unsigned count, const void *symbolTag)
+      : SymbolData(SymbolConjuredKind, sym), S(s), T(t), Count(count),
+        LCtx(lctx), SymbolTag(symbolTag) {}
 
-  const StmtgetStmt() const { return S; }
+  const Stmt *getStmt() const { return S; }
   unsigned getCount() const { return Count; }
-  const voidgetTag() const { return SymbolTag; }
+  const void *getTag() const { return SymbolTag; }
 
-  QualType getType(ASTContext&) const;
+  QualType getType() const override;
 
-  void dumpToStream(raw_ostream &os) const;
+  void dumpToStream(raw_ostream &os) const override;
 
-  static void Profile(llvm::FoldingSetNodeID& profile, const Stmt* S,
-                      QualType T, unsigned Count, const void* SymbolTag) {
-    profile.AddInteger((unsigned) ConjuredKind);
+  static void Profile(llvm::FoldingSetNodeID& profile, const Stmt *S,
+                      QualType T, unsigned Count, const LocationContext *LCtx,
+                      const void *SymbolTag) {
+    profile.AddInteger((unsigned) SymbolConjuredKind);
     profile.AddPointer(S);
+    profile.AddPointer(LCtx);
     profile.Add(T);
     profile.AddInteger(Count);
     profile.AddPointer(SymbolTag);
   }
 
-  virtual void Profile(llvm::FoldingSetNodeID& profile) {
-    Profile(profile, S, T, Count, SymbolTag);
+  void Profile(llvm::FoldingSetNodeID& profile) override {
+    Profile(profile, S, T, Count, LCtx, SymbolTag);
   }
 
   // Implement isa<T> support.
-  static inline bool classof(const SymExprSE) {
-    return SE->getKind() == ConjuredKind;
+  static inline bool classof(const SymExpr *SE) {
+    return SE->getKind() == SymbolConjuredKind;
   }
 };
 
@@ -170,29 +209,29 @@ class SymbolDerived : public SymbolData {
 
 public:
   SymbolDerived(SymbolID sym, SymbolRef parent, const TypedValueRegion *r)
-    : SymbolData(DerivedKind, sym), parentSymbol(parent), R(r) {}
+    : SymbolData(SymbolDerivedKind, sym), parentSymbol(parent), R(r) {}
 
   SymbolRef getParentSymbol() const { return parentSymbol; }
   const TypedValueRegion *getRegion() const { return R; }
 
-  QualType getType(ASTContext&) const;
+  QualType getType() const override;
 
-  void dumpToStream(raw_ostream &os) const;
+  void dumpToStream(raw_ostream &os) const override;
 
   static void Profile(llvm::FoldingSetNodeID& profile, SymbolRef parent,
                       const TypedValueRegion *r) {
-    profile.AddInteger((unsigned) DerivedKind);
+    profile.AddInteger((unsigned) SymbolDerivedKind);
     profile.AddPointer(r);
     profile.AddPointer(parent);
   }
 
-  virtual void Profile(llvm::FoldingSetNodeID& profile) {
+  void Profile(llvm::FoldingSetNodeID& profile) override {
     Profile(profile, parentSymbol, R);
   }
 
   // Implement isa<T> support.
-  static inline bool classof(const SymExprSE) {
-    return SE->getKind() == DerivedKind;
+  static inline bool classof(const SymExpr *SE) {
+    return SE->getKind() == SymbolDerivedKind;
   }
 };
 
@@ -204,26 +243,26 @@ class SymbolExtent : public SymbolData {
   
 public:
   SymbolExtent(SymbolID sym, const SubRegion *r)
-  : SymbolData(ExtentKind, sym), R(r) {}
+  : SymbolData(SymbolExtentKind, sym), R(r) {}
 
   const SubRegion *getRegion() const { return R; }
 
-  QualType getType(ASTContext&) const;
+  QualType getType() const override;
 
-  void dumpToStream(raw_ostream &os) const;
+  void dumpToStream(raw_ostream &os) const override;
 
   static void Profile(llvm::FoldingSetNodeID& profile, const SubRegion *R) {
-    profile.AddInteger((unsigned) ExtentKind);
+    profile.AddInteger((unsigned) SymbolExtentKind);
     profile.AddPointer(R);
   }
 
-  virtual void Profile(llvm::FoldingSetNodeID& profile) {
+  void Profile(llvm::FoldingSetNodeID& profile) override {
     Profile(profile, R);
   }
 
   // Implement isa<T> support.
-  static inline bool classof(const SymExprSE) {
-    return SE->getKind() == ExtentKind;
+  static inline bool classof(const SymExpr *SE) {
+    return SE->getKind() == SymbolExtentKind;
   }
 };
 
@@ -233,28 +272,28 @@ public:
 ///  Intended for use by checkers.
 class SymbolMetadata : public SymbolData {
   const MemRegion* R;
-  const StmtS;
+  const Stmt *S;
   QualType T;
   unsigned Count;
-  const voidTag;
+  const void *Tag;
 public:
-  SymbolMetadata(SymbolID sym, const MemRegion* r, const Stmts, QualType t,
-                 unsigned count, const voidtag)
-  : SymbolData(MetadataKind, sym), R(r), S(s), T(t), Count(count), Tag(tag) {}
+  SymbolMetadata(SymbolID sym, const MemRegion* r, const Stmt *s, QualType t,
+                 unsigned count, const void *tag)
+  : SymbolData(SymbolMetadataKind, sym), R(r), S(s), T(t), Count(count), Tag(tag) {}
 
   const MemRegion *getRegion() const { return R; }
-  const StmtgetStmt() const { return S; }
+  const Stmt *getStmt() const { return S; }
   unsigned getCount() const { return Count; }
-  const voidgetTag() const { return Tag; }
+  const void *getTag() const { return Tag; }
 
-  QualType getType(ASTContext&) const;
+  QualType getType() const override;
 
-  void dumpToStream(raw_ostream &os) const;
+  void dumpToStream(raw_ostream &os) const override;
 
   static void Profile(llvm::FoldingSetNodeID& profile, const MemRegion *R,
                       const Stmt *S, QualType T, unsigned Count,
                       const void *Tag) {
-    profile.AddInteger((unsigned) MetadataKind);
+    profile.AddInteger((unsigned) SymbolMetadataKind);
     profile.AddPointer(R);
     profile.AddPointer(S);
     profile.Add(T);
@@ -262,35 +301,86 @@ public:
     profile.AddPointer(Tag);
   }
 
-  virtual void Profile(llvm::FoldingSetNodeID& profile) {
+  void Profile(llvm::FoldingSetNodeID& profile) override {
     Profile(profile, R, S, T, Count, Tag);
   }
 
   // Implement isa<T> support.
-  static inline bool classof(const SymExprSE) {
-    return SE->getKind() == MetadataKind;
+  static inline bool classof(const SymExpr *SE) {
+    return SE->getKind() == SymbolMetadataKind;
   }
 };
 
-/// SymIntExpr - Represents symbolic expression like 'x' + 3.
-class SymIntExpr : public SymExpr {
-  const SymExpr *LHS;
+/// \brief Represents a cast expression.
+class SymbolCast : public SymExpr {
+  const SymExpr *Operand;
+  /// Type of the operand.
+  QualType FromTy;
+  /// The type of the result.
+  QualType ToTy;
+
+public:
+  SymbolCast(const SymExpr *In, QualType From, QualType To) :
+    SymExpr(SymbolCastKind), Operand(In), FromTy(From), ToTy(To) { }
+
+  QualType getType() const override { return ToTy; }
+
+  const SymExpr *getOperand() const { return Operand; }
+
+  void dumpToStream(raw_ostream &os) const override;
+
+  static void Profile(llvm::FoldingSetNodeID& ID,
+                      const SymExpr *In, QualType From, QualType To) {
+    ID.AddInteger((unsigned) SymbolCastKind);
+    ID.AddPointer(In);
+    ID.Add(From);
+    ID.Add(To);
+  }
+
+  void Profile(llvm::FoldingSetNodeID& ID) override {
+    Profile(ID, Operand, FromTy, ToTy);
+  }
+
+  // Implement isa<T> support.
+  static inline bool classof(const SymExpr *SE) {
+    return SE->getKind() == SymbolCastKind;
+  }
+};
+
+/// \brief Represents a symbolic expression involving a binary operator 
+class BinarySymExpr : public SymExpr {
   BinaryOperator::Opcode Op;
-  const llvm::APSInt& RHS;
   QualType T;
 
-public:
-  SymIntExpr(const SymExpr *lhs, BinaryOperator::Opcode op,
-             const llvm::APSInt& rhs, QualType t)
-    : SymExpr(SymIntKind), LHS(lhs), Op(op), RHS(rhs), T(t) {}
+protected:
+  BinarySymExpr(Kind k, BinaryOperator::Opcode op, QualType t)
+    : SymExpr(k), Op(op), T(t) {}
 
+public:
   // FIXME: We probably need to make this out-of-line to avoid redundant
   // generation of virtual functions.
-  QualType getType(ASTContext& C) const { return T; }
+  QualType getType() const override { return T; }
 
   BinaryOperator::Opcode getOpcode() const { return Op; }
 
-  void dumpToStream(raw_ostream &os) const;
+  // Implement isa<T> support.
+  static inline bool classof(const SymExpr *SE) {
+    Kind k = SE->getKind();
+    return k >= BEGIN_BINARYSYMEXPRS && k <= END_BINARYSYMEXPRS;
+  }
+};
+
+/// \brief Represents a symbolic expression like 'x' + 3.
+class SymIntExpr : public BinarySymExpr {
+  const SymExpr *LHS;
+  const llvm::APSInt& RHS;
+
+public:
+  SymIntExpr(const SymExpr *lhs, BinaryOperator::Opcode op,
+             const llvm::APSInt& rhs, QualType t)
+    : BinarySymExpr(SymIntExprKind, op, t), LHS(lhs), RHS(rhs) {}
+
+  void dumpToStream(raw_ostream &os) const override;
 
   const SymExpr *getLHS() const { return LHS; }
   const llvm::APSInt &getRHS() const { return RHS; }
@@ -298,61 +388,89 @@ public:
   static void Profile(llvm::FoldingSetNodeID& ID, const SymExpr *lhs,
                       BinaryOperator::Opcode op, const llvm::APSInt& rhs,
                       QualType t) {
-    ID.AddInteger((unsigned) SymIntKind);
+    ID.AddInteger((unsigned) SymIntExprKind);
     ID.AddPointer(lhs);
     ID.AddInteger(op);
     ID.AddPointer(&rhs);
     ID.Add(t);
   }
 
-  void Profile(llvm::FoldingSetNodeID& ID) {
-    Profile(ID, LHS, Op, RHS, T);
+  void Profile(llvm::FoldingSetNodeID& ID) override {
+    Profile(ID, LHS, getOpcode(), RHS, getType());
   }
 
   // Implement isa<T> support.
-  static inline bool classof(const SymExprSE) {
-    return SE->getKind() == SymIntKind;
+  static inline bool classof(const SymExpr *SE) {
+    return SE->getKind() == SymIntExprKind;
   }
 };
 
-/// SymSymExpr - Represents symbolic expression like 'x' + 'y'.
-class SymSymExpr : public SymExpr {
+/// \brief Represents a symbolic expression like 3 - 'x'.
+class IntSymExpr : public BinarySymExpr {
+  const llvm::APSInt& LHS;
+  const SymExpr *RHS;
+
+public:
+  IntSymExpr(const llvm::APSInt& lhs, BinaryOperator::Opcode op,
+             const SymExpr *rhs, QualType t)
+    : BinarySymExpr(IntSymExprKind, op, t), LHS(lhs), RHS(rhs) {}
+
+  void dumpToStream(raw_ostream &os) const override;
+
+  const SymExpr *getRHS() const { return RHS; }
+  const llvm::APSInt &getLHS() const { return LHS; }
+
+  static void Profile(llvm::FoldingSetNodeID& ID, const llvm::APSInt& lhs,
+                      BinaryOperator::Opcode op, const SymExpr *rhs,
+                      QualType t) {
+    ID.AddInteger((unsigned) IntSymExprKind);
+    ID.AddPointer(&lhs);
+    ID.AddInteger(op);
+    ID.AddPointer(rhs);
+    ID.Add(t);
+  }
+
+  void Profile(llvm::FoldingSetNodeID& ID) override {
+    Profile(ID, LHS, getOpcode(), RHS, getType());
+  }
+
+  // Implement isa<T> support.
+  static inline bool classof(const SymExpr *SE) {
+    return SE->getKind() == IntSymExprKind;
+  }
+};
+
+/// \brief Represents a symbolic expression like 'x' + 'y'.
+class SymSymExpr : public BinarySymExpr {
   const SymExpr *LHS;
-  BinaryOperator::Opcode Op;
   const SymExpr *RHS;
-  QualType T;
 
 public:
   SymSymExpr(const SymExpr *lhs, BinaryOperator::Opcode op, const SymExpr *rhs,
              QualType t)
-    : SymExpr(SymSymKind), LHS(lhs), Op(op), RHS(rhs), T(t) {}
+    : BinarySymExpr(SymSymExprKind, op, t), LHS(lhs), RHS(rhs) {}
 
-  BinaryOperator::Opcode getOpcode() const { return Op; }
   const SymExpr *getLHS() const { return LHS; }
   const SymExpr *getRHS() const { return RHS; }
 
-  // FIXME: We probably need to make this out-of-line to avoid redundant
-  // generation of virtual functions.
-  QualType getType(ASTContext& C) const { return T; }
-
-  void dumpToStream(raw_ostream &os) const;
+  void dumpToStream(raw_ostream &os) const override;
 
   static void Profile(llvm::FoldingSetNodeID& ID, const SymExpr *lhs,
                     BinaryOperator::Opcode op, const SymExpr *rhs, QualType t) {
-    ID.AddInteger((unsigned) SymSymKind);
+    ID.AddInteger((unsigned) SymSymExprKind);
     ID.AddPointer(lhs);
     ID.AddInteger(op);
     ID.AddPointer(rhs);
     ID.Add(t);
   }
 
-  void Profile(llvm::FoldingSetNodeID& ID) {
-    Profile(ID, LHS, Op, RHS, T);
+  void Profile(llvm::FoldingSetNodeID& ID) override {
+    Profile(ID, LHS, getOpcode(), RHS, getType());
   }
 
   // Implement isa<T> support.
-  static inline bool classof(const SymExprSE) {
-    return SE->getKind() == SymSymKind;
+  static inline bool classof(const SymExpr *SE) {
+    return SE->getKind() == SymSymExprKind;
   }
 };
 
@@ -367,10 +485,10 @@ class SymbolManager {
   unsigned SymbolCounter;
   llvm::BumpPtrAllocator& BPAlloc;
   BasicValueFactory &BV;
-  ASTContextCtx;
+  ASTContext &Ctx;
 
 public:
-  SymbolManager(ASTContextctx, BasicValueFactory &bv,
+  SymbolManager(ASTContext &ctx, BasicValueFactory &bv,
                 llvm::BumpPtrAllocator& bpalloc)
     : SymbolDependencies(16), SymbolCounter(0),
       BPAlloc(bpalloc), BV(bv), Ctx(ctx) {}
@@ -382,13 +500,17 @@ public:
   /// \brief Make a unique symbol for MemRegion R according to its kind.
   const SymbolRegionValue* getRegionValueSymbol(const TypedValueRegion* R);
 
-  const SymbolConjured* getConjuredSymbol(const Stmt* E, QualType T,
-                                          unsigned VisitCount,
-                                          const void* SymbolTag = 0);
-
-  const SymbolConjured* getConjuredSymbol(const Expr* E, unsigned VisitCount,
-                                          const void* SymbolTag = 0) {
-    return getConjuredSymbol(E, E->getType(), VisitCount, SymbolTag);
+  const SymbolConjured* conjureSymbol(const Stmt *E,
+                                      const LocationContext *LCtx,
+                                      QualType T,
+                                      unsigned VisitCount,
+                                      const void *SymbolTag = nullptr);
+
+  const SymbolConjured* conjureSymbol(const Expr *E,
+                                      const LocationContext *LCtx,
+                                      unsigned VisitCount,
+                                      const void *SymbolTag = nullptr) {
+    return conjureSymbol(E, LCtx, E->getType(), VisitCount, SymbolTag);
   }
 
   const SymbolDerived *getDerivedSymbol(SymbolRef parentSymbol,
@@ -400,9 +522,12 @@ public:
   ///
   /// VisitCount can be used to differentiate regions corresponding to
   /// different loop iterations, thus, making the symbol path-dependent.
-  const SymbolMetadata* getMetadataSymbol(const MemRegion* R, const Stmt* S,
+  const SymbolMetadata *getMetadataSymbol(const MemRegion *R, const Stmt *S,
                                           QualType T, unsigned VisitCount,
-                                          const void* SymbolTag = 0);
+                                          const void *SymbolTag = nullptr);
+
+  const SymbolCast* getCastSymbol(const SymExpr *Operand,
+                                  QualType From, QualType To);
 
   const SymIntExpr *getSymIntExpr(const SymExpr *lhs, BinaryOperator::Opcode op,
                                   const llvm::APSInt& rhs, QualType t);
@@ -412,11 +537,15 @@ public:
     return getSymIntExpr(&lhs, op, rhs, t);
   }
 
+  const IntSymExpr *getIntSymExpr(const llvm::APSInt& lhs,
+                                  BinaryOperator::Opcode op,
+                                  const SymExpr *rhs, QualType t);
+
   const SymSymExpr *getSymSymExpr(const SymExpr *lhs, BinaryOperator::Opcode op,
                                   const SymExpr *rhs, QualType t);
 
   QualType getType(const SymExpr *SE) const {
-    return SE->getType(Ctx);
+    return SE->getType();
   }
 
   /// \brief Add artificial symbol dependency.
@@ -430,6 +559,7 @@ public:
   BasicValueFactory &getBasicVals() { return BV; }
 };
 
+/// \brief A class responsible for cleaning up unused symbols.
 class SymbolReaper {
   enum SymbolStatus {
     NotProcessed,
@@ -446,25 +576,30 @@ class SymbolReaper {
 
   RegionSetTy RegionRoots;
   
-  const LocationContext *LCtx;
+  const StackFrameContext *LCtx;
   const Stmt *Loc;
   SymbolManager& SymMgr;
   StoreRef reapedStore;
   llvm::DenseMap<const MemRegion *, unsigned> includedRegionCache;
 
 public:
-  SymbolReaper(const LocationContext *ctx, const Stmt *s, SymbolManager& symmgr,
+  /// \brief Construct a reaper object, which removes everything which is not
+  /// live before we execute statement s in the given location context.
+  ///
+  /// If the statement is NULL, everything is this and parent contexts is
+  /// considered live.
+  /// If the stack frame context is NULL, everything on stack is considered
+  /// dead.
+  SymbolReaper(const StackFrameContext *Ctx, const Stmt *s, SymbolManager& symmgr,
                StoreManager &storeMgr)
-   : LCtx(ctx), Loc(s), SymMgr(symmgr), reapedStore(0, storeMgr) {}
-
-  ~SymbolReaper() {}
+   : LCtx(Ctx), Loc(s), SymMgr(symmgr),
+     reapedStore(nullptr, storeMgr) {}
 
   const LocationContext *getLocationContext() const { return LCtx; }
-  const Stmt *getCurrentStatement() const { return Loc; }
 
   bool isLive(SymbolRef sym);
   bool isLiveRegion(const MemRegion *region);
-  bool isLive(const Stmt *ExprVal) const;
+  bool isLive(const Stmt *ExprVal, const LocationContext *LCtx) const;
   bool isLive(const VarRegion *VR, bool includeStoreBindings = false) const;
 
   /// \brief Unconditionally marks a symbol as live.
@@ -510,6 +645,7 @@ public:
   }
   
   void markLive(const MemRegion *region);
+  void markElementIndicesLive(const MemRegion *region);
   
   /// \brief Set to the value of the symbolic store after
   /// StoreManager::removeDeadBindings has been called.
@@ -521,14 +657,20 @@ private:
 };
 
 class SymbolVisitor {
+protected:
+  ~SymbolVisitor() = default;
+
 public:
-  /// \brief A visitor method invoked by GRStateManager::scanReachableSymbols.
+  SymbolVisitor() = default;
+  SymbolVisitor(const SymbolVisitor &) = default;
+  SymbolVisitor(SymbolVisitor &&) {}
+
+  /// \brief A visitor method invoked by ProgramStateManager::scanReachableSymbols.
   ///
   /// The method returns \c true if symbols should continue be scanned and \c
   /// false otherwise.
   virtual bool VisitSymbol(SymbolRef sym) = 0;
   virtual bool VisitMemRegion(const MemRegion *region) { return true; }
-  virtual ~SymbolVisitor();
 };
 
 } // end GR namespace
@@ -536,8 +678,8 @@ public:
 } // end clang namespace
 
 namespace llvm {
-static inline raw_ostream& operator<<(raw_ostream& os,
-                                            const clang::ento::SymExpr *SE) {
+static inline raw_ostream &operator<<(raw_ostream &os,
+                                      const clang::ento::SymExpr *SE) {
   SE->dumpToStream(os);
   return os;
 }