diff options
Diffstat (limited to 'include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h')
-rw-r--r-- | include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h | 242 |
1 files changed, 156 insertions, 86 deletions
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h index c2134cf..1c5519e 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h @@ -16,8 +16,8 @@ #define LLVM_CLANG_GR_RVALUE_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; @@ -69,6 +69,29 @@ protected: public: explicit SVal() : Data(0), 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; @@ -161,29 +184,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) : 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(); } }; @@ -191,61 +217,79 @@ 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(); } + +private: + friend class SVal; + static bool isKind(const SVal& V) { + return V.getBaseKind() == LocKind; + } }; //==------------------------------------------------------------------------==// @@ -266,17 +310,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; } }; @@ -297,38 +344,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 { @@ -337,14 +386,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; } }; @@ -362,12 +413,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; } }; @@ -381,14 +435,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; } }; @@ -410,12 +467,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; } }; @@ -434,7 +494,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 { @@ -445,14 +505,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; } }; @@ -468,19 +530,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 @@ -491,6 +556,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 |