From 5251abea41b446c26e3239c8dd6c7edea6fc335d Mon Sep 17 00:00:00 2001 From: David Blaikie Date: Wed, 20 Feb 2013 05:52:05 +0000 Subject: [PATCH] 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 --- .../Core/PathSensitive/ExprEngine.h | 7 +- .../Core/PathSensitive/MemRegion.h | 4 +- .../Core/PathSensitive/ProgramState.h | 18 +- .../StaticAnalyzer/Core/PathSensitive/SVals.h | 189 +++++++++++------- .../Checkers/ArrayBoundCheckerV2.cpp | 29 ++- .../Checkers/AttrNonNullChecker.cpp | 9 +- .../Checkers/BasicObjCFoundationChecks.cpp | 24 ++- .../Checkers/BoolAssignmentChecker.cpp | 18 +- .../Checkers/BuiltinFunctionChecker.cpp | 2 +- .../Checkers/CStringChecker.cpp | 154 +++++++------- .../Checkers/CallAndMessageChecker.cpp | 14 +- .../Checkers/DereferenceChecker.cpp | 7 +- .../Checkers/DivZeroChecker.cpp | 2 +- .../Checkers/ExprInspectionChecker.cpp | 2 +- .../Checkers/GenericTaintChecker.cpp | 2 +- .../Checkers/IdempotentOperationChecker.cpp | 4 +- .../Checkers/MacOSKeychainAPIChecker.cpp | 4 +- lib/StaticAnalyzer/Checkers/MallocChecker.cpp | 36 ++-- .../Checkers/NSErrorChecker.cpp | 8 +- .../Checkers/ObjCAtSyncChecker.cpp | 4 +- .../Checkers/ObjCContainersChecker.cpp | 5 +- .../Checkers/ObjCSelfInitChecker.cpp | 11 +- .../Checkers/PthreadLockChecker.cpp | 2 +- .../Checkers/RetainCountChecker.cpp | 3 +- lib/StaticAnalyzer/Checkers/StreamChecker.cpp | 9 +- .../Checkers/UnixAPIChecker.cpp | 13 +- .../Checkers/VLASizeChecker.cpp | 12 +- .../Core/BugReporterVisitors.cpp | 46 ++--- lib/StaticAnalyzer/Core/CallEvent.cpp | 7 +- lib/StaticAnalyzer/Core/Environment.cpp | 6 +- lib/StaticAnalyzer/Core/ExprEngine.cpp | 59 +++--- lib/StaticAnalyzer/Core/ExprEngineC.cpp | 30 +-- lib/StaticAnalyzer/Core/ExprEngineCXX.cpp | 8 +- .../Core/ExprEngineCallAndReturn.cpp | 6 +- lib/StaticAnalyzer/Core/ExprEngineObjC.cpp | 10 +- lib/StaticAnalyzer/Core/MemRegion.cpp | 6 +- lib/StaticAnalyzer/Core/PathDiagnostic.cpp | 2 +- lib/StaticAnalyzer/Core/ProgramState.cpp | 27 +-- lib/StaticAnalyzer/Core/RegionStore.cpp | 76 +++---- lib/StaticAnalyzer/Core/SValBuilder.cpp | 39 ++-- lib/StaticAnalyzer/Core/SVals.cpp | 54 +++-- .../Core/SimpleConstraintManager.cpp | 19 +- lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp | 72 +++---- lib/StaticAnalyzer/Core/Store.cpp | 25 ++- 44 files changed, 579 insertions(+), 505 deletions(-) diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h index 598a915cd8..959c1dc6aa 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h @@ -429,11 +429,11 @@ public: geteagerlyAssumeBinOpBifurcationTags(); SVal evalMinus(SVal X) { - return X.isValid() ? svalBuilder.evalMinus(cast(X)) : X; + return X.isValid() ? svalBuilder.evalMinus(X.castAs()) : X; } SVal evalComplement(SVal X) { - return X.isValid() ? svalBuilder.evalComplement(cast(X)) : X; + return X.isValid() ? svalBuilder.evalComplement(X.castAs()) : 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(R), T) : R; + return R.isValid() ? svalBuilder.evalBinOpNN(state, op, L, + R.castAs(), T) : R; } SVal evalBinOp(ProgramStateRef ST, BinaryOperator::Opcode Op, diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h b/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h index 59225cb150..a72273f8e5 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h @@ -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(&Idx) || - cast(&Idx)->getValue().isSigned()) && + assert((!Idx.getAs() || + Idx.castAs().getValue().isSigned()) && "The index must be signed"); } diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h index 0985f12966..c23cc49a21 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h @@ -620,22 +620,24 @@ inline ProgramStateRef ProgramState::assume(DefinedOrUnknownSVal Cond, bool Assumption) const { if (Cond.isUnknown()) return this; - - return getStateManager().ConstraintMgr->assume(this, cast(Cond), - Assumption); + + return getStateManager().ConstraintMgr + ->assume(this, Cond.castAs(), Assumption); } inline std::pair ProgramState::assume(DefinedOrUnknownSVal Cond) const { if (Cond.isUnknown()) return std::make_pair(this, this); - - return getStateManager().ConstraintMgr->assumeDual(this, - cast(Cond)); + + return getStateManager().ConstraintMgr + ->assumeDual(this, Cond.castAs()); } inline ProgramStateRef ProgramState::bindLoc(SVal LV, SVal V) const { - return !isa(LV) ? this : bindLoc(cast(LV), V); + if (llvm::Optional L = LV.getAs()) + 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(&Idx)) + if (llvm::Optional N = Idx.getAs()) return getStateManager().StoreMgr->getLValueElement(ElementType, *N, Base); return UnknownVal(); } diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h index d77a7969b4..def060f3fb 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h @@ -69,6 +69,25 @@ protected: public: explicit SVal() : Data(0), Kind(0) {} + template + T castAs() const { + assert(T::isType(*this)); + T t; + SVal& sv = t; + sv = *this; + return t; + } + + template + llvm::Optional getAs() const { + if (!T::isType(*this)) + return llvm::Optional(); + T t; + SVal& sv = t; + sv = *this; + return t; + } + /// BufferTy - A temporary buffer to hold a set of SVals. typedef SmallVector 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 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 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 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(D), true, SubKind) {} public: void dumpToStream(raw_ostream &Out) const; - // Implement isa 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(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 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& data) : - NonLoc(LocAsIntegerKind, &data) { - assert (isa(data.first)); - } + explicit LocAsInteger(const std::pair &data) + : NonLoc(LocAsIntegerKind, &data) { + assert (data.first.getAs()); + } public: Loc getLoc() const { const std::pair *D = static_cast *>(Data); - return cast(D->first); + return D->first.castAs(); } - const Loc& getPersistentLoc() const { + Loc getPersistentLoc() const { const std::pair *D = static_cast *>(Data); const SVal& V = D->first; - return cast(V); + return V.castAs(); } unsigned getNumBits() const { @@ -335,14 +369,16 @@ public: return D->second; } - // Implement isa 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(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 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 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; } }; diff --git a/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp b/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp index f60b7d709d..27692fe46d 100644 --- a/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp +++ b/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp @@ -53,7 +53,7 @@ public: RegionRawOffsetV2(const SubRegion* base, SVal offset) : baseRegion(base), byteOffset(offset) {} - NonLoc getByteOffset() const { return cast(byteOffset); } + NonLoc getByteOffset() const { return byteOffset.castAs(); } 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(extentBegin)) { - SVal lowerBound - = svalBuilder.evalBinOpNN(state, BO_LT, rawOffset.getByteOffset(), - cast(extentBegin), + if (llvm::Optional NV = extentBegin.getAs()) { + SVal lowerBound = + svalBuilder.evalBinOpNN(state, BO_LT, rawOffset.getByteOffset(), *NV, svalBuilder.getConditionType()); - NonLoc *lowerBoundToCheck = dyn_cast(&lowerBound); + llvm::Optional lowerBoundToCheck = lowerBound.getAs(); 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(extentVal)) + if (!extentVal.getAs()) break; SVal upperbound = svalBuilder.evalBinOpNN(state, BO_GE, rawOffset.getByteOffset(), - cast(extentVal), + extentVal.castAs(), svalBuilder.getConditionType()); - NonLoc *upperboundToCheck = dyn_cast(&upperbound); + llvm::Optional upperboundToCheck = upperbound.getAs(); 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(val) ? svalBuilder.makeArrayIndex(0) : val; + return val.getAs() ? 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(x), cast(y), + + return svalBuilder.evalBinOpNN(state, BO_Add, x.castAs(), + y.castAs(), svalBuilder.getArrayIndexType()); } @@ -284,7 +283,7 @@ RegionRawOffsetV2 RegionRawOffsetV2::computeOffset(ProgramStateRef state, case MemRegion::ElementRegionKind: { const ElementRegion *elemReg = cast(region); SVal index = elemReg->getIndex(); - if (!isa(index)) + if (!index.getAs()) 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(index), + index.castAs(), astContext.getTypeSizeInChars(elemType), svalBuilder), svalBuilder); diff --git a/lib/StaticAnalyzer/Checkers/AttrNonNullChecker.cpp b/lib/StaticAnalyzer/Checkers/AttrNonNullChecker.cpp index 3af793c23f..6185a8ee8c 100644 --- a/lib/StaticAnalyzer/Checkers/AttrNonNullChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/AttrNonNullChecker.cpp @@ -51,13 +51,13 @@ void AttrNonNullChecker::checkPreCall(const CallEvent &Call, continue; SVal V = Call.getArgSVal(idx); - DefinedSVal *DV = dyn_cast(&V); + llvm::Optional DV = V.getAs(); // If the value is unknown or undefined, we can't perform this check. if (!DV) continue; - if (!isa(*DV)) { + if (!DV->getAs()) { // 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()) continue; - if (nonloc::CompoundVal *CSV = dyn_cast(DV)) { + if (llvm::Optional CSV = + DV->getAs()) { nonloc::CompoundVal::iterator CSV_I = CSV->begin(); assert(CSV_I != CSV->end()); V = *CSV_I; - DV = dyn_cast(&V); + DV = V.getAs(); assert(++CSV_I == CSV->end()); if (!DV) continue; diff --git a/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp b/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp index 12e7527f75..313778cdb2 100644 --- a/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp +++ b/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp @@ -84,7 +84,7 @@ static FoundationClass findKnownClass(const ObjCInterfaceDecl *ID) { } static inline bool isNil(SVal X) { - return isa(X); + return X.getAs(); } //===----------------------------------------------------------------------===// @@ -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(&TheTypeVal); + llvm::Optional V = + TheTypeVal.getAs(); 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(&TheValueExpr); + llvm::Optional LV = + TheValueExpr.getAs(); 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(&ArgVal); + llvm::Optional DefArgVal = ArgVal.getAs(); if (!DefArgVal) return; // Get a NULL value. SValBuilder &svalBuilder = C.getSValBuilder(); - DefinedSVal zero = cast(svalBuilder.makeZeroVal(Arg->getType())); + DefinedSVal zero = + svalBuilder.makeZeroVal(Arg->getType()).castAs(); // 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(msg.getArgSVal(I))) + if (msg.getArgSVal(I).getAs()) 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(ElementVar)) + if (!ElementVar.getAs()) return; // Go ahead and assume the value is non-nil. - SVal Val = State->getSVal(cast(ElementVar)); - State = State->assume(cast(Val), true); + SVal Val = State->getSVal(ElementVar.castAs()); + State = State->assume(Val.castAs(), 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(&Val)) + if (llvm::Optional DV = + Val.getAs()) return State->assume(*DV, true); return State; } diff --git a/lib/StaticAnalyzer/Checkers/BoolAssignmentChecker.cpp b/lib/StaticAnalyzer/Checkers/BoolAssignmentChecker.cpp index 36fe092fdc..3ceb8c4889 100644 --- a/lib/StaticAnalyzer/Checkers/BoolAssignmentChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/BoolAssignmentChecker.cpp @@ -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(&val); + llvm::Optional DV = val.getAs(); 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(&greaterThanOrEqualToZeroVal); - + + llvm::Optional greaterThanEqualToZero = + greaterThanOrEqualToZeroVal.getAs(); + 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(&lessThanEqToOneVal); - + + llvm::Optional lessThanEqToOne = + lessThanEqToOneVal.getAs(); + if (!lessThanEqToOne) { // The SValBuilder cannot construct a valid SVal for this condition. // This means we cannot properly reason about it. diff --git a/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp b/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp index e89a4bda26..a3327d8b31 100644 --- a/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp @@ -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(state->getSVal(*(CE->arg_begin()), LCtx)); + state->getSVal(*(CE->arg_begin()), LCtx).castAs(); SValBuilder& svalBuilder = C.getSValBuilder(); DefinedOrUnknownSVal Extent = R->getExtent(svalBuilder); diff --git a/lib/StaticAnalyzer/Checkers/CStringChecker.cpp b/lib/StaticAnalyzer/Checkers/CStringChecker.cpp index 0a94747d04..1c9956727a 100644 --- a/lib/StaticAnalyzer/Checkers/CStringChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/CStringChecker.cpp @@ -201,7 +201,7 @@ REGISTER_MAP_WITH_PROGRAMSTATE(CStringLength, const MemRegion *, SVal) std::pair CStringChecker::assumeZero(CheckerContext &C, ProgramStateRef state, SVal V, QualType Ty) { - DefinedSVal *val = dyn_cast(&V); + llvm::Optional val = V.getAs(); if (!val) return std::pair(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(Extent); + DefinedOrUnknownSVal Size = Extent.castAs(); // Get the index of the accessed element. DefinedOrUnknownSVal Idx = cast(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(&LengthVal); + llvm::Optional Length = LengthVal.getAs(); if (!Length) return state; // Compute the offset of the last element to be accessed: size-1. - NonLoc One = cast(svalBuilder.makeIntVal(1, sizeTy)); - NonLoc LastOffset = cast(svalBuilder.evalBinOpNN(state, BO_Sub, - *Length, One, sizeTy)); + NonLoc One = svalBuilder.makeIntVal(1, sizeTy).castAs(); + NonLoc LastOffset = svalBuilder + .evalBinOpNN(state, BO_Sub, *Length, One, sizeTy).castAs(); // Check that the first buffer is sufficiently long. SVal BufStart = svalBuilder.evalCast(BufVal, PtrTy, FirstBuf->getType()); - if (Loc *BufLoc = dyn_cast(&BufStart)) { + if (llvm::Optional BufLoc = BufStart.getAs()) { 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(&BufStart)) { + if (llvm::Optional BufLoc = BufStart.getAs()) { 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(&firstVal); + llvm::Optional firstLoc = firstVal.getAs(); if (!firstLoc) return state; - Loc *secondLoc = dyn_cast(&secondVal); + llvm::Optional secondLoc = secondVal.getAs(); 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(&reverse); + llvm::Optional reverseTest = + reverse.getAs(); 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(&LengthVal); + llvm::Optional Length = LengthVal.getAs(); 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(&FirstStart); + llvm::Optional FirstStartLoc = FirstStart.getAs(); 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(&FirstEnd); + llvm::Optional FirstEndLoc = FirstEnd.getAs(); 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(&Overlap); + llvm::Optional OverlapTest = + Overlap.getAs(); if (!OverlapTest) return state; @@ -557,7 +555,7 @@ ProgramStateRef CStringChecker::checkAdditionOverflow(CheckerContext &C, NonLoc maxVal = svalBuilder.makeIntVal(maxValInt); SVal maxMinusRight; - if (isa(right)) { + if (right.getAs()) { 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(&maxMinusRight)) { + if (llvm::Optional maxMinusRightNL = maxMinusRight.getAs()) { 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(willOverflow)); + state->assume(willOverflow.castAs()); 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(&Buf)) { + if (llvm::Optional Label = Buf.getAs()) { 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(&V); + llvm::Optional L = V.getAs(); 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(L)) { + if (llvm::Optional MR = L->getAs()) { 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(&destVal); - assert(destRegVal && "Destination should be a known MemRegionVal here"); + loc::MemRegionVal destRegVal = destVal.castAs(); // Get the length to copy. - NonLoc *lenValNonLoc = dyn_cast(&sizeVal); - - if (lenValNonLoc) { + if (llvm::Optional lenValNonLoc = sizeVal.getAs()) { // 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(state->getSVal(Left, LCtx)); + state->getSVal(Left, LCtx).castAs(); DefinedOrUnknownSVal RV = - cast(state->getSVal(Right, LCtx)); + state->getSVal(Right, LCtx).castAs(); // 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(&strLength); - NonLoc *maxlenValNL = dyn_cast(&maxlenVal); + llvm::Optional strLengthNL = strLength.getAs(); + llvm::Optional maxlenValNL = maxlenVal.getAs(); if (strLengthNL && maxlenValNL) { ProgramStateRef stateStringTooLong, stateStringNotTooLong; // Check if the strLength is greater than the maxlen. llvm::tie(stateStringTooLong, stateStringNotTooLong) = - state->assume(cast - (C.getSValBuilder().evalBinOpNN(state, BO_GT, - *strLengthNL, - *maxlenValNL, - cmpTy))); + state->assume(C.getSValBuilder().evalBinOpNN( + state, BO_GT, *strLengthNL, *maxlenValNL, cmpTy) + .castAs()); 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(&result); + NonLoc resultNL = result.castAs(); if (strLengthNL) { - state = state->assume(cast - (C.getSValBuilder().evalBinOpNN(state, BO_LE, - *resultNL, - *strLengthNL, - cmpTy)), true); + state = state->assume(C.getSValBuilder().evalBinOpNN( + state, BO_LE, resultNL, *strLengthNL, cmpTy) + .castAs(), true); } if (maxlenValNL) { - state = state->assume(cast - (C.getSValBuilder().evalBinOpNN(state, BO_LE, - *resultNL, - *maxlenValNL, - cmpTy)), true); + state = state->assume(C.getSValBuilder().evalBinOpNN( + state, BO_LE, resultNL, *maxlenValNL, cmpTy) + .castAs(), true); } } } else { // This is a plain strlen(), not strnlen(). - result = cast(strLength); + result = strLength.castAs(); // 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(&strLength); - NonLoc *lenValNL = dyn_cast(&lenVal); + llvm::Optional strLengthNL = strLength.getAs(); + llvm::Optional lenValNL = lenVal.getAs(); // 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 - (svalBuilder.evalBinOpNN(state, BO_GE, *strLengthNL, - *lenValNL, cmpTy))); + llvm::tie(stateSourceTooLong, stateSourceNotTooLong) = state->assume( + svalBuilder.evalBinOpNN(state, BO_GE, *strLengthNL, *lenValNL, cmpTy) + .castAs()); 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(&dstStrLength)) { + if (llvm::Optional dstStrLengthNL = + dstStrLength.getAs()) { 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(svalBuilder.makeIntVal(1, sizeTy)); + NonLoc one = svalBuilder.makeIntVal(1, sizeTy).castAs(); 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(&amountCopied)) { + if (llvm::Optional amountCopiedNL = + amountCopied.getAs()) { if (lenValNL) { // amountCopied <= lenVal SVal copiedLessThanBound = svalBuilder.evalBinOpNN(state, BO_LE, *amountCopiedNL, *lenValNL, cmpTy); - state = state->assume(cast(copiedLessThanBound), - true); + state = state->assume( + copiedLessThanBound.castAs(), true); if (!state) return; } @@ -1444,8 +1434,8 @@ void CStringChecker::evalStrcpyCommon(CheckerContext &C, const CallExpr *CE, *amountCopiedNL, *strLengthNL, cmpTy); - state = state->assume(cast(copiedLessThanSrc), - true); + state = state->assume( + copiedLessThanSrc.castAs(), true); if (!state) return; } @@ -1475,8 +1465,8 @@ void CStringChecker::evalStrcpyCommon(CheckerContext &C, const CallExpr *CE, if (dstStrLength.isUndef()) return; - NonLoc *srcStrLengthNL = dyn_cast(&amountCopied); - NonLoc *dstStrLengthNL = dyn_cast(&dstStrLength); + llvm::Optional srcStrLengthNL = amountCopied.getAs(); + llvm::Optional dstStrLengthNL = dstStrLength.getAs(); // 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(&finalStrLength)) { + if (llvm::Optional finalStrLengthNL = + finalStrLength.getAs()) { if (srcStrLengthNL) { // finalStrLength >= srcStrLength SVal sourceInResult = svalBuilder.evalBinOpNN(state, BO_GE, *finalStrLengthNL, *srcStrLengthNL, cmpTy); - state = state->assume(cast(sourceInResult), + state = state->assume(sourceInResult.castAs(), true); if (!state) return; @@ -1516,8 +1507,8 @@ void CStringChecker::evalStrcpyCommon(CheckerContext &C, const CallExpr *CE, *finalStrLengthNL, *dstStrLengthNL, cmpTy); - state = state->assume(cast(destInResult), - true); + state = + state->assume(destInResult.castAs(), 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(&DstVal)) { + if (llvm::Optional dstRegVal = + DstVal.getAs()) { 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(&maxLastElementIndex)) { + if (llvm::Optional maxLastNL = + maxLastElementIndex.getAs()) { 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(&finalStrLength)) { + if (llvm::Optional knownStrLength = + finalStrLength.getAs()) { 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(s1Val); - DefinedOrUnknownSVal RV = cast(s2Val); + DefinedOrUnknownSVal LV = s1Val.castAs(); + DefinedOrUnknownSVal RV = s2Val.castAs(); // 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(getCStringLength(C, state, Init, StrVal)); + DefinedOrUnknownSVal strLength = + getCStringLength(C, state, Init, StrVal).castAs(); state = state->set(MR, strLength); } diff --git a/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp b/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp index e32091e228..d5203a80df 100644 --- a/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp @@ -133,9 +133,9 @@ bool CallAndMessageChecker::PreVisitProcessArg(CheckerContext &C, if (!checkUninitFields) return false; - - if (const nonloc::LazyCompoundVal *LV = - dyn_cast(&V)) { + + if (llvm::Optional LV = + V.getAs()) { class FindUninitializedField { public: @@ -236,7 +236,8 @@ void CallAndMessageChecker::checkPreStmt(const CallExpr *CE, } ProgramStateRef StNonNull, StNull; - llvm::tie(StNonNull, StNull) = State->assume(cast(L)); + llvm::tie(StNonNull, StNull) = + State->assume(L.castAs()); 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(V)); + llvm::tie(StNonNull, StNull) = + State->assume(V.castAs()); 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(recVal); + DefinedOrUnknownSVal receiverVal = recVal.castAs(); ProgramStateRef state = C.getState(); ProgramStateRef notNilState, nilState; diff --git a/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp b/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp index c77e2e3e4c..3aa8aaac0d 100644 --- a/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp @@ -183,10 +183,10 @@ void DereferenceChecker::checkLocation(SVal l, bool isLoad, const Stmt* S, return; } - DefinedOrUnknownSVal location = cast(l); + DefinedOrUnknownSVal location = l.castAs(); // Check for null dereferences. - if (!isa(location)) + if (!location.getAs()) 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(V)); + llvm::tie(StNonNull, StNull) = + State->assume(V.castAs()); if (StNull) { if (!StNonNull) { diff --git a/lib/StaticAnalyzer/Checkers/DivZeroChecker.cpp b/lib/StaticAnalyzer/Checkers/DivZeroChecker.cpp index 228f5ccad8..3c14e7e32e 100644 --- a/lib/StaticAnalyzer/Checkers/DivZeroChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/DivZeroChecker.cpp @@ -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(&Denom); + llvm::Optional DV = Denom.getAs(); // Divide-by-undefined handled in the generic checking for uses of // undefined values. diff --git a/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp b/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp index fec29d796d..810473f1a6 100644 --- a/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp @@ -65,7 +65,7 @@ static const char *getArgumentValueString(const CallExpr *CE, ProgramStateRef StTrue, StFalse; llvm::tie(StTrue, StFalse) = - State->assume(cast(AssertionVal)); + State->assume(AssertionVal.castAs()); if (StTrue) { if (StFalse) diff --git a/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp b/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp index 2f4b9e96f5..00ef1f65b4 100644 --- a/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp @@ -431,7 +431,7 @@ SymbolRef GenericTaintChecker::getPointedToSymbol(CheckerContext &C, if (AddrVal.isUnknownOrUndef()) return 0; - Loc *AddrLoc = dyn_cast(&AddrVal); + llvm::Optional AddrLoc = AddrVal.getAs(); if (!AddrLoc) return 0; diff --git a/lib/StaticAnalyzer/Checkers/IdempotentOperationChecker.cpp b/lib/StaticAnalyzer/Checkers/IdempotentOperationChecker.cpp index a42a54bcc7..54c32f87e5 100644 --- a/lib/StaticAnalyzer/Checkers/IdempotentOperationChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/IdempotentOperationChecker.cpp @@ -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(LHSVal)) { + if (!LHSVal.getAs()) { A = Impossible; return; } - LHSVal = state->getSVal(cast(LHSVal), LHS->getType()); + LHSVal = state->getSVal(LHSVal.castAs(), LHS->getType()); } diff --git a/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp b/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp index b11553c1d4..50114e953a 100644 --- a/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp @@ -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(&ArgV)) { + if (llvm::Optional X = ArgV.getAs()) { 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(ArgSVal), false) && + if (State->assume(ArgSVal.castAs(), false) && !definitelyDidnotReturnError(AS->Region, State, C.getSValBuilder())) { ExplodedNode *N = C.addTransition(State); if (!N) diff --git a/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/lib/StaticAnalyzer/Checkers/MallocChecker.cpp index 2242b21efb..aaaafeb5ef 100644 --- a/lib/StaticAnalyzer/Checkers/MallocChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/MallocChecker.cpp @@ -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(svalBuilder.getConjuredHeapSymbolVal(CE, LCtx, Count)); + DefinedSVal RetVal = svalBuilder.getConjuredHeapSymbolVal(CE, LCtx, Count) + .castAs(); state = state->BindExpr(CE, C.getLocationContext(), RetVal); // We expect the malloc functions to return a pointer. - if (!isa(RetVal)) + if (!RetVal.getAs()) return 0; // Fill the region with the initialization value. @@ -571,12 +571,12 @@ ProgramStateRef MallocChecker::MallocMemAux(CheckerContext &C, dyn_cast_or_null(RetVal.getAsRegion()); if (!R) return 0; - if (isa(Size)) { + if (llvm::Optional DefinedSize = + Size.getAs()) { SValBuilder &svalBuilder = C.getSValBuilder(); DefinedOrUnknownSVal Extent = R->getExtent(svalBuilder); - DefinedOrUnknownSVal DefinedSize = cast(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(retVal)) + if (!retVal.getAs()) 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(ArgVal)) + if (!ArgVal.getAs()) return 0; - DefinedOrUnknownSVal location = cast(ArgVal); + DefinedOrUnknownSVal location = ArgVal.castAs(); // Check for null dereferences. - if (!isa(location)) + if (!location.getAs()) 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(&V)) + if (llvm::Optional IntVal = + V.getAs()) os << "an integer (" << IntVal->getValue() << ")"; - else if (loc::ConcreteInt *ConstAddr = dyn_cast(&V)) + else if (llvm::Optional ConstAddr = + V.getAs()) os << "a constant address (" << ConstAddr->getValue() << ")"; - else if (loc::GotoLabel *Label = dyn_cast(&V)) + else if (llvm::Optional Label = V.getAs()) 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(Arg0Val)) + if (!Arg0Val.getAs()) return 0; - DefinedOrUnknownSVal arg0Val = cast(Arg0Val); + DefinedOrUnknownSVal arg0Val = Arg0Val.castAs(); 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(Arg1ValG)) + if (!Arg1ValG.getAs()) return 0; - DefinedOrUnknownSVal Arg1Val = cast(Arg1ValG); + DefinedOrUnknownSVal Arg1Val = Arg1ValG.castAs(); // Compare the size argument to 0. DefinedOrUnknownSVal SizeZero = diff --git a/lib/StaticAnalyzer/Checkers/NSErrorChecker.cpp b/lib/StaticAnalyzer/Checkers/NSErrorChecker.cpp index 19f79fa1dc..9e2202b842 100644 --- a/lib/StaticAnalyzer/Checkers/NSErrorChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/NSErrorChecker.cpp @@ -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(&val)) { + if (llvm::Optional X = val.getAs()) { const MemRegion* R = X->getRegion(); if (const VarRegion *VR = R->getAs()) 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)) + if (loc.isUndef() || !loc.getAs()) 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(state, state->getSVal(cast(loc)), C); + setFlag(state, state->getSVal(loc.castAs()), C); return; } if (ShouldCheckCFError && IsCFError(parmT, CFErrorII)) { - setFlag(state, state->getSVal(cast(loc)), C); + setFlag(state, state->getSVal(loc.castAs()), C); return; } } diff --git a/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp b/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp index 62a20a7674..4018a66ecf 100644 --- a/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp @@ -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(V)) { + if (V.getAs()) { 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(V)); + llvm::tie(notNullState, nullState) = state->assume(V.castAs()); if (nullState) { if (!notNullState) { diff --git a/lib/StaticAnalyzer/Checkers/ObjCContainersChecker.cpp b/lib/StaticAnalyzer/Checkers/ObjCContainersChecker.cpp index 747c9c91cb..b9e96ee99f 100644 --- a/lib/StaticAnalyzer/Checkers/ObjCContainersChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/ObjCContainersChecker.cpp @@ -72,7 +72,8 @@ void ObjCContainersChecker::addSizeInfo(const Expr *Array, const Expr *Size, if (!ArraySym) return; - C.addTransition(State->set(ArraySym, cast(SizeV))); + C.addTransition( + State->set(ArraySym, SizeV.castAs())); 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(IdxVal); + DefinedSVal Idx = IdxVal.castAs(); // Now, check if 'Idx in [0, Size-1]'. const QualType T = IdxExpr->getType(); diff --git a/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp b/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp index 485ae77242..8506e08b2b 100644 --- a/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp @@ -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(argV)), C); + unsigned selfFlags = getSelfFlags(state->getSVal(argV.castAs()), C); C.addTransition(state->set(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(argV)), prevFlags, C); + addSelfFlag(state, state->getSVal(argV.castAs()), 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(location)), SelfFlag_Self, C); + addSelfFlag(state, state->getSVal(location.castAs()), 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(location)) + if (!location.getAs()) return false; - loc::MemRegionVal MRV = cast(location); + loc::MemRegionVal MRV = location.castAs(); if (const DeclRegion *DR = dyn_cast(MRV.stripCasts())) return (DR->getDecl() == analCtx->getSelfDecl()); diff --git a/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp b/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp index 8407ea4cd6..ffb8cf2020 100644 --- a/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp @@ -98,7 +98,7 @@ void PthreadLockChecker::AcquireLock(CheckerContext &C, const CallExpr *CE, if (X.isUnknownOrUndef()) return; - DefinedSVal retVal = cast(X); + DefinedSVal retVal = X.castAs(); if (state->contains(lockR)) { if (!BT_doublelock) diff --git a/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp b/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp index 533d0b8420..cb731fcee1 100644 --- a/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp @@ -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)) { + if (llvm::Optional regionLoc = + loc.getAs()) { escapes = !regionLoc->getRegion()->hasStackStorage(); if (!escapes) { diff --git a/lib/StaticAnalyzer/Checkers/StreamChecker.cpp b/lib/StaticAnalyzer/Checkers/StreamChecker.cpp index a39f28225f..2a6c217f0c 100644 --- a/lib/StaticAnalyzer/Checkers/StreamChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/StreamChecker.cpp @@ -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(svalBuilder.conjureSymbolVal(0, CE, LCtx, - C.blockCount())); + DefinedSVal RetVal = svalBuilder.conjureSymbolVal(0, CE, LCtx, C.blockCount()) + .castAs(); 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(&Whence); + llvm::Optional CI = Whence.getAs(); 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(&SV); + llvm::Optional DV = SV.getAs(); if (!DV) return 0; diff --git a/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp b/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp index c6ea3283eb..3e11fd810e 100644 --- a/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp @@ -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(V)) { + if (!V.getAs()) { // 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(V); - NonLoc ocreateFlag = - cast(C.getSValBuilder().makeIntVal(Val_O_CREAT.getValue(), - oflagsEx->getType())); + NonLoc oflags = V.castAs(); + NonLoc ocreateFlag = C.getSValBuilder() + .makeIntVal(Val_O_CREAT.getValue(), oflagsEx->getType()).castAs(); SVal maskedFlagsUC = C.getSValBuilder().evalBinOpNN(state, BO_And, oflags, ocreateFlag, oflagsEx->getType()); if (maskedFlagsUC.isUnknownOrUndef()) return; - DefinedSVal maskedFlags = cast(maskedFlagsUC); + DefinedSVal maskedFlags = maskedFlagsUC.castAs(); // 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(argVal)); + state->assume(argVal.castAs()); return (*falseState && !*trueState); } diff --git a/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp b/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp index 6ca9a35c56..30aef06069 100644 --- a/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp @@ -110,7 +110,7 @@ void VLASizeChecker::checkPreStmt(const DeclStmt *DS, CheckerContext &C) const { } // Check if the size is zero. - DefinedSVal sizeD = cast(sizeV); + DefinedSVal sizeD = sizeV.castAs(); 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(svalBuilder.evalCast(sizeD, SizeTy, - SE->getType())); + NonLoc ArrayLength = + svalBuilder.evalCast(sizeD, SizeTy, SE->getType()).castAs(); // 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(EleSizeVal), SizeTy); + SVal ArraySizeVal = svalBuilder.evalBinOpNN( + state, BO_Mul, ArrayLength, EleSizeVal.castAs(), 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(ArraySizeVal); + DefinedOrUnknownSVal ArraySize = ArraySizeVal.castAs(); DefinedOrUnknownSVal sizeIsKnown = svalBuilder.evalEQ(state, Extent, ArraySize); state = state->assume(sizeIsKnown, true); diff --git a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp index 17dd772a68..8afd4887cf 100644 --- a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp +++ b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp @@ -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(V), true)) { + if (State->assume(V.castAs(), 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(V)) { + if (V.getAs()) { // 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(ArgV)) + if (!ArgV.getAs()) 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(ArgV), true)) + if (State->assume(ArgV.castAs(), 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(V)) { + if (V.isUndef() || V.getAs()) { 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(V)) { + if (V.getAs()) { bool b = false; if (R->isBoundable()) { if (const TypedValueRegion *TR = dyn_cast(R)) { @@ -475,9 +475,9 @@ PathDiagnosticPiece *FindLastStoreBRVisitor::VisitNode(const ExplodedNode *Succ, if (!b) os << action << "a null pointer value"; - } - else if (isa(V)) { - os << action << cast(V).getValue(); + } else if (llvm::Optional CVal = + V.getAs()) { + os << action << CVal->getValue(); } else if (DS) { if (V.isUndef()) { @@ -499,15 +499,16 @@ PathDiagnosticPiece *FindLastStoreBRVisitor::VisitNode(const ExplodedNode *Succ, os << "Passing "; - if (isa(V)) { + if (V.getAs()) { if (Param->getType()->isObjCObjectPointerType()) os << "nil object reference"; else os << "null pointer value"; } else if (V.isUndef()) { os << "uninitialized value"; - } else if (isa(V)) { - os << "the value " << cast(V).getValue(); + } else if (llvm::Optional CI = + V.getAs()) { + os << "the value " << CI->getValue(); } else { os << "value"; } @@ -521,7 +522,7 @@ PathDiagnosticPiece *FindLastStoreBRVisitor::VisitNode(const ExplodedNode *Succ, } if (os.str().empty()) { - if (isa(V)) { + if (V.getAs()) { bool b = false; if (R->isBoundable()) { if (const TypedValueRegion *TR = dyn_cast(R)) { @@ -537,10 +538,9 @@ PathDiagnosticPiece *FindLastStoreBRVisitor::VisitNode(const ExplodedNode *Succ, } else if (V.isUndef()) { os << "Uninitialized value stored to "; - } - else if (isa(V)) { - os << "The value " << cast(V).getValue() - << " is assigned to "; + } else if (llvm::Optional CV = + V.getAs()) { + 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(Constraint)) { + if (Constraint.getAs()) { 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(V), false); + BugReporterVisitor *ConstraintTracker = + new TrackConstraintBRVisitor(V.castAs(), 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(&V)) { + if (llvm::Optional L = V.getAs()) { // 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(&V); + llvm::Optional DV = V.getAs(); 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(V) || isa(V)) { + if (V.getAs() || V.getAs()) { // Register a new visitor with the BugReport. BR.addVisitor(new FindLastStoreBRVisitor(V, R)); } diff --git a/lib/StaticAnalyzer/Core/CallEvent.cpp b/lib/StaticAnalyzer/Core/CallEvent.cpp index a75efc60b9..a09d483150 100644 --- a/lib/StaticAnalyzer/Core/CallEvent.cpp +++ b/lib/StaticAnalyzer/Core/CallEvent.cpp @@ -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(&V)) + if (llvm::Optional Wrapped = + V.getAs()) V = Wrapped->getLoc(); - else if (!isa(V)) + else if (!V.getAs()) 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(ThisVal)); + assert(ThisVal.isUnknownOrUndef() || ThisVal.getAs()); return ThisVal; } diff --git a/lib/StaticAnalyzer/Core/Environment.cpp b/lib/StaticAnalyzer/Core/Environment.cpp index 2b069a04a5..481e1bfd37 100644 --- a/lib/StaticAnalyzer/Core/Environment.cpp +++ b/lib/StaticAnalyzer/Core/Environment.cpp @@ -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(X)) { - const MemRegion *R = cast(X).getRegion(); - SymReaper.markLive(R); - } + if (llvm::Optional R = X.getAs()) + SymReaper.markLive(R->getRegion()); // Mark all symbols in the block expr's value live. RSScaner.scan(X); diff --git a/lib/StaticAnalyzer/Core/ExprEngine.cpp b/lib/StaticAnalyzer/Core/ExprEngine.cpp index 18ac0964aa..a077056174 100644 --- a/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -118,8 +118,8 @@ ProgramStateRef ExprEngine::getInitialState(const LocationContext *InitLoc) { svalBuilder.makeZeroVal(T), getContext().IntTy); - DefinedOrUnknownSVal *Constraint = - dyn_cast(&Constraint_untested); + llvm::Optional Constraint = + Constraint_untested.getAs(); 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(&V)) { + if (llvm::Optional LV = V.getAs()) { // 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(&V)) { + if (llvm::Optional LV = V.getAs()) { 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(V)) { + if (V.getAs()) { 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(dest).getRegion(), - Dtor.getTriggerStmt(), /*IsBase=*/false, Pred, Dst); + VisitCXXDestructor(varType, dest.castAs().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(BaseVal).getRegion(), - CurDtor->getBody(), /*IsBase=*/true, Pred, Dst); + VisitCXXDestructor(BaseTy, BaseVal.castAs().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(LCtx->getDecl()); Loc ThisVal = getSValBuilder().getCXXThis(CurDtor, LCtx->getCurrentStackFrame()); - SVal FieldVal = State->getLValue(Member, cast(State->getSVal(ThisVal))); + SVal FieldVal = + State->getLValue(Member, State->getSVal(ThisVal).castAs()); VisitCXXDestructor(Member->getType(), - cast(FieldVal).getRegion(), + FieldVal.castAs().getRegion(), CurDtor->getBody(), /*IsBase=*/false, Pred, Dst); } @@ -1287,7 +1288,7 @@ void ExprEngine::processBranch(const Stmt *Condition, const Stmt *Term, continue; } - DefinedSVal V = cast(X); + DefinedSVal V = X.castAs(); ProgramStateRef StTrue, StFalse; tie(StTrue, StFalse) = PrevState->assume(V); @@ -1327,8 +1328,8 @@ void ExprEngine::processIndirectGoto(IndirectGotoNodeBuilder &builder) { typedef IndirectGotoNodeBuilder::iterator iterator; - if (isa(V)) { - const LabelDecl *L = cast(V).getLabel(); + if (llvm::Optional LV = V.getAs()) { + 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(V) || isa(V)) { + if (V.getAs() || V.getAs()) { // 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(CondV_untested); + DefinedOrUnknownSVal CondV = CondV_untested.castAs(); 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(CondV)) + if (CondV.getAs()) 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(V), true); + state = state->assume(V.castAs(), 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)) { + if (llvm::Optional regionLoc = + Loc.getAs()) { 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(location)) { + if (!location.getAs()) { 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(location), + state = state->bindLoc(location.castAs(), Val, /* notifyChanges = */ !atDeclInit); const MemRegion *LocReg = 0; - if (loc::MemRegionVal *LocRegVal = dyn_cast(&location)) { + if (llvm::Optional LocRegVal = + location.getAs()) { LocReg = LocRegVal->getRegion(); } @@ -1826,7 +1829,7 @@ void ExprEngine::evalLoad(ExplodedNodeSet &Dst, const ProgramPointTag *tag, QualType LoadTy) { - assert(!isa(location) && "location cannot be a NonLoc."); + assert(!location.getAs() && "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(location), LoadTy); + V = state->getSVal(location.castAs(), 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(&V); + llvm::Optional SEV = V.getAs(); if (SEV && SEV->isExpression()) { const std::pair &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(X)); // Should be an Lval, or unknown, undef. + assert (!X.getAs()); // Should be an Lval, or unknown, undef. - if (isa(X)) - state = state->bindLoc(cast(X), UnknownVal()); + if (llvm::Optional LV = X.getAs()) + state = state->bindLoc(*LV, UnknownVal()); } Bldr.generateNode(A, Pred, state); diff --git a/lib/StaticAnalyzer/Core/ExprEngineC.cpp b/lib/StaticAnalyzer/Core/ExprEngineC.cpp index f33f56176d..fe132df4b5 100644 --- a/lib/StaticAnalyzer/Core/ExprEngineC.cpp +++ b/lib/StaticAnalyzer/Core/ExprEngineC.cpp @@ -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(LeftV) && + if (LeftV.getAs() && RHS->getType()->isIntegerType() && RightV.isUnknown()) { RightV = svalBuilder.conjureSymbolVal(RHS, LCtx, RHS->getType(), Count); } - if (isa(RightV) && + if (RightV.getAs() && 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(InitVal)){ - InitVal = state->getSVal(cast(InitVal).getRegion()); - assert(isa(InitVal)); + if (AMgr.getLangOpts().CPlusPlus && VD->getType()->isRecordType() && + !VD->getType()->isReferenceType()) { + if (llvm::Optional M = + InitVal.getAs()) { + InitVal = state->getSVal(M->getRegion()); + assert(InitVal.getAs()); + } } // 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(RHSVal); + DefinedOrUnknownSVal DefinedRHS = RHSVal.castAs(); 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(V))); + state = state->BindExpr(U, LCtx, evalComplement(V.castAs())); break; case UO_Minus: // FIXME: Do we need to handle promotions? - state = state->BindExpr(U, LCtx, evalMinus(cast(V))); + state = state->BindExpr(U, LCtx, evalMinus(V.castAs())); 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(V)) { + if (llvm::Optional LV = V.getAs()) { Loc X = svalBuilder.makeNull(); - Result = evalBinOp(state, BO_EQ, cast(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(V), X, + Result = evalBinOp(state, BO_EQ, V.castAs(), 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(V2_untested); + DefinedSVal V2 = V2_untested.castAs(); // Handle all other values. BinaryOperator::Opcode Op = U->isIncrementOp() ? BO_Add : BO_Sub; diff --git a/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp b/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp index fdd50a6b54..7e86a56759 100644 --- a/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp +++ b/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp @@ -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(&V)) + if (llvm::Optional L = V.getAs()) 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(symVal).getRegion(); + const MemRegion *NewReg = symVal.castAs().getRegion(); QualType ObjTy = CNE->getType()->getAs()->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(Location)) - State = State->bindLoc(cast(Location), State->getSVal(Init, LCtx)); + if (llvm::Optional LV = Location.getAs()) + State = State->bindLoc(*LV, State->getSVal(Init, LCtx)); } } diff --git a/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp b/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp index 1d006b09cc..0d4673cdbf 100644 --- a/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp +++ b/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp @@ -121,7 +121,7 @@ static std::pair(V)) + if (!V.getAs()) 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(ThisV)); + ThisV = state->getSVal(ThisV.castAs()); 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(E), ThisV)) - ThisV = State->getSVal(cast(ThisV)); + ThisV = State->getSVal(ThisV.castAs()); return State->BindExpr(E, LCtx, ThisV); } diff --git a/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp b/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp index de73dd7c3e..69a5052e90 100644 --- a/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp +++ b/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp @@ -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(&elementV)) + + if (llvm::Optional MV = + elementV.getAs()) if (const TypedValueRegion *R = dyn_cast(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(recVal); - + DefinedOrUnknownSVal receiverVal = + recVal.castAs(); + ProgramStateRef notNilState, nilState; llvm::tie(notNilState, nilState) = State->assume(receiverVal); diff --git a/lib/StaticAnalyzer/Core/MemRegion.cpp b/lib/StaticAnalyzer/Core/MemRegion.cpp index a0abe42253..c48343a824 100644 --- a/lib/StaticAnalyzer/Core/MemRegion.cpp +++ b/lib/StaticAnalyzer/Core/MemRegion.cpp @@ -1044,7 +1044,8 @@ RegionRawOffset ElementRegion::getAsArrayOffset() const { // FIXME: generalize to symbolic offsets. SVal index = ER->getIndex(); - if (nonloc::ConcreteInt *CI = dyn_cast(&index)) { + if (llvm::Optional CI = + index.getAs()) { // 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(&Index)) { + if (llvm::Optional CI = + Index.getAs()) { // Don't bother calculating precise offsets if we already have a // symbolic offset somewhere in the chain. if (SymbolicOffsetBase) diff --git a/lib/StaticAnalyzer/Core/PathDiagnostic.cpp b/lib/StaticAnalyzer/Core/PathDiagnostic.cpp index 3c6ff6cac6..c723bc8844 100644 --- a/lib/StaticAnalyzer/Core/PathDiagnostic.cpp +++ b/lib/StaticAnalyzer/Core/PathDiagnostic.cpp @@ -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(&SV)) { + if (llvm::Optional Reg = SV.getAs()) { SVal PSV = State->getSVal(Reg->getRegion()); SymbolRef AS = PSV.getAsLocSymbol(); if (AS == Sym) { diff --git a/lib/StaticAnalyzer/Core/ProgramState.cpp b/lib/StaticAnalyzer/Core/ProgramState.cpp index a3db3764fb..6c76ebfbe5 100644 --- a/lib/StaticAnalyzer/Core/ProgramState.cpp +++ b/lib/StaticAnalyzer/Core/ProgramState.cpp @@ -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).getRegion(); + const MemRegion *R = loc.castAs().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 Regions, } ProgramStateRef ProgramState::killBinding(Loc LV) const { - assert(!isa(LV) && "Use invalidateRegion instead."); + assert(!LV.getAs() && "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(V)) + if (V.getAs()) 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(Idx), Min, indexTy); + Idx.castAs(), Min, indexTy); if (newIdx.isUnknownOrUndef()) return this; // Adjust the upper bound. SVal newBound = - svalBuilder.evalBinOpNN(this, BO_Add, cast(UpperBound), + svalBuilder.evalBinOpNN(this, BO_Add, UpperBound.castAs(), Min, indexTy); if (newBound.isUnknownOrUndef()) return this; // Build the actual comparison. - SVal inBound = svalBuilder.evalBinOpNN(this, BO_LT, - cast(newIdx), cast(newBound), - Ctx.IntTy); + SVal inBound = svalBuilder.evalBinOpNN(this, BO_LT, newIdx.castAs(), + newBound.castAs(), 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(inBound), Assumption); + return CM.assume(this, inBound.castAs(), 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(&val)) + if (llvm::Optional X = val.getAs()) return scan(X->getRegion()); - if (nonloc::LazyCompoundVal *X = dyn_cast(&val)) { + if (llvm::Optional X = + val.getAs()) { 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(&val)) + if (llvm::Optional X = + val.getAs()) 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(&val)) + if (llvm::Optional X = val.getAs()) return scan(*X); return true; diff --git a/lib/StaticAnalyzer/Core/RegionStore.cpp b/lib/StaticAnalyzer/Core/RegionStore.cpp index 4d9a313a02..39417afbd0 100644 --- a/lib/StaticAnalyzer/Core/RegionStore.cpp +++ b/lib/StaticAnalyzer/Core/RegionStore.cpp @@ -753,7 +753,8 @@ static void collectSubRegionKeys(SmallVectorImpl &Keys, // be using this function anyway. uint64_t Length = UINT64_MAX; SVal Extent = Top->getExtent(SVB); - if (nonloc::ConcreteInt *ExtentCI = dyn_cast(&Extent)) { + if (llvm::Optional ExtentCI = + Extent.getAs()) { 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(&V)) { + if (llvm::Optional LCS = + V.getAs()) { 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(&V)) { + if (llvm::Optional L = V.getAs()) { 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(Array)) + if (!Array.getAs()) return UnknownVal(); - const MemRegion* R = cast(&Array)->getRegion(); + const MemRegion* R = Array.castAs().getRegion(); const TypedValueRegion* ArrayR = dyn_cast(R); if (!ArrayR) @@ -1134,8 +1135,8 @@ SVal RegionStoreManager::ArrayToPointer(Loc Array) { //===----------------------------------------------------------------------===// SVal RegionStoreManager::getBinding(RegionBindingsConstRef B, Loc L, QualType T) { - assert(!isa(L) && "location unknown"); - assert(!isa(L) && "location undefined"); + assert(!L.getAs() && "location unknown"); + assert(!L.getAs() && "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(L)) { + if (L.getAs()) { return UnknownVal(); } - if (!isa(L)) { + if (!L.getAs()) { return UnknownVal(); } - const MemRegion *MR = cast(L).getRegion(); + const MemRegion *MR = L.castAs().getRegion(); if (isa(MR) || isa(MR) || @@ -1263,8 +1264,8 @@ RegionStoreManager::getLazyBinding(RegionBindingsConstRef B, if (originalRegion != R) { if (Optional OV = B.getDefaultBinding(R)) { - if (const nonloc::LazyCompoundVal *V = - dyn_cast(OV.getPointer())) + if (llvm::Optional V = + OV.getPointer()->getAs()) 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(&Idx)) { + if (llvm::Optional CI = + Idx.getAs()) { 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(val)) + if (val.getAs()) return Optional(); 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(&V); - if (InnerLCV) { + if (llvm::Optional InnerLCV = + V.getAs()) { 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 V = B.getDefaultBinding(R)) { - const nonloc::LazyCompoundVal *LCV = - dyn_cast(V.getPointer()); - if (LCV) { + if (llvm::Optional LCV = + V.getPointer()->getAs()) { 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(L)) - if (const MemRegion* R = cast(L).getRegion()) + if (llvm::Optional LV = L.getAs()) + 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(L)) + if (L.getAs()) return B; // If we get here, the location should be a region. - const MemRegion *R = cast(L).getRegion(); + const MemRegion *R = L.castAs().getRegion(); // Check if the region is a struct region. if (const TypedValueRegion* TR = dyn_cast(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(&Init)) { + if (llvm::Optional MRV = Init.getAs()) { const StringRegion *S = cast(MRV->getRegion()); // Treat the string as a lazy compound value. StoreRef store(B.asStore(), *this); - nonloc::LazyCompoundVal LCV = - cast(svalBuilder.makeLazyCompoundVal(store, S)); + nonloc::LazyCompoundVal LCV = svalBuilder.makeLazyCompoundVal(store, S) + .castAs(); return bindAggregate(B, R, LCV); } // Handle lazy compound values. - if (isa(Init)) + if (Init.getAs()) 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(Init); + const nonloc::CompoundVal& CV = Init.castAs(); 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(); // Use getAs for typedefs. // Handle lazy compound values and symbolic values. - if (isa(V) || isa(V)) + if (V.getAs() || V.getAs()) 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(V)) { + if (!V.getAs()) { return bindAggregate(B, R, UnknownVal()); } QualType ElemType = VT->getElementType(); - nonloc::CompoundVal& CV = cast(V); + nonloc::CompoundVal CV = V.castAs(); 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(V) || isa(V)) + if (V.getAs() || V.getAs()) 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(V)) + if (V.isUnknown() || !V.getAs()) return bindAggregate(B, R, UnknownVal()); - nonloc::CompoundVal& CV = cast(V); + const nonloc::CompoundVal& CV = V.castAs(); 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(&V)) { + if (llvm::Optional LCS = + V.getAs()) { const RegionStoreManager::SValListTy &Vals = RM.getInterestingValues(*LCS); diff --git a/lib/StaticAnalyzer/Core/SValBuilder.cpp b/lib/StaticAnalyzer/Core/SValBuilder.cpp index 96e46b801f..d099a8fca8 100644 --- a/lib/StaticAnalyzer/Core/SValBuilder.cpp +++ b/lib/StaticAnalyzer/Core/SValBuilder.cpp @@ -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(&val)) { + if (llvm::Optional CI = + val.getAs()) { const llvm::APSInt& I = CI->getValue(); if (I.getBitWidth() == ArrayIndexWidth && I.isSigned()) return val; } - return evalCastFromNonLoc(cast(val), ArrayIndexTy); + return evalCastFromNonLoc(val.castAs(), 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(&RHS)) + if (llvm::Optional rInt = + RHS.getAs()) return makeNonLoc(symLHS, Op, rInt->getValue(), ResultTy); if (symRHS && symRHS->computeComplexity() < MaxComp) - if (const nonloc::ConcreteInt *lInt = dyn_cast(&LHS)) + if (llvm::Optional lInt = + LHS.getAs()) 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(lhs)) { - if (isa(rhs)) - return evalBinOpLL(state, op, cast(lhs), cast(rhs), type); + if (llvm::Optional LV = lhs.getAs()) { + if (llvm::Optional RV = rhs.getAs()) + return evalBinOpLL(state, op, *LV, *RV, type); - return evalBinOpLN(state, op, cast(lhs), cast(rhs), type); + return evalBinOpLN(state, op, *LV, rhs.castAs(), type); } - if (isa(rhs)) { + if (llvm::Optional RV = rhs.getAs()) { // 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(rhs), cast(lhs), type); + return evalBinOpLN(state, op, *RV, lhs.castAs(), type); } - return evalBinOpNN(state, op, cast(lhs), cast(rhs), type); + return evalBinOpNN(state, op, lhs.castAs(), rhs.castAs(), + type); } DefinedOrUnknownSVal SValBuilder::evalEQ(ProgramStateRef state, DefinedOrUnknownSVal lhs, DefinedOrUnknownSVal rhs) { - return cast(evalBinOp(state, BO_EQ, lhs, rhs, - Context.IntTy)); + return evalBinOp(state, BO_EQ, lhs, rhs, Context.IntTy) + .castAs(); } /// 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(val), castTy); + return evalCastFromLoc(val.castAs(), castTy); // Check for casts from integers to pointers. if (Loc::isLocType(castTy) && originalTy->isIntegerType()) { - if (nonloc::LocAsInteger *LV = dyn_cast(&val)) { + if (llvm::Optional LV = + val.getAs()) { 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(val)); + val = StateMgr.ArrayToPointer(val.castAs()); // 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(originalTy)->getElementType(); // QualType pointerTy = C.getPointerType(elemTy); - return evalCastFromLoc(cast(val), castTy); + return evalCastFromLoc(val.castAs(), castTy); } // Check for casts from a region to a specific type. diff --git a/lib/StaticAnalyzer/Core/SVals.cpp b/lib/StaticAnalyzer/Core/SVals.cpp index 5906068c89..72959f506d 100644 --- a/lib/StaticAnalyzer/Core/SVals.cpp +++ b/lib/StaticAnalyzer/Core/SVals.cpp @@ -30,13 +30,13 @@ using llvm::APSInt; //===----------------------------------------------------------------------===// bool SVal::hasConjuredSymbol() const { - if (const nonloc::SymbolVal* SV = dyn_cast(this)) { + if (llvm::Optional SV = getAs()) { SymbolRef sym = SV->getSymbol(); if (isa(sym)) return true; } - if (const loc::MemRegionVal *RV = dyn_cast(this)) { + if (llvm::Optional RV = getAs()) { const MemRegion *R = RV->getRegion(); if (const SymbolicRegion *SR = dyn_cast(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(this)) { + if (llvm::Optional X = getAs()) { const MemRegion* R = X->getRegion(); if (const FunctionTextRegion *CTR = R->getAs()) if (const FunctionDecl *FD = dyn_cast(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(this)) + if (llvm::Optional X = getAs()) return X->getLoc().getAsLocSymbol(); - if (const loc::MemRegionVal *X = dyn_cast(this)) { + if (llvm::Optional X = getAs()) { const MemRegion *R = X->stripCasts(); if (const SymbolicRegion *SymR = dyn_cast(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(this); + llvm::Optional X = getAs(); 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(this)) + if (llvm::Optional X = getAs()) 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(this)) + if (llvm::Optional X = getAs()) 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(this)) + if (llvm::Optional X = getAs()) return X->getRegion(); - if (const nonloc::LocAsInteger *X = dyn_cast(this)) { + if (llvm::Optional X = getAs()) return X->getLoc().getAsRegion(); - } return 0; } @@ -165,16 +164,15 @@ nonloc::CompoundVal::iterator nonloc::CompoundVal::end() const { //===----------------------------------------------------------------------===// bool SVal::isConstant() const { - return isa(this) || isa(this); + return getAs() || getAs(); } bool SVal::isConstant(int I) const { - if (isa(*this)) - return cast(*this).getValue() == I; - else if (isa(*this)) - return cast(*this).getValue() == I; - else - return false; + if (llvm::Optional LV = getAs()) + return LV->getValue() == I; + if (llvm::Optional NV = getAs()) + 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(this)->dumpToStream(os); + castAs().dumpToStream(os); break; case LocKind: - cast(this)->dumpToStream(os); + castAs().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(this); + const nonloc::ConcreteInt& C = castAs(); 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(this)->getSymbol(); + os << castAs().getSymbol(); break; } case nonloc::LocAsIntegerKind: { - const nonloc::LocAsInteger& C = *cast(this); + const nonloc::LocAsInteger& C = castAs(); os << C.getLoc() << " [as " << C.getNumBits() << " bit integer]"; break; } case nonloc::CompoundValKind: { - const nonloc::CompoundVal& C = *cast(this); + const nonloc::CompoundVal& C = castAs(); 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(this); + const nonloc::LazyCompoundVal &C = castAs(); os << "lazyCompoundVal{" << const_cast(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(this)->getValue().getZExtValue() << " (Loc)"; + os << castAs().getValue().getZExtValue() << " (Loc)"; break; case loc::GotoLabelKind: - os << "&&" << cast(this)->getLabel()->getName(); + os << "&&" << castAs().getLabel()->getName(); break; case loc::MemRegionKind: - os << '&' << cast(this)->getRegion()->getString(); + os << '&' << castAs().getRegion()->getString(); break; default: llvm_unreachable("Pretty-printing not implemented for this Loc."); diff --git a/lib/StaticAnalyzer/Core/SimpleConstraintManager.cpp b/lib/StaticAnalyzer/Core/SimpleConstraintManager.cpp index 4236ee470a..3838830fa9 100644 --- a/lib/StaticAnalyzer/Core/SimpleConstraintManager.cpp +++ b/lib/StaticAnalyzer/Core/SimpleConstraintManager.cpp @@ -24,7 +24,7 @@ namespace ento { SimpleConstraintManager::~SimpleConstraintManager() {} bool SimpleConstraintManager::canReasonAbout(SVal X) const { - nonloc::SymbolVal *SymVal = dyn_cast(&X); + llvm::Optional SymVal = X.getAs(); 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(Cond)) - return assume(state, cast(Cond), Assumption); - else - return assume(state, cast(Cond), Assumption); + if (llvm::Optional NV = Cond.getAs()) + return assume(state, *NV, Assumption); + return assume(state, Cond.castAs(), 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(Cond).getRegion(); + const MemRegion *R = Cond.castAs().getRegion(); const SubRegion *SubR = dyn_cast(R); while (SubR) { @@ -104,7 +103,7 @@ ProgramStateRef SimpleConstraintManager::assumeAux(ProgramStateRef state, return Assumption ? state : NULL; case loc::ConcreteIntKind: { - bool b = cast(Cond).getValue() != 0; + bool b = Cond.castAs().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(Cond); + nonloc::SymbolVal SV = Cond.castAs(); SymbolRef sym = SV.getSymbol(); assert(sym); @@ -204,13 +203,13 @@ ProgramStateRef SimpleConstraintManager::assumeAux(ProgramStateRef state, } case nonloc::ConcreteIntKind: { - bool b = cast(Cond).getValue() != 0; + bool b = Cond.castAs().getValue() != 0; bool isFeasible = b ? Assumption : !Assumption; return isFeasible ? state : NULL; } case nonloc::LocAsIntegerKind: - return assumeAux(state, cast(Cond).getLoc(), + return assumeAux(state, Cond.castAs().getLoc(), Assumption); } // end switch } diff --git a/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp b/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp index a59cd500f1..080e81d2ce 100644 --- a/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp +++ b/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp @@ -60,16 +60,17 @@ SValBuilder *ento::createSimpleSValBuilder(llvm::BumpPtrAllocator &alloc, //===----------------------------------------------------------------------===// SVal SimpleSValBuilder::dispatchCast(SVal Val, QualType CastTy) { - assert(isa(&Val) || isa(&Val)); - return isa(Val) ? evalCastFromLoc(cast(Val), CastTy) - : evalCastFromNonLoc(cast(Val), CastTy); + assert(Val.getAs() || Val.getAs()); + return Val.getAs() ? evalCastFromLoc(Val.castAs(), CastTy) + : evalCastFromNonLoc(Val.castAs(), CastTy); } SVal SimpleSValBuilder::evalCastFromNonLoc(NonLoc val, QualType castTy) { bool isLocType = Loc::isLocType(castTy); - if (nonloc::LocAsInteger *LI = dyn_cast(&val)) { + if (llvm::Optional LI = + val.getAs()) { 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(val)) + if (!val.getAs()) return UnknownVal(); // Handle casts to a boolean type. if (castTy->isBooleanType()) { - bool b = cast(val).getValue().getBoolValue(); + bool b = val.castAs().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(val).getValue(); + llvm::APSInt i = val.castAs().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(val)) + if (!val.getAs()) return makeLocAsInteger(val, BitWidth); - llvm::APSInt i = cast(val).getValue(); + llvm::APSInt i = val.castAs().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(val).evalMinus(*this); + return val.castAs().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(X).evalComplement(*this); + return X.castAs().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(lhs).getLoc(); + Loc lhsL = lhs.castAs().getLoc(); switch (rhs.getSubKind()) { case nonloc::LocAsIntegerKind: return evalBinOpLL(state, op, lhsL, - cast(rhs).getLoc(), + rhs.castAs().getLoc(), resultTy); case nonloc::ConcreteIntKind: { // Transform the integer into a location and compare. - llvm::APSInt i = cast(rhs).getValue(); + llvm::APSInt i = rhs.castAs().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(lhs).getValue(); + llvm::APSInt LHSValue = lhs.castAs().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(lhs).getSymbol(); + SymbolRef Sym = lhs.castAs().getSymbol(); // LHS is a symbolic expression. if (const SymIntExpr *symIntExpr = dyn_cast(Sym)) { @@ -601,15 +602,15 @@ SVal SimpleSValBuilder::evalBinOpLL(ProgramStateRef state, if (!BinaryOperator::isComparisonOp(op)) return UnknownVal(); - const llvm::APSInt &lVal = cast(lhs).getValue(); + const llvm::APSInt &lVal = lhs.castAs().getValue(); return makeNonLoc(rSym, ReverseComparison(op), lVal, resultTy); } // If both operands are constants, just perform the operation. - if (loc::ConcreteInt *rInt = dyn_cast(&rhs)) { - SVal ResultVal = cast(lhs).evalBinOp(BasicVals, op, - *rInt); - if (Loc *Result = dyn_cast(&ResultVal)) + if (llvm::Optional rInt = rhs.getAs()) { + SVal ResultVal = + lhs.castAs().evalBinOp(BasicVals, op, *rInt); + if (llvm::Optional Result = ResultVal.getAs()) 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(rhs) || isa(rhs)); + assert(rhs.getAs() || rhs.getAs()); 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(&rhs)) { + if (llvm::Optional rInt = rhs.getAs()) { // 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(&LeftIndexVal); + llvm::Optional LeftIndex = LeftIndexVal.getAs(); if (!LeftIndex) return UnknownVal(); LeftIndexVal = evalCastFromNonLoc(*LeftIndex, ArrayIndexTy); - LeftIndex = dyn_cast(&LeftIndexVal); + LeftIndex = LeftIndexVal.getAs(); if (!LeftIndex) return UnknownVal(); // Do the same for the right index. SVal RightIndexVal = RightER->getIndex(); - NonLoc *RightIndex = dyn_cast(&RightIndexVal); + llvm::Optional RightIndex = RightIndexVal.getAs(); if (!RightIndex) return UnknownVal(); RightIndexVal = evalCastFromNonLoc(*RightIndex, ArrayIndexTy); - RightIndex = dyn_cast(&RightIndexVal); + RightIndex = RightIndexVal.getAs(); 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(&rhs)) { + if (llvm::Optional rhsInt = + rhs.getAs()) { 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(&rhs)) { - if (loc::ConcreteInt *lhsInt = dyn_cast(&lhs)) { + if (llvm::Optional rhsInt = + rhs.getAs()) { + if (llvm::Optional lhsInt = + lhs.getAs()) { 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(convertToArrayIndex(rhs)); + rhs = convertToArrayIndex(rhs).castAs(); 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(&index)) { + if (llvm::Optional indexV = index.getAs()) { 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(&V)) + if (llvm::Optional X = V.getAs()) return &X->getValue(); - if (nonloc::ConcreteInt* X = dyn_cast(&V)) + if (llvm::Optional X = V.getAs()) return &X->getValue(); if (SymbolRef Sym = V.getAsSymbol()) diff --git a/lib/StaticAnalyzer/Core/Store.cpp b/lib/StaticAnalyzer/Core/Store.cpp index 128dce4988..5177d0ed6f 100644 --- a/lib/StaticAnalyzer/Core/Store.cpp +++ b/lib/StaticAnalyzer/Core/Store.cpp @@ -270,7 +270,8 @@ SVal StoreManager::evalDerivedToBase(SVal Derived, const CXXBasePath &Path) { } SVal StoreManager::evalDerivedToBase(SVal Derived, QualType BaseType) { - loc::MemRegionVal *DerivedRegVal = dyn_cast(&Derived); + llvm::Optional DerivedRegVal = + Derived.getAs(); if (!DerivedRegVal) return Derived; @@ -289,7 +290,8 @@ SVal StoreManager::evalDynamicCast(SVal Base, QualType DerivedType, bool &Failed) { Failed = false; - loc::MemRegionVal *BaseRegVal = dyn_cast(&Base); + llvm::Optional BaseRegVal = + Base.getAs(); 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(Base); + Loc BaseL = Base.castAs(); const MemRegion* BaseR = 0; switch (BaseL.getSubKind()) { case loc::MemRegionKind: - BaseR = cast(BaseL).getRegion(); + BaseR = BaseL.castAs().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(Base)) + if (Base.isUnknownOrUndef() || Base.getAs()) return Base; - const MemRegion* BaseRegion = cast(Base).getRegion(); + const MemRegion* BaseRegion = Base.castAs().getRegion(); // Pointer of any type can be cast and used as array base. const ElementRegion *ElemR = dyn_cast(BaseRegion); // Convert the offset to the appropriate size and signedness. - Offset = cast(svalBuilder.convertToArrayIndex(Offset)); + Offset = svalBuilder.convertToArrayIndex(Offset).castAs(); if (!ElemR) { // @@ -442,15 +444,16 @@ SVal StoreManager::getLValueElement(QualType elementType, NonLoc Offset, SVal BaseIdx = ElemR->getIndex(); - if (!isa(BaseIdx)) + if (!BaseIdx.getAs()) return UnknownVal(); - const llvm::APSInt& BaseIdxI = cast(BaseIdx).getValue(); + const llvm::APSInt &BaseIdxI = + BaseIdx.castAs().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(Offset)) { + if (!Offset.getAs()) { if (isa(BaseRegion->StripCasts())) return UnknownVal(); @@ -459,7 +462,7 @@ SVal StoreManager::getLValueElement(QualType elementType, NonLoc Offset, Ctx)); } - const llvm::APSInt& OffI = cast(Offset).getValue(); + const llvm::APSInt& OffI = Offset.castAs().getValue(); assert(BaseIdxI.isSigned()); // Compute the new index. -- 2.40.0