зеркало из https://github.com/microsoft/clang-1.git
Replace SVal llvm::cast support to be well-defined.
See r175462 for another example/more details. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@175594 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
a905c4fd25
Коммит
5251abea41
|
@ -429,11 +429,11 @@ public:
|
|||
geteagerlyAssumeBinOpBifurcationTags();
|
||||
|
||||
SVal evalMinus(SVal X) {
|
||||
return X.isValid() ? svalBuilder.evalMinus(cast<NonLoc>(X)) : X;
|
||||
return X.isValid() ? svalBuilder.evalMinus(X.castAs<NonLoc>()) : X;
|
||||
}
|
||||
|
||||
SVal evalComplement(SVal X) {
|
||||
return X.isValid() ? svalBuilder.evalComplement(cast<NonLoc>(X)) : X;
|
||||
return X.isValid() ? svalBuilder.evalComplement(X.castAs<NonLoc>()) : X;
|
||||
}
|
||||
|
||||
public:
|
||||
|
@ -445,7 +445,8 @@ public:
|
|||
|
||||
SVal evalBinOp(ProgramStateRef state, BinaryOperator::Opcode op,
|
||||
NonLoc L, SVal R, QualType T) {
|
||||
return R.isValid() ? svalBuilder.evalBinOpNN(state,op,L, cast<NonLoc>(R), T) : R;
|
||||
return R.isValid() ? svalBuilder.evalBinOpNN(state, op, L,
|
||||
R.castAs<NonLoc>(), T) : R;
|
||||
}
|
||||
|
||||
SVal evalBinOp(ProgramStateRef ST, BinaryOperator::Opcode Op,
|
||||
|
|
|
@ -991,8 +991,8 @@ class ElementRegion : public TypedValueRegion {
|
|||
ElementRegion(QualType elementType, NonLoc Idx, const MemRegion* sReg)
|
||||
: TypedValueRegion(sReg, ElementRegionKind),
|
||||
ElementType(elementType), Index(Idx) {
|
||||
assert((!isa<nonloc::ConcreteInt>(&Idx) ||
|
||||
cast<nonloc::ConcreteInt>(&Idx)->getValue().isSigned()) &&
|
||||
assert((!Idx.getAs<nonloc::ConcreteInt>() ||
|
||||
Idx.castAs<nonloc::ConcreteInt>().getValue().isSigned()) &&
|
||||
"The index must be signed");
|
||||
}
|
||||
|
||||
|
|
|
@ -620,22 +620,24 @@ inline ProgramStateRef ProgramState::assume(DefinedOrUnknownSVal Cond,
|
|||
bool Assumption) const {
|
||||
if (Cond.isUnknown())
|
||||
return this;
|
||||
|
||||
return getStateManager().ConstraintMgr->assume(this, cast<DefinedSVal>(Cond),
|
||||
Assumption);
|
||||
|
||||
return getStateManager().ConstraintMgr
|
||||
->assume(this, Cond.castAs<DefinedSVal>(), Assumption);
|
||||
}
|
||||
|
||||
inline std::pair<ProgramStateRef , ProgramStateRef >
|
||||
ProgramState::assume(DefinedOrUnknownSVal Cond) const {
|
||||
if (Cond.isUnknown())
|
||||
return std::make_pair(this, this);
|
||||
|
||||
return getStateManager().ConstraintMgr->assumeDual(this,
|
||||
cast<DefinedSVal>(Cond));
|
||||
|
||||
return getStateManager().ConstraintMgr
|
||||
->assumeDual(this, Cond.castAs<DefinedSVal>());
|
||||
}
|
||||
|
||||
inline ProgramStateRef ProgramState::bindLoc(SVal LV, SVal V) const {
|
||||
return !isa<Loc>(LV) ? this : bindLoc(cast<Loc>(LV), V);
|
||||
if (llvm::Optional<Loc> L = LV.getAs<Loc>())
|
||||
return bindLoc(*L, V);
|
||||
return this;
|
||||
}
|
||||
|
||||
inline Loc ProgramState::getLValue(const VarDecl *VD,
|
||||
|
@ -669,7 +671,7 @@ inline SVal ProgramState::getLValue(const IndirectFieldDecl *D,
|
|||
}
|
||||
|
||||
inline SVal ProgramState::getLValue(QualType ElementType, SVal Idx, SVal Base) const{
|
||||
if (NonLoc *N = dyn_cast<NonLoc>(&Idx))
|
||||
if (llvm::Optional<NonLoc> N = Idx.getAs<NonLoc>())
|
||||
return getStateManager().StoreMgr->getLValueElement(ElementType, *N, Base);
|
||||
return UnknownVal();
|
||||
}
|
||||
|
|
|
@ -69,6 +69,25 @@ protected:
|
|||
public:
|
||||
explicit SVal() : Data(0), Kind(0) {}
|
||||
|
||||
template<typename T>
|
||||
T castAs() const {
|
||||
assert(T::isType(*this));
|
||||
T t;
|
||||
SVal& sv = t;
|
||||
sv = *this;
|
||||
return t;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
llvm::Optional<T> getAs() const {
|
||||
if (!T::isType(*this))
|
||||
return llvm::Optional<T>();
|
||||
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,8 +180,10 @@ 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 isType(const SVal& V) {
|
||||
return V.getBaseKind() == UndefinedKind;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -174,16 +195,17 @@ private:
|
|||
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 isType(const SVal& V) {
|
||||
return !V.isUndef();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -191,8 +213,10 @@ 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 isType(const SVal& V) {
|
||||
return V.getBaseKind() == UnknownKind;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -204,46 +228,51 @@ private:
|
|||
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 isType(const SVal& V) {
|
||||
return !V.isUnknownOrUndef();
|
||||
}
|
||||
};
|
||||
|
||||
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 isType(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;
|
||||
|
||||
// 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 isType(const SVal& V) {
|
||||
return V.getBaseKind() == LocKind;
|
||||
}
|
||||
};
|
||||
|
||||
//==------------------------------------------------------------------------==//
|
||||
|
@ -264,17 +293,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 isType(const SVal& V) {
|
||||
return V.getBaseKind() == NonLocKind &&
|
||||
V.getSubKind() == SymbolValKind;
|
||||
}
|
||||
|
||||
static inline bool classof(const NonLoc* V) {
|
||||
return V->getSubKind() == SymbolValKind;
|
||||
static bool isType(const NonLoc& V) {
|
||||
return V.getSubKind() == SymbolValKind;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -295,38 +327,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 isType(const SVal& V) {
|
||||
return V.getBaseKind() == NonLocKind &&
|
||||
V.getSubKind() == ConcreteIntKind;
|
||||
}
|
||||
|
||||
static inline bool classof(const NonLoc* V) {
|
||||
return V->getSubKind() == ConcreteIntKind;
|
||||
static bool isType(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 {
|
||||
|
@ -335,14 +369,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 isType(const SVal& V) {
|
||||
return V.getBaseKind() == NonLocKind &&
|
||||
V.getSubKind() == LocAsIntegerKind;
|
||||
}
|
||||
|
||||
static inline bool classof(const NonLoc* V) {
|
||||
return V->getSubKind() == LocAsIntegerKind;
|
||||
static bool isType(const NonLoc& V) {
|
||||
return V.getSubKind() == LocAsIntegerKind;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -360,12 +396,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 isType(const SVal& V) {
|
||||
return V.getBaseKind() == NonLocKind && V.getSubKind() == CompoundValKind;
|
||||
}
|
||||
|
||||
static bool classof(const NonLoc* V) {
|
||||
return V->getSubKind() == CompoundValKind;
|
||||
static bool isType(const NonLoc& V) {
|
||||
return V.getSubKind() == CompoundValKind;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -381,12 +420,15 @@ public:
|
|||
const void *getStore() 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 isType(const SVal& V) {
|
||||
return V.getBaseKind() == NonLocKind &&
|
||||
V.getSubKind() == LazyCompoundValKind;
|
||||
}
|
||||
static bool classof(const NonLoc *V) {
|
||||
return V->getSubKind() == LazyCompoundValKind;
|
||||
static bool isType(const NonLoc& V) {
|
||||
return V.getSubKind() == LazyCompoundValKind;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -408,12 +450,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 isType(const SVal& V) {
|
||||
return V.getBaseKind() == LocKind && V.getSubKind() == GotoLabelKind;
|
||||
}
|
||||
|
||||
static inline bool classof(const Loc* V) {
|
||||
return V->getSubKind() == GotoLabelKind;
|
||||
static bool isType(const Loc& V) {
|
||||
return V.getSubKind() == GotoLabelKind;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -443,14 +488,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 isType(const SVal& V) {
|
||||
return V.getBaseKind() == LocKind &&
|
||||
V.getSubKind() == MemRegionKind;
|
||||
}
|
||||
|
||||
static inline bool classof(const Loc* V) {
|
||||
return V->getSubKind() == MemRegionKind;
|
||||
static bool isType(const Loc& V) {
|
||||
return V.getSubKind() == MemRegionKind;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -466,14 +513,16 @@ 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 isType(const SVal& V) {
|
||||
return V.getBaseKind() == LocKind &&
|
||||
V.getSubKind() == ConcreteIntKind;
|
||||
}
|
||||
|
||||
static inline bool classof(const Loc* V) {
|
||||
return V->getSubKind() == ConcreteIntKind;
|
||||
static bool isType(const Loc& V) {
|
||||
return V.getSubKind() == ConcreteIntKind;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -53,7 +53,7 @@ public:
|
|||
RegionRawOffsetV2(const SubRegion* base, SVal offset)
|
||||
: baseRegion(base), byteOffset(offset) {}
|
||||
|
||||
NonLoc getByteOffset() const { return cast<NonLoc>(byteOffset); }
|
||||
NonLoc getByteOffset() const { return byteOffset.castAs<NonLoc>(); }
|
||||
const SubRegion *getRegion() const { return baseRegion; }
|
||||
|
||||
static RegionRawOffsetV2 computeOffset(ProgramStateRef state,
|
||||
|
@ -110,13 +110,12 @@ void ArrayBoundCheckerV2::checkLocation(SVal location, bool isLoad,
|
|||
|
||||
SVal extentBegin = computeExtentBegin(svalBuilder, rawOffset.getRegion());
|
||||
|
||||
if (isa<NonLoc>(extentBegin)) {
|
||||
SVal lowerBound
|
||||
= svalBuilder.evalBinOpNN(state, BO_LT, rawOffset.getByteOffset(),
|
||||
cast<NonLoc>(extentBegin),
|
||||
if (llvm::Optional<NonLoc> NV = extentBegin.getAs<NonLoc>()) {
|
||||
SVal lowerBound =
|
||||
svalBuilder.evalBinOpNN(state, BO_LT, rawOffset.getByteOffset(), *NV,
|
||||
svalBuilder.getConditionType());
|
||||
|
||||
NonLoc *lowerBoundToCheck = dyn_cast<NonLoc>(&lowerBound);
|
||||
llvm::Optional<NonLoc> lowerBoundToCheck = lowerBound.getAs<NonLoc>();
|
||||
if (!lowerBoundToCheck)
|
||||
return;
|
||||
|
||||
|
@ -140,15 +139,15 @@ void ArrayBoundCheckerV2::checkLocation(SVal location, bool isLoad,
|
|||
// we are doing a load/store after the last valid offset.
|
||||
DefinedOrUnknownSVal extentVal =
|
||||
rawOffset.getRegion()->getExtent(svalBuilder);
|
||||
if (!isa<NonLoc>(extentVal))
|
||||
if (!extentVal.getAs<NonLoc>())
|
||||
break;
|
||||
|
||||
SVal upperbound
|
||||
= svalBuilder.evalBinOpNN(state, BO_GE, rawOffset.getByteOffset(),
|
||||
cast<NonLoc>(extentVal),
|
||||
extentVal.castAs<NonLoc>(),
|
||||
svalBuilder.getConditionType());
|
||||
|
||||
NonLoc *upperboundToCheck = dyn_cast<NonLoc>(&upperbound);
|
||||
llvm::Optional<NonLoc> upperboundToCheck = upperbound.getAs<NonLoc>();
|
||||
if (!upperboundToCheck)
|
||||
break;
|
||||
|
||||
|
@ -235,7 +234,7 @@ static bool IsCompleteType(ASTContext &Ctx, QualType Ty) {
|
|||
// is unknown or undefined, we lazily substitute '0'. Otherwise,
|
||||
// return 'val'.
|
||||
static inline SVal getValue(SVal val, SValBuilder &svalBuilder) {
|
||||
return isa<UndefinedVal>(val) ? svalBuilder.makeArrayIndex(0) : val;
|
||||
return val.getAs<UndefinedVal>() ? svalBuilder.makeArrayIndex(0) : val;
|
||||
}
|
||||
|
||||
// Scale a base value by a scaling factor, and return the scaled
|
||||
|
@ -256,9 +255,9 @@ static SVal addValue(ProgramStateRef state, SVal x, SVal y,
|
|||
// only care about computing offsets.
|
||||
if (x.isUnknownOrUndef() || y.isUnknownOrUndef())
|
||||
return UnknownVal();
|
||||
|
||||
return svalBuilder.evalBinOpNN(state, BO_Add,
|
||||
cast<NonLoc>(x), cast<NonLoc>(y),
|
||||
|
||||
return svalBuilder.evalBinOpNN(state, BO_Add, x.castAs<NonLoc>(),
|
||||
y.castAs<NonLoc>(),
|
||||
svalBuilder.getArrayIndexType());
|
||||
}
|
||||
|
||||
|
@ -284,7 +283,7 @@ RegionRawOffsetV2 RegionRawOffsetV2::computeOffset(ProgramStateRef state,
|
|||
case MemRegion::ElementRegionKind: {
|
||||
const ElementRegion *elemReg = cast<ElementRegion>(region);
|
||||
SVal index = elemReg->getIndex();
|
||||
if (!isa<NonLoc>(index))
|
||||
if (!index.getAs<NonLoc>())
|
||||
return RegionRawOffsetV2();
|
||||
QualType elemType = elemReg->getElementType();
|
||||
// If the element is an incomplete type, go no further.
|
||||
|
@ -296,7 +295,7 @@ RegionRawOffsetV2 RegionRawOffsetV2::computeOffset(ProgramStateRef state,
|
|||
offset = addValue(state,
|
||||
getValue(offset, svalBuilder),
|
||||
scaleValue(state,
|
||||
cast<NonLoc>(index),
|
||||
index.castAs<NonLoc>(),
|
||||
astContext.getTypeSizeInChars(elemType),
|
||||
svalBuilder),
|
||||
svalBuilder);
|
||||
|
|
|
@ -51,13 +51,13 @@ void AttrNonNullChecker::checkPreCall(const CallEvent &Call,
|
|||
continue;
|
||||
|
||||
SVal V = Call.getArgSVal(idx);
|
||||
DefinedSVal *DV = dyn_cast<DefinedSVal>(&V);
|
||||
llvm::Optional<DefinedSVal> DV = V.getAs<DefinedSVal>();
|
||||
|
||||
// If the value is unknown or undefined, we can't perform this check.
|
||||
if (!DV)
|
||||
continue;
|
||||
|
||||
if (!isa<Loc>(*DV)) {
|
||||
if (!DV->getAs<Loc>()) {
|
||||
// If the argument is a union type, we want to handle a potential
|
||||
// transparent_union GCC extension.
|
||||
const Expr *ArgE = Call.getArgExpr(idx);
|
||||
|
@ -69,11 +69,12 @@ void AttrNonNullChecker::checkPreCall(const CallEvent &Call,
|
|||
if (!UT || !UT->getDecl()->hasAttr<TransparentUnionAttr>())
|
||||
continue;
|
||||
|
||||
if (nonloc::CompoundVal *CSV = dyn_cast<nonloc::CompoundVal>(DV)) {
|
||||
if (llvm::Optional<nonloc::CompoundVal> CSV =
|
||||
DV->getAs<nonloc::CompoundVal>()) {
|
||||
nonloc::CompoundVal::iterator CSV_I = CSV->begin();
|
||||
assert(CSV_I != CSV->end());
|
||||
V = *CSV_I;
|
||||
DV = dyn_cast<DefinedSVal>(&V);
|
||||
DV = V.getAs<DefinedSVal>();
|
||||
assert(++CSV_I == CSV->end());
|
||||
if (!DV)
|
||||
continue;
|
||||
|
|
|
@ -84,7 +84,7 @@ static FoundationClass findKnownClass(const ObjCInterfaceDecl *ID) {
|
|||
}
|
||||
|
||||
static inline bool isNil(SVal X) {
|
||||
return isa<loc::ConcreteInt>(X);
|
||||
return X.getAs<loc::ConcreteInt>();
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -290,7 +290,8 @@ void CFNumberCreateChecker::checkPreStmt(const CallExpr *CE,
|
|||
|
||||
// FIXME: We really should allow ranges of valid theType values, and
|
||||
// bifurcate the state appropriately.
|
||||
nonloc::ConcreteInt* V = dyn_cast<nonloc::ConcreteInt>(&TheTypeVal);
|
||||
llvm::Optional<nonloc::ConcreteInt> V =
|
||||
TheTypeVal.getAs<nonloc::ConcreteInt>();
|
||||
if (!V)
|
||||
return;
|
||||
|
||||
|
@ -308,7 +309,8 @@ void CFNumberCreateChecker::checkPreStmt(const CallExpr *CE,
|
|||
|
||||
// FIXME: Eventually we should handle arbitrary locations. We can do this
|
||||
// by having an enhanced memory model that does low-level typing.
|
||||
loc::MemRegionVal* LV = dyn_cast<loc::MemRegionVal>(&TheValueExpr);
|
||||
llvm::Optional<loc::MemRegionVal> LV =
|
||||
TheValueExpr.getAs<loc::MemRegionVal>();
|
||||
if (!LV)
|
||||
return;
|
||||
|
||||
|
@ -409,13 +411,14 @@ void CFRetainReleaseChecker::checkPreStmt(const CallExpr *CE,
|
|||
// Get the argument's value.
|
||||
const Expr *Arg = CE->getArg(0);
|
||||
SVal ArgVal = state->getSVal(Arg, C.getLocationContext());
|
||||
DefinedSVal *DefArgVal = dyn_cast<DefinedSVal>(&ArgVal);
|
||||
llvm::Optional<DefinedSVal> DefArgVal = ArgVal.getAs<DefinedSVal>();
|
||||
if (!DefArgVal)
|
||||
return;
|
||||
|
||||
// Get a NULL value.
|
||||
SValBuilder &svalBuilder = C.getSValBuilder();
|
||||
DefinedSVal zero = cast<DefinedSVal>(svalBuilder.makeZeroVal(Arg->getType()));
|
||||
DefinedSVal zero =
|
||||
svalBuilder.makeZeroVal(Arg->getType()).castAs<DefinedSVal>();
|
||||
|
||||
// Make an expression asserting that they're equal.
|
||||
DefinedOrUnknownSVal ArgIsNull = svalBuilder.evalEQ(state, zero, *DefArgVal);
|
||||
|
@ -619,7 +622,7 @@ void VariadicMethodTypeChecker::checkPreObjCMessage(const ObjCMethodCall &msg,
|
|||
continue;
|
||||
|
||||
// Ignore pointer constants.
|
||||
if (isa<loc::ConcreteInt>(msg.getArgSVal(I)))
|
||||
if (msg.getArgSVal(I).getAs<loc::ConcreteInt>())
|
||||
continue;
|
||||
|
||||
// Ignore pointer types annotated with 'NSObject' attribute.
|
||||
|
@ -716,12 +719,12 @@ void ObjCLoopChecker::checkPostStmt(const ObjCForCollectionStmt *FCS,
|
|||
ElementVar = State->getSVal(Element, C.getLocationContext());
|
||||
}
|
||||
|
||||
if (!isa<Loc>(ElementVar))
|
||||
if (!ElementVar.getAs<Loc>())
|
||||
return;
|
||||
|
||||
// Go ahead and assume the value is non-nil.
|
||||
SVal Val = State->getSVal(cast<Loc>(ElementVar));
|
||||
State = State->assume(cast<DefinedOrUnknownSVal>(Val), true);
|
||||
SVal Val = State->getSVal(ElementVar.castAs<Loc>());
|
||||
State = State->assume(Val.castAs<DefinedOrUnknownSVal>(), true);
|
||||
C.addTransition(State);
|
||||
}
|
||||
|
||||
|
@ -745,7 +748,8 @@ static ProgramStateRef assumeExprIsNonNull(const Expr *NonNullExpr,
|
|||
ProgramStateRef State,
|
||||
CheckerContext &C) {
|
||||
SVal Val = State->getSVal(NonNullExpr, C.getLocationContext());
|
||||
if (DefinedOrUnknownSVal *DV = dyn_cast<DefinedOrUnknownSVal>(&Val))
|
||||
if (llvm::Optional<DefinedOrUnknownSVal> DV =
|
||||
Val.getAs<DefinedOrUnknownSVal>())
|
||||
return State->assume(*DV, true);
|
||||
return State;
|
||||
}
|
||||
|
|
|
@ -69,7 +69,7 @@ void BoolAssignmentChecker::checkBind(SVal loc, SVal val, const Stmt *S,
|
|||
// Get the value of the right-hand side. We only care about values
|
||||
// that are defined (UnknownVals and UndefinedVals are handled by other
|
||||
// checkers).
|
||||
const DefinedSVal *DV = dyn_cast<DefinedSVal>(&val);
|
||||
llvm::Optional<DefinedSVal> DV = val.getAs<DefinedSVal>();
|
||||
if (!DV)
|
||||
return;
|
||||
|
||||
|
@ -85,10 +85,10 @@ void BoolAssignmentChecker::checkBind(SVal loc, SVal val, const Stmt *S,
|
|||
SVal greaterThanOrEqualToZeroVal =
|
||||
svalBuilder.evalBinOp(state, BO_GE, *DV, zeroVal,
|
||||
svalBuilder.getConditionType());
|
||||
|
||||
DefinedSVal *greaterThanEqualToZero =
|
||||
dyn_cast<DefinedSVal>(&greaterThanOrEqualToZeroVal);
|
||||
|
||||
|
||||
llvm::Optional<DefinedSVal> greaterThanEqualToZero =
|
||||
greaterThanOrEqualToZeroVal.getAs<DefinedSVal>();
|
||||
|
||||
if (!greaterThanEqualToZero) {
|
||||
// The SValBuilder cannot construct a valid SVal for this condition.
|
||||
// This means we cannot properly reason about it.
|
||||
|
@ -121,10 +121,10 @@ void BoolAssignmentChecker::checkBind(SVal loc, SVal val, const Stmt *S,
|
|||
SVal lessThanEqToOneVal =
|
||||
svalBuilder.evalBinOp(state, BO_LE, *DV, OneVal,
|
||||
svalBuilder.getConditionType());
|
||||
|
||||
DefinedSVal *lessThanEqToOne =
|
||||
dyn_cast<DefinedSVal>(&lessThanEqToOneVal);
|
||||
|
||||
|
||||
llvm::Optional<DefinedSVal> lessThanEqToOne =
|
||||
lessThanEqToOneVal.getAs<DefinedSVal>();
|
||||
|
||||
if (!lessThanEqToOne) {
|
||||
// The SValBuilder cannot construct a valid SVal for this condition.
|
||||
// This means we cannot properly reason about it.
|
||||
|
|
|
@ -61,7 +61,7 @@ bool BuiltinFunctionChecker::evalCall(const CallExpr *CE,
|
|||
// SVal of the argument directly. If we save the extent in bits, we
|
||||
// cannot represent values like symbol*8.
|
||||
DefinedOrUnknownSVal Size =
|
||||
cast<DefinedOrUnknownSVal>(state->getSVal(*(CE->arg_begin()), LCtx));
|
||||
state->getSVal(*(CE->arg_begin()), LCtx).castAs<DefinedOrUnknownSVal>();
|
||||
|
||||
SValBuilder& svalBuilder = C.getSValBuilder();
|
||||
DefinedOrUnknownSVal Extent = R->getExtent(svalBuilder);
|
||||
|
|
|
@ -201,7 +201,7 @@ REGISTER_MAP_WITH_PROGRAMSTATE(CStringLength, const MemRegion *, SVal)
|
|||
std::pair<ProgramStateRef , ProgramStateRef >
|
||||
CStringChecker::assumeZero(CheckerContext &C, ProgramStateRef state, SVal V,
|
||||
QualType Ty) {
|
||||
DefinedSVal *val = dyn_cast<DefinedSVal>(&V);
|
||||
llvm::Optional<DefinedSVal> val = V.getAs<DefinedSVal>();
|
||||
if (!val)
|
||||
return std::pair<ProgramStateRef , ProgramStateRef >(state, state);
|
||||
|
||||
|
@ -278,7 +278,7 @@ ProgramStateRef CStringChecker::CheckLocation(CheckerContext &C,
|
|||
SValBuilder &svalBuilder = C.getSValBuilder();
|
||||
SVal Extent =
|
||||
svalBuilder.convertToArrayIndex(superReg->getExtent(svalBuilder));
|
||||
DefinedOrUnknownSVal Size = cast<DefinedOrUnknownSVal>(Extent);
|
||||
DefinedOrUnknownSVal Size = Extent.castAs<DefinedOrUnknownSVal>();
|
||||
|
||||
// Get the index of the accessed element.
|
||||
DefinedOrUnknownSVal Idx = cast<DefinedOrUnknownSVal>(ER->getIndex());
|
||||
|
@ -359,18 +359,18 @@ ProgramStateRef CStringChecker::CheckBufferAccess(CheckerContext &C,
|
|||
// FIXME: This assumes the caller has already checked that the access length
|
||||
// is positive. And that it's unsigned.
|
||||
SVal LengthVal = state->getSVal(Size, LCtx);
|
||||
NonLoc *Length = dyn_cast<NonLoc>(&LengthVal);
|
||||
llvm::Optional<NonLoc> Length = LengthVal.getAs<NonLoc>();
|
||||
if (!Length)
|
||||
return state;
|
||||
|
||||
// Compute the offset of the last element to be accessed: size-1.
|
||||
NonLoc One = cast<NonLoc>(svalBuilder.makeIntVal(1, sizeTy));
|
||||
NonLoc LastOffset = cast<NonLoc>(svalBuilder.evalBinOpNN(state, BO_Sub,
|
||||
*Length, One, sizeTy));
|
||||
NonLoc One = svalBuilder.makeIntVal(1, sizeTy).castAs<NonLoc>();
|
||||
NonLoc LastOffset = svalBuilder
|
||||
.evalBinOpNN(state, BO_Sub, *Length, One, sizeTy).castAs<NonLoc>();
|
||||
|
||||
// Check that the first buffer is sufficiently long.
|
||||
SVal BufStart = svalBuilder.evalCast(BufVal, PtrTy, FirstBuf->getType());
|
||||
if (Loc *BufLoc = dyn_cast<Loc>(&BufStart)) {
|
||||
if (llvm::Optional<Loc> BufLoc = BufStart.getAs<Loc>()) {
|
||||
const Expr *warningExpr = (WarnAboutSize ? Size : FirstBuf);
|
||||
|
||||
SVal BufEnd = svalBuilder.evalBinOpLN(state, BO_Add, *BufLoc,
|
||||
|
@ -390,7 +390,7 @@ ProgramStateRef CStringChecker::CheckBufferAccess(CheckerContext &C,
|
|||
return NULL;
|
||||
|
||||
BufStart = svalBuilder.evalCast(BufVal, PtrTy, SecondBuf->getType());
|
||||
if (Loc *BufLoc = dyn_cast<Loc>(&BufStart)) {
|
||||
if (llvm::Optional<Loc> BufLoc = BufStart.getAs<Loc>()) {
|
||||
const Expr *warningExpr = (WarnAboutSize ? Size : SecondBuf);
|
||||
|
||||
SVal BufEnd = svalBuilder.evalBinOpLN(state, BO_Add, *BufLoc,
|
||||
|
@ -426,11 +426,11 @@ ProgramStateRef CStringChecker::CheckOverlap(CheckerContext &C,
|
|||
SVal firstVal = state->getSVal(First, LCtx);
|
||||
SVal secondVal = state->getSVal(Second, LCtx);
|
||||
|
||||
Loc *firstLoc = dyn_cast<Loc>(&firstVal);
|
||||
llvm::Optional<Loc> firstLoc = firstVal.getAs<Loc>();
|
||||
if (!firstLoc)
|
||||
return state;
|
||||
|
||||
Loc *secondLoc = dyn_cast<Loc>(&secondVal);
|
||||
llvm::Optional<Loc> secondLoc = secondVal.getAs<Loc>();
|
||||
if (!secondLoc)
|
||||
return state;
|
||||
|
||||
|
@ -453,7 +453,8 @@ ProgramStateRef CStringChecker::CheckOverlap(CheckerContext &C,
|
|||
QualType cmpTy = svalBuilder.getConditionType();
|
||||
SVal reverse = svalBuilder.evalBinOpLL(state, BO_GT,
|
||||
*firstLoc, *secondLoc, cmpTy);
|
||||
DefinedOrUnknownSVal *reverseTest = dyn_cast<DefinedOrUnknownSVal>(&reverse);
|
||||
llvm::Optional<DefinedOrUnknownSVal> reverseTest =
|
||||
reverse.getAs<DefinedOrUnknownSVal>();
|
||||
if (!reverseTest)
|
||||
return state;
|
||||
|
||||
|
@ -464,20 +465,16 @@ ProgramStateRef CStringChecker::CheckOverlap(CheckerContext &C,
|
|||
return state;
|
||||
} else {
|
||||
// Switch the values so that firstVal is before secondVal.
|
||||
Loc *tmpLoc = firstLoc;
|
||||
firstLoc = secondLoc;
|
||||
secondLoc = tmpLoc;
|
||||
std::swap(firstLoc, secondLoc);
|
||||
|
||||
// Switch the Exprs as well, so that they still correspond.
|
||||
const Expr *tmpExpr = First;
|
||||
First = Second;
|
||||
Second = tmpExpr;
|
||||
std::swap(First, Second);
|
||||
}
|
||||
}
|
||||
|
||||
// Get the length, and make sure it too is known.
|
||||
SVal LengthVal = state->getSVal(Size, LCtx);
|
||||
NonLoc *Length = dyn_cast<NonLoc>(&LengthVal);
|
||||
llvm::Optional<NonLoc> Length = LengthVal.getAs<NonLoc>();
|
||||
if (!Length)
|
||||
return state;
|
||||
|
||||
|
@ -487,21 +484,22 @@ ProgramStateRef CStringChecker::CheckOverlap(CheckerContext &C,
|
|||
QualType CharPtrTy = Ctx.getPointerType(Ctx.CharTy);
|
||||
SVal FirstStart = svalBuilder.evalCast(*firstLoc, CharPtrTy,
|
||||
First->getType());
|
||||
Loc *FirstStartLoc = dyn_cast<Loc>(&FirstStart);
|
||||
llvm::Optional<Loc> FirstStartLoc = FirstStart.getAs<Loc>();
|
||||
if (!FirstStartLoc)
|
||||
return state;
|
||||
|
||||
// Compute the end of the first buffer. Bail out if THAT fails.
|
||||
SVal FirstEnd = svalBuilder.evalBinOpLN(state, BO_Add,
|
||||
*FirstStartLoc, *Length, CharPtrTy);
|
||||
Loc *FirstEndLoc = dyn_cast<Loc>(&FirstEnd);
|
||||
llvm::Optional<Loc> FirstEndLoc = FirstEnd.getAs<Loc>();
|
||||
if (!FirstEndLoc)
|
||||
return state;
|
||||
|
||||
// Is the end of the first buffer past the start of the second buffer?
|
||||
SVal Overlap = svalBuilder.evalBinOpLL(state, BO_GT,
|
||||
*FirstEndLoc, *secondLoc, cmpTy);
|
||||
DefinedOrUnknownSVal *OverlapTest = dyn_cast<DefinedOrUnknownSVal>(&Overlap);
|
||||
llvm::Optional<DefinedOrUnknownSVal> OverlapTest =
|
||||
Overlap.getAs<DefinedOrUnknownSVal>();
|
||||
if (!OverlapTest)
|
||||
return state;
|
||||
|
||||
|
@ -557,7 +555,7 @@ ProgramStateRef CStringChecker::checkAdditionOverflow(CheckerContext &C,
|
|||
NonLoc maxVal = svalBuilder.makeIntVal(maxValInt);
|
||||
|
||||
SVal maxMinusRight;
|
||||
if (isa<nonloc::ConcreteInt>(right)) {
|
||||
if (right.getAs<nonloc::ConcreteInt>()) {
|
||||
maxMinusRight = svalBuilder.evalBinOpNN(state, BO_Sub, maxVal, right,
|
||||
sizeTy);
|
||||
} else {
|
||||
|
@ -568,7 +566,7 @@ ProgramStateRef CStringChecker::checkAdditionOverflow(CheckerContext &C,
|
|||
left = right;
|
||||
}
|
||||
|
||||
if (NonLoc *maxMinusRightNL = dyn_cast<NonLoc>(&maxMinusRight)) {
|
||||
if (llvm::Optional<NonLoc> maxMinusRightNL = maxMinusRight.getAs<NonLoc>()) {
|
||||
QualType cmpTy = svalBuilder.getConditionType();
|
||||
// If left > max - right, we have an overflow.
|
||||
SVal willOverflow = svalBuilder.evalBinOpNN(state, BO_GT, left,
|
||||
|
@ -576,7 +574,7 @@ ProgramStateRef CStringChecker::checkAdditionOverflow(CheckerContext &C,
|
|||
|
||||
ProgramStateRef stateOverflow, stateOkay;
|
||||
llvm::tie(stateOverflow, stateOkay) =
|
||||
state->assume(cast<DefinedOrUnknownSVal>(willOverflow));
|
||||
state->assume(willOverflow.castAs<DefinedOrUnknownSVal>());
|
||||
|
||||
if (stateOverflow && !stateOkay) {
|
||||
// We have an overflow. Emit a bug report.
|
||||
|
@ -683,7 +681,7 @@ SVal CStringChecker::getCStringLength(CheckerContext &C, ProgramStateRef &state,
|
|||
// If we can't get a region, see if it's something we /know/ isn't a
|
||||
// C string. In the context of locations, the only time we can issue such
|
||||
// a warning is for labels.
|
||||
if (loc::GotoLabel *Label = dyn_cast<loc::GotoLabel>(&Buf)) {
|
||||
if (llvm::Optional<loc::GotoLabel> Label = Buf.getAs<loc::GotoLabel>()) {
|
||||
if (!Filter.CheckCStringNotNullTerm)
|
||||
return UndefinedVal();
|
||||
|
||||
|
@ -798,14 +796,14 @@ const StringLiteral *CStringChecker::getCStringLiteral(CheckerContext &C,
|
|||
ProgramStateRef CStringChecker::InvalidateBuffer(CheckerContext &C,
|
||||
ProgramStateRef state,
|
||||
const Expr *E, SVal V) {
|
||||
Loc *L = dyn_cast<Loc>(&V);
|
||||
llvm::Optional<Loc> L = V.getAs<Loc>();
|
||||
if (!L)
|
||||
return state;
|
||||
|
||||
// FIXME: This is a simplified version of what's in CFRefCount.cpp -- it makes
|
||||
// some assumptions about the value that CFRefCount can't. Even so, it should
|
||||
// probably be refactored.
|
||||
if (loc::MemRegionVal* MR = dyn_cast<loc::MemRegionVal>(L)) {
|
||||
if (llvm::Optional<loc::MemRegionVal> MR = L->getAs<loc::MemRegionVal>()) {
|
||||
const MemRegion *R = MR->getRegion()->StripCasts();
|
||||
|
||||
// Are we dealing with an ElementRegion? If so, we should be invalidating
|
||||
|
@ -929,16 +927,13 @@ void CStringChecker::evalCopyCommon(CheckerContext &C,
|
|||
// If this is mempcpy, get the byte after the last byte copied and
|
||||
// bind the expr.
|
||||
if (IsMempcpy) {
|
||||
loc::MemRegionVal *destRegVal = dyn_cast<loc::MemRegionVal>(&destVal);
|
||||
assert(destRegVal && "Destination should be a known MemRegionVal here");
|
||||
loc::MemRegionVal destRegVal = destVal.castAs<loc::MemRegionVal>();
|
||||
|
||||
// Get the length to copy.
|
||||
NonLoc *lenValNonLoc = dyn_cast<NonLoc>(&sizeVal);
|
||||
|
||||
if (lenValNonLoc) {
|
||||
if (llvm::Optional<NonLoc> lenValNonLoc = sizeVal.getAs<NonLoc>()) {
|
||||
// Get the byte after the last byte copied.
|
||||
SVal lastElement = C.getSValBuilder().evalBinOpLN(state, BO_Add,
|
||||
*destRegVal,
|
||||
destRegVal,
|
||||
*lenValNonLoc,
|
||||
Dest->getType());
|
||||
|
||||
|
@ -1054,9 +1049,9 @@ void CStringChecker::evalMemcmp(CheckerContext &C, const CallExpr *CE) const {
|
|||
// First, get the two buffers' addresses. Another checker will have already
|
||||
// made sure they're not undefined.
|
||||
DefinedOrUnknownSVal LV =
|
||||
cast<DefinedOrUnknownSVal>(state->getSVal(Left, LCtx));
|
||||
state->getSVal(Left, LCtx).castAs<DefinedOrUnknownSVal>();
|
||||
DefinedOrUnknownSVal RV =
|
||||
cast<DefinedOrUnknownSVal>(state->getSVal(Right, LCtx));
|
||||
state->getSVal(Right, LCtx).castAs<DefinedOrUnknownSVal>();
|
||||
|
||||
// See if they are the same.
|
||||
DefinedOrUnknownSVal SameBuf = svalBuilder.evalEQ(state, LV, RV);
|
||||
|
@ -1166,19 +1161,17 @@ void CStringChecker::evalstrLengthCommon(CheckerContext &C, const CallExpr *CE,
|
|||
const Expr *maxlenExpr = CE->getArg(1);
|
||||
SVal maxlenVal = state->getSVal(maxlenExpr, LCtx);
|
||||
|
||||
NonLoc *strLengthNL = dyn_cast<NonLoc>(&strLength);
|
||||
NonLoc *maxlenValNL = dyn_cast<NonLoc>(&maxlenVal);
|
||||
llvm::Optional<NonLoc> strLengthNL = strLength.getAs<NonLoc>();
|
||||
llvm::Optional<NonLoc> maxlenValNL = maxlenVal.getAs<NonLoc>();
|
||||
|
||||
if (strLengthNL && maxlenValNL) {
|
||||
ProgramStateRef stateStringTooLong, stateStringNotTooLong;
|
||||
|
||||
// Check if the strLength is greater than the maxlen.
|
||||
llvm::tie(stateStringTooLong, stateStringNotTooLong) =
|
||||
state->assume(cast<DefinedOrUnknownSVal>
|
||||
(C.getSValBuilder().evalBinOpNN(state, BO_GT,
|
||||
*strLengthNL,
|
||||
*maxlenValNL,
|
||||
cmpTy)));
|
||||
state->assume(C.getSValBuilder().evalBinOpNN(
|
||||
state, BO_GT, *strLengthNL, *maxlenValNL, cmpTy)
|
||||
.castAs<DefinedOrUnknownSVal>());
|
||||
|
||||
if (stateStringTooLong && !stateStringNotTooLong) {
|
||||
// If the string is longer than maxlen, return maxlen.
|
||||
|
@ -1195,28 +1188,24 @@ void CStringChecker::evalstrLengthCommon(CheckerContext &C, const CallExpr *CE,
|
|||
// All we know is the return value is the min of the string length
|
||||
// and the limit. This is better than nothing.
|
||||
result = C.getSValBuilder().conjureSymbolVal(0, CE, LCtx, C.blockCount());
|
||||
NonLoc *resultNL = cast<NonLoc>(&result);
|
||||
NonLoc resultNL = result.castAs<NonLoc>();
|
||||
|
||||
if (strLengthNL) {
|
||||
state = state->assume(cast<DefinedOrUnknownSVal>
|
||||
(C.getSValBuilder().evalBinOpNN(state, BO_LE,
|
||||
*resultNL,
|
||||
*strLengthNL,
|
||||
cmpTy)), true);
|
||||
state = state->assume(C.getSValBuilder().evalBinOpNN(
|
||||
state, BO_LE, resultNL, *strLengthNL, cmpTy)
|
||||
.castAs<DefinedOrUnknownSVal>(), true);
|
||||
}
|
||||
|
||||
if (maxlenValNL) {
|
||||
state = state->assume(cast<DefinedOrUnknownSVal>
|
||||
(C.getSValBuilder().evalBinOpNN(state, BO_LE,
|
||||
*resultNL,
|
||||
*maxlenValNL,
|
||||
cmpTy)), true);
|
||||
state = state->assume(C.getSValBuilder().evalBinOpNN(
|
||||
state, BO_LE, resultNL, *maxlenValNL, cmpTy)
|
||||
.castAs<DefinedOrUnknownSVal>(), true);
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
// This is a plain strlen(), not strnlen().
|
||||
result = cast<DefinedOrUnknownSVal>(strLength);
|
||||
result = strLength.castAs<DefinedOrUnknownSVal>();
|
||||
|
||||
// If we don't know the length of the string, conjure a return
|
||||
// value, so it can be used in constraints, at least.
|
||||
|
@ -1335,8 +1324,8 @@ void CStringChecker::evalStrcpyCommon(CheckerContext &C, const CallExpr *CE,
|
|||
// Protect against misdeclared strncpy().
|
||||
lenVal = svalBuilder.evalCast(lenVal, sizeTy, lenExpr->getType());
|
||||
|
||||
NonLoc *strLengthNL = dyn_cast<NonLoc>(&strLength);
|
||||
NonLoc *lenValNL = dyn_cast<NonLoc>(&lenVal);
|
||||
llvm::Optional<NonLoc> strLengthNL = strLength.getAs<NonLoc>();
|
||||
llvm::Optional<NonLoc> lenValNL = lenVal.getAs<NonLoc>();
|
||||
|
||||
// If we know both values, we might be able to figure out how much
|
||||
// we're copying.
|
||||
|
@ -1346,10 +1335,9 @@ void CStringChecker::evalStrcpyCommon(CheckerContext &C, const CallExpr *CE,
|
|||
// Check if the max number to copy is less than the length of the src.
|
||||
// If the bound is equal to the source length, strncpy won't null-
|
||||
// terminate the result!
|
||||
llvm::tie(stateSourceTooLong, stateSourceNotTooLong) =
|
||||
state->assume(cast<DefinedOrUnknownSVal>
|
||||
(svalBuilder.evalBinOpNN(state, BO_GE, *strLengthNL,
|
||||
*lenValNL, cmpTy)));
|
||||
llvm::tie(stateSourceTooLong, stateSourceNotTooLong) = state->assume(
|
||||
svalBuilder.evalBinOpNN(state, BO_GE, *strLengthNL, *lenValNL, cmpTy)
|
||||
.castAs<DefinedOrUnknownSVal>());
|
||||
|
||||
if (stateSourceTooLong && !stateSourceNotTooLong) {
|
||||
// Max number to copy is less than the length of the src, so the actual
|
||||
|
@ -1376,7 +1364,8 @@ void CStringChecker::evalStrcpyCommon(CheckerContext &C, const CallExpr *CE,
|
|||
if (dstStrLength.isUndef())
|
||||
return;
|
||||
|
||||
if (NonLoc *dstStrLengthNL = dyn_cast<NonLoc>(&dstStrLength)) {
|
||||
if (llvm::Optional<NonLoc> dstStrLengthNL =
|
||||
dstStrLength.getAs<NonLoc>()) {
|
||||
maxLastElementIndex = svalBuilder.evalBinOpNN(state, BO_Add,
|
||||
*lenValNL,
|
||||
*dstStrLengthNL,
|
||||
|
@ -1407,7 +1396,7 @@ void CStringChecker::evalStrcpyCommon(CheckerContext &C, const CallExpr *CE,
|
|||
// Otherwise, go ahead and figure out the last element we'll touch.
|
||||
// We don't record the non-zero assumption here because we can't
|
||||
// be sure. We won't warn on a possible zero.
|
||||
NonLoc one = cast<NonLoc>(svalBuilder.makeIntVal(1, sizeTy));
|
||||
NonLoc one = svalBuilder.makeIntVal(1, sizeTy).castAs<NonLoc>();
|
||||
maxLastElementIndex = svalBuilder.evalBinOpNN(state, BO_Sub, *lenValNL,
|
||||
one, sizeTy);
|
||||
boundWarning = "Size argument is greater than the length of the "
|
||||
|
@ -1425,15 +1414,16 @@ void CStringChecker::evalStrcpyCommon(CheckerContext &C, const CallExpr *CE,
|
|||
amountCopied = getCStringLength(C, state, lenExpr, srcVal, true);
|
||||
assert(!amountCopied.isUndef());
|
||||
|
||||
if (NonLoc *amountCopiedNL = dyn_cast<NonLoc>(&amountCopied)) {
|
||||
if (llvm::Optional<NonLoc> amountCopiedNL =
|
||||
amountCopied.getAs<NonLoc>()) {
|
||||
if (lenValNL) {
|
||||
// amountCopied <= lenVal
|
||||
SVal copiedLessThanBound = svalBuilder.evalBinOpNN(state, BO_LE,
|
||||
*amountCopiedNL,
|
||||
*lenValNL,
|
||||
cmpTy);
|
||||
state = state->assume(cast<DefinedOrUnknownSVal>(copiedLessThanBound),
|
||||
true);
|
||||
state = state->assume(
|
||||
copiedLessThanBound.castAs<DefinedOrUnknownSVal>(), true);
|
||||
if (!state)
|
||||
return;
|
||||
}
|
||||
|
@ -1444,8 +1434,8 @@ void CStringChecker::evalStrcpyCommon(CheckerContext &C, const CallExpr *CE,
|
|||
*amountCopiedNL,
|
||||
*strLengthNL,
|
||||
cmpTy);
|
||||
state = state->assume(cast<DefinedOrUnknownSVal>(copiedLessThanSrc),
|
||||
true);
|
||||
state = state->assume(
|
||||
copiedLessThanSrc.castAs<DefinedOrUnknownSVal>(), true);
|
||||
if (!state)
|
||||
return;
|
||||
}
|
||||
|
@ -1475,8 +1465,8 @@ void CStringChecker::evalStrcpyCommon(CheckerContext &C, const CallExpr *CE,
|
|||
if (dstStrLength.isUndef())
|
||||
return;
|
||||
|
||||
NonLoc *srcStrLengthNL = dyn_cast<NonLoc>(&amountCopied);
|
||||
NonLoc *dstStrLengthNL = dyn_cast<NonLoc>(&dstStrLength);
|
||||
llvm::Optional<NonLoc> srcStrLengthNL = amountCopied.getAs<NonLoc>();
|
||||
llvm::Optional<NonLoc> dstStrLengthNL = dstStrLength.getAs<NonLoc>();
|
||||
|
||||
// If we know both string lengths, we might know the final string length.
|
||||
if (srcStrLengthNL && dstStrLengthNL) {
|
||||
|
@ -1497,14 +1487,15 @@ void CStringChecker::evalStrcpyCommon(CheckerContext &C, const CallExpr *CE,
|
|||
finalStrLength = getCStringLength(C, state, CE, DstVal, true);
|
||||
assert(!finalStrLength.isUndef());
|
||||
|
||||
if (NonLoc *finalStrLengthNL = dyn_cast<NonLoc>(&finalStrLength)) {
|
||||
if (llvm::Optional<NonLoc> finalStrLengthNL =
|
||||
finalStrLength.getAs<NonLoc>()) {
|
||||
if (srcStrLengthNL) {
|
||||
// finalStrLength >= srcStrLength
|
||||
SVal sourceInResult = svalBuilder.evalBinOpNN(state, BO_GE,
|
||||
*finalStrLengthNL,
|
||||
*srcStrLengthNL,
|
||||
cmpTy);
|
||||
state = state->assume(cast<DefinedOrUnknownSVal>(sourceInResult),
|
||||
state = state->assume(sourceInResult.castAs<DefinedOrUnknownSVal>(),
|
||||
true);
|
||||
if (!state)
|
||||
return;
|
||||
|
@ -1516,8 +1507,8 @@ void CStringChecker::evalStrcpyCommon(CheckerContext &C, const CallExpr *CE,
|
|||
*finalStrLengthNL,
|
||||
*dstStrLengthNL,
|
||||
cmpTy);
|
||||
state = state->assume(cast<DefinedOrUnknownSVal>(destInResult),
|
||||
true);
|
||||
state =
|
||||
state->assume(destInResult.castAs<DefinedOrUnknownSVal>(), true);
|
||||
if (!state)
|
||||
return;
|
||||
}
|
||||
|
@ -1538,13 +1529,15 @@ void CStringChecker::evalStrcpyCommon(CheckerContext &C, const CallExpr *CE,
|
|||
|
||||
// If the destination is a MemRegion, try to check for a buffer overflow and
|
||||
// record the new string length.
|
||||
if (loc::MemRegionVal *dstRegVal = dyn_cast<loc::MemRegionVal>(&DstVal)) {
|
||||
if (llvm::Optional<loc::MemRegionVal> dstRegVal =
|
||||
DstVal.getAs<loc::MemRegionVal>()) {
|
||||
QualType ptrTy = Dst->getType();
|
||||
|
||||
// If we have an exact value on a bounded copy, use that to check for
|
||||
// overflows, rather than our estimate about how much is actually copied.
|
||||
if (boundWarning) {
|
||||
if (NonLoc *maxLastNL = dyn_cast<NonLoc>(&maxLastElementIndex)) {
|
||||
if (llvm::Optional<NonLoc> maxLastNL =
|
||||
maxLastElementIndex.getAs<NonLoc>()) {
|
||||
SVal maxLastElement = svalBuilder.evalBinOpLN(state, BO_Add, *dstRegVal,
|
||||
*maxLastNL, ptrTy);
|
||||
state = CheckLocation(C, state, CE->getArg(2), maxLastElement,
|
||||
|
@ -1555,7 +1548,8 @@ void CStringChecker::evalStrcpyCommon(CheckerContext &C, const CallExpr *CE,
|
|||
}
|
||||
|
||||
// Then, if the final length is known...
|
||||
if (NonLoc *knownStrLength = dyn_cast<NonLoc>(&finalStrLength)) {
|
||||
if (llvm::Optional<NonLoc> knownStrLength =
|
||||
finalStrLength.getAs<NonLoc>()) {
|
||||
SVal lastElement = svalBuilder.evalBinOpLN(state, BO_Add, *dstRegVal,
|
||||
*knownStrLength, ptrTy);
|
||||
|
||||
|
@ -1673,8 +1667,8 @@ void CStringChecker::evalStrcmpCommon(CheckerContext &C, const CallExpr *CE,
|
|||
// If we know the two buffers are the same, we know the result is 0.
|
||||
// First, get the two buffers' addresses. Another checker will have already
|
||||
// made sure they're not undefined.
|
||||
DefinedOrUnknownSVal LV = cast<DefinedOrUnknownSVal>(s1Val);
|
||||
DefinedOrUnknownSVal RV = cast<DefinedOrUnknownSVal>(s2Val);
|
||||
DefinedOrUnknownSVal LV = s1Val.castAs<DefinedOrUnknownSVal>();
|
||||
DefinedOrUnknownSVal RV = s2Val.castAs<DefinedOrUnknownSVal>();
|
||||
|
||||
// See if they are the same.
|
||||
SValBuilder &svalBuilder = C.getSValBuilder();
|
||||
|
@ -1859,8 +1853,8 @@ void CStringChecker::checkPreStmt(const DeclStmt *DS, CheckerContext &C) const {
|
|||
|
||||
SVal StrVal = state->getSVal(Init, C.getLocationContext());
|
||||
assert(StrVal.isValid() && "Initializer string is unknown or undefined");
|
||||
DefinedOrUnknownSVal strLength
|
||||
= cast<DefinedOrUnknownSVal>(getCStringLength(C, state, Init, StrVal));
|
||||
DefinedOrUnknownSVal strLength =
|
||||
getCStringLength(C, state, Init, StrVal).castAs<DefinedOrUnknownSVal>();
|
||||
|
||||
state = state->set<CStringLength>(MR, strLength);
|
||||
}
|
||||
|
|
|
@ -133,9 +133,9 @@ bool CallAndMessageChecker::PreVisitProcessArg(CheckerContext &C,
|
|||
|
||||
if (!checkUninitFields)
|
||||
return false;
|
||||
|
||||
if (const nonloc::LazyCompoundVal *LV =
|
||||
dyn_cast<nonloc::LazyCompoundVal>(&V)) {
|
||||
|
||||
if (llvm::Optional<nonloc::LazyCompoundVal> LV =
|
||||
V.getAs<nonloc::LazyCompoundVal>()) {
|
||||
|
||||
class FindUninitializedField {
|
||||
public:
|
||||
|
@ -236,7 +236,8 @@ void CallAndMessageChecker::checkPreStmt(const CallExpr *CE,
|
|||
}
|
||||
|
||||
ProgramStateRef StNonNull, StNull;
|
||||
llvm::tie(StNonNull, StNull) = State->assume(cast<DefinedOrUnknownSVal>(L));
|
||||
llvm::tie(StNonNull, StNull) =
|
||||
State->assume(L.castAs<DefinedOrUnknownSVal>());
|
||||
|
||||
if (StNull && !StNonNull) {
|
||||
if (!BT_call_null)
|
||||
|
@ -265,7 +266,8 @@ void CallAndMessageChecker::checkPreCall(const CallEvent &Call,
|
|||
}
|
||||
|
||||
ProgramStateRef StNonNull, StNull;
|
||||
llvm::tie(StNonNull, StNull) = State->assume(cast<DefinedOrUnknownSVal>(V));
|
||||
llvm::tie(StNonNull, StNull) =
|
||||
State->assume(V.castAs<DefinedOrUnknownSVal>());
|
||||
|
||||
if (StNull && !StNonNull) {
|
||||
if (!BT_cxx_call_null)
|
||||
|
@ -344,7 +346,7 @@ void CallAndMessageChecker::checkPreObjCMessage(const ObjCMethodCall &msg,
|
|||
return;
|
||||
} else {
|
||||
// Bifurcate the state into nil and non-nil ones.
|
||||
DefinedOrUnknownSVal receiverVal = cast<DefinedOrUnknownSVal>(recVal);
|
||||
DefinedOrUnknownSVal receiverVal = recVal.castAs<DefinedOrUnknownSVal>();
|
||||
|
||||
ProgramStateRef state = C.getState();
|
||||
ProgramStateRef notNilState, nilState;
|
||||
|
|
|
@ -183,10 +183,10 @@ void DereferenceChecker::checkLocation(SVal l, bool isLoad, const Stmt* S,
|
|||
return;
|
||||
}
|
||||
|
||||
DefinedOrUnknownSVal location = cast<DefinedOrUnknownSVal>(l);
|
||||
DefinedOrUnknownSVal location = l.castAs<DefinedOrUnknownSVal>();
|
||||
|
||||
// Check for null dereferences.
|
||||
if (!isa<Loc>(location))
|
||||
if (!location.getAs<Loc>())
|
||||
return;
|
||||
|
||||
ProgramStateRef state = C.getState();
|
||||
|
@ -231,7 +231,8 @@ void DereferenceChecker::checkBind(SVal L, SVal V, const Stmt *S,
|
|||
ProgramStateRef State = C.getState();
|
||||
|
||||
ProgramStateRef StNonNull, StNull;
|
||||
llvm::tie(StNonNull, StNull) = State->assume(cast<DefinedOrUnknownSVal>(V));
|
||||
llvm::tie(StNonNull, StNull) =
|
||||
State->assume(V.castAs<DefinedOrUnknownSVal>());
|
||||
|
||||
if (StNull) {
|
||||
if (!StNonNull) {
|
||||
|
|
|
@ -58,7 +58,7 @@ void DivZeroChecker::checkPreStmt(const BinaryOperator *B,
|
|||
return;
|
||||
|
||||
SVal Denom = C.getState()->getSVal(B->getRHS(), C.getLocationContext());
|
||||
const DefinedSVal *DV = dyn_cast<DefinedSVal>(&Denom);
|
||||
llvm::Optional<DefinedSVal> DV = Denom.getAs<DefinedSVal>();
|
||||
|
||||
// Divide-by-undefined handled in the generic checking for uses of
|
||||
// undefined values.
|
||||
|
|
|
@ -65,7 +65,7 @@ static const char *getArgumentValueString(const CallExpr *CE,
|
|||
|
||||
ProgramStateRef StTrue, StFalse;
|
||||
llvm::tie(StTrue, StFalse) =
|
||||
State->assume(cast<DefinedOrUnknownSVal>(AssertionVal));
|
||||
State->assume(AssertionVal.castAs<DefinedOrUnknownSVal>());
|
||||
|
||||
if (StTrue) {
|
||||
if (StFalse)
|
||||
|
|
|
@ -431,7 +431,7 @@ SymbolRef GenericTaintChecker::getPointedToSymbol(CheckerContext &C,
|
|||
if (AddrVal.isUnknownOrUndef())
|
||||
return 0;
|
||||
|
||||
Loc *AddrLoc = dyn_cast<Loc>(&AddrVal);
|
||||
llvm::Optional<Loc> AddrLoc = AddrVal.getAs<Loc>();
|
||||
if (!AddrLoc)
|
||||
return 0;
|
||||
|
||||
|
|
|
@ -173,11 +173,11 @@ void IdempotentOperationChecker::checkPreStmt(const BinaryOperator *B,
|
|||
case BO_ShrAssign:
|
||||
case BO_Assign:
|
||||
// Assign statements have one extra level of indirection
|
||||
if (!isa<Loc>(LHSVal)) {
|
||||
if (!LHSVal.getAs<Loc>()) {
|
||||
A = Impossible;
|
||||
return;
|
||||
}
|
||||
LHSVal = state->getSVal(cast<Loc>(LHSVal), LHS->getType());
|
||||
LHSVal = state->getSVal(LHSVal.castAs<Loc>(), LHS->getType());
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -217,7 +217,7 @@ static SymbolRef getAsPointeeSymbol(const Expr *Expr,
|
|||
ProgramStateRef State = C.getState();
|
||||
SVal ArgV = State->getSVal(Expr, C.getLocationContext());
|
||||
|
||||
if (const loc::MemRegionVal *X = dyn_cast<loc::MemRegionVal>(&ArgV)) {
|
||||
if (llvm::Optional<loc::MemRegionVal> X = ArgV.getAs<loc::MemRegionVal>()) {
|
||||
StoreManager& SM = C.getStoreManager();
|
||||
SymbolRef sym = SM.getBinding(State->getStore(), *X).getAsLocSymbol();
|
||||
if (sym)
|
||||
|
@ -421,7 +421,7 @@ void MacOSKeychainAPIChecker::checkPreStmt(const CallExpr *CE,
|
|||
|
||||
// If the buffer can be null and the return status can be an error,
|
||||
// report a bad call to free.
|
||||
if (State->assume(cast<DefinedSVal>(ArgSVal), false) &&
|
||||
if (State->assume(ArgSVal.castAs<DefinedSVal>(), false) &&
|
||||
!definitelyDidnotReturnError(AS->Region, State, C.getSValBuilder())) {
|
||||
ExplodedNode *N = C.addTransition(State);
|
||||
if (!N)
|
||||
|
|
|
@ -555,12 +555,12 @@ ProgramStateRef MallocChecker::MallocMemAux(CheckerContext &C,
|
|||
unsigned Count = C.blockCount();
|
||||
SValBuilder &svalBuilder = C.getSValBuilder();
|
||||
const LocationContext *LCtx = C.getPredecessor()->getLocationContext();
|
||||
DefinedSVal RetVal =
|
||||
cast<DefinedSVal>(svalBuilder.getConjuredHeapSymbolVal(CE, LCtx, Count));
|
||||
DefinedSVal RetVal = svalBuilder.getConjuredHeapSymbolVal(CE, LCtx, Count)
|
||||
.castAs<DefinedSVal>();
|
||||
state = state->BindExpr(CE, C.getLocationContext(), RetVal);
|
||||
|
||||
// We expect the malloc functions to return a pointer.
|
||||
if (!isa<Loc>(RetVal))
|
||||
if (!RetVal.getAs<Loc>())
|
||||
return 0;
|
||||
|
||||
// Fill the region with the initialization value.
|
||||
|
@ -571,12 +571,12 @@ ProgramStateRef MallocChecker::MallocMemAux(CheckerContext &C,
|
|||
dyn_cast_or_null<SymbolicRegion>(RetVal.getAsRegion());
|
||||
if (!R)
|
||||
return 0;
|
||||
if (isa<DefinedOrUnknownSVal>(Size)) {
|
||||
if (llvm::Optional<DefinedOrUnknownSVal> DefinedSize =
|
||||
Size.getAs<DefinedOrUnknownSVal>()) {
|
||||
SValBuilder &svalBuilder = C.getSValBuilder();
|
||||
DefinedOrUnknownSVal Extent = R->getExtent(svalBuilder);
|
||||
DefinedOrUnknownSVal DefinedSize = cast<DefinedOrUnknownSVal>(Size);
|
||||
DefinedOrUnknownSVal extentMatchesSize =
|
||||
svalBuilder.evalEQ(state, Extent, DefinedSize);
|
||||
svalBuilder.evalEQ(state, Extent, *DefinedSize);
|
||||
|
||||
state = state->assume(extentMatchesSize, true);
|
||||
assert(state);
|
||||
|
@ -592,7 +592,7 @@ ProgramStateRef MallocChecker::MallocUpdateRefState(CheckerContext &C,
|
|||
SVal retVal = state->getSVal(CE, C.getLocationContext());
|
||||
|
||||
// We expect the malloc functions to return a pointer.
|
||||
if (!isa<Loc>(retVal))
|
||||
if (!retVal.getAs<Loc>())
|
||||
return 0;
|
||||
|
||||
SymbolRef Sym = retVal.getAsLocSymbol();
|
||||
|
@ -661,12 +661,12 @@ ProgramStateRef MallocChecker::FreeMemAux(CheckerContext &C,
|
|||
bool ReturnsNullOnFailure) const {
|
||||
|
||||
SVal ArgVal = State->getSVal(ArgExpr, C.getLocationContext());
|
||||
if (!isa<DefinedOrUnknownSVal>(ArgVal))
|
||||
if (!ArgVal.getAs<DefinedOrUnknownSVal>())
|
||||
return 0;
|
||||
DefinedOrUnknownSVal location = cast<DefinedOrUnknownSVal>(ArgVal);
|
||||
DefinedOrUnknownSVal location = ArgVal.castAs<DefinedOrUnknownSVal>();
|
||||
|
||||
// Check for null dereferences.
|
||||
if (!isa<Loc>(location))
|
||||
if (!location.getAs<Loc>())
|
||||
return 0;
|
||||
|
||||
// The explicit NULL case, no operation is performed.
|
||||
|
@ -782,11 +782,13 @@ ProgramStateRef MallocChecker::FreeMemAux(CheckerContext &C,
|
|||
}
|
||||
|
||||
bool MallocChecker::SummarizeValue(raw_ostream &os, SVal V) {
|
||||
if (nonloc::ConcreteInt *IntVal = dyn_cast<nonloc::ConcreteInt>(&V))
|
||||
if (llvm::Optional<nonloc::ConcreteInt> IntVal =
|
||||
V.getAs<nonloc::ConcreteInt>())
|
||||
os << "an integer (" << IntVal->getValue() << ")";
|
||||
else if (loc::ConcreteInt *ConstAddr = dyn_cast<loc::ConcreteInt>(&V))
|
||||
else if (llvm::Optional<loc::ConcreteInt> ConstAddr =
|
||||
V.getAs<loc::ConcreteInt>())
|
||||
os << "a constant address (" << ConstAddr->getValue() << ")";
|
||||
else if (loc::GotoLabel *Label = dyn_cast<loc::GotoLabel>(&V))
|
||||
else if (llvm::Optional<loc::GotoLabel> Label = V.getAs<loc::GotoLabel>())
|
||||
os << "the address of the label '" << Label->getLabel()->getName() << "'";
|
||||
else
|
||||
return false;
|
||||
|
@ -952,9 +954,9 @@ ProgramStateRef MallocChecker::ReallocMem(CheckerContext &C,
|
|||
const Expr *arg0Expr = CE->getArg(0);
|
||||
const LocationContext *LCtx = C.getLocationContext();
|
||||
SVal Arg0Val = state->getSVal(arg0Expr, LCtx);
|
||||
if (!isa<DefinedOrUnknownSVal>(Arg0Val))
|
||||
if (!Arg0Val.getAs<DefinedOrUnknownSVal>())
|
||||
return 0;
|
||||
DefinedOrUnknownSVal arg0Val = cast<DefinedOrUnknownSVal>(Arg0Val);
|
||||
DefinedOrUnknownSVal arg0Val = Arg0Val.castAs<DefinedOrUnknownSVal>();
|
||||
|
||||
SValBuilder &svalBuilder = C.getSValBuilder();
|
||||
|
||||
|
@ -968,9 +970,9 @@ ProgramStateRef MallocChecker::ReallocMem(CheckerContext &C,
|
|||
|
||||
// Get the value of the size argument.
|
||||
SVal Arg1ValG = state->getSVal(Arg1, LCtx);
|
||||
if (!isa<DefinedOrUnknownSVal>(Arg1ValG))
|
||||
if (!Arg1ValG.getAs<DefinedOrUnknownSVal>())
|
||||
return 0;
|
||||
DefinedOrUnknownSVal Arg1Val = cast<DefinedOrUnknownSVal>(Arg1ValG);
|
||||
DefinedOrUnknownSVal Arg1Val = Arg1ValG.castAs<DefinedOrUnknownSVal>();
|
||||
|
||||
// Compare the size argument to 0.
|
||||
DefinedOrUnknownSVal SizeZero =
|
||||
|
|
|
@ -186,7 +186,7 @@ static void setFlag(ProgramStateRef state, SVal val, CheckerContext &C) {
|
|||
static QualType parameterTypeFromSVal(SVal val, CheckerContext &C) {
|
||||
const StackFrameContext *
|
||||
SFC = C.getLocationContext()->getCurrentStackFrame();
|
||||
if (const loc::MemRegionVal* X = dyn_cast<loc::MemRegionVal>(&val)) {
|
||||
if (llvm::Optional<loc::MemRegionVal> X = val.getAs<loc::MemRegionVal>()) {
|
||||
const MemRegion* R = X->getRegion();
|
||||
if (const VarRegion *VR = R->getAs<VarRegion>())
|
||||
if (const StackArgumentsSpaceRegion *
|
||||
|
@ -203,7 +203,7 @@ void NSOrCFErrorDerefChecker::checkLocation(SVal loc, bool isLoad,
|
|||
CheckerContext &C) const {
|
||||
if (!isLoad)
|
||||
return;
|
||||
if (loc.isUndef() || !isa<Loc>(loc))
|
||||
if (loc.isUndef() || !loc.getAs<Loc>())
|
||||
return;
|
||||
|
||||
ASTContext &Ctx = C.getASTContext();
|
||||
|
@ -225,12 +225,12 @@ void NSOrCFErrorDerefChecker::checkLocation(SVal loc, bool isLoad,
|
|||
CFErrorII = &Ctx.Idents.get("CFErrorRef");
|
||||
|
||||
if (ShouldCheckNSError && IsNSError(parmT, NSErrorII)) {
|
||||
setFlag<NSErrorOut>(state, state->getSVal(cast<Loc>(loc)), C);
|
||||
setFlag<NSErrorOut>(state, state->getSVal(loc.castAs<Loc>()), C);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ShouldCheckCFError && IsCFError(parmT, CFErrorII)) {
|
||||
setFlag<CFErrorOut>(state, state->getSVal(cast<Loc>(loc)), C);
|
||||
setFlag<CFErrorOut>(state, state->getSVal(loc.castAs<Loc>()), C);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,7 +42,7 @@ void ObjCAtSyncChecker::checkPreStmt(const ObjCAtSynchronizedStmt *S,
|
|||
SVal V = state->getSVal(Ex, C.getLocationContext());
|
||||
|
||||
// Uninitialized value used for the mutex?
|
||||
if (isa<UndefinedVal>(V)) {
|
||||
if (V.getAs<UndefinedVal>()) {
|
||||
if (ExplodedNode *N = C.generateSink()) {
|
||||
if (!BT_undef)
|
||||
BT_undef.reset(new BuiltinBug("Uninitialized value used as mutex "
|
||||
|
@ -60,7 +60,7 @@ void ObjCAtSyncChecker::checkPreStmt(const ObjCAtSynchronizedStmt *S,
|
|||
|
||||
// Check for null mutexes.
|
||||
ProgramStateRef notNullState, nullState;
|
||||
llvm::tie(notNullState, nullState) = state->assume(cast<DefinedSVal>(V));
|
||||
llvm::tie(notNullState, nullState) = state->assume(V.castAs<DefinedSVal>());
|
||||
|
||||
if (nullState) {
|
||||
if (!notNullState) {
|
||||
|
|
|
@ -72,7 +72,8 @@ void ObjCContainersChecker::addSizeInfo(const Expr *Array, const Expr *Size,
|
|||
if (!ArraySym)
|
||||
return;
|
||||
|
||||
C.addTransition(State->set<ArraySizeMap>(ArraySym, cast<DefinedSVal>(SizeV)));
|
||||
C.addTransition(
|
||||
State->set<ArraySizeMap>(ArraySym, SizeV.castAs<DefinedSVal>()));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -125,7 +126,7 @@ void ObjCContainersChecker::checkPreStmt(const CallExpr *CE,
|
|||
SVal IdxVal = State->getSVal(IdxExpr, C.getLocationContext());
|
||||
if (IdxVal.isUnknownOrUndef())
|
||||
return;
|
||||
DefinedSVal Idx = cast<DefinedSVal>(IdxVal);
|
||||
DefinedSVal Idx = IdxVal.castAs<DefinedSVal>();
|
||||
|
||||
// Now, check if 'Idx in [0, Size-1]'.
|
||||
const QualType T = IdxExpr->getType();
|
||||
|
|
|
@ -255,7 +255,7 @@ void ObjCSelfInitChecker::checkPreCall(const CallEvent &CE,
|
|||
for (unsigned i = 0; i < NumArgs; ++i) {
|
||||
SVal argV = CE.getArgSVal(i);
|
||||
if (isSelfVar(argV, C)) {
|
||||
unsigned selfFlags = getSelfFlags(state->getSVal(cast<Loc>(argV)), C);
|
||||
unsigned selfFlags = getSelfFlags(state->getSVal(argV.castAs<Loc>()), C);
|
||||
C.addTransition(state->set<PreCallSelfFlags>(selfFlags));
|
||||
return;
|
||||
} else if (hasSelfFlag(argV, SelfFlag_Self, C)) {
|
||||
|
@ -286,7 +286,7 @@ void ObjCSelfInitChecker::checkPostCall(const CallEvent &CE,
|
|||
// If the address of 'self' is being passed to the call, assume that the
|
||||
// 'self' after the call will have the same flags.
|
||||
// EX: log(&self)
|
||||
addSelfFlag(state, state->getSVal(cast<Loc>(argV)), prevFlags, C);
|
||||
addSelfFlag(state, state->getSVal(argV.castAs<Loc>()), prevFlags, C);
|
||||
return;
|
||||
} else if (hasSelfFlag(argV, SelfFlag_Self, C)) {
|
||||
// If 'self' is passed to the call by value, assume that the function
|
||||
|
@ -312,7 +312,8 @@ void ObjCSelfInitChecker::checkLocation(SVal location, bool isLoad,
|
|||
// value is the object that 'self' points to.
|
||||
ProgramStateRef state = C.getState();
|
||||
if (isSelfVar(location, C))
|
||||
addSelfFlag(state, state->getSVal(cast<Loc>(location)), SelfFlag_Self, C);
|
||||
addSelfFlag(state, state->getSVal(location.castAs<Loc>()), SelfFlag_Self,
|
||||
C);
|
||||
}
|
||||
|
||||
|
||||
|
@ -417,10 +418,10 @@ static bool isSelfVar(SVal location, CheckerContext &C) {
|
|||
AnalysisDeclContext *analCtx = C.getCurrentAnalysisDeclContext();
|
||||
if (!analCtx->getSelfDecl())
|
||||
return false;
|
||||
if (!isa<loc::MemRegionVal>(location))
|
||||
if (!location.getAs<loc::MemRegionVal>())
|
||||
return false;
|
||||
|
||||
loc::MemRegionVal MRV = cast<loc::MemRegionVal>(location);
|
||||
loc::MemRegionVal MRV = location.castAs<loc::MemRegionVal>();
|
||||
if (const DeclRegion *DR = dyn_cast<DeclRegion>(MRV.stripCasts()))
|
||||
return (DR->getDecl() == analCtx->getSelfDecl());
|
||||
|
||||
|
|
|
@ -98,7 +98,7 @@ void PthreadLockChecker::AcquireLock(CheckerContext &C, const CallExpr *CE,
|
|||
if (X.isUnknownOrUndef())
|
||||
return;
|
||||
|
||||
DefinedSVal retVal = cast<DefinedSVal>(X);
|
||||
DefinedSVal retVal = X.castAs<DefinedSVal>();
|
||||
|
||||
if (state->contains<LockSet>(lockR)) {
|
||||
if (!BT_doublelock)
|
||||
|
|
|
@ -3361,7 +3361,8 @@ void RetainCountChecker::checkBind(SVal loc, SVal val, const Stmt *S,
|
|||
// does not understand.
|
||||
ProgramStateRef state = C.getState();
|
||||
|
||||
if (loc::MemRegionVal *regionLoc = dyn_cast<loc::MemRegionVal>(&loc)) {
|
||||
if (llvm::Optional<loc::MemRegionVal> regionLoc =
|
||||
loc.getAs<loc::MemRegionVal>()) {
|
||||
escapes = !regionLoc->getRegion()->hasStackStorage();
|
||||
|
||||
if (!escapes) {
|
||||
|
|
|
@ -210,9 +210,8 @@ void StreamChecker::OpenFileAux(CheckerContext &C, const CallExpr *CE) const {
|
|||
ProgramStateRef state = C.getState();
|
||||
SValBuilder &svalBuilder = C.getSValBuilder();
|
||||
const LocationContext *LCtx = C.getPredecessor()->getLocationContext();
|
||||
DefinedSVal RetVal =
|
||||
cast<DefinedSVal>(svalBuilder.conjureSymbolVal(0, CE, LCtx,
|
||||
C.blockCount()));
|
||||
DefinedSVal RetVal = svalBuilder.conjureSymbolVal(0, CE, LCtx, C.blockCount())
|
||||
.castAs<DefinedSVal>();
|
||||
state = state->BindExpr(CE, C.getLocationContext(), RetVal);
|
||||
|
||||
ConstraintManager &CM = C.getConstraintManager();
|
||||
|
@ -260,7 +259,7 @@ void StreamChecker::Fseek(CheckerContext &C, const CallExpr *CE) const {
|
|||
return;
|
||||
// Check the legality of the 'whence' argument of 'fseek'.
|
||||
SVal Whence = state->getSVal(CE->getArg(2), C.getLocationContext());
|
||||
const nonloc::ConcreteInt *CI = dyn_cast<nonloc::ConcreteInt>(&Whence);
|
||||
llvm::Optional<nonloc::ConcreteInt> CI = Whence.getAs<nonloc::ConcreteInt>();
|
||||
|
||||
if (!CI)
|
||||
return;
|
||||
|
@ -338,7 +337,7 @@ void StreamChecker::Fileno(CheckerContext &C, const CallExpr *CE) const {
|
|||
|
||||
ProgramStateRef StreamChecker::CheckNullStream(SVal SV, ProgramStateRef state,
|
||||
CheckerContext &C) const {
|
||||
const DefinedSVal *DV = dyn_cast<DefinedSVal>(&SV);
|
||||
llvm::Optional<DefinedSVal> DV = SV.getAs<DefinedSVal>();
|
||||
if (!DV)
|
||||
return 0;
|
||||
|
||||
|
|
|
@ -103,21 +103,20 @@ void UnixAPIChecker::CheckOpen(CheckerContext &C, const CallExpr *CE) const {
|
|||
// Now check if oflags has O_CREAT set.
|
||||
const Expr *oflagsEx = CE->getArg(1);
|
||||
const SVal V = state->getSVal(oflagsEx, C.getLocationContext());
|
||||
if (!isa<NonLoc>(V)) {
|
||||
if (!V.getAs<NonLoc>()) {
|
||||
// The case where 'V' can be a location can only be due to a bad header,
|
||||
// so in this case bail out.
|
||||
return;
|
||||
}
|
||||
NonLoc oflags = cast<NonLoc>(V);
|
||||
NonLoc ocreateFlag =
|
||||
cast<NonLoc>(C.getSValBuilder().makeIntVal(Val_O_CREAT.getValue(),
|
||||
oflagsEx->getType()));
|
||||
NonLoc oflags = V.castAs<NonLoc>();
|
||||
NonLoc ocreateFlag = C.getSValBuilder()
|
||||
.makeIntVal(Val_O_CREAT.getValue(), oflagsEx->getType()).castAs<NonLoc>();
|
||||
SVal maskedFlagsUC = C.getSValBuilder().evalBinOpNN(state, BO_And,
|
||||
oflags, ocreateFlag,
|
||||
oflagsEx->getType());
|
||||
if (maskedFlagsUC.isUnknownOrUndef())
|
||||
return;
|
||||
DefinedSVal maskedFlags = cast<DefinedSVal>(maskedFlagsUC);
|
||||
DefinedSVal maskedFlags = maskedFlagsUC.castAs<DefinedSVal>();
|
||||
|
||||
// Check if maskedFlags is non-zero.
|
||||
ProgramStateRef trueState, falseState;
|
||||
|
@ -202,7 +201,7 @@ static bool IsZeroByteAllocation(ProgramStateRef state,
|
|||
ProgramStateRef *trueState,
|
||||
ProgramStateRef *falseState) {
|
||||
llvm::tie(*trueState, *falseState) =
|
||||
state->assume(cast<DefinedSVal>(argVal));
|
||||
state->assume(argVal.castAs<DefinedSVal>());
|
||||
|
||||
return (*falseState && !*trueState);
|
||||
}
|
||||
|
|
|
@ -110,7 +110,7 @@ void VLASizeChecker::checkPreStmt(const DeclStmt *DS, CheckerContext &C) const {
|
|||
}
|
||||
|
||||
// Check if the size is zero.
|
||||
DefinedSVal sizeD = cast<DefinedSVal>(sizeV);
|
||||
DefinedSVal sizeD = sizeV.castAs<DefinedSVal>();
|
||||
|
||||
ProgramStateRef stateNotZero, stateZero;
|
||||
llvm::tie(stateNotZero, stateZero) = state->assume(sizeD);
|
||||
|
@ -130,22 +130,22 @@ void VLASizeChecker::checkPreStmt(const DeclStmt *DS, CheckerContext &C) const {
|
|||
// Convert the array length to size_t.
|
||||
SValBuilder &svalBuilder = C.getSValBuilder();
|
||||
QualType SizeTy = Ctx.getSizeType();
|
||||
NonLoc ArrayLength = cast<NonLoc>(svalBuilder.evalCast(sizeD, SizeTy,
|
||||
SE->getType()));
|
||||
NonLoc ArrayLength =
|
||||
svalBuilder.evalCast(sizeD, SizeTy, SE->getType()).castAs<NonLoc>();
|
||||
|
||||
// Get the element size.
|
||||
CharUnits EleSize = Ctx.getTypeSizeInChars(VLA->getElementType());
|
||||
SVal EleSizeVal = svalBuilder.makeIntVal(EleSize.getQuantity(), SizeTy);
|
||||
|
||||
// Multiply the array length by the element size.
|
||||
SVal ArraySizeVal = svalBuilder.evalBinOpNN(state, BO_Mul, ArrayLength,
|
||||
cast<NonLoc>(EleSizeVal), SizeTy);
|
||||
SVal ArraySizeVal = svalBuilder.evalBinOpNN(
|
||||
state, BO_Mul, ArrayLength, EleSizeVal.castAs<NonLoc>(), SizeTy);
|
||||
|
||||
// Finally, assume that the array's extent matches the given size.
|
||||
const LocationContext *LC = C.getLocationContext();
|
||||
DefinedOrUnknownSVal Extent =
|
||||
state->getRegion(VD, LC)->getExtent(svalBuilder);
|
||||
DefinedOrUnknownSVal ArraySize = cast<DefinedOrUnknownSVal>(ArraySizeVal);
|
||||
DefinedOrUnknownSVal ArraySize = ArraySizeVal.castAs<DefinedOrUnknownSVal>();
|
||||
DefinedOrUnknownSVal sizeIsKnown =
|
||||
svalBuilder.evalEQ(state, Extent, ArraySize);
|
||||
state = state->assume(sizeIsKnown, true);
|
||||
|
|
|
@ -228,7 +228,7 @@ public:
|
|||
|
||||
// If we can't prove the return value is 0, just mark it interesting, and
|
||||
// make sure to track it into any further inner functions.
|
||||
if (State->assume(cast<DefinedSVal>(V), true)) {
|
||||
if (State->assume(V.castAs<DefinedSVal>(), true)) {
|
||||
BR.markInteresting(V);
|
||||
ReturnVisitor::addVisitorIfNecessary(N, RetE, BR);
|
||||
return 0;
|
||||
|
@ -241,7 +241,7 @@ public:
|
|||
SmallString<64> Msg;
|
||||
llvm::raw_svector_ostream Out(Msg);
|
||||
|
||||
if (isa<Loc>(V)) {
|
||||
if (V.getAs<Loc>()) {
|
||||
// If we are pruning null-return paths as unlikely error paths, mark the
|
||||
// report invalid. We still want to emit a path note, however, in case
|
||||
// the report is resurrected as valid later on.
|
||||
|
@ -298,7 +298,7 @@ public:
|
|||
CallEventRef<> Call = CallMgr.getCaller(StackFrame, State);
|
||||
for (unsigned I = 0, E = Call->getNumArgs(); I != E; ++I) {
|
||||
SVal ArgV = Call->getArgSVal(I);
|
||||
if (!isa<Loc>(ArgV))
|
||||
if (!ArgV.getAs<Loc>())
|
||||
continue;
|
||||
|
||||
const Expr *ArgE = Call->getArgExpr(I);
|
||||
|
@ -306,7 +306,7 @@ public:
|
|||
continue;
|
||||
|
||||
// Is it possible for this argument to be non-null?
|
||||
if (State->assume(cast<Loc>(ArgV), true))
|
||||
if (State->assume(ArgV.castAs<Loc>(), true))
|
||||
continue;
|
||||
|
||||
if (bugreporter::trackNullOrUndefValue(N, ArgE, BR, /*IsArg=*/true))
|
||||
|
@ -415,7 +415,7 @@ PathDiagnosticPiece *FindLastStoreBRVisitor::VisitNode(const ExplodedNode *Succ,
|
|||
// If we have an expression that provided the value, try to track where it
|
||||
// came from.
|
||||
if (InitE) {
|
||||
if (V.isUndef() || isa<loc::ConcreteInt>(V)) {
|
||||
if (V.isUndef() || V.getAs<loc::ConcreteInt>()) {
|
||||
if (!IsParam)
|
||||
InitE = InitE->IgnoreParenCasts();
|
||||
bugreporter::trackNullOrUndefValue(StoreSite, InitE, BR, IsParam);
|
||||
|
@ -462,7 +462,7 @@ PathDiagnosticPiece *FindLastStoreBRVisitor::VisitNode(const ExplodedNode *Succ,
|
|||
|
||||
os << "Variable '" << *VR->getDecl() << "' ";
|
||||
|
||||
if (isa<loc::ConcreteInt>(V)) {
|
||||
if (V.getAs<loc::ConcreteInt>()) {
|
||||
bool b = false;
|
||||
if (R->isBoundable()) {
|
||||
if (const TypedValueRegion *TR = dyn_cast<TypedValueRegion>(R)) {
|
||||
|
@ -475,9 +475,9 @@ PathDiagnosticPiece *FindLastStoreBRVisitor::VisitNode(const ExplodedNode *Succ,
|
|||
|
||||
if (!b)
|
||||
os << action << "a null pointer value";
|
||||
}
|
||||
else if (isa<nonloc::ConcreteInt>(V)) {
|
||||
os << action << cast<nonloc::ConcreteInt>(V).getValue();
|
||||
} else if (llvm::Optional<nonloc::ConcreteInt> CVal =
|
||||
V.getAs<nonloc::ConcreteInt>()) {
|
||||
os << action << CVal->getValue();
|
||||
}
|
||||
else if (DS) {
|
||||
if (V.isUndef()) {
|
||||
|
@ -499,15 +499,16 @@ PathDiagnosticPiece *FindLastStoreBRVisitor::VisitNode(const ExplodedNode *Succ,
|
|||
|
||||
os << "Passing ";
|
||||
|
||||
if (isa<loc::ConcreteInt>(V)) {
|
||||
if (V.getAs<loc::ConcreteInt>()) {
|
||||
if (Param->getType()->isObjCObjectPointerType())
|
||||
os << "nil object reference";
|
||||
else
|
||||
os << "null pointer value";
|
||||
} else if (V.isUndef()) {
|
||||
os << "uninitialized value";
|
||||
} else if (isa<nonloc::ConcreteInt>(V)) {
|
||||
os << "the value " << cast<nonloc::ConcreteInt>(V).getValue();
|
||||
} else if (llvm::Optional<nonloc::ConcreteInt> CI =
|
||||
V.getAs<nonloc::ConcreteInt>()) {
|
||||
os << "the value " << CI->getValue();
|
||||
} else {
|
||||
os << "value";
|
||||
}
|
||||
|
@ -521,7 +522,7 @@ PathDiagnosticPiece *FindLastStoreBRVisitor::VisitNode(const ExplodedNode *Succ,
|
|||
}
|
||||
|
||||
if (os.str().empty()) {
|
||||
if (isa<loc::ConcreteInt>(V)) {
|
||||
if (V.getAs<loc::ConcreteInt>()) {
|
||||
bool b = false;
|
||||
if (R->isBoundable()) {
|
||||
if (const TypedValueRegion *TR = dyn_cast<TypedValueRegion>(R)) {
|
||||
|
@ -537,10 +538,9 @@ PathDiagnosticPiece *FindLastStoreBRVisitor::VisitNode(const ExplodedNode *Succ,
|
|||
}
|
||||
else if (V.isUndef()) {
|
||||
os << "Uninitialized value stored to ";
|
||||
}
|
||||
else if (isa<nonloc::ConcreteInt>(V)) {
|
||||
os << "The value " << cast<nonloc::ConcreteInt>(V).getValue()
|
||||
<< " is assigned to ";
|
||||
} else if (llvm::Optional<nonloc::ConcreteInt> CV =
|
||||
V.getAs<nonloc::ConcreteInt>()) {
|
||||
os << "The value " << CV->getValue() << " is assigned to ";
|
||||
}
|
||||
else
|
||||
os << "Value assigned to ";
|
||||
|
@ -601,7 +601,7 @@ TrackConstraintBRVisitor::VisitNode(const ExplodedNode *N,
|
|||
std::string sbuf;
|
||||
llvm::raw_string_ostream os(sbuf);
|
||||
|
||||
if (isa<Loc>(Constraint)) {
|
||||
if (Constraint.getAs<Loc>()) {
|
||||
os << "Assuming pointer value is ";
|
||||
os << (Assumption ? "non-null" : "null");
|
||||
}
|
||||
|
@ -693,8 +693,8 @@ bool bugreporter::trackNullOrUndefValue(const ExplodedNode *N, const Stmt *S,
|
|||
|
||||
// If the contents are symbolic, find out when they became null.
|
||||
if (V.getAsLocSymbol()) {
|
||||
BugReporterVisitor *ConstraintTracker
|
||||
= new TrackConstraintBRVisitor(cast<DefinedSVal>(V), false);
|
||||
BugReporterVisitor *ConstraintTracker =
|
||||
new TrackConstraintBRVisitor(V.castAs<DefinedSVal>(), false);
|
||||
report.addVisitor(ConstraintTracker);
|
||||
}
|
||||
|
||||
|
@ -713,7 +713,7 @@ bool bugreporter::trackNullOrUndefValue(const ExplodedNode *N, const Stmt *S,
|
|||
// assert(!V.isUnknownOrUndef());
|
||||
|
||||
// Is it a symbolic value?
|
||||
if (loc::MemRegionVal *L = dyn_cast<loc::MemRegionVal>(&V)) {
|
||||
if (llvm::Optional<loc::MemRegionVal> L = V.getAs<loc::MemRegionVal>()) {
|
||||
// At this point we are dealing with the region's LValue.
|
||||
// However, if the rvalue is a symbolic region, we should track it as well.
|
||||
SVal RVal = state->getSVal(L->getRegion());
|
||||
|
@ -766,7 +766,7 @@ PathDiagnosticPiece *NilReceiverBRVisitor::VisitNode(const ExplodedNode *N,
|
|||
return 0;
|
||||
ProgramStateRef state = N->getState();
|
||||
const SVal &V = state->getSVal(Receiver, N->getLocationContext());
|
||||
const DefinedOrUnknownSVal *DV = dyn_cast<DefinedOrUnknownSVal>(&V);
|
||||
llvm::Optional<DefinedOrUnknownSVal> DV = V.getAs<DefinedOrUnknownSVal>();
|
||||
if (!DV)
|
||||
return 0;
|
||||
state = state->assume(*DV, true);
|
||||
|
@ -806,7 +806,7 @@ void FindLastStoreBRVisitor::registerStatementVarDecls(BugReport &BR,
|
|||
// What did we load?
|
||||
SVal V = state->getSVal(S, N->getLocationContext());
|
||||
|
||||
if (isa<loc::ConcreteInt>(V) || isa<nonloc::ConcreteInt>(V)) {
|
||||
if (V.getAs<loc::ConcreteInt>() || V.getAs<nonloc::ConcreteInt>()) {
|
||||
// Register a new visitor with the BugReport.
|
||||
BR.addVisitor(new FindLastStoreBRVisitor(V, R));
|
||||
}
|
||||
|
|
|
@ -156,9 +156,10 @@ ProgramStateRef CallEvent::invalidateRegions(unsigned BlockCount,
|
|||
|
||||
// If we are passing a location wrapped as an integer, unwrap it and
|
||||
// invalidate the values referred by the location.
|
||||
if (nonloc::LocAsInteger *Wrapped = dyn_cast<nonloc::LocAsInteger>(&V))
|
||||
if (llvm::Optional<nonloc::LocAsInteger> Wrapped =
|
||||
V.getAs<nonloc::LocAsInteger>())
|
||||
V = Wrapped->getLoc();
|
||||
else if (!isa<Loc>(V))
|
||||
else if (!V.getAs<Loc>())
|
||||
continue;
|
||||
|
||||
if (const MemRegion *R = V.getAsRegion()) {
|
||||
|
@ -419,7 +420,7 @@ SVal CXXInstanceCall::getCXXThisVal() const {
|
|||
return UnknownVal();
|
||||
|
||||
SVal ThisVal = getSVal(Base);
|
||||
assert(ThisVal.isUnknownOrUndef() || isa<Loc>(ThisVal));
|
||||
assert(ThisVal.isUnknownOrUndef() || ThisVal.getAs<Loc>());
|
||||
return ThisVal;
|
||||
}
|
||||
|
||||
|
|
|
@ -198,10 +198,8 @@ EnvironmentManager::removeDeadBindings(Environment Env,
|
|||
EBMapRef = EBMapRef.add(BlkExpr, X);
|
||||
|
||||
// If the block expr's value is a memory region, then mark that region.
|
||||
if (isa<loc::MemRegionVal>(X)) {
|
||||
const MemRegion *R = cast<loc::MemRegionVal>(X).getRegion();
|
||||
SymReaper.markLive(R);
|
||||
}
|
||||
if (llvm::Optional<loc::MemRegionVal> R = X.getAs<loc::MemRegionVal>())
|
||||
SymReaper.markLive(R->getRegion());
|
||||
|
||||
// Mark all symbols in the block expr's value live.
|
||||
RSScaner.scan(X);
|
||||
|
|
|
@ -118,8 +118,8 @@ ProgramStateRef ExprEngine::getInitialState(const LocationContext *InitLoc) {
|
|||
svalBuilder.makeZeroVal(T),
|
||||
getContext().IntTy);
|
||||
|
||||
DefinedOrUnknownSVal *Constraint =
|
||||
dyn_cast<DefinedOrUnknownSVal>(&Constraint_untested);
|
||||
llvm::Optional<DefinedOrUnknownSVal> Constraint =
|
||||
Constraint_untested.getAs<DefinedOrUnknownSVal>();
|
||||
|
||||
if (!Constraint)
|
||||
break;
|
||||
|
@ -138,7 +138,7 @@ ProgramStateRef ExprEngine::getInitialState(const LocationContext *InitLoc) {
|
|||
const MemRegion *R = state->getRegion(SelfD, InitLoc);
|
||||
SVal V = state->getSVal(loc::MemRegionVal(R));
|
||||
|
||||
if (const Loc *LV = dyn_cast<Loc>(&V)) {
|
||||
if (llvm::Optional<Loc> LV = V.getAs<Loc>()) {
|
||||
// Assume that the pointer value in 'self' is non-null.
|
||||
state = state->assume(*LV, true);
|
||||
assert(state && "'self' cannot be null");
|
||||
|
@ -154,7 +154,7 @@ ProgramStateRef ExprEngine::getInitialState(const LocationContext *InitLoc) {
|
|||
if (SFC->getParent() == 0) {
|
||||
loc::MemRegionVal L = svalBuilder.getCXXThis(MD, SFC);
|
||||
SVal V = state->getSVal(L);
|
||||
if (const Loc *LV = dyn_cast<Loc>(&V)) {
|
||||
if (llvm::Optional<Loc> LV = V.getAs<Loc>()) {
|
||||
state = state->assume(*LV, true);
|
||||
assert(state && "'this' cannot be null");
|
||||
}
|
||||
|
@ -172,7 +172,7 @@ static ProgramStateRef createTemporaryRegionIfNeeded(ProgramStateRef State,
|
|||
const Expr *E) {
|
||||
SVal V = State->getSVal(E, LC);
|
||||
|
||||
if (isa<NonLoc>(V)) {
|
||||
if (V.getAs<NonLoc>()) {
|
||||
MemRegionManager &MRMgr = State->getStateManager().getRegionManager();
|
||||
const MemRegion *R = MRMgr.getCXXTempObjectRegion(E, LC);
|
||||
State = State->bindLoc(loc::MemRegionVal(R), V);
|
||||
|
@ -472,8 +472,8 @@ void ExprEngine::ProcessAutomaticObjDtor(const CFGAutomaticObjDtor Dtor,
|
|||
|
||||
Loc dest = state->getLValue(varDecl, Pred->getLocationContext());
|
||||
|
||||
VisitCXXDestructor(varType, cast<loc::MemRegionVal>(dest).getRegion(),
|
||||
Dtor.getTriggerStmt(), /*IsBase=*/false, Pred, Dst);
|
||||
VisitCXXDestructor(varType, dest.castAs<loc::MemRegionVal>().getRegion(),
|
||||
Dtor.getTriggerStmt(), /*IsBase=*/ false, Pred, Dst);
|
||||
}
|
||||
|
||||
void ExprEngine::ProcessBaseDtor(const CFGBaseDtor D,
|
||||
|
@ -490,8 +490,8 @@ void ExprEngine::ProcessBaseDtor(const CFGBaseDtor D,
|
|||
QualType BaseTy = D.getBaseSpecifier()->getType();
|
||||
SVal BaseVal = getStoreManager().evalDerivedToBase(ThisVal, BaseTy);
|
||||
|
||||
VisitCXXDestructor(BaseTy, cast<loc::MemRegionVal>(BaseVal).getRegion(),
|
||||
CurDtor->getBody(), /*IsBase=*/true, Pred, Dst);
|
||||
VisitCXXDestructor(BaseTy, BaseVal.castAs<loc::MemRegionVal>().getRegion(),
|
||||
CurDtor->getBody(), /*IsBase=*/ true, Pred, Dst);
|
||||
}
|
||||
|
||||
void ExprEngine::ProcessMemberDtor(const CFGMemberDtor D,
|
||||
|
@ -503,10 +503,11 @@ void ExprEngine::ProcessMemberDtor(const CFGMemberDtor D,
|
|||
const CXXDestructorDecl *CurDtor = cast<CXXDestructorDecl>(LCtx->getDecl());
|
||||
Loc ThisVal = getSValBuilder().getCXXThis(CurDtor,
|
||||
LCtx->getCurrentStackFrame());
|
||||
SVal FieldVal = State->getLValue(Member, cast<Loc>(State->getSVal(ThisVal)));
|
||||
SVal FieldVal =
|
||||
State->getLValue(Member, State->getSVal(ThisVal).castAs<Loc>());
|
||||
|
||||
VisitCXXDestructor(Member->getType(),
|
||||
cast<loc::MemRegionVal>(FieldVal).getRegion(),
|
||||
FieldVal.castAs<loc::MemRegionVal>().getRegion(),
|
||||
CurDtor->getBody(), /*IsBase=*/false, Pred, Dst);
|
||||
}
|
||||
|
||||
|
@ -1287,7 +1288,7 @@ void ExprEngine::processBranch(const Stmt *Condition, const Stmt *Term,
|
|||
continue;
|
||||
}
|
||||
|
||||
DefinedSVal V = cast<DefinedSVal>(X);
|
||||
DefinedSVal V = X.castAs<DefinedSVal>();
|
||||
|
||||
ProgramStateRef StTrue, StFalse;
|
||||
tie(StTrue, StFalse) = PrevState->assume(V);
|
||||
|
@ -1327,8 +1328,8 @@ void ExprEngine::processIndirectGoto(IndirectGotoNodeBuilder &builder) {
|
|||
|
||||
typedef IndirectGotoNodeBuilder::iterator iterator;
|
||||
|
||||
if (isa<loc::GotoLabel>(V)) {
|
||||
const LabelDecl *L = cast<loc::GotoLabel>(V).getLabel();
|
||||
if (llvm::Optional<loc::GotoLabel> LV = V.getAs<loc::GotoLabel>()) {
|
||||
const LabelDecl *L = LV->getLabel();
|
||||
|
||||
for (iterator I = builder.begin(), E = builder.end(); I != E; ++I) {
|
||||
if (I.getLabel() == L) {
|
||||
|
@ -1340,7 +1341,7 @@ void ExprEngine::processIndirectGoto(IndirectGotoNodeBuilder &builder) {
|
|||
llvm_unreachable("No block with label.");
|
||||
}
|
||||
|
||||
if (isa<loc::ConcreteInt>(V) || isa<UndefinedVal>(V)) {
|
||||
if (V.getAs<loc::ConcreteInt>() || V.getAs<UndefinedVal>()) {
|
||||
// Dispatch to the first target and mark it as a sink.
|
||||
//ExplodedNode* N = builder.generateNode(builder.begin(), state, true);
|
||||
// FIXME: add checker visit.
|
||||
|
@ -1394,7 +1395,7 @@ void ExprEngine::processSwitch(SwitchNodeBuilder& builder) {
|
|||
|
||||
return;
|
||||
}
|
||||
DefinedOrUnknownSVal CondV = cast<DefinedOrUnknownSVal>(CondV_untested);
|
||||
DefinedOrUnknownSVal CondV = CondV_untested.castAs<DefinedOrUnknownSVal>();
|
||||
|
||||
ProgramStateRef DefaultSt = state;
|
||||
|
||||
|
@ -1435,7 +1436,7 @@ void ExprEngine::processSwitch(SwitchNodeBuilder& builder) {
|
|||
// If CondV evaluates to a constant, then we know that this
|
||||
// is the *only* case that we can take, so stop evaluating the
|
||||
// others.
|
||||
if (isa<nonloc::ConcreteInt>(CondV))
|
||||
if (CondV.getAs<nonloc::ConcreteInt>())
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1529,7 +1530,7 @@ void ExprEngine::VisitCommonDeclRefExpr(const Expr *Ex, const NamedDecl *D,
|
|||
// results in boolean contexts.
|
||||
SVal V = svalBuilder.conjureSymbolVal(Ex, LCtx, getContext().VoidPtrTy,
|
||||
currBldrCtx->blockCount());
|
||||
state = state->assume(cast<DefinedOrUnknownSVal>(V), true);
|
||||
state = state->assume(V.castAs<DefinedOrUnknownSVal>(), true);
|
||||
Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, V), 0,
|
||||
ProgramPoint::PostLValueKind);
|
||||
return;
|
||||
|
@ -1646,7 +1647,8 @@ ProgramStateRef ExprEngine::processPointerEscapedOnBind(ProgramStateRef State,
|
|||
bool escapes = true;
|
||||
|
||||
// TODO: Move to StoreManager.
|
||||
if (loc::MemRegionVal *regionLoc = dyn_cast<loc::MemRegionVal>(&Loc)) {
|
||||
if (llvm::Optional<loc::MemRegionVal> regionLoc =
|
||||
Loc.getAs<loc::MemRegionVal>()) {
|
||||
escapes = !regionLoc->getRegion()->hasStackStorage();
|
||||
|
||||
if (!escapes) {
|
||||
|
@ -1754,7 +1756,7 @@ void ExprEngine::evalBind(ExplodedNodeSet &Dst, const Stmt *StoreE,
|
|||
|
||||
// If the location is not a 'Loc', it will already be handled by
|
||||
// the checkers. There is nothing left to do.
|
||||
if (!isa<Loc>(location)) {
|
||||
if (!location.getAs<Loc>()) {
|
||||
const ProgramPoint L = PostStore(StoreE, LC, /*Loc*/0, /*tag*/0);
|
||||
ProgramStateRef state = Pred->getState();
|
||||
state = processPointerEscapedOnBind(state, location, Val);
|
||||
|
@ -1773,11 +1775,12 @@ void ExprEngine::evalBind(ExplodedNodeSet &Dst, const Stmt *StoreE,
|
|||
// When binding the value, pass on the hint that this is a initialization.
|
||||
// For initializations, we do not need to inform clients of region
|
||||
// changes.
|
||||
state = state->bindLoc(cast<Loc>(location),
|
||||
state = state->bindLoc(location.castAs<Loc>(),
|
||||
Val, /* notifyChanges = */ !atDeclInit);
|
||||
|
||||
const MemRegion *LocReg = 0;
|
||||
if (loc::MemRegionVal *LocRegVal = dyn_cast<loc::MemRegionVal>(&location)) {
|
||||
if (llvm::Optional<loc::MemRegionVal> LocRegVal =
|
||||
location.getAs<loc::MemRegionVal>()) {
|
||||
LocReg = LocRegVal->getRegion();
|
||||
}
|
||||
|
||||
|
@ -1826,7 +1829,7 @@ void ExprEngine::evalLoad(ExplodedNodeSet &Dst,
|
|||
const ProgramPointTag *tag,
|
||||
QualType LoadTy)
|
||||
{
|
||||
assert(!isa<NonLoc>(location) && "location cannot be a NonLoc.");
|
||||
assert(!location.getAs<NonLoc>() && "location cannot be a NonLoc.");
|
||||
|
||||
// Are we loading from a region? This actually results in two loads; one
|
||||
// to fetch the address of the referenced value and one to fetch the
|
||||
|
@ -1885,7 +1888,7 @@ void ExprEngine::evalLoadCommon(ExplodedNodeSet &Dst,
|
|||
if (location.isValid()) {
|
||||
if (LoadTy.isNull())
|
||||
LoadTy = BoundEx->getType();
|
||||
V = state->getSVal(cast<Loc>(location), LoadTy);
|
||||
V = state->getSVal(location.castAs<Loc>(), LoadTy);
|
||||
}
|
||||
|
||||
Bldr.generateNode(NodeEx, *NI, state->BindExpr(BoundEx, LCtx, V), tag,
|
||||
|
@ -1955,7 +1958,7 @@ void ExprEngine::evalEagerlyAssumeBinOpBifurcation(ExplodedNodeSet &Dst,
|
|||
|
||||
ProgramStateRef state = Pred->getState();
|
||||
SVal V = state->getSVal(Ex, Pred->getLocationContext());
|
||||
nonloc::SymbolVal *SEV = dyn_cast<nonloc::SymbolVal>(&V);
|
||||
llvm::Optional<nonloc::SymbolVal> SEV = V.getAs<nonloc::SymbolVal>();
|
||||
if (SEV && SEV->isExpression()) {
|
||||
const std::pair<const ProgramPointTag *, const ProgramPointTag*> &tags =
|
||||
geteagerlyAssumeBinOpBifurcationTags();
|
||||
|
@ -1995,10 +1998,10 @@ void ExprEngine::VisitGCCAsmStmt(const GCCAsmStmt *A, ExplodedNode *Pred,
|
|||
for (GCCAsmStmt::const_outputs_iterator OI = A->begin_outputs(),
|
||||
OE = A->end_outputs(); OI != OE; ++OI) {
|
||||
SVal X = state->getSVal(*OI, Pred->getLocationContext());
|
||||
assert (!isa<NonLoc>(X)); // Should be an Lval, or unknown, undef.
|
||||
assert (!X.getAs<NonLoc>()); // Should be an Lval, or unknown, undef.
|
||||
|
||||
if (isa<Loc>(X))
|
||||
state = state->bindLoc(cast<Loc>(X), UnknownVal());
|
||||
if (llvm::Optional<Loc> LV = X.getAs<Loc>())
|
||||
state = state->bindLoc(*LV, UnknownVal());
|
||||
}
|
||||
|
||||
Bldr.generateNode(A, Pred, state);
|
||||
|
|
|
@ -67,12 +67,12 @@ void ExprEngine::VisitBinaryOperator(const BinaryOperator* B,
|
|||
// TODO: This can be removed after we enable history tracking with
|
||||
// SymSymExpr.
|
||||
unsigned Count = currBldrCtx->blockCount();
|
||||
if (isa<Loc>(LeftV) &&
|
||||
if (LeftV.getAs<Loc>() &&
|
||||
RHS->getType()->isIntegerType() && RightV.isUnknown()) {
|
||||
RightV = svalBuilder.conjureSymbolVal(RHS, LCtx, RHS->getType(),
|
||||
Count);
|
||||
}
|
||||
if (isa<Loc>(RightV) &&
|
||||
if (RightV.getAs<Loc>() &&
|
||||
LHS->getType()->isIntegerType() && LeftV.isUnknown()) {
|
||||
LeftV = svalBuilder.conjureSymbolVal(LHS, LCtx, LHS->getType(),
|
||||
Count);
|
||||
|
@ -480,10 +480,13 @@ void ExprEngine::VisitDeclStmt(const DeclStmt *DS, ExplodedNode *Pred,
|
|||
} else {
|
||||
// We bound the temp obj region to the CXXConstructExpr. Now recover
|
||||
// the lazy compound value when the variable is not a reference.
|
||||
if (AMgr.getLangOpts().CPlusPlus && VD->getType()->isRecordType() &&
|
||||
!VD->getType()->isReferenceType() && isa<loc::MemRegionVal>(InitVal)){
|
||||
InitVal = state->getSVal(cast<loc::MemRegionVal>(InitVal).getRegion());
|
||||
assert(isa<nonloc::LazyCompoundVal>(InitVal));
|
||||
if (AMgr.getLangOpts().CPlusPlus && VD->getType()->isRecordType() &&
|
||||
!VD->getType()->isReferenceType()) {
|
||||
if (llvm::Optional<loc::MemRegionVal> M =
|
||||
InitVal.getAs<loc::MemRegionVal>()) {
|
||||
InitVal = state->getSVal(M->getRegion());
|
||||
assert(InitVal.getAs<nonloc::LazyCompoundVal>());
|
||||
}
|
||||
}
|
||||
|
||||
// Recover some path-sensitivity if a scalar value evaluated to
|
||||
|
@ -558,7 +561,7 @@ void ExprEngine::VisitLogicalExpr(const BinaryOperator* B, ExplodedNode *Pred,
|
|||
if (RHSVal.isUndef()) {
|
||||
X = RHSVal;
|
||||
} else {
|
||||
DefinedOrUnknownSVal DefinedRHS = cast<DefinedOrUnknownSVal>(RHSVal);
|
||||
DefinedOrUnknownSVal DefinedRHS = RHSVal.castAs<DefinedOrUnknownSVal>();
|
||||
ProgramStateRef StTrue, StFalse;
|
||||
llvm::tie(StTrue, StFalse) = N->getState()->assume(DefinedRHS);
|
||||
if (StTrue) {
|
||||
|
@ -810,11 +813,11 @@ void ExprEngine::VisitUnaryOperator(const UnaryOperator* U,
|
|||
llvm_unreachable("Invalid Opcode.");
|
||||
case UO_Not:
|
||||
// FIXME: Do we need to handle promotions?
|
||||
state = state->BindExpr(U, LCtx, evalComplement(cast<NonLoc>(V)));
|
||||
state = state->BindExpr(U, LCtx, evalComplement(V.castAs<NonLoc>()));
|
||||
break;
|
||||
case UO_Minus:
|
||||
// FIXME: Do we need to handle promotions?
|
||||
state = state->BindExpr(U, LCtx, evalMinus(cast<NonLoc>(V)));
|
||||
state = state->BindExpr(U, LCtx, evalMinus(V.castAs<NonLoc>()));
|
||||
break;
|
||||
case UO_LNot:
|
||||
// C99 6.5.3.3: "The expression !E is equivalent to (0==E)."
|
||||
|
@ -822,17 +825,16 @@ void ExprEngine::VisitUnaryOperator(const UnaryOperator* U,
|
|||
// Note: technically we do "E == 0", but this is the same in the
|
||||
// transfer functions as "0 == E".
|
||||
SVal Result;
|
||||
if (isa<Loc>(V)) {
|
||||
if (llvm::Optional<Loc> LV = V.getAs<Loc>()) {
|
||||
Loc X = svalBuilder.makeNull();
|
||||
Result = evalBinOp(state, BO_EQ, cast<Loc>(V), X,
|
||||
U->getType());
|
||||
Result = evalBinOp(state, BO_EQ, *LV, X, U->getType());
|
||||
}
|
||||
else if (Ex->getType()->isFloatingType()) {
|
||||
// FIXME: handle floating point types.
|
||||
Result = UnknownVal();
|
||||
} else {
|
||||
nonloc::ConcreteInt X(getBasicVals().getValue(0, Ex->getType()));
|
||||
Result = evalBinOp(state, BO_EQ, cast<NonLoc>(V), X,
|
||||
Result = evalBinOp(state, BO_EQ, V.castAs<NonLoc>(), X,
|
||||
U->getType());
|
||||
}
|
||||
|
||||
|
@ -874,7 +876,7 @@ void ExprEngine::VisitIncrementDecrementOperator(const UnaryOperator* U,
|
|||
Bldr.generateNode(U, *I, state->BindExpr(U, LCtx, V2_untested));
|
||||
continue;
|
||||
}
|
||||
DefinedSVal V2 = cast<DefinedSVal>(V2_untested);
|
||||
DefinedSVal V2 = V2_untested.castAs<DefinedSVal>();
|
||||
|
||||
// Handle all other values.
|
||||
BinaryOperator::Opcode Op = U->isIncrementOp() ? BO_Add : BO_Sub;
|
||||
|
|
|
@ -64,7 +64,7 @@ void ExprEngine::performTrivialCopy(NodeBuilder &Bldr, ExplodedNode *Pred,
|
|||
SVal V = Call.getArgSVal(0);
|
||||
|
||||
// Make sure the value being copied is not unknown.
|
||||
if (const Loc *L = dyn_cast<Loc>(&V))
|
||||
if (llvm::Optional<Loc> L = V.getAs<Loc>())
|
||||
V = Pred->getState()->getSVal(*L);
|
||||
|
||||
evalBind(Dst, CtorExpr, Pred, ThisVal, V, true);
|
||||
|
@ -287,7 +287,7 @@ void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred,
|
|||
if (CNE->isArray()) {
|
||||
// FIXME: allocating an array requires simulating the constructors.
|
||||
// For now, just return a symbolicated region.
|
||||
const MemRegion *NewReg = cast<loc::MemRegionVal>(symVal).getRegion();
|
||||
const MemRegion *NewReg = symVal.castAs<loc::MemRegionVal>().getRegion();
|
||||
QualType ObjTy = CNE->getType()->getAs<PointerType>()->getPointeeType();
|
||||
const ElementRegion *EleReg =
|
||||
getStoreManager().GetElementZeroRegion(NewReg, ObjTy);
|
||||
|
@ -319,8 +319,8 @@ void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred,
|
|||
(void)ObjTy;
|
||||
assert(!ObjTy->isRecordType());
|
||||
SVal Location = State->getSVal(CNE, LCtx);
|
||||
if (isa<Loc>(Location))
|
||||
State = State->bindLoc(cast<Loc>(Location), State->getSVal(Init, LCtx));
|
||||
if (llvm::Optional<Loc> LV = Location.getAs<Loc>())
|
||||
State = State->bindLoc(*LV, State->getSVal(Init, LCtx));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -121,7 +121,7 @@ static std::pair<const Stmt*,
|
|||
static SVal adjustReturnValue(SVal V, QualType ExpectedTy, QualType ActualTy,
|
||||
StoreManager &StoreMgr) {
|
||||
// For now, the only adjustments we handle apply only to locations.
|
||||
if (!isa<Loc>(V))
|
||||
if (!V.getAs<Loc>())
|
||||
return V;
|
||||
|
||||
// If the types already match, don't do any unnecessary work.
|
||||
|
@ -266,7 +266,7 @@ void ExprEngine::processCallExit(ExplodedNode *CEBNode) {
|
|||
|
||||
// If the constructed object is a temporary prvalue, get its bindings.
|
||||
if (isTemporaryPRValue(CCE, ThisV))
|
||||
ThisV = state->getSVal(cast<Loc>(ThisV));
|
||||
ThisV = state->getSVal(ThisV.castAs<Loc>());
|
||||
|
||||
state = state->BindExpr(CCE, callerCtx, ThisV);
|
||||
}
|
||||
|
@ -709,7 +709,7 @@ ProgramStateRef ExprEngine::bindReturnValue(const CallEvent &Call,
|
|||
|
||||
// If the constructed object is a temporary prvalue, get its bindings.
|
||||
if (isTemporaryPRValue(cast<CXXConstructExpr>(E), ThisV))
|
||||
ThisV = State->getSVal(cast<Loc>(ThisV));
|
||||
ThisV = State->getSVal(ThisV.castAs<Loc>());
|
||||
|
||||
return State->BindExpr(E, LCtx, ThisV);
|
||||
}
|
||||
|
|
|
@ -103,8 +103,9 @@ void ExprEngine::VisitObjCForCollectionStmt(const ObjCForCollectionStmt *S,
|
|||
// Handle the case where the container has no elements.
|
||||
SVal FalseV = svalBuilder.makeTruthVal(0);
|
||||
ProgramStateRef noElems = state->BindExpr(S, LCtx, FalseV);
|
||||
|
||||
if (loc::MemRegionVal *MV = dyn_cast<loc::MemRegionVal>(&elementV))
|
||||
|
||||
if (llvm::Optional<loc::MemRegionVal> MV =
|
||||
elementV.getAs<loc::MemRegionVal>())
|
||||
if (const TypedValueRegion *R =
|
||||
dyn_cast<TypedValueRegion>(MV->getRegion())) {
|
||||
// FIXME: The proper thing to do is to really iterate over the
|
||||
|
@ -161,8 +162,9 @@ void ExprEngine::VisitObjCMessage(const ObjCMessageExpr *ME,
|
|||
SVal recVal = UpdatedMsg->getReceiverSVal();
|
||||
if (!recVal.isUndef()) {
|
||||
// Bifurcate the state into nil and non-nil ones.
|
||||
DefinedOrUnknownSVal receiverVal = cast<DefinedOrUnknownSVal>(recVal);
|
||||
|
||||
DefinedOrUnknownSVal receiverVal =
|
||||
recVal.castAs<DefinedOrUnknownSVal>();
|
||||
|
||||
ProgramStateRef notNilState, nilState;
|
||||
llvm::tie(notNilState, nilState) = State->assume(receiverVal);
|
||||
|
||||
|
|
|
@ -1044,7 +1044,8 @@ RegionRawOffset ElementRegion::getAsArrayOffset() const {
|
|||
|
||||
// FIXME: generalize to symbolic offsets.
|
||||
SVal index = ER->getIndex();
|
||||
if (nonloc::ConcreteInt *CI = dyn_cast<nonloc::ConcreteInt>(&index)) {
|
||||
if (llvm::Optional<nonloc::ConcreteInt> CI =
|
||||
index.getAs<nonloc::ConcreteInt>()) {
|
||||
// Update the offset.
|
||||
int64_t i = CI->getValue().getSExtValue();
|
||||
|
||||
|
@ -1171,7 +1172,8 @@ RegionOffset MemRegion::getAsOffset() const {
|
|||
}
|
||||
|
||||
SVal Index = ER->getIndex();
|
||||
if (const nonloc::ConcreteInt *CI=dyn_cast<nonloc::ConcreteInt>(&Index)) {
|
||||
if (llvm::Optional<nonloc::ConcreteInt> CI =
|
||||
Index.getAs<nonloc::ConcreteInt>()) {
|
||||
// Don't bother calculating precise offsets if we already have a
|
||||
// symbolic offset somewhere in the chain.
|
||||
if (SymbolicOffsetBase)
|
||||
|
|
|
@ -1029,7 +1029,7 @@ std::string StackHintGeneratorForSymbol::getMessage(const ExplodedNode *N){
|
|||
}
|
||||
|
||||
// Check if the parameter is a pointer to the symbol.
|
||||
if (const loc::MemRegionVal *Reg = dyn_cast<loc::MemRegionVal>(&SV)) {
|
||||
if (llvm::Optional<loc::MemRegionVal> Reg = SV.getAs<loc::MemRegionVal>()) {
|
||||
SVal PSV = State->getSVal(Reg->getRegion());
|
||||
SymbolRef AS = PSV.getAsLocSymbol();
|
||||
if (AS == Sym) {
|
||||
|
|
|
@ -132,7 +132,7 @@ ProgramStateRef ProgramState::bindLoc(Loc LV, SVal V, bool notifyChanges) const
|
|||
|
||||
ProgramStateRef ProgramState::bindDefault(SVal loc, SVal V) const {
|
||||
ProgramStateManager &Mgr = getStateManager();
|
||||
const MemRegion *R = cast<loc::MemRegionVal>(loc).getRegion();
|
||||
const MemRegion *R = loc.castAs<loc::MemRegionVal>().getRegion();
|
||||
const StoreRef &newStore = Mgr.StoreMgr->BindDefault(getStore(), R, V);
|
||||
ProgramStateRef new_state = makeWithStore(newStore);
|
||||
return Mgr.getOwningEngine() ?
|
||||
|
@ -189,7 +189,7 @@ ProgramState::invalidateRegionsImpl(ArrayRef<const MemRegion *> Regions,
|
|||
}
|
||||
|
||||
ProgramStateRef ProgramState::killBinding(Loc LV) const {
|
||||
assert(!isa<loc::MemRegionVal>(LV) && "Use invalidateRegion instead.");
|
||||
assert(!LV.getAs<loc::MemRegionVal>() && "Use invalidateRegion instead.");
|
||||
|
||||
Store OldStore = getStore();
|
||||
const StoreRef &newStore =
|
||||
|
@ -253,7 +253,7 @@ SVal ProgramState::getSVal(Loc location, QualType T) const {
|
|||
// not unsigned.
|
||||
const llvm::APSInt &NewV = getBasicVals().Convert(T, *Int);
|
||||
|
||||
if (isa<Loc>(V))
|
||||
if (V.getAs<Loc>())
|
||||
return loc::ConcreteInt(NewV);
|
||||
else
|
||||
return nonloc::ConcreteInt(NewV);
|
||||
|
@ -301,28 +301,27 @@ ProgramStateRef ProgramState::assumeInBound(DefinedOrUnknownSVal Idx,
|
|||
|
||||
// Adjust the index.
|
||||
SVal newIdx = svalBuilder.evalBinOpNN(this, BO_Add,
|
||||
cast<NonLoc>(Idx), Min, indexTy);
|
||||
Idx.castAs<NonLoc>(), Min, indexTy);
|
||||
if (newIdx.isUnknownOrUndef())
|
||||
return this;
|
||||
|
||||
// Adjust the upper bound.
|
||||
SVal newBound =
|
||||
svalBuilder.evalBinOpNN(this, BO_Add, cast<NonLoc>(UpperBound),
|
||||
svalBuilder.evalBinOpNN(this, BO_Add, UpperBound.castAs<NonLoc>(),
|
||||
Min, indexTy);
|
||||
|
||||
if (newBound.isUnknownOrUndef())
|
||||
return this;
|
||||
|
||||
// Build the actual comparison.
|
||||
SVal inBound = svalBuilder.evalBinOpNN(this, BO_LT,
|
||||
cast<NonLoc>(newIdx), cast<NonLoc>(newBound),
|
||||
Ctx.IntTy);
|
||||
SVal inBound = svalBuilder.evalBinOpNN(this, BO_LT, newIdx.castAs<NonLoc>(),
|
||||
newBound.castAs<NonLoc>(), Ctx.IntTy);
|
||||
if (inBound.isUnknownOrUndef())
|
||||
return this;
|
||||
|
||||
// Finally, let the constraint manager take care of it.
|
||||
ConstraintManager &CM = SM.getConstraintManager();
|
||||
return CM.assume(this, cast<DefinedSVal>(inBound), Assumption);
|
||||
return CM.assume(this, inBound.castAs<DefinedSVal>(), Assumption);
|
||||
}
|
||||
|
||||
ProgramStateRef ProgramStateManager::getInitialState(const LocationContext *InitLoc) {
|
||||
|
@ -509,10 +508,11 @@ bool ScanReachableSymbols::scan(const SymExpr *sym) {
|
|||
}
|
||||
|
||||
bool ScanReachableSymbols::scan(SVal val) {
|
||||
if (loc::MemRegionVal *X = dyn_cast<loc::MemRegionVal>(&val))
|
||||
if (llvm::Optional<loc::MemRegionVal> X = val.getAs<loc::MemRegionVal>())
|
||||
return scan(X->getRegion());
|
||||
|
||||
if (nonloc::LazyCompoundVal *X = dyn_cast<nonloc::LazyCompoundVal>(&val)) {
|
||||
if (llvm::Optional<nonloc::LazyCompoundVal> X =
|
||||
val.getAs<nonloc::LazyCompoundVal>()) {
|
||||
StoreManager &StoreMgr = state->getStateManager().getStoreManager();
|
||||
// FIXME: We don't really want to use getBaseRegion() here because pointer
|
||||
// arithmetic doesn't apply, but scanReachableSymbols only accepts base
|
||||
|
@ -523,7 +523,8 @@ bool ScanReachableSymbols::scan(SVal val) {
|
|||
return false;
|
||||
}
|
||||
|
||||
if (nonloc::LocAsInteger *X = dyn_cast<nonloc::LocAsInteger>(&val))
|
||||
if (llvm::Optional<nonloc::LocAsInteger> X =
|
||||
val.getAs<nonloc::LocAsInteger>())
|
||||
return scan(X->getLoc());
|
||||
|
||||
if (SymbolRef Sym = val.getAsSymbol())
|
||||
|
@ -532,7 +533,7 @@ bool ScanReachableSymbols::scan(SVal val) {
|
|||
if (const SymExpr *Sym = val.getAsSymbolicExpression())
|
||||
return scan(Sym);
|
||||
|
||||
if (nonloc::CompoundVal *X = dyn_cast<nonloc::CompoundVal>(&val))
|
||||
if (llvm::Optional<nonloc::CompoundVal> X = val.getAs<nonloc::CompoundVal>())
|
||||
return scan(*X);
|
||||
|
||||
return true;
|
||||
|
|
|
@ -753,7 +753,8 @@ static void collectSubRegionKeys(SmallVectorImpl<BindingKey> &Keys,
|
|||
// be using this function anyway.
|
||||
uint64_t Length = UINT64_MAX;
|
||||
SVal Extent = Top->getExtent(SVB);
|
||||
if (nonloc::ConcreteInt *ExtentCI = dyn_cast<nonloc::ConcreteInt>(&Extent)) {
|
||||
if (llvm::Optional<nonloc::ConcreteInt> ExtentCI =
|
||||
Extent.getAs<nonloc::ConcreteInt>()) {
|
||||
const llvm::APSInt &ExtentInt = ExtentCI->getValue();
|
||||
assert(ExtentInt.isNonNegative() || ExtentInt.isUnsigned());
|
||||
// Extents are in bytes but region offsets are in bits. Be careful!
|
||||
|
@ -893,8 +894,8 @@ void invalidateRegionsWorker::VisitBinding(SVal V) {
|
|||
}
|
||||
|
||||
// Is it a LazyCompoundVal? All references get invalidated as well.
|
||||
if (const nonloc::LazyCompoundVal *LCS =
|
||||
dyn_cast<nonloc::LazyCompoundVal>(&V)) {
|
||||
if (llvm::Optional<nonloc::LazyCompoundVal> LCS =
|
||||
V.getAs<nonloc::LazyCompoundVal>()) {
|
||||
|
||||
const RegionStoreManager::SValListTy &Vals = RM.getInterestingValues(*LCS);
|
||||
|
||||
|
@ -938,7 +939,7 @@ void invalidateRegionsWorker::VisitBaseRegion(const MemRegion *baseR) {
|
|||
// a pointer value, but the thing pointed by that pointer may
|
||||
// get invalidated.
|
||||
SVal V = RM.getBinding(B, loc::MemRegionVal(VR));
|
||||
if (const Loc *L = dyn_cast<Loc>(&V)) {
|
||||
if (llvm::Optional<Loc> L = V.getAs<Loc>()) {
|
||||
if (const MemRegion *LR = L->getAsRegion())
|
||||
AddToWorkList(LR);
|
||||
}
|
||||
|
@ -1111,10 +1112,10 @@ RegionStoreManager::getSizeInElements(ProgramStateRef state,
|
|||
/// the array). This is called by ExprEngine when evaluating casts
|
||||
/// from arrays to pointers.
|
||||
SVal RegionStoreManager::ArrayToPointer(Loc Array) {
|
||||
if (!isa<loc::MemRegionVal>(Array))
|
||||
if (!Array.getAs<loc::MemRegionVal>())
|
||||
return UnknownVal();
|
||||
|
||||
const MemRegion* R = cast<loc::MemRegionVal>(&Array)->getRegion();
|
||||
const MemRegion* R = Array.castAs<loc::MemRegionVal>().getRegion();
|
||||
const TypedValueRegion* ArrayR = dyn_cast<TypedValueRegion>(R);
|
||||
|
||||
if (!ArrayR)
|
||||
|
@ -1134,8 +1135,8 @@ SVal RegionStoreManager::ArrayToPointer(Loc Array) {
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
SVal RegionStoreManager::getBinding(RegionBindingsConstRef B, Loc L, QualType T) {
|
||||
assert(!isa<UnknownVal>(L) && "location unknown");
|
||||
assert(!isa<UndefinedVal>(L) && "location undefined");
|
||||
assert(!L.getAs<UnknownVal>() && "location unknown");
|
||||
assert(!L.getAs<UndefinedVal>() && "location undefined");
|
||||
|
||||
// For access to concrete addresses, return UnknownVal. Checks
|
||||
// for null dereferences (and similar errors) are done by checkers, not
|
||||
|
@ -1143,14 +1144,14 @@ SVal RegionStoreManager::getBinding(RegionBindingsConstRef B, Loc L, QualType T)
|
|||
// FIXME: We can consider lazily symbolicating such memory, but we really
|
||||
// should defer this when we can reason easily about symbolicating arrays
|
||||
// of bytes.
|
||||
if (isa<loc::ConcreteInt>(L)) {
|
||||
if (L.getAs<loc::ConcreteInt>()) {
|
||||
return UnknownVal();
|
||||
}
|
||||
if (!isa<loc::MemRegionVal>(L)) {
|
||||
if (!L.getAs<loc::MemRegionVal>()) {
|
||||
return UnknownVal();
|
||||
}
|
||||
|
||||
const MemRegion *MR = cast<loc::MemRegionVal>(L).getRegion();
|
||||
const MemRegion *MR = L.castAs<loc::MemRegionVal>().getRegion();
|
||||
|
||||
if (isa<AllocaRegion>(MR) ||
|
||||
isa<SymbolicRegion>(MR) ||
|
||||
|
@ -1263,8 +1264,8 @@ RegionStoreManager::getLazyBinding(RegionBindingsConstRef B,
|
|||
|
||||
if (originalRegion != R) {
|
||||
if (Optional<SVal> OV = B.getDefaultBinding(R)) {
|
||||
if (const nonloc::LazyCompoundVal *V =
|
||||
dyn_cast<nonloc::LazyCompoundVal>(OV.getPointer()))
|
||||
if (llvm::Optional<nonloc::LazyCompoundVal> V =
|
||||
OV.getPointer()->getAs<nonloc::LazyCompoundVal>())
|
||||
return std::make_pair(V->getStore(), V->getRegion());
|
||||
}
|
||||
}
|
||||
|
@ -1345,7 +1346,8 @@ SVal RegionStoreManager::getBindingForElement(RegionBindingsConstRef B,
|
|||
|
||||
const StringLiteral *Str = StrR->getStringLiteral();
|
||||
SVal Idx = R->getIndex();
|
||||
if (nonloc::ConcreteInt *CI = dyn_cast<nonloc::ConcreteInt>(&Idx)) {
|
||||
if (llvm::Optional<nonloc::ConcreteInt> CI =
|
||||
Idx.getAs<nonloc::ConcreteInt>()) {
|
||||
int64_t i = CI->getValue().getSExtValue();
|
||||
// Abort on string underrun. This can be possible by arbitrary
|
||||
// clients of getBindingForElement().
|
||||
|
@ -1431,7 +1433,7 @@ RegionStoreManager::getBindingForDerivedDefaultValue(RegionBindingsConstRef B,
|
|||
return val;
|
||||
|
||||
// Lazy bindings are handled later.
|
||||
if (isa<nonloc::LazyCompoundVal>(val))
|
||||
if (val.getAs<nonloc::LazyCompoundVal>())
|
||||
return Optional<SVal>();
|
||||
|
||||
llvm_unreachable("Unknown default value");
|
||||
|
@ -1650,9 +1652,8 @@ RegionStoreManager::getInterestingValues(nonloc::LazyCompoundVal LCV) {
|
|||
if (V.isUnknownOrUndef() || V.isConstant())
|
||||
continue;
|
||||
|
||||
const nonloc::LazyCompoundVal *InnerLCV =
|
||||
dyn_cast<nonloc::LazyCompoundVal>(&V);
|
||||
if (InnerLCV) {
|
||||
if (llvm::Optional<nonloc::LazyCompoundVal> InnerLCV =
|
||||
V.getAs<nonloc::LazyCompoundVal>()) {
|
||||
const SValListTy &InnerList = getInterestingValues(*InnerLCV);
|
||||
List.insert(List.end(), InnerList.begin(), InnerList.end());
|
||||
continue;
|
||||
|
@ -1669,9 +1670,8 @@ NonLoc RegionStoreManager::createLazyBinding(RegionBindingsConstRef B,
|
|||
// If we already have a lazy binding, and it's for the whole structure,
|
||||
// don't create a new lazy binding.
|
||||
if (Optional<SVal> V = B.getDefaultBinding(R)) {
|
||||
const nonloc::LazyCompoundVal *LCV =
|
||||
dyn_cast<nonloc::LazyCompoundVal>(V.getPointer());
|
||||
if (LCV) {
|
||||
if (llvm::Optional<nonloc::LazyCompoundVal> LCV =
|
||||
V.getPointer()->getAs<nonloc::LazyCompoundVal>()) {
|
||||
QualType RegionTy = R->getValueType();
|
||||
QualType SourceRegionTy = LCV->getRegion()->getValueType();
|
||||
if (Ctx.hasSameUnqualifiedType(RegionTy, SourceRegionTy))
|
||||
|
@ -1728,8 +1728,8 @@ bool RegionStoreManager::includedInBindings(Store store,
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
StoreRef RegionStoreManager::killBinding(Store ST, Loc L) {
|
||||
if (isa<loc::MemRegionVal>(L))
|
||||
if (const MemRegion* R = cast<loc::MemRegionVal>(L).getRegion())
|
||||
if (llvm::Optional<loc::MemRegionVal> LV = L.getAs<loc::MemRegionVal>())
|
||||
if (const MemRegion* R = LV->getRegion())
|
||||
return StoreRef(getRegionBindings(ST).removeBinding(R)
|
||||
.asImmutableMap()
|
||||
.getRootWithoutRetain(),
|
||||
|
@ -1740,11 +1740,11 @@ StoreRef RegionStoreManager::killBinding(Store ST, Loc L) {
|
|||
|
||||
RegionBindingsRef
|
||||
RegionStoreManager::bind(RegionBindingsConstRef B, Loc L, SVal V) {
|
||||
if (isa<loc::ConcreteInt>(L))
|
||||
if (L.getAs<loc::ConcreteInt>())
|
||||
return B;
|
||||
|
||||
// If we get here, the location should be a region.
|
||||
const MemRegion *R = cast<loc::MemRegionVal>(L).getRegion();
|
||||
const MemRegion *R = L.castAs<loc::MemRegionVal>().getRegion();
|
||||
|
||||
// Check if the region is a struct region.
|
||||
if (const TypedValueRegion* TR = dyn_cast<TypedValueRegion>(R)) {
|
||||
|
@ -1820,18 +1820,18 @@ RegionStoreManager::bindArray(RegionBindingsConstRef B,
|
|||
Size = CAT->getSize().getZExtValue();
|
||||
|
||||
// Check if the init expr is a string literal.
|
||||
if (loc::MemRegionVal *MRV = dyn_cast<loc::MemRegionVal>(&Init)) {
|
||||
if (llvm::Optional<loc::MemRegionVal> MRV = Init.getAs<loc::MemRegionVal>()) {
|
||||
const StringRegion *S = cast<StringRegion>(MRV->getRegion());
|
||||
|
||||
// Treat the string as a lazy compound value.
|
||||
StoreRef store(B.asStore(), *this);
|
||||
nonloc::LazyCompoundVal LCV =
|
||||
cast<nonloc::LazyCompoundVal>(svalBuilder.makeLazyCompoundVal(store, S));
|
||||
nonloc::LazyCompoundVal LCV = svalBuilder.makeLazyCompoundVal(store, S)
|
||||
.castAs<nonloc::LazyCompoundVal>();
|
||||
return bindAggregate(B, R, LCV);
|
||||
}
|
||||
|
||||
// Handle lazy compound values.
|
||||
if (isa<nonloc::LazyCompoundVal>(Init))
|
||||
if (Init.getAs<nonloc::LazyCompoundVal>())
|
||||
return bindAggregate(B, R, Init);
|
||||
|
||||
// Remaining case: explicit compound values.
|
||||
|
@ -1839,7 +1839,7 @@ RegionStoreManager::bindArray(RegionBindingsConstRef B,
|
|||
if (Init.isUnknown())
|
||||
return setImplicitDefaultValue(B, R, ElementTy);
|
||||
|
||||
nonloc::CompoundVal& CV = cast<nonloc::CompoundVal>(Init);
|
||||
const nonloc::CompoundVal& CV = Init.castAs<nonloc::CompoundVal>();
|
||||
nonloc::CompoundVal::iterator VI = CV.begin(), VE = CV.end();
|
||||
uint64_t i = 0;
|
||||
|
||||
|
@ -1877,18 +1877,18 @@ RegionBindingsRef RegionStoreManager::bindVector(RegionBindingsConstRef B,
|
|||
const VectorType *VT = T->getAs<VectorType>(); // Use getAs for typedefs.
|
||||
|
||||
// Handle lazy compound values and symbolic values.
|
||||
if (isa<nonloc::LazyCompoundVal>(V) || isa<nonloc::SymbolVal>(V))
|
||||
if (V.getAs<nonloc::LazyCompoundVal>() || V.getAs<nonloc::SymbolVal>())
|
||||
return bindAggregate(B, R, V);
|
||||
|
||||
// We may get non-CompoundVal accidentally due to imprecise cast logic or
|
||||
// that we are binding symbolic struct value. Kill the field values, and if
|
||||
// the value is symbolic go and bind it as a "default" binding.
|
||||
if (!isa<nonloc::CompoundVal>(V)) {
|
||||
if (!V.getAs<nonloc::CompoundVal>()) {
|
||||
return bindAggregate(B, R, UnknownVal());
|
||||
}
|
||||
|
||||
QualType ElemType = VT->getElementType();
|
||||
nonloc::CompoundVal& CV = cast<nonloc::CompoundVal>(V);
|
||||
nonloc::CompoundVal CV = V.castAs<nonloc::CompoundVal>();
|
||||
nonloc::CompoundVal::iterator VI = CV.begin(), VE = CV.end();
|
||||
unsigned index = 0, numElements = VT->getNumElements();
|
||||
RegionBindingsRef NewB(B);
|
||||
|
@ -1926,16 +1926,16 @@ RegionBindingsRef RegionStoreManager::bindStruct(RegionBindingsConstRef B,
|
|||
return B;
|
||||
|
||||
// Handle lazy compound values and symbolic values.
|
||||
if (isa<nonloc::LazyCompoundVal>(V) || isa<nonloc::SymbolVal>(V))
|
||||
if (V.getAs<nonloc::LazyCompoundVal>() || V.getAs<nonloc::SymbolVal>())
|
||||
return bindAggregate(B, R, V);
|
||||
|
||||
// We may get non-CompoundVal accidentally due to imprecise cast logic or
|
||||
// that we are binding symbolic struct value. Kill the field values, and if
|
||||
// the value is symbolic go and bind it as a "default" binding.
|
||||
if (V.isUnknown() || !isa<nonloc::CompoundVal>(V))
|
||||
if (V.isUnknown() || !V.getAs<nonloc::CompoundVal>())
|
||||
return bindAggregate(B, R, UnknownVal());
|
||||
|
||||
nonloc::CompoundVal& CV = cast<nonloc::CompoundVal>(V);
|
||||
const nonloc::CompoundVal& CV = V.castAs<nonloc::CompoundVal>();
|
||||
nonloc::CompoundVal::iterator VI = CV.begin(), VE = CV.end();
|
||||
|
||||
RecordDecl::field_iterator FI, FE;
|
||||
|
@ -2057,8 +2057,8 @@ void removeDeadBindingsWorker::VisitCluster(const MemRegion *baseR,
|
|||
|
||||
void removeDeadBindingsWorker::VisitBinding(SVal V) {
|
||||
// Is it a LazyCompoundVal? All referenced regions are live as well.
|
||||
if (const nonloc::LazyCompoundVal *LCS =
|
||||
dyn_cast<nonloc::LazyCompoundVal>(&V)) {
|
||||
if (llvm::Optional<nonloc::LazyCompoundVal> LCS =
|
||||
V.getAs<nonloc::LazyCompoundVal>()) {
|
||||
|
||||
const RegionStoreManager::SValListTy &Vals = RM.getInterestingValues(*LCS);
|
||||
|
||||
|
|
|
@ -78,13 +78,14 @@ SVal SValBuilder::convertToArrayIndex(SVal val) {
|
|||
return val;
|
||||
|
||||
// Common case: we have an appropriately sized integer.
|
||||
if (nonloc::ConcreteInt* CI = dyn_cast<nonloc::ConcreteInt>(&val)) {
|
||||
if (llvm::Optional<nonloc::ConcreteInt> CI =
|
||||
val.getAs<nonloc::ConcreteInt>()) {
|
||||
const llvm::APSInt& I = CI->getValue();
|
||||
if (I.getBitWidth() == ArrayIndexWidth && I.isSigned())
|
||||
return val;
|
||||
}
|
||||
|
||||
return evalCastFromNonLoc(cast<NonLoc>(val), ArrayIndexTy);
|
||||
return evalCastFromNonLoc(val.castAs<NonLoc>(), ArrayIndexTy);
|
||||
}
|
||||
|
||||
nonloc::ConcreteInt SValBuilder::makeBoolVal(const CXXBoolLiteralExpr *boolean){
|
||||
|
@ -237,11 +238,13 @@ SVal SValBuilder::makeSymExprValNN(ProgramStateRef State,
|
|||
return makeNonLoc(symLHS, Op, symRHS, ResultTy);
|
||||
|
||||
if (symLHS && symLHS->computeComplexity() < MaxComp)
|
||||
if (const nonloc::ConcreteInt *rInt = dyn_cast<nonloc::ConcreteInt>(&RHS))
|
||||
if (llvm::Optional<nonloc::ConcreteInt> rInt =
|
||||
RHS.getAs<nonloc::ConcreteInt>())
|
||||
return makeNonLoc(symLHS, Op, rInt->getValue(), ResultTy);
|
||||
|
||||
if (symRHS && symRHS->computeComplexity() < MaxComp)
|
||||
if (const nonloc::ConcreteInt *lInt = dyn_cast<nonloc::ConcreteInt>(&LHS))
|
||||
if (llvm::Optional<nonloc::ConcreteInt> lInt =
|
||||
LHS.getAs<nonloc::ConcreteInt>())
|
||||
return makeNonLoc(lInt->getValue(), Op, symRHS, ResultTy);
|
||||
|
||||
return UnknownVal();
|
||||
|
@ -257,30 +260,31 @@ SVal SValBuilder::evalBinOp(ProgramStateRef state, BinaryOperator::Opcode op,
|
|||
if (lhs.isUnknown() || rhs.isUnknown())
|
||||
return UnknownVal();
|
||||
|
||||
if (isa<Loc>(lhs)) {
|
||||
if (isa<Loc>(rhs))
|
||||
return evalBinOpLL(state, op, cast<Loc>(lhs), cast<Loc>(rhs), type);
|
||||
if (llvm::Optional<Loc> LV = lhs.getAs<Loc>()) {
|
||||
if (llvm::Optional<Loc> RV = rhs.getAs<Loc>())
|
||||
return evalBinOpLL(state, op, *LV, *RV, type);
|
||||
|
||||
return evalBinOpLN(state, op, cast<Loc>(lhs), cast<NonLoc>(rhs), type);
|
||||
return evalBinOpLN(state, op, *LV, rhs.castAs<NonLoc>(), type);
|
||||
}
|
||||
|
||||
if (isa<Loc>(rhs)) {
|
||||
if (llvm::Optional<Loc> RV = rhs.getAs<Loc>()) {
|
||||
// Support pointer arithmetic where the addend is on the left
|
||||
// and the pointer on the right.
|
||||
assert(op == BO_Add);
|
||||
|
||||
// Commute the operands.
|
||||
return evalBinOpLN(state, op, cast<Loc>(rhs), cast<NonLoc>(lhs), type);
|
||||
return evalBinOpLN(state, op, *RV, lhs.castAs<NonLoc>(), type);
|
||||
}
|
||||
|
||||
return evalBinOpNN(state, op, cast<NonLoc>(lhs), cast<NonLoc>(rhs), type);
|
||||
return evalBinOpNN(state, op, lhs.castAs<NonLoc>(), rhs.castAs<NonLoc>(),
|
||||
type);
|
||||
}
|
||||
|
||||
DefinedOrUnknownSVal SValBuilder::evalEQ(ProgramStateRef state,
|
||||
DefinedOrUnknownSVal lhs,
|
||||
DefinedOrUnknownSVal rhs) {
|
||||
return cast<DefinedOrUnknownSVal>(evalBinOp(state, BO_EQ, lhs, rhs,
|
||||
Context.IntTy));
|
||||
return evalBinOp(state, BO_EQ, lhs, rhs, Context.IntTy)
|
||||
.castAs<DefinedOrUnknownSVal>();
|
||||
}
|
||||
|
||||
/// Recursively check if the pointer types are equal modulo const, volatile,
|
||||
|
@ -327,11 +331,12 @@ SVal SValBuilder::evalCast(SVal val, QualType castTy, QualType originalTy) {
|
|||
|
||||
// Check for casts from pointers to integers.
|
||||
if (castTy->isIntegerType() && Loc::isLocType(originalTy))
|
||||
return evalCastFromLoc(cast<Loc>(val), castTy);
|
||||
return evalCastFromLoc(val.castAs<Loc>(), castTy);
|
||||
|
||||
// Check for casts from integers to pointers.
|
||||
if (Loc::isLocType(castTy) && originalTy->isIntegerType()) {
|
||||
if (nonloc::LocAsInteger *LV = dyn_cast<nonloc::LocAsInteger>(&val)) {
|
||||
if (llvm::Optional<nonloc::LocAsInteger> LV =
|
||||
val.getAs<nonloc::LocAsInteger>()) {
|
||||
if (const MemRegion *R = LV->getLoc().getAsRegion()) {
|
||||
StoreManager &storeMgr = StateMgr.getStoreManager();
|
||||
R = storeMgr.castRegion(R, castTy);
|
||||
|
@ -351,7 +356,7 @@ SVal SValBuilder::evalCast(SVal val, QualType castTy, QualType originalTy) {
|
|||
// Check for casts from array type to another type.
|
||||
if (originalTy->isArrayType()) {
|
||||
// We will always decay to a pointer.
|
||||
val = StateMgr.ArrayToPointer(cast<Loc>(val));
|
||||
val = StateMgr.ArrayToPointer(val.castAs<Loc>());
|
||||
|
||||
// Are we casting from an array to a pointer? If so just pass on
|
||||
// the decayed value.
|
||||
|
@ -366,7 +371,7 @@ SVal SValBuilder::evalCast(SVal val, QualType castTy, QualType originalTy) {
|
|||
// need the original decayed type.
|
||||
// QualType elemTy = cast<ArrayType>(originalTy)->getElementType();
|
||||
// QualType pointerTy = C.getPointerType(elemTy);
|
||||
return evalCastFromLoc(cast<Loc>(val), castTy);
|
||||
return evalCastFromLoc(val.castAs<Loc>(), castTy);
|
||||
}
|
||||
|
||||
// Check for casts from a region to a specific type.
|
||||
|
|
|
@ -30,13 +30,13 @@ using llvm::APSInt;
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
bool SVal::hasConjuredSymbol() const {
|
||||
if (const nonloc::SymbolVal* SV = dyn_cast<nonloc::SymbolVal>(this)) {
|
||||
if (llvm::Optional<nonloc::SymbolVal> SV = getAs<nonloc::SymbolVal>()) {
|
||||
SymbolRef sym = SV->getSymbol();
|
||||
if (isa<SymbolConjured>(sym))
|
||||
return true;
|
||||
}
|
||||
|
||||
if (const loc::MemRegionVal *RV = dyn_cast<loc::MemRegionVal>(this)) {
|
||||
if (llvm::Optional<loc::MemRegionVal> RV = getAs<loc::MemRegionVal>()) {
|
||||
const MemRegion *R = RV->getRegion();
|
||||
if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R)) {
|
||||
SymbolRef sym = SR->getSymbol();
|
||||
|
@ -49,7 +49,7 @@ bool SVal::hasConjuredSymbol() const {
|
|||
}
|
||||
|
||||
const FunctionDecl *SVal::getAsFunctionDecl() const {
|
||||
if (const loc::MemRegionVal* X = dyn_cast<loc::MemRegionVal>(this)) {
|
||||
if (llvm::Optional<loc::MemRegionVal> X = getAs<loc::MemRegionVal>()) {
|
||||
const MemRegion* R = X->getRegion();
|
||||
if (const FunctionTextRegion *CTR = R->getAs<FunctionTextRegion>())
|
||||
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CTR->getDecl()))
|
||||
|
@ -66,10 +66,10 @@ const FunctionDecl *SVal::getAsFunctionDecl() const {
|
|||
/// region. If that is the case, gets the underlining region.
|
||||
SymbolRef SVal::getAsLocSymbol() const {
|
||||
// FIXME: should we consider SymbolRef wrapped in CodeTextRegion?
|
||||
if (const nonloc::LocAsInteger *X = dyn_cast<nonloc::LocAsInteger>(this))
|
||||
if (llvm::Optional<nonloc::LocAsInteger> X = getAs<nonloc::LocAsInteger>())
|
||||
return X->getLoc().getAsLocSymbol();
|
||||
|
||||
if (const loc::MemRegionVal *X = dyn_cast<loc::MemRegionVal>(this)) {
|
||||
if (llvm::Optional<loc::MemRegionVal> X = getAs<loc::MemRegionVal>()) {
|
||||
const MemRegion *R = X->stripCasts();
|
||||
if (const SymbolicRegion *SymR = dyn_cast<SymbolicRegion>(R))
|
||||
return SymR->getSymbol();
|
||||
|
@ -79,7 +79,7 @@ SymbolRef SVal::getAsLocSymbol() const {
|
|||
|
||||
/// Get the symbol in the SVal or its base region.
|
||||
SymbolRef SVal::getLocSymbolInBase() const {
|
||||
const loc::MemRegionVal *X = dyn_cast<loc::MemRegionVal>(this);
|
||||
llvm::Optional<loc::MemRegionVal> X = getAs<loc::MemRegionVal>();
|
||||
|
||||
if (!X)
|
||||
return 0;
|
||||
|
@ -102,7 +102,7 @@ SymbolRef SVal::getLocSymbolInBase() const {
|
|||
/// Otherwise return 0.
|
||||
SymbolRef SVal::getAsSymbol() const {
|
||||
// FIXME: should we consider SymbolRef wrapped in CodeTextRegion?
|
||||
if (const nonloc::SymbolVal *X = dyn_cast<nonloc::SymbolVal>(this))
|
||||
if (llvm::Optional<nonloc::SymbolVal> X = getAs<nonloc::SymbolVal>())
|
||||
return X->getSymbol();
|
||||
|
||||
return getAsLocSymbol();
|
||||
|
@ -111,7 +111,7 @@ SymbolRef SVal::getAsSymbol() const {
|
|||
/// getAsSymbolicExpression - If this Sval wraps a symbolic expression then
|
||||
/// return that expression. Otherwise return NULL.
|
||||
const SymExpr *SVal::getAsSymbolicExpression() const {
|
||||
if (const nonloc::SymbolVal *X = dyn_cast<nonloc::SymbolVal>(this))
|
||||
if (llvm::Optional<nonloc::SymbolVal> X = getAs<nonloc::SymbolVal>())
|
||||
return X->getSymbol();
|
||||
|
||||
return getAsSymbol();
|
||||
|
@ -125,12 +125,11 @@ const SymExpr* SVal::getAsSymExpr() const {
|
|||
}
|
||||
|
||||
const MemRegion *SVal::getAsRegion() const {
|
||||
if (const loc::MemRegionVal *X = dyn_cast<loc::MemRegionVal>(this))
|
||||
if (llvm::Optional<loc::MemRegionVal> X = getAs<loc::MemRegionVal>())
|
||||
return X->getRegion();
|
||||
|
||||
if (const nonloc::LocAsInteger *X = dyn_cast<nonloc::LocAsInteger>(this)) {
|
||||
if (llvm::Optional<nonloc::LocAsInteger> X = getAs<nonloc::LocAsInteger>())
|
||||
return X->getLoc().getAsRegion();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -165,16 +164,15 @@ nonloc::CompoundVal::iterator nonloc::CompoundVal::end() const {
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
bool SVal::isConstant() const {
|
||||
return isa<nonloc::ConcreteInt>(this) || isa<loc::ConcreteInt>(this);
|
||||
return getAs<nonloc::ConcreteInt>() || getAs<loc::ConcreteInt>();
|
||||
}
|
||||
|
||||
bool SVal::isConstant(int I) const {
|
||||
if (isa<loc::ConcreteInt>(*this))
|
||||
return cast<loc::ConcreteInt>(*this).getValue() == I;
|
||||
else if (isa<nonloc::ConcreteInt>(*this))
|
||||
return cast<nonloc::ConcreteInt>(*this).getValue() == I;
|
||||
else
|
||||
return false;
|
||||
if (llvm::Optional<loc::ConcreteInt> LV = getAs<loc::ConcreteInt>())
|
||||
return LV->getValue() == I;
|
||||
if (llvm::Optional<nonloc::ConcreteInt> NV = getAs<nonloc::ConcreteInt>())
|
||||
return NV->getValue() == I;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SVal::isZeroConstant() const {
|
||||
|
@ -239,10 +237,10 @@ void SVal::dumpToStream(raw_ostream &os) const {
|
|||
os << "Unknown";
|
||||
break;
|
||||
case NonLocKind:
|
||||
cast<NonLoc>(this)->dumpToStream(os);
|
||||
castAs<NonLoc>().dumpToStream(os);
|
||||
break;
|
||||
case LocKind:
|
||||
cast<Loc>(this)->dumpToStream(os);
|
||||
castAs<Loc>().dumpToStream(os);
|
||||
break;
|
||||
case UndefinedKind:
|
||||
os << "Undefined";
|
||||
|
@ -253,7 +251,7 @@ void SVal::dumpToStream(raw_ostream &os) const {
|
|||
void NonLoc::dumpToStream(raw_ostream &os) const {
|
||||
switch (getSubKind()) {
|
||||
case nonloc::ConcreteIntKind: {
|
||||
const nonloc::ConcreteInt& C = *cast<nonloc::ConcreteInt>(this);
|
||||
const nonloc::ConcreteInt& C = castAs<nonloc::ConcreteInt>();
|
||||
if (C.getValue().isUnsigned())
|
||||
os << C.getValue().getZExtValue();
|
||||
else
|
||||
|
@ -263,16 +261,16 @@ void NonLoc::dumpToStream(raw_ostream &os) const {
|
|||
break;
|
||||
}
|
||||
case nonloc::SymbolValKind: {
|
||||
os << cast<nonloc::SymbolVal>(this)->getSymbol();
|
||||
os << castAs<nonloc::SymbolVal>().getSymbol();
|
||||
break;
|
||||
}
|
||||
case nonloc::LocAsIntegerKind: {
|
||||
const nonloc::LocAsInteger& C = *cast<nonloc::LocAsInteger>(this);
|
||||
const nonloc::LocAsInteger& C = castAs<nonloc::LocAsInteger>();
|
||||
os << C.getLoc() << " [as " << C.getNumBits() << " bit integer]";
|
||||
break;
|
||||
}
|
||||
case nonloc::CompoundValKind: {
|
||||
const nonloc::CompoundVal& C = *cast<nonloc::CompoundVal>(this);
|
||||
const nonloc::CompoundVal& C = castAs<nonloc::CompoundVal>();
|
||||
os << "compoundVal{";
|
||||
bool first = true;
|
||||
for (nonloc::CompoundVal::iterator I=C.begin(), E=C.end(); I!=E; ++I) {
|
||||
|
@ -288,7 +286,7 @@ void NonLoc::dumpToStream(raw_ostream &os) const {
|
|||
break;
|
||||
}
|
||||
case nonloc::LazyCompoundValKind: {
|
||||
const nonloc::LazyCompoundVal &C = *cast<nonloc::LazyCompoundVal>(this);
|
||||
const nonloc::LazyCompoundVal &C = castAs<nonloc::LazyCompoundVal>();
|
||||
os << "lazyCompoundVal{" << const_cast<void *>(C.getStore())
|
||||
<< ',' << C.getRegion()
|
||||
<< '}';
|
||||
|
@ -303,13 +301,13 @@ void NonLoc::dumpToStream(raw_ostream &os) const {
|
|||
void Loc::dumpToStream(raw_ostream &os) const {
|
||||
switch (getSubKind()) {
|
||||
case loc::ConcreteIntKind:
|
||||
os << cast<loc::ConcreteInt>(this)->getValue().getZExtValue() << " (Loc)";
|
||||
os << castAs<loc::ConcreteInt>().getValue().getZExtValue() << " (Loc)";
|
||||
break;
|
||||
case loc::GotoLabelKind:
|
||||
os << "&&" << cast<loc::GotoLabel>(this)->getLabel()->getName();
|
||||
os << "&&" << castAs<loc::GotoLabel>().getLabel()->getName();
|
||||
break;
|
||||
case loc::MemRegionKind:
|
||||
os << '&' << cast<loc::MemRegionVal>(this)->getRegion()->getString();
|
||||
os << '&' << castAs<loc::MemRegionVal>().getRegion()->getString();
|
||||
break;
|
||||
default:
|
||||
llvm_unreachable("Pretty-printing not implemented for this Loc.");
|
||||
|
|
|
@ -24,7 +24,7 @@ namespace ento {
|
|||
SimpleConstraintManager::~SimpleConstraintManager() {}
|
||||
|
||||
bool SimpleConstraintManager::canReasonAbout(SVal X) const {
|
||||
nonloc::SymbolVal *SymVal = dyn_cast<nonloc::SymbolVal>(&X);
|
||||
llvm::Optional<nonloc::SymbolVal> SymVal = X.getAs<nonloc::SymbolVal>();
|
||||
if (SymVal && SymVal->isExpression()) {
|
||||
const SymExpr *SE = SymVal->getSymbol();
|
||||
|
||||
|
@ -58,10 +58,9 @@ bool SimpleConstraintManager::canReasonAbout(SVal X) const {
|
|||
ProgramStateRef SimpleConstraintManager::assume(ProgramStateRef state,
|
||||
DefinedSVal Cond,
|
||||
bool Assumption) {
|
||||
if (isa<NonLoc>(Cond))
|
||||
return assume(state, cast<NonLoc>(Cond), Assumption);
|
||||
else
|
||||
return assume(state, cast<Loc>(Cond), Assumption);
|
||||
if (llvm::Optional<NonLoc> NV = Cond.getAs<NonLoc>())
|
||||
return assume(state, *NV, Assumption);
|
||||
return assume(state, Cond.castAs<Loc>(), Assumption);
|
||||
}
|
||||
|
||||
ProgramStateRef SimpleConstraintManager::assume(ProgramStateRef state, Loc cond,
|
||||
|
@ -82,7 +81,7 @@ ProgramStateRef SimpleConstraintManager::assumeAux(ProgramStateRef state,
|
|||
case loc::MemRegionKind: {
|
||||
// FIXME: Should this go into the storemanager?
|
||||
|
||||
const MemRegion *R = cast<loc::MemRegionVal>(Cond).getRegion();
|
||||
const MemRegion *R = Cond.castAs<loc::MemRegionVal>().getRegion();
|
||||
const SubRegion *SubR = dyn_cast<SubRegion>(R);
|
||||
|
||||
while (SubR) {
|
||||
|
@ -104,7 +103,7 @@ ProgramStateRef SimpleConstraintManager::assumeAux(ProgramStateRef state,
|
|||
return Assumption ? state : NULL;
|
||||
|
||||
case loc::ConcreteIntKind: {
|
||||
bool b = cast<loc::ConcreteInt>(Cond).getValue() != 0;
|
||||
bool b = Cond.castAs<loc::ConcreteInt>().getValue() != 0;
|
||||
bool isFeasible = b ? Assumption : !Assumption;
|
||||
return isFeasible ? state : NULL;
|
||||
}
|
||||
|
@ -172,7 +171,7 @@ ProgramStateRef SimpleConstraintManager::assumeAux(ProgramStateRef state,
|
|||
llvm_unreachable("'Assume' not implemented for this NonLoc");
|
||||
|
||||
case nonloc::SymbolValKind: {
|
||||
nonloc::SymbolVal& SV = cast<nonloc::SymbolVal>(Cond);
|
||||
nonloc::SymbolVal SV = Cond.castAs<nonloc::SymbolVal>();
|
||||
SymbolRef sym = SV.getSymbol();
|
||||
assert(sym);
|
||||
|
||||
|
@ -204,13 +203,13 @@ ProgramStateRef SimpleConstraintManager::assumeAux(ProgramStateRef state,
|
|||
}
|
||||
|
||||
case nonloc::ConcreteIntKind: {
|
||||
bool b = cast<nonloc::ConcreteInt>(Cond).getValue() != 0;
|
||||
bool b = Cond.castAs<nonloc::ConcreteInt>().getValue() != 0;
|
||||
bool isFeasible = b ? Assumption : !Assumption;
|
||||
return isFeasible ? state : NULL;
|
||||
}
|
||||
|
||||
case nonloc::LocAsIntegerKind:
|
||||
return assumeAux(state, cast<nonloc::LocAsInteger>(Cond).getLoc(),
|
||||
return assumeAux(state, Cond.castAs<nonloc::LocAsInteger>().getLoc(),
|
||||
Assumption);
|
||||
} // end switch
|
||||
}
|
||||
|
|
|
@ -60,16 +60,17 @@ SValBuilder *ento::createSimpleSValBuilder(llvm::BumpPtrAllocator &alloc,
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
SVal SimpleSValBuilder::dispatchCast(SVal Val, QualType CastTy) {
|
||||
assert(isa<Loc>(&Val) || isa<NonLoc>(&Val));
|
||||
return isa<Loc>(Val) ? evalCastFromLoc(cast<Loc>(Val), CastTy)
|
||||
: evalCastFromNonLoc(cast<NonLoc>(Val), CastTy);
|
||||
assert(Val.getAs<Loc>() || Val.getAs<NonLoc>());
|
||||
return Val.getAs<Loc>() ? evalCastFromLoc(Val.castAs<Loc>(), CastTy)
|
||||
: evalCastFromNonLoc(Val.castAs<NonLoc>(), CastTy);
|
||||
}
|
||||
|
||||
SVal SimpleSValBuilder::evalCastFromNonLoc(NonLoc val, QualType castTy) {
|
||||
|
||||
bool isLocType = Loc::isLocType(castTy);
|
||||
|
||||
if (nonloc::LocAsInteger *LI = dyn_cast<nonloc::LocAsInteger>(&val)) {
|
||||
if (llvm::Optional<nonloc::LocAsInteger> LI =
|
||||
val.getAs<nonloc::LocAsInteger>()) {
|
||||
if (isLocType)
|
||||
return LI->getLoc();
|
||||
|
||||
|
@ -98,12 +99,12 @@ SVal SimpleSValBuilder::evalCastFromNonLoc(NonLoc val, QualType castTy) {
|
|||
}
|
||||
|
||||
// If value is a non integer constant, produce unknown.
|
||||
if (!isa<nonloc::ConcreteInt>(val))
|
||||
if (!val.getAs<nonloc::ConcreteInt>())
|
||||
return UnknownVal();
|
||||
|
||||
// Handle casts to a boolean type.
|
||||
if (castTy->isBooleanType()) {
|
||||
bool b = cast<nonloc::ConcreteInt>(val).getValue().getBoolValue();
|
||||
bool b = val.castAs<nonloc::ConcreteInt>().getValue().getBoolValue();
|
||||
return makeTruthVal(b, castTy);
|
||||
}
|
||||
|
||||
|
@ -112,7 +113,7 @@ SVal SimpleSValBuilder::evalCastFromNonLoc(NonLoc val, QualType castTy) {
|
|||
if (!isLocType && !castTy->isIntegerType())
|
||||
return UnknownVal();
|
||||
|
||||
llvm::APSInt i = cast<nonloc::ConcreteInt>(val).getValue();
|
||||
llvm::APSInt i = val.castAs<nonloc::ConcreteInt>().getValue();
|
||||
BasicVals.getAPSIntType(castTy).apply(i);
|
||||
|
||||
if (isLocType)
|
||||
|
@ -140,10 +141,10 @@ SVal SimpleSValBuilder::evalCastFromLoc(Loc val, QualType castTy) {
|
|||
if (castTy->isIntegerType()) {
|
||||
unsigned BitWidth = Context.getTypeSize(castTy);
|
||||
|
||||
if (!isa<loc::ConcreteInt>(val))
|
||||
if (!val.getAs<loc::ConcreteInt>())
|
||||
return makeLocAsInteger(val, BitWidth);
|
||||
|
||||
llvm::APSInt i = cast<loc::ConcreteInt>(val).getValue();
|
||||
llvm::APSInt i = val.castAs<loc::ConcreteInt>().getValue();
|
||||
BasicVals.getAPSIntType(castTy).apply(i);
|
||||
return makeIntVal(i);
|
||||
}
|
||||
|
@ -161,7 +162,7 @@ SVal SimpleSValBuilder::evalCastFromLoc(Loc val, QualType castTy) {
|
|||
SVal SimpleSValBuilder::evalMinus(NonLoc val) {
|
||||
switch (val.getSubKind()) {
|
||||
case nonloc::ConcreteIntKind:
|
||||
return cast<nonloc::ConcreteInt>(val).evalMinus(*this);
|
||||
return val.castAs<nonloc::ConcreteInt>().evalMinus(*this);
|
||||
default:
|
||||
return UnknownVal();
|
||||
}
|
||||
|
@ -170,7 +171,7 @@ SVal SimpleSValBuilder::evalMinus(NonLoc val) {
|
|||
SVal SimpleSValBuilder::evalComplement(NonLoc X) {
|
||||
switch (X.getSubKind()) {
|
||||
case nonloc::ConcreteIntKind:
|
||||
return cast<nonloc::ConcreteInt>(X).evalComplement(*this);
|
||||
return X.castAs<nonloc::ConcreteInt>().evalComplement(*this);
|
||||
default:
|
||||
return UnknownVal();
|
||||
}
|
||||
|
@ -337,15 +338,15 @@ SVal SimpleSValBuilder::evalBinOpNN(ProgramStateRef state,
|
|||
default:
|
||||
return makeSymExprValNN(state, op, lhs, rhs, resultTy);
|
||||
case nonloc::LocAsIntegerKind: {
|
||||
Loc lhsL = cast<nonloc::LocAsInteger>(lhs).getLoc();
|
||||
Loc lhsL = lhs.castAs<nonloc::LocAsInteger>().getLoc();
|
||||
switch (rhs.getSubKind()) {
|
||||
case nonloc::LocAsIntegerKind:
|
||||
return evalBinOpLL(state, op, lhsL,
|
||||
cast<nonloc::LocAsInteger>(rhs).getLoc(),
|
||||
rhs.castAs<nonloc::LocAsInteger>().getLoc(),
|
||||
resultTy);
|
||||
case nonloc::ConcreteIntKind: {
|
||||
// Transform the integer into a location and compare.
|
||||
llvm::APSInt i = cast<nonloc::ConcreteInt>(rhs).getValue();
|
||||
llvm::APSInt i = rhs.castAs<nonloc::ConcreteInt>().getValue();
|
||||
BasicVals.getAPSIntType(Context.VoidPtrTy).apply(i);
|
||||
return evalBinOpLL(state, op, lhsL, makeLoc(i), resultTy);
|
||||
}
|
||||
|
@ -362,7 +363,7 @@ SVal SimpleSValBuilder::evalBinOpNN(ProgramStateRef state,
|
|||
}
|
||||
}
|
||||
case nonloc::ConcreteIntKind: {
|
||||
llvm::APSInt LHSValue = cast<nonloc::ConcreteInt>(lhs).getValue();
|
||||
llvm::APSInt LHSValue = lhs.castAs<nonloc::ConcreteInt>().getValue();
|
||||
|
||||
// If we're dealing with two known constants, just perform the operation.
|
||||
if (const llvm::APSInt *KnownRHSValue = getKnownValue(state, rhs)) {
|
||||
|
@ -425,7 +426,7 @@ SVal SimpleSValBuilder::evalBinOpNN(ProgramStateRef state,
|
|||
}
|
||||
case nonloc::SymbolValKind: {
|
||||
// We only handle LHS as simple symbols or SymIntExprs.
|
||||
SymbolRef Sym = cast<nonloc::SymbolVal>(lhs).getSymbol();
|
||||
SymbolRef Sym = lhs.castAs<nonloc::SymbolVal>().getSymbol();
|
||||
|
||||
// LHS is a symbolic expression.
|
||||
if (const SymIntExpr *symIntExpr = dyn_cast<SymIntExpr>(Sym)) {
|
||||
|
@ -601,15 +602,15 @@ SVal SimpleSValBuilder::evalBinOpLL(ProgramStateRef state,
|
|||
if (!BinaryOperator::isComparisonOp(op))
|
||||
return UnknownVal();
|
||||
|
||||
const llvm::APSInt &lVal = cast<loc::ConcreteInt>(lhs).getValue();
|
||||
const llvm::APSInt &lVal = lhs.castAs<loc::ConcreteInt>().getValue();
|
||||
return makeNonLoc(rSym, ReverseComparison(op), lVal, resultTy);
|
||||
}
|
||||
|
||||
// If both operands are constants, just perform the operation.
|
||||
if (loc::ConcreteInt *rInt = dyn_cast<loc::ConcreteInt>(&rhs)) {
|
||||
SVal ResultVal = cast<loc::ConcreteInt>(lhs).evalBinOp(BasicVals, op,
|
||||
*rInt);
|
||||
if (Loc *Result = dyn_cast<Loc>(&ResultVal))
|
||||
if (llvm::Optional<loc::ConcreteInt> rInt = rhs.getAs<loc::ConcreteInt>()) {
|
||||
SVal ResultVal =
|
||||
lhs.castAs<loc::ConcreteInt>().evalBinOp(BasicVals, op, *rInt);
|
||||
if (llvm::Optional<Loc> Result = ResultVal.getAs<Loc>())
|
||||
return evalCastFromLoc(*Result, resultTy);
|
||||
else
|
||||
return UnknownVal();
|
||||
|
@ -619,7 +620,7 @@ SVal SimpleSValBuilder::evalBinOpLL(ProgramStateRef state,
|
|||
// This must come after the test if the RHS is a symbol, which is used to
|
||||
// build constraints. The address of any non-symbolic region is guaranteed
|
||||
// to be non-NULL, as is any label.
|
||||
assert(isa<loc::MemRegionVal>(rhs) || isa<loc::GotoLabel>(rhs));
|
||||
assert(rhs.getAs<loc::MemRegionVal>() || rhs.getAs<loc::GotoLabel>());
|
||||
if (lhs.isZeroConstant()) {
|
||||
switch (op) {
|
||||
default:
|
||||
|
@ -640,7 +641,7 @@ SVal SimpleSValBuilder::evalBinOpLL(ProgramStateRef state,
|
|||
return UnknownVal();
|
||||
}
|
||||
case loc::MemRegionKind: {
|
||||
if (loc::ConcreteInt *rInt = dyn_cast<loc::ConcreteInt>(&rhs)) {
|
||||
if (llvm::Optional<loc::ConcreteInt> rInt = rhs.getAs<loc::ConcreteInt>()) {
|
||||
// If one of the operands is a symbol and the other is a constant,
|
||||
// build an expression for use by the constraint manager.
|
||||
if (SymbolRef lSym = lhs.getAsLocSymbol())
|
||||
|
@ -738,21 +739,21 @@ SVal SimpleSValBuilder::evalBinOpLL(ProgramStateRef state,
|
|||
// Get the left index and cast it to the correct type.
|
||||
// If the index is unknown or undefined, bail out here.
|
||||
SVal LeftIndexVal = LeftER->getIndex();
|
||||
NonLoc *LeftIndex = dyn_cast<NonLoc>(&LeftIndexVal);
|
||||
llvm::Optional<NonLoc> LeftIndex = LeftIndexVal.getAs<NonLoc>();
|
||||
if (!LeftIndex)
|
||||
return UnknownVal();
|
||||
LeftIndexVal = evalCastFromNonLoc(*LeftIndex, ArrayIndexTy);
|
||||
LeftIndex = dyn_cast<NonLoc>(&LeftIndexVal);
|
||||
LeftIndex = LeftIndexVal.getAs<NonLoc>();
|
||||
if (!LeftIndex)
|
||||
return UnknownVal();
|
||||
|
||||
// Do the same for the right index.
|
||||
SVal RightIndexVal = RightER->getIndex();
|
||||
NonLoc *RightIndex = dyn_cast<NonLoc>(&RightIndexVal);
|
||||
llvm::Optional<NonLoc> RightIndex = RightIndexVal.getAs<NonLoc>();
|
||||
if (!RightIndex)
|
||||
return UnknownVal();
|
||||
RightIndexVal = evalCastFromNonLoc(*RightIndex, ArrayIndexTy);
|
||||
RightIndex = dyn_cast<NonLoc>(&RightIndexVal);
|
||||
RightIndex = RightIndexVal.getAs<NonLoc>();
|
||||
if (!RightIndex)
|
||||
return UnknownVal();
|
||||
|
||||
|
@ -862,7 +863,8 @@ SVal SimpleSValBuilder::evalBinOpLN(ProgramStateRef state,
|
|||
// can generate comparisons that trigger this code.
|
||||
// FIXME: Are all locations guaranteed to have pointer width?
|
||||
if (BinaryOperator::isComparisonOp(op)) {
|
||||
if (nonloc::ConcreteInt *rhsInt = dyn_cast<nonloc::ConcreteInt>(&rhs)) {
|
||||
if (llvm::Optional<nonloc::ConcreteInt> rhsInt =
|
||||
rhs.getAs<nonloc::ConcreteInt>()) {
|
||||
const llvm::APSInt *x = &rhsInt->getValue();
|
||||
ASTContext &ctx = Context;
|
||||
if (ctx.getTypeSize(ctx.VoidPtrTy) == x->getBitWidth()) {
|
||||
|
@ -879,8 +881,10 @@ SVal SimpleSValBuilder::evalBinOpLN(ProgramStateRef state,
|
|||
// We are dealing with pointer arithmetic.
|
||||
|
||||
// Handle pointer arithmetic on constant values.
|
||||
if (nonloc::ConcreteInt *rhsInt = dyn_cast<nonloc::ConcreteInt>(&rhs)) {
|
||||
if (loc::ConcreteInt *lhsInt = dyn_cast<loc::ConcreteInt>(&lhs)) {
|
||||
if (llvm::Optional<nonloc::ConcreteInt> rhsInt =
|
||||
rhs.getAs<nonloc::ConcreteInt>()) {
|
||||
if (llvm::Optional<loc::ConcreteInt> lhsInt =
|
||||
lhs.getAs<loc::ConcreteInt>()) {
|
||||
const llvm::APSInt &leftI = lhsInt->getValue();
|
||||
assert(leftI.isUnsigned());
|
||||
llvm::APSInt rightI(rhsInt->getValue(), /* isUnsigned */ true);
|
||||
|
@ -910,7 +914,7 @@ SVal SimpleSValBuilder::evalBinOpLN(ProgramStateRef state,
|
|||
|
||||
// Handle cases where 'lhs' is a region.
|
||||
if (const MemRegion *region = lhs.getAsRegion()) {
|
||||
rhs = cast<NonLoc>(convertToArrayIndex(rhs));
|
||||
rhs = convertToArrayIndex(rhs).castAs<NonLoc>();
|
||||
SVal index = UnknownVal();
|
||||
const MemRegion *superR = 0;
|
||||
QualType elementType;
|
||||
|
@ -929,7 +933,7 @@ SVal SimpleSValBuilder::evalBinOpLN(ProgramStateRef state,
|
|||
elementType = resultTy->getPointeeType();
|
||||
}
|
||||
|
||||
if (NonLoc *indexV = dyn_cast<NonLoc>(&index)) {
|
||||
if (llvm::Optional<NonLoc> indexV = index.getAs<NonLoc>()) {
|
||||
return loc::MemRegionVal(MemMgr.getElementRegion(elementType, *indexV,
|
||||
superR, getContext()));
|
||||
}
|
||||
|
@ -942,10 +946,10 @@ const llvm::APSInt *SimpleSValBuilder::getKnownValue(ProgramStateRef state,
|
|||
if (V.isUnknownOrUndef())
|
||||
return NULL;
|
||||
|
||||
if (loc::ConcreteInt* X = dyn_cast<loc::ConcreteInt>(&V))
|
||||
if (llvm::Optional<loc::ConcreteInt> X = V.getAs<loc::ConcreteInt>())
|
||||
return &X->getValue();
|
||||
|
||||
if (nonloc::ConcreteInt* X = dyn_cast<nonloc::ConcreteInt>(&V))
|
||||
if (llvm::Optional<nonloc::ConcreteInt> X = V.getAs<nonloc::ConcreteInt>())
|
||||
return &X->getValue();
|
||||
|
||||
if (SymbolRef Sym = V.getAsSymbol())
|
||||
|
|
|
@ -270,7 +270,8 @@ SVal StoreManager::evalDerivedToBase(SVal Derived, const CXXBasePath &Path) {
|
|||
}
|
||||
|
||||
SVal StoreManager::evalDerivedToBase(SVal Derived, QualType BaseType) {
|
||||
loc::MemRegionVal *DerivedRegVal = dyn_cast<loc::MemRegionVal>(&Derived);
|
||||
llvm::Optional<loc::MemRegionVal> DerivedRegVal =
|
||||
Derived.getAs<loc::MemRegionVal>();
|
||||
if (!DerivedRegVal)
|
||||
return Derived;
|
||||
|
||||
|
@ -289,7 +290,8 @@ SVal StoreManager::evalDynamicCast(SVal Base, QualType DerivedType,
|
|||
bool &Failed) {
|
||||
Failed = false;
|
||||
|
||||
loc::MemRegionVal *BaseRegVal = dyn_cast<loc::MemRegionVal>(&Base);
|
||||
llvm::Optional<loc::MemRegionVal> BaseRegVal =
|
||||
Base.getAs<loc::MemRegionVal>();
|
||||
if (!BaseRegVal)
|
||||
return UnknownVal();
|
||||
const MemRegion *BaseRegion = BaseRegVal->stripCasts(/*StripBases=*/false);
|
||||
|
@ -373,12 +375,12 @@ SVal StoreManager::getLValueFieldOrIvar(const Decl *D, SVal Base) {
|
|||
if (Base.isUnknownOrUndef())
|
||||
return Base;
|
||||
|
||||
Loc BaseL = cast<Loc>(Base);
|
||||
Loc BaseL = Base.castAs<Loc>();
|
||||
const MemRegion* BaseR = 0;
|
||||
|
||||
switch (BaseL.getSubKind()) {
|
||||
case loc::MemRegionKind:
|
||||
BaseR = cast<loc::MemRegionVal>(BaseL).getRegion();
|
||||
BaseR = BaseL.castAs<loc::MemRegionVal>().getRegion();
|
||||
break;
|
||||
|
||||
case loc::GotoLabelKind:
|
||||
|
@ -415,16 +417,16 @@ SVal StoreManager::getLValueElement(QualType elementType, NonLoc Offset,
|
|||
// FIXME: For absolute pointer addresses, we just return that value back as
|
||||
// well, although in reality we should return the offset added to that
|
||||
// value.
|
||||
if (Base.isUnknownOrUndef() || isa<loc::ConcreteInt>(Base))
|
||||
if (Base.isUnknownOrUndef() || Base.getAs<loc::ConcreteInt>())
|
||||
return Base;
|
||||
|
||||
const MemRegion* BaseRegion = cast<loc::MemRegionVal>(Base).getRegion();
|
||||
const MemRegion* BaseRegion = Base.castAs<loc::MemRegionVal>().getRegion();
|
||||
|
||||
// Pointer of any type can be cast and used as array base.
|
||||
const ElementRegion *ElemR = dyn_cast<ElementRegion>(BaseRegion);
|
||||
|
||||
// Convert the offset to the appropriate size and signedness.
|
||||
Offset = cast<NonLoc>(svalBuilder.convertToArrayIndex(Offset));
|
||||
Offset = svalBuilder.convertToArrayIndex(Offset).castAs<NonLoc>();
|
||||
|
||||
if (!ElemR) {
|
||||
//
|
||||
|
@ -442,15 +444,16 @@ SVal StoreManager::getLValueElement(QualType elementType, NonLoc Offset,
|
|||
|
||||
SVal BaseIdx = ElemR->getIndex();
|
||||
|
||||
if (!isa<nonloc::ConcreteInt>(BaseIdx))
|
||||
if (!BaseIdx.getAs<nonloc::ConcreteInt>())
|
||||
return UnknownVal();
|
||||
|
||||
const llvm::APSInt& BaseIdxI = cast<nonloc::ConcreteInt>(BaseIdx).getValue();
|
||||
const llvm::APSInt &BaseIdxI =
|
||||
BaseIdx.castAs<nonloc::ConcreteInt>().getValue();
|
||||
|
||||
// Only allow non-integer offsets if the base region has no offset itself.
|
||||
// FIXME: This is a somewhat arbitrary restriction. We should be using
|
||||
// SValBuilder here to add the two offsets without checking their types.
|
||||
if (!isa<nonloc::ConcreteInt>(Offset)) {
|
||||
if (!Offset.getAs<nonloc::ConcreteInt>()) {
|
||||
if (isa<ElementRegion>(BaseRegion->StripCasts()))
|
||||
return UnknownVal();
|
||||
|
||||
|
@ -459,7 +462,7 @@ SVal StoreManager::getLValueElement(QualType elementType, NonLoc Offset,
|
|||
Ctx));
|
||||
}
|
||||
|
||||
const llvm::APSInt& OffI = cast<nonloc::ConcreteInt>(Offset).getValue();
|
||||
const llvm::APSInt& OffI = Offset.castAs<nonloc::ConcreteInt>().getValue();
|
||||
assert(BaseIdxI.isSigned());
|
||||
|
||||
// Compute the new index.
|
||||
|
|
Загрузка…
Ссылка в новой задаче