//
//===----------------------------------------------------------------------===//
-#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/ProgramState_Fwd.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
-#include "llvm/Support/Casting.h"
#include "llvm/ADT/ImmutableList.h"
-namespace llvm {
- class raw_ostream;
-}
-
//==------------------------------------------------------------------------==//
// Base SVal types.
//==------------------------------------------------------------------------==//
class CompoundValData;
class LazyCompoundValData;
-class GRState;
+class ProgramState;
class BasicValueFactory;
class MemRegion;
-class TypedRegion;
+class TypedValueRegion;
class MemRegionManager;
-class GRStateManager;
+class ProgramStateManager;
class SValBuilder;
/// SVal - This represents a symbolic expression, which can be either
enum { BaseBits = 2, BaseMask = 0x3 };
protected:
- const void* Data;
+ const void *Data;
/// The lowest 2 bits are a BaseKind (0 -- 3).
/// The higher bits are an unsigned "kind" value.
unsigned Kind;
-protected:
- explicit SVal(const void* d, bool isLoc, unsigned ValKind)
+ 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) {}
- ~SVal() {}
+ 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 llvm::SmallVector<SVal,5> BufferTy;
+ typedef SmallVector<SVal,5> BufferTy;
inline unsigned getRawKind() const { return Kind; }
inline BaseKind getBaseKind() const { return (BaseKind) (Kind & BaseMask); }
inline unsigned getSubKind() const { return (Kind & ~BaseMask) >> BaseBits; }
+ // This method is required for using SVal in a FoldingSetNode. It
+ // extracts a unique signature for this SVal object.
inline void Profile(llvm::FoldingSetNodeID& ID) const {
ID.AddInteger((unsigned) getRawKind());
ID.AddPointer(Data);
/// getAsFunctionDecl - If this SVal is a MemRegionVal and wraps a
/// CodeTextRegion wrapping a FunctionDecl, return that FunctionDecl.
/// Otherwise return 0.
- const FunctionDecl* getAsFunctionDecl() const;
+ const FunctionDecl *getAsFunctionDecl() const;
- /// getAsLocSymbol - If this SVal is a location (subclasses Loc) and
- /// wraps a symbol, return that SymbolRef. Otherwise return NULL.
- 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;
- /// getAsSymbol - If this Sval wraps a symbol return that SymbolRef.
- /// Otherwise return a SymbolRef where 'isValid()' returns false.
- SymbolRef getAsSymbol() const;
+ /// \brief If this SVal 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 getAsSymbol(bool IncludeBaseRegions = false) const;
/// getAsSymbolicExpression - If this Sval wraps a symbolic expression then
/// return that expression. Otherwise return NULL.
const SymExpr *getAsSymbolicExpression() const;
+ const SymExpr* getAsSymExpr() const;
+
const MemRegion *getAsRegion() const;
- void dumpToStream(llvm::raw_ostream& OS) const;
+ void dumpToStream(raw_ostream &OS) const;
void dump() const;
- // Iterators.
- class symbol_iterator {
- llvm::SmallVector<const SymExpr*, 5> itr;
- void expand();
- public:
- symbol_iterator() {}
- symbol_iterator(const SymExpr* SE);
-
- symbol_iterator& operator++();
- SymbolRef operator*();
-
- bool operator==(const symbol_iterator& X) const;
- bool operator!=(const symbol_iterator& X) const;
- };
-
- symbol_iterator symbol_begin() const {
+ SymExpr::symbol_iterator symbol_begin() const {
const SymExpr *SE = getAsSymbolicExpression();
if (SE)
- return symbol_iterator(SE);
+ return SE->symbol_begin();
else
- return symbol_iterator();
+ return SymExpr::symbol_iterator();
}
- symbol_iterator symbol_end() const { return symbol_iterator(); }
-
- // Implement isa<T> support.
- static inline bool classof(const SVal*) { return true; }
+ SymExpr::symbol_iterator symbol_end() const {
+ return SymExpr::symbol_end();
+ }
};
class UndefinedVal : public SVal {
public:
UndefinedVal() : SVal(UndefinedKind) {}
- UndefinedVal(const void* D) : SVal(UndefinedKind, D) {}
- 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;
}
-
- const void* getData() const { return Data; }
};
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:
- explicit DefinedOrUnknownSVal(const void* d, bool isLoc, unsigned ValKind)
+ 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();
}
};
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:
- explicit DefinedSVal(const void* d, bool isLoc, unsigned ValKind)
+ 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:
- explicit NonLoc(unsigned SubKind, const void* d)
+ NonLoc() {}
+ explicit NonLoc(unsigned SubKind, const void *d)
: DefinedSVal(d, false, SubKind) {}
public:
- void dumpToStream(llvm::raw_ostream& Out) const;
+ 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:
- explicit Loc(unsigned SubKind, const void* D)
+ Loc() {}
+ explicit Loc(unsigned SubKind, const void *D)
: DefinedSVal(const_cast<void*>(D), true, SubKind) {}
public:
- void dumpToStream(llvm::raw_ostream& Out) const;
-
- Loc(const Loc& X) : DefinedSVal(X.Data, true, X.getSubKind()) {}
+ void dumpToStream(raw_ostream &Out) const;
- // 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->isNullPtrType();
}
- 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;
}
};
namespace nonloc {
-enum Kind { ConcreteIntKind, SymbolValKind, SymExprValKind,
+enum Kind { ConcreteIntKind, SymbolValKind,
LocAsIntegerKind, CompoundValKind, LazyCompoundValKind };
+/// \brief Represents symbolic expression.
class SymbolVal : public NonLoc {
public:
SymbolVal(SymbolRef sym) : NonLoc(SymbolValKind, sym) {}
SymbolRef getSymbol() const {
- return (const SymbolData*) Data;
+ return (const SymExpr*) Data;
}
- static inline bool classof(const SVal* V) {
- return V->getBaseKind() == NonLocKind &&
- V->getSubKind() == SymbolValKind;
+ bool isExpression() const {
+ return !isa<SymbolData>(getSymbol());
}
- static inline bool classof(const NonLoc* V) {
- return V->getSubKind() == SymbolValKind;
- }
-};
-
-class SymExprVal : public NonLoc {
-public:
- explicit SymExprVal(const SymExpr *SE)
- : NonLoc(SymExprValKind, reinterpret_cast<const void*>(SE)) {}
-
- const SymExpr *getSymbolicExpression() const {
- return reinterpret_cast<const SymExpr*>(Data);
- }
-
- static inline bool classof(const SVal* V) {
- return V->getBaseKind() == NonLocKind &&
- V->getSubKind() == SymExprValKind;
+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() == SymExprValKind;
+ static bool isKind(const NonLoc& V) {
+ return V.getSubKind() == SymbolValKind;
}
};
+/// \brief Value representing integer constant.
class ConcreteInt : public NonLoc {
public:
explicit ConcreteInt(const llvm::APSInt& V) : NonLoc(ConcreteIntKind, &V) {}
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 {
- return cast<Loc>(((std::pair<SVal, uintptr_t>*) Data)->first);
+ const std::pair<SVal, uintptr_t> *D =
+ static_cast<const std::pair<SVal, uintptr_t> *>(Data);
+ return D->first.castAs<Loc>();
}
- const Loc& getPersistentLoc() const {
- const SVal& V = ((std::pair<SVal, uintptr_t>*) Data)->first;
- return cast<Loc>(V);
+ 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 V.castAs<Loc>();
}
unsigned getNumBits() const {
- return ((std::pair<SVal, unsigned>*) Data)->second;
+ const std::pair<SVal, uintptr_t> *D =
+ static_cast<const std::pair<SVal, uintptr_t> *>(Data);
+ 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;
}
};
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;
}
};
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;
}
};
namespace loc {
-enum Kind { GotoLabelKind, MemRegionKind, ConcreteIntKind, ObjCPropRefKind };
+enum Kind { GotoLabelKind, MemRegionKind, ConcreteIntKind };
class GotoLabel : public Loc {
public:
- explicit GotoLabel(LabelStmt* Label) : Loc(GotoLabelKind, Label) {}
+ explicit GotoLabel(LabelDecl *Label) : Loc(GotoLabelKind, Label) {}
- const LabelStmt* getLabel() const {
- return static_cast<const LabelStmt*>(Data);
+ const LabelDecl *getLabel() const {
+ 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;
}
};
public:
explicit MemRegionVal(const MemRegion* r) : Loc(MemRegionKind, r) {}
+ /// \brief Get the underlining region.
const MemRegion* getRegion() const {
return static_cast<const MemRegion*>(Data);
}
- const MemRegion* StripCasts() const;
+ /// \brief Get the underlining region and strip casts.
+ const MemRegion* stripCasts(bool StripBaseCasts = true) const;
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 {
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;
}
};
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;
- }
-
- static inline bool classof(const Loc* V) {
- return V->getSubKind() == ConcreteIntKind;
- }
-};
-
-/// \brief Pseudo-location SVal used by the ExprEngine to simulate a "load" or
-/// "store" of an ObjC property for the dot syntax.
-class ObjCPropRef : public Loc {
-public:
- explicit ObjCPropRef(const ObjCPropertyRefExpr *E)
- : Loc(ObjCPropRefKind, E) {}
-
- const ObjCPropertyRefExpr *getPropRefExpr() const {
- return static_cast<const ObjCPropertyRefExpr *>(Data);
- }
-
- // Implement isa<T> support.
- static inline bool classof(const SVal* V) {
- return V->getBaseKind() == LocKind &&
- V->getSubKind() == ObjCPropRefKind;
+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() == ObjCPropRefKind;
+ static bool isKind(const Loc& V) {
+ return V.getSubKind() == ConcreteIntKind;
}
};
} // end ento::loc namespace
-} // end GR namespace
+
+} // end ento namespace
} // end clang namespace
namespace llvm {
-static inline llvm::raw_ostream& operator<<(llvm::raw_ostream& os,
+static inline raw_ostream &operator<<(raw_ostream &os,
clang::ento::SVal V) {
V.dumpToStream(os);
return os;
}
+template <typename T> struct isPodLike;
+template <> struct isPodLike<clang::ento::SVal> {
+ static const bool value = true;
+};
+
} // end llvm namespace
#endif