//
//===----------------------------------------------------------------------===//
-#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"
//==------------------------------------------------------------------------==//
class ProgramState;
class BasicValueFactory;
class MemRegion;
-class TypedRegion;
+class TypedValueRegion;
class MemRegionManager;
class ProgramStateManager;
class SValBuilder;
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;
/// 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.
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();
}
};
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;
}
};
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;
}
};
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 {
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;
}
};
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;
}
};
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;
+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
return os;
}
+template <typename T> struct isPodLike;
+template <> struct isPodLike<clang::ento::SVal> {
+ static const bool value = true;
+};
+
} // end llvm namespace
#endif