]> granicus.if.org Git - clang/blobdiff - include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h
Header guard canonicalization, clang part.
[clang] / include / clang / StaticAnalyzer / Core / PathSensitive / SVals.h
index e0b5f64b900b54db82dd6a1814bcdf2c34db11ac..ef43fe0eea9aa5f066ad6fb5a6dbcf4e6e62825c 100644 (file)
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_CLANG_GR_RVALUE_H
-#define LLVM_CLANG_GR_RVALUE_H
+#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SVALS_H
+#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SVALS_H
 
 #include "clang/Basic/LLVM.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
 #include "llvm/ADT/ImmutableList.h"
 
 //==------------------------------------------------------------------------==//
@@ -33,7 +33,7 @@ class LazyCompoundValData;
 class ProgramState;
 class BasicValueFactory;
 class MemRegion;
-class TypedRegion;
+class TypedValueRegion;
 class MemRegionManager;
 class ProgramStateManager;
 class SValBuilder;
@@ -63,11 +63,34 @@ protected:
   explicit SVal(const void *d, bool isLoc, unsigned ValKind)
   : Data(d), Kind((isLoc ? LocKind : NonLocKind) | (ValKind << BaseBits)) {}
 
-  explicit SVal(BaseKind k, const void *D = NULL)
+  explicit SVal(BaseKind k, const void *D = nullptr)
     : Data(D), Kind(k) {}
 
 public:
-  explicit SVal() : Data(0), Kind(0) {}
+  explicit SVal() : Data(nullptr), Kind(0) {}
+
+  /// \brief Convert to the specified SVal type, asserting that this SVal is of
+  /// the desired type.
+  template<typename T>
+  T castAs() const {
+    assert(T::isKind(*this));
+    T t;
+    SVal& sv = t;
+    sv = *this;
+    return t;
+  }
+
+  /// \brief Convert to the specified SVal type, returning None if this SVal is
+  /// not of the desired type.
+  template<typename T>
+  Optional<T> getAs() const {
+    if (!T::isKind(*this))
+      return None;
+    T t;
+    SVal& sv = t;
+    sv = *this;
+    return t;
+  }
 
   /// BufferTy - A temporary buffer to hold a set of SVals.
   typedef SmallVector<SVal,5> BufferTy;
@@ -121,16 +144,24 @@ public:
   /// Otherwise return 0.
   const FunctionDecl *getAsFunctionDecl() const;
 
-  /// If this SVal is a location (subclasses Loc) and
-  /// wraps a symbol, return that SymbolRef.  Otherwise return 0.
-  SymbolRef getAsLocSymbol() const;
+  /// \brief If this SVal is a location and wraps a symbol, return that
+  ///  SymbolRef. Otherwise return 0.
+  ///
+  /// Casts are ignored during lookup.
+  /// \param IncludeBaseRegions The boolean that controls whether the search
+  /// should continue to the base regions if the region is not symbolic.
+  SymbolRef getAsLocSymbol(bool IncludeBaseRegions = false) const;
 
   /// Get the symbol in the SVal or its base region.
   SymbolRef getLocSymbolInBase() const;
 
-  /// If this SVal wraps a symbol return that SymbolRef.
+  /// \brief If this SVal wraps a symbol return that SymbolRef.
   /// Otherwise, return 0.
-  SymbolRef getAsSymbol() const;
+  ///
+  /// Casts are ignored during lookup.
+  /// \param IncludeBaseRegions The boolean that controls whether the search
+  /// should continue to the base regions if the region is not symbolic.
+  SymbolRef getAsSymbol(bool IncludeBaseRegions = false) const;
 
   /// getAsSymbolicExpression - If this Sval wraps a symbolic expression then
   ///  return that expression.  Otherwise return NULL.
@@ -154,9 +185,6 @@ public:
   SymExpr::symbol_iterator symbol_end() const { 
     return SymExpr::symbol_end();
   }
-
-  // Implement isa<T> support.
-  static inline bool classof(const SVal*) { return true; }
 };
 
 
@@ -164,29 +192,32 @@ class UndefinedVal : public SVal {
 public:
   UndefinedVal() : SVal(UndefinedKind) {}
 
-  static inline bool classof(const SVal* V) {
-    return V->getBaseKind() == UndefinedKind;
+private:
+  friend class SVal;
+  static bool isKind(const SVal& V) {
+    return V.getBaseKind() == UndefinedKind;
   }
 };
 
 class DefinedOrUnknownSVal : public SVal {
 private:
-  // Do not implement.  We want calling these methods to be a compiler
-  // error since they are tautologically false.
-  bool isUndef() const;
-  bool isValid() const;
+  // We want calling these methods to be a compiler error since they are
+  // tautologically false.
+  bool isUndef() const LLVM_DELETED_FUNCTION;
+  bool isValid() const LLVM_DELETED_FUNCTION;
   
 protected:
+  DefinedOrUnknownSVal() {}
   explicit DefinedOrUnknownSVal(const void *d, bool isLoc, unsigned ValKind)
     : SVal(d, isLoc, ValKind) {}
   
-  explicit DefinedOrUnknownSVal(BaseKind k, void *D = NULL)
+  explicit DefinedOrUnknownSVal(BaseKind k, void *D = nullptr)
     : SVal(k, D) {}
   
-public:
-    // Implement isa<T> support.
-  static inline bool classof(const SVal *V) {
-    return !V->isUndef();
+private:
+  friend class SVal;
+  static bool isKind(const SVal& V) {
+    return !V.isUndef();
   }
 };
   
@@ -194,60 +225,78 @@ class UnknownVal : public DefinedOrUnknownSVal {
 public:
   explicit UnknownVal() : DefinedOrUnknownSVal(UnknownKind) {}
   
-  static inline bool classof(const SVal *V) {
-    return V->getBaseKind() == UnknownKind;
+private:
+  friend class SVal;
+  static bool isKind(const SVal &V) {
+    return V.getBaseKind() == UnknownKind;
   }
 };
 
 class DefinedSVal : public DefinedOrUnknownSVal {
 private:
-  // Do not implement.  We want calling these methods to be a compiler
-  // error since they are tautologically true/false.
-  bool isUnknown() const;
-  bool isUnknownOrUndef() const;
-  bool isValid() const;  
+  // We want calling these methods to be a compiler error since they are
+  // tautologically true/false.
+  bool isUnknown() const LLVM_DELETED_FUNCTION;
+  bool isUnknownOrUndef() const LLVM_DELETED_FUNCTION;
+  bool isValid() const LLVM_DELETED_FUNCTION;
 protected:
+  DefinedSVal() {}
   explicit DefinedSVal(const void *d, bool isLoc, unsigned ValKind)
     : DefinedOrUnknownSVal(d, isLoc, ValKind) {}
-public:
-  // Implement isa<T> support.
-  static inline bool classof(const SVal *V) {
-    return !V->isUnknownOrUndef();
+private:
+  friend class SVal;
+  static bool isKind(const SVal& V) {
+    return !V.isUnknownOrUndef();
+  }
+};
+
+
+/// \brief Represents an SVal that is guaranteed to not be UnknownVal.
+class KnownSVal : public SVal {
+  KnownSVal() {}
+  friend class SVal;
+  static bool isKind(const SVal &V) {
+    return !V.isUnknown();
   }
+public:
+  KnownSVal(const DefinedSVal &V) : SVal(V) {}
+  KnownSVal(const UndefinedVal &V) : SVal(V) {}
 };
 
 class NonLoc : public DefinedSVal {
 protected:
+  NonLoc() {}
   explicit NonLoc(unsigned SubKind, const void *d)
     : DefinedSVal(d, false, SubKind) {}
 
 public:
   void dumpToStream(raw_ostream &Out) const;
 
-  // Implement isa<T> support.
-  static inline bool classof(const SVal* V) {
-    return V->getBaseKind() == NonLocKind;
+private:
+  friend class SVal;
+  static bool isKind(const SVal& V) {
+    return V.getBaseKind() == NonLocKind;
   }
 };
 
 class Loc : public DefinedSVal {
 protected:
+  Loc() {}
   explicit Loc(unsigned SubKind, const void *D)
   : DefinedSVal(const_cast<void*>(D), true, SubKind) {}
 
 public:
   void dumpToStream(raw_ostream &Out) const;
 
-  Loc(const Loc& X) : DefinedSVal(X.Data, true, X.getSubKind()) {}
-
-  // Implement isa<T> support.
-  static inline bool classof(const SVal* V) {
-    return V->getBaseKind() == LocKind;
-  }
-
   static inline bool isLocType(QualType T) {
     return T->isAnyPointerType() || T->isBlockPointerType() || 
-           T->isReferenceType();
+           T->isReferenceType() || T->isNullPtrType();
+  }
+
+private:
+  friend class SVal;
+  static bool isKind(const SVal& V) {
+    return V.getBaseKind() == LocKind;
   }
 };
 
@@ -257,7 +306,7 @@ public:
 
 namespace nonloc {
 
-enum Kind { ConcreteIntKind, SymbolValKind, SymExprValKind,
+enum Kind { ConcreteIntKind, SymbolValKind,
             LocAsIntegerKind, CompoundValKind, LazyCompoundValKind };
 
 /// \brief Represents symbolic expression.
@@ -269,17 +318,20 @@ public:
     return (const SymExpr*) Data;
   }
 
-  bool isExpression() {
+  bool isExpression() const {
     return !isa<SymbolData>(getSymbol());
   }
 
-  static inline bool classof(const SVal* V) {
-    return V->getBaseKind() == NonLocKind &&
-           V->getSubKind() == SymbolValKind;
+private:
+  friend class SVal;
+  SymbolVal() {}
+  static bool isKind(const SVal& V) {
+    return V.getBaseKind() == NonLocKind &&
+           V.getSubKind() == SymbolValKind;
   }
 
-  static inline bool classof(const NonLoc* V) {
-    return V->getSubKind() == SymbolValKind;
+  static bool isKind(const NonLoc& V) {
+    return V.getSubKind() == SymbolValKind;
   }
 };
 
@@ -300,38 +352,40 @@ public:
 
   ConcreteInt evalMinus(SValBuilder &svalBuilder) const;
 
-  // Implement isa<T> support.
-  static inline bool classof(const SVal* V) {
-    return V->getBaseKind() == NonLocKind &&
-           V->getSubKind() == ConcreteIntKind;
+private:
+  friend class SVal;
+  ConcreteInt() {}
+  static bool isKind(const SVal& V) {
+    return V.getBaseKind() == NonLocKind &&
+           V.getSubKind() == ConcreteIntKind;
   }
 
-  static inline bool classof(const NonLoc* V) {
-    return V->getSubKind() == ConcreteIntKind;
+  static bool isKind(const NonLoc& V) {
+    return V.getSubKind() == ConcreteIntKind;
   }
 };
 
 class LocAsInteger : public NonLoc {
   friend class ento::SValBuilder;
 
-  explicit LocAsInteger(const std::pair<SVal, uintptr_t>& data) :
-    NonLoc(LocAsIntegerKind, &data) {
-      assert (isa<Loc>(data.first));
-    }
+  explicit LocAsInteger(const std::pair<SVal, uintptr_t> &data)
+      : NonLoc(LocAsIntegerKind, &data) {
+    assert (data.first.getAs<Loc>());
+  }
 
 public:
 
   Loc getLoc() const {
     const std::pair<SVal, uintptr_t> *D =
       static_cast<const std::pair<SVal, uintptr_t> *>(Data);
-    return cast<Loc>(D->first);
+    return D->first.castAs<Loc>();
   }
 
-  const Loc& getPersistentLoc() const {
+  Loc getPersistentLoc() const {
     const std::pair<SVal, uintptr_t> *D =
       static_cast<const std::pair<SVal, uintptr_t> *>(Data);
     const SVal& V = D->first;
-    return cast<Loc>(V);
+    return V.castAs<Loc>();
   }
 
   unsigned getNumBits() const {
@@ -340,14 +394,16 @@ public:
     return D->second;
   }
 
-  // Implement isa<T> support.
-  static inline bool classof(const SVal* V) {
-    return V->getBaseKind() == NonLocKind &&
-           V->getSubKind() == LocAsIntegerKind;
+private:
+  friend class SVal;
+  LocAsInteger() {}
+  static bool isKind(const SVal& V) {
+    return V.getBaseKind() == NonLocKind &&
+           V.getSubKind() == LocAsIntegerKind;
   }
 
-  static inline bool classof(const NonLoc* V) {
-    return V->getSubKind() == LocAsIntegerKind;
+  static bool isKind(const NonLoc& V) {
+    return V.getSubKind() == LocAsIntegerKind;
   }
 };
 
@@ -365,12 +421,15 @@ public:
   iterator begin() const;
   iterator end() const;
 
-  static bool classof(const SVal* V) {
-    return V->getBaseKind() == NonLocKind && V->getSubKind() == CompoundValKind;
+private:
+  friend class SVal;
+  CompoundVal() {}
+  static bool isKind(const SVal& V) {
+    return V.getBaseKind() == NonLocKind && V.getSubKind() == CompoundValKind;
   }
 
-  static bool classof(const NonLoc* V) {
-    return V->getSubKind() == CompoundValKind;
+  static bool isKind(const NonLoc& V) {
+    return V.getSubKind() == CompoundValKind;
   }
 };
 
@@ -384,14 +443,17 @@ public:
     return static_cast<const LazyCompoundValData*>(Data);
   }
   const void *getStore() const;
-  const TypedRegion *getRegion() const;
+  const TypedValueRegion *getRegion() const;
 
-  static bool classof(const SVal *V) {
-    return V->getBaseKind() == NonLocKind &&
-           V->getSubKind() == LazyCompoundValKind;
+private:
+  friend class SVal;
+  LazyCompoundVal() {}
+  static bool isKind(const SVal& V) {
+    return V.getBaseKind() == NonLocKind &&
+           V.getSubKind() == LazyCompoundValKind;
   }
-  static bool classof(const NonLoc *V) {
-    return V->getSubKind() == LazyCompoundValKind;
+  static bool isKind(const NonLoc& V) {
+    return V.getSubKind() == LazyCompoundValKind;
   }
 };
 
@@ -413,12 +475,15 @@ public:
     return static_cast<const LabelDecl*>(Data);
   }
 
-  static inline bool classof(const SVal* V) {
-    return V->getBaseKind() == LocKind && V->getSubKind() == GotoLabelKind;
+private:
+  friend class SVal;
+  GotoLabel() {}
+  static bool isKind(const SVal& V) {
+    return V.getBaseKind() == LocKind && V.getSubKind() == GotoLabelKind;
   }
 
-  static inline bool classof(const Loc* V) {
-    return V->getSubKind() == GotoLabelKind;
+  static bool isKind(const Loc& V) {
+    return V.getSubKind() == GotoLabelKind;
   }
 };
 
@@ -437,7 +502,7 @@ public:
 
   template <typename REGION>
   const REGION* getRegionAs() const {
-    return llvm::dyn_cast<REGION>(getRegion());
+    return dyn_cast<REGION>(getRegion());
   }
 
   inline bool operator==(const MemRegionVal& R) const {
@@ -448,14 +513,16 @@ public:
     return getRegion() != R.getRegion();
   }
 
-  // Implement isa<T> support.
-  static inline bool classof(const SVal* V) {
-    return V->getBaseKind() == LocKind &&
-           V->getSubKind() == MemRegionKind;
+private:
+  friend class SVal;
+  MemRegionVal() {}
+  static bool isKind(const SVal& V) {
+    return V.getBaseKind() == LocKind &&
+           V.getSubKind() == MemRegionKind;
   }
 
-  static inline bool classof(const Loc* V) {
-    return V->getSubKind() == MemRegionKind;
+  static bool isKind(const Loc& V) {
+    return V.getSubKind() == MemRegionKind;
   }
 };
 
@@ -471,19 +538,22 @@ public:
   SVal evalBinOp(BasicValueFactory& BasicVals, BinaryOperator::Opcode Op,
                  const ConcreteInt& R) const;
 
-  // Implement isa<T> support.
-  static inline bool classof(const SVal* V) {
-    return V->getBaseKind() == LocKind &&
-           V->getSubKind() == ConcreteIntKind;
+private:
+  friend class SVal;
+  ConcreteInt() {}
+  static bool isKind(const SVal& V) {
+    return V.getBaseKind() == LocKind &&
+           V.getSubKind() == ConcreteIntKind;
   }
 
-  static inline bool classof(const Loc* V) {
-    return V->getSubKind() == ConcreteIntKind;
+  static bool isKind(const Loc& V) {
+    return V.getSubKind() == ConcreteIntKind;
   }
 };
 
 } // end ento::loc namespace
-} // end GR namespace
+
+} // end ento namespace
 
 } // end clang namespace
 
@@ -494,6 +564,11 @@ static inline raw_ostream &operator<<(raw_ostream &os,
   return os;
 }
 
+template <typename T> struct isPodLike;
+template <> struct isPodLike<clang::ento::SVal> {
+  static const bool value = true;
+};
+
 } // end llvm namespace
 
 #endif