diff options
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<NonLoc>(X)) : X; + return X.isValid() ? svalBuilder.evalMinus(X.castAs<NonLoc>()) : X; } SVal evalComplement(SVal X) { - return X.isValid() ? svalBuilder.evalComplement(cast<NonLoc>(X)) : X; + return X.isValid() ? svalBuilder.evalComplement(X.castAs<NonLoc>()) : X; } public: @@ -445,7 +445,8 @@ public: SVal evalBinOp(ProgramStateRef state, BinaryOperator::Opcode op, NonLoc L, SVal R, QualType T) { - return R.isValid() ? svalBuilder.evalBinOpNN(state,op,L, cast<NonLoc>(R), T) : R; + return R.isValid() ? svalBuilder.evalBinOpNN(state, op, L, + R.castAs<NonLoc>(), T) : R; } SVal evalBinOp(ProgramStateRef ST, BinaryOperator::Opcode Op, 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<nonloc::ConcreteInt>(&Idx) || - cast<nonloc::ConcreteInt>(&Idx)->getValue().isSigned()) && + assert((!Idx.getAs<nonloc::ConcreteInt>() || + Idx.castAs<nonloc::ConcreteInt>().getValue().isSigned()) && "The index must be signed"); } 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<DefinedSVal>(Cond), - Assumption); + + return getStateManager().ConstraintMgr + ->assume(this, Cond.castAs<DefinedSVal>(), Assumption); } inline std::pair<ProgramStateRef , ProgramStateRef > ProgramState::assume(DefinedOrUnknownSVal Cond) const { if (Cond.isUnknown()) return std::make_pair(this, this); - - return getStateManager().ConstraintMgr->assumeDual(this, - cast<DefinedSVal>(Cond)); + + return getStateManager().ConstraintMgr + ->assumeDual(this, Cond.castAs<DefinedSVal>()); } inline ProgramStateRef ProgramState::bindLoc(SVal LV, SVal V) const { - return !isa<Loc>(LV) ? this : bindLoc(cast<Loc>(LV), V); + if (llvm::Optional<Loc> L = LV.getAs<Loc>()) + return bindLoc(*L, V); + return this; } inline Loc ProgramState::getLValue(const VarDecl *VD, @@ -669,7 +671,7 @@ inline SVal ProgramState::getLValue(const IndirectFieldDecl *D, } inline SVal ProgramState::getLValue(QualType ElementType, SVal Idx, SVal Base) const{ - if (NonLoc *N = dyn_cast<NonLoc>(&Idx)) + if (llvm::Optional<NonLoc> N = Idx.getAs<NonLoc>()) return getStateManager().StoreMgr->getLValueElement(ElementType, *N, Base); return UnknownVal(); } 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<typename T> + T castAs() const { + assert(T::isType(*this)); + T t; + SVal& sv = t; + sv = *this; + return t; + } + + template<typename T> + llvm::Optional<T> getAs() const { + if (!T::isType(*this)) + return llvm::Optional<T>(); + T t; + SVal& sv = t; + sv = *this; + return t; + } + /// BufferTy - A temporary buffer to hold a set of SVals. typedef SmallVector<SVal,5> BufferTy; @@ -161,8 +180,10 @@ class UndefinedVal : public SVal { public: UndefinedVal() : SVal(UndefinedKind) {} - static inline bool classof(const SVal* V) { - return V->getBaseKind() == UndefinedKind; +private: + friend class SVal; + static bool isType(const SVal& V) { + return V.getBaseKind() == UndefinedKind; } }; @@ -174,16 +195,17 @@ private: bool isValid() const LLVM_DELETED_FUNCTION; protected: + DefinedOrUnknownSVal() {} explicit DefinedOrUnknownSVal(const void *d, bool isLoc, unsigned ValKind) : SVal(d, isLoc, ValKind) {} explicit DefinedOrUnknownSVal(BaseKind k, void *D = NULL) : SVal(k, D) {} -public: - // Implement isa<T> support. - static inline bool classof(const SVal *V) { - return !V->isUndef(); +private: + friend class SVal; + static bool isType(const SVal& V) { + return !V.isUndef(); } }; @@ -191,8 +213,10 @@ class UnknownVal : public DefinedOrUnknownSVal { public: explicit UnknownVal() : DefinedOrUnknownSVal(UnknownKind) {} - static inline bool classof(const SVal *V) { - return V->getBaseKind() == UnknownKind; +private: + friend class SVal; + static bool isType(const SVal& V) { + return V.getBaseKind() == UnknownKind; } }; @@ -204,46 +228,51 @@ private: bool isUnknownOrUndef() const LLVM_DELETED_FUNCTION; bool isValid() const LLVM_DELETED_FUNCTION; protected: + DefinedSVal() {} explicit DefinedSVal(const void *d, bool isLoc, unsigned ValKind) : DefinedOrUnknownSVal(d, isLoc, ValKind) {} -public: - // Implement isa<T> support. - static inline bool classof(const SVal *V) { - return !V->isUnknownOrUndef(); +private: + friend class SVal; + static bool isType(const SVal& V) { + return !V.isUnknownOrUndef(); } }; class NonLoc : public DefinedSVal { protected: + NonLoc() {} explicit NonLoc(unsigned SubKind, const void *d) : DefinedSVal(d, false, SubKind) {} public: void dumpToStream(raw_ostream &Out) const; - // Implement isa<T> support. - static inline bool classof(const SVal* V) { - return V->getBaseKind() == NonLocKind; +private: + friend class SVal; + static bool isType(const SVal& V) { + return V.getBaseKind() == NonLocKind; } }; class Loc : public DefinedSVal { protected: + Loc() {} explicit Loc(unsigned SubKind, const void *D) : DefinedSVal(const_cast<void*>(D), true, SubKind) {} public: void dumpToStream(raw_ostream &Out) const; - // Implement isa<T> support. - static inline bool classof(const SVal* V) { - return V->getBaseKind() == LocKind; - } - static inline bool isLocType(QualType T) { return T->isAnyPointerType() || T->isBlockPointerType() || T->isReferenceType(); } + +private: + friend class SVal; + static bool isType(const SVal& V) { + return V.getBaseKind() == LocKind; + } }; //==------------------------------------------------------------------------==// @@ -264,17 +293,20 @@ public: return (const SymExpr*) Data; } - bool isExpression() { + bool isExpression() const { return !isa<SymbolData>(getSymbol()); } - static inline bool classof(const SVal* V) { - return V->getBaseKind() == NonLocKind && - V->getSubKind() == SymbolValKind; +private: + friend class SVal; + SymbolVal() {} + static bool isType(const SVal& V) { + return V.getBaseKind() == NonLocKind && + V.getSubKind() == SymbolValKind; } - static inline bool classof(const NonLoc* V) { - return V->getSubKind() == SymbolValKind; + static bool isType(const NonLoc& V) { + return V.getSubKind() == SymbolValKind; } }; @@ -295,38 +327,40 @@ public: ConcreteInt evalMinus(SValBuilder &svalBuilder) const; - // Implement isa<T> support. - static inline bool classof(const SVal* V) { - return V->getBaseKind() == NonLocKind && - V->getSubKind() == ConcreteIntKind; +private: + friend class SVal; + ConcreteInt() {} + static bool isType(const SVal& V) { + return V.getBaseKind() == NonLocKind && + V.getSubKind() == ConcreteIntKind; } - static inline bool classof(const NonLoc* V) { - return V->getSubKind() == ConcreteIntKind; + static bool isType(const NonLoc& V) { + return V.getSubKind() == ConcreteIntKind; } }; class LocAsInteger : public NonLoc { friend class ento::SValBuilder; - explicit LocAsInteger(const std::pair<SVal, uintptr_t>& data) : - NonLoc(LocAsIntegerKind, &data) { - assert (isa<Loc>(data.first)); - } + explicit LocAsInteger(const std::pair<SVal, uintptr_t> &data) + : NonLoc(LocAsIntegerKind, &data) { + assert (data.first.getAs<Loc>()); + } public: Loc getLoc() const { const std::pair<SVal, uintptr_t> *D = static_cast<const std::pair<SVal, uintptr_t> *>(Data); - return cast<Loc>(D->first); + return D->first.castAs<Loc>(); } - const Loc& getPersistentLoc() const { + Loc getPersistentLoc() const { const std::pair<SVal, uintptr_t> *D = static_cast<const std::pair<SVal, uintptr_t> *>(Data); const SVal& V = D->first; - return cast<Loc>(V); + return V.castAs<Loc>(); } unsigned getNumBits() const { @@ -335,14 +369,16 @@ public: return D->second; } - // Implement isa<T> support. - static inline bool classof(const SVal* V) { - return V->getBaseKind() == NonLocKind && - V->getSubKind() == LocAsIntegerKind; +private: + friend class SVal; + LocAsInteger() {} + static bool isType(const SVal& V) { + return V.getBaseKind() == NonLocKind && + V.getSubKind() == LocAsIntegerKind; } - static inline bool classof(const NonLoc* V) { - return V->getSubKind() == LocAsIntegerKind; + static bool isType(const NonLoc& V) { + return V.getSubKind() == LocAsIntegerKind; } }; @@ -360,12 +396,15 @@ public: iterator begin() const; iterator end() const; - static bool classof(const SVal* V) { - return V->getBaseKind() == NonLocKind && V->getSubKind() == CompoundValKind; +private: + friend class SVal; + CompoundVal() {} + static bool isType(const SVal& V) { + return V.getBaseKind() == NonLocKind && V.getSubKind() == CompoundValKind; } - static bool classof(const NonLoc* V) { - return V->getSubKind() == CompoundValKind; + static bool isType(const NonLoc& V) { + return V.getSubKind() == CompoundValKind; } }; @@ -381,12 +420,15 @@ public: const void *getStore() const; const TypedValueRegion *getRegion() const; - static bool classof(const SVal *V) { - return V->getBaseKind() == NonLocKind && - V->getSubKind() == LazyCompoundValKind; +private: + friend class SVal; + LazyCompoundVal() {} + static bool isType(const SVal& V) { + return V.getBaseKind() == NonLocKind && + V.getSubKind() == LazyCompoundValKind; } - static bool classof(const NonLoc *V) { - return V->getSubKind() == LazyCompoundValKind; + static bool isType(const NonLoc& V) { + return V.getSubKind() == LazyCompoundValKind; } }; @@ -408,12 +450,15 @@ public: return static_cast<const LabelDecl*>(Data); } - static inline bool classof(const SVal* V) { - return V->getBaseKind() == LocKind && V->getSubKind() == GotoLabelKind; +private: + friend class SVal; + GotoLabel() {} + static bool isType(const SVal& V) { + return V.getBaseKind() == LocKind && V.getSubKind() == GotoLabelKind; } - static inline bool classof(const Loc* V) { - return V->getSubKind() == GotoLabelKind; + static bool isType(const Loc& V) { + return V.getSubKind() == GotoLabelKind; } }; @@ -443,14 +488,16 @@ public: return getRegion() != R.getRegion(); } - // Implement isa<T> support. - static inline bool classof(const SVal* V) { - return V->getBaseKind() == LocKind && - V->getSubKind() == MemRegionKind; +private: + friend class SVal; + MemRegionVal() {} + static bool isType(const SVal& V) { + return V.getBaseKind() == LocKind && + V.getSubKind() == MemRegionKind; } - static inline bool classof(const Loc* V) { - return V->getSubKind() == MemRegionKind; + static bool isType(const Loc& V) { + return V.getSubKind() == MemRegionKind; } }; @@ -466,14 +513,16 @@ public: SVal evalBinOp(BasicValueFactory& BasicVals, BinaryOperator::Opcode Op, const ConcreteInt& R) const; - // Implement isa<T> support. - static inline bool classof(const SVal* V) { - return V->getBaseKind() == LocKind && - V->getSubKind() == ConcreteIntKind; +private: + friend class SVal; + ConcreteInt() {} + static bool isType(const SVal& V) { + return V.getBaseKind() == LocKind && + V.getSubKind() == ConcreteIntKind; } - static inline bool classof(const Loc* V) { - return V->getSubKind() == ConcreteIntKind; + static bool isType(const Loc& V) { + return V.getSubKind() == ConcreteIntKind; } }; 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<NonLoc>(byteOffset); } + NonLoc getByteOffset() const { return byteOffset.castAs<NonLoc>(); } const SubRegion *getRegion() const { return baseRegion; } static RegionRawOffsetV2 computeOffset(ProgramStateRef state, @@ -110,13 +110,12 @@ void ArrayBoundCheckerV2::checkLocation(SVal location, bool isLoad, SVal extentBegin = computeExtentBegin(svalBuilder, rawOffset.getRegion()); - if (isa<NonLoc>(extentBegin)) { - SVal lowerBound - = svalBuilder.evalBinOpNN(state, BO_LT, rawOffset.getByteOffset(), - cast<NonLoc>(extentBegin), + if (llvm::Optional<NonLoc> NV = extentBegin.getAs<NonLoc>()) { + SVal lowerBound = + svalBuilder.evalBinOpNN(state, BO_LT, rawOffset.getByteOffset(), *NV, svalBuilder.getConditionType()); - NonLoc *lowerBoundToCheck = dyn_cast<NonLoc>(&lowerBound); + llvm::Optional<NonLoc> lowerBoundToCheck = lowerBound.getAs<NonLoc>(); if (!lowerBoundToCheck) return; @@ -140,15 +139,15 @@ void ArrayBoundCheckerV2::checkLocation(SVal location, bool isLoad, // we are doing a load/store after the last valid offset. DefinedOrUnknownSVal extentVal = rawOffset.getRegion()->getExtent(svalBuilder); - if (!isa<NonLoc>(extentVal)) + if (!extentVal.getAs<NonLoc>()) break; SVal upperbound = svalBuilder.evalBinOpNN(state, BO_GE, rawOffset.getByteOffset(), - cast<NonLoc>(extentVal), + extentVal.castAs<NonLoc>(), svalBuilder.getConditionType()); - NonLoc *upperboundToCheck = dyn_cast<NonLoc>(&upperbound); + llvm::Optional<NonLoc> upperboundToCheck = upperbound.getAs<NonLoc>(); if (!upperboundToCheck) break; @@ -235,7 +234,7 @@ static bool IsCompleteType(ASTContext &Ctx, QualType Ty) { // is unknown or undefined, we lazily substitute '0'. Otherwise, // return 'val'. static inline SVal getValue(SVal val, SValBuilder &svalBuilder) { - return isa<UndefinedVal>(val) ? svalBuilder.makeArrayIndex(0) : val; + return val.getAs<UndefinedVal>() ? svalBuilder.makeArrayIndex(0) : val; } // Scale a base value by a scaling factor, and return the scaled @@ -256,9 +255,9 @@ static SVal addValue(ProgramStateRef state, SVal x, SVal y, // only care about computing offsets. if (x.isUnknownOrUndef() || y.isUnknownOrUndef()) return UnknownVal(); - - return svalBuilder.evalBinOpNN(state, BO_Add, - cast<NonLoc>(x), cast<NonLoc>(y), + + return svalBuilder.evalBinOpNN(state, BO_Add, x.castAs<NonLoc>(), + y.castAs<NonLoc>(), svalBuilder.getArrayIndexType()); } @@ -284,7 +283,7 @@ RegionRawOffsetV2 RegionRawOffsetV2::computeOffset(ProgramStateRef state, case MemRegion::ElementRegionKind: { const ElementRegion *elemReg = cast<ElementRegion>(region); SVal index = elemReg->getIndex(); - if (!isa<NonLoc>(index)) + if (!index.getAs<NonLoc>()) return RegionRawOffsetV2(); QualType elemType = elemReg->getElementType(); // If the element is an incomplete type, go no further. @@ -296,7 +295,7 @@ RegionRawOffsetV2 RegionRawOffsetV2::computeOffset(ProgramStateRef state, offset = addValue(state, getValue(offset, svalBuilder), scaleValue(state, - cast<NonLoc>(index), + index.castAs<NonLoc>(), astContext.getTypeSizeInChars(elemType), svalBuilder), svalBuilder); 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<DefinedSVal>(&V); + llvm::Optional<DefinedSVal> DV = V.getAs<DefinedSVal>(); // If the value is unknown or undefined, we can't perform this check. if (!DV) continue; - if (!isa<Loc>(*DV)) { + if (!DV->getAs<Loc>()) { // If the argument is a union type, we want to handle a potential // transparent_union GCC extension. const Expr *ArgE = Call.getArgExpr(idx); @@ -69,11 +69,12 @@ void AttrNonNullChecker::checkPreCall(const CallEvent &Call, if (!UT || !UT->getDecl()->hasAttr<TransparentUnionAttr>()) continue; - if (nonloc::CompoundVal *CSV = dyn_cast<nonloc::CompoundVal>(DV)) { + if (llvm::Optional<nonloc::CompoundVal> CSV = + DV->getAs<nonloc::CompoundVal>()) { nonloc::CompoundVal::iterator CSV_I = CSV->begin(); assert(CSV_I != CSV->end()); V = *CSV_I; - DV = dyn_cast<DefinedSVal>(&V); + DV = V.getAs<DefinedSVal>(); assert(++CSV_I == CSV->end()); if (!DV) continue; 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<loc::ConcreteInt>(X); + return X.getAs<loc::ConcreteInt>(); } //===----------------------------------------------------------------------===// @@ -290,7 +290,8 @@ void CFNumberCreateChecker::checkPreStmt(const CallExpr *CE, // FIXME: We really should allow ranges of valid theType values, and // bifurcate the state appropriately. - nonloc::ConcreteInt* V = dyn_cast<nonloc::ConcreteInt>(&TheTypeVal); + llvm::Optional<nonloc::ConcreteInt> V = + TheTypeVal.getAs<nonloc::ConcreteInt>(); if (!V) return; @@ -308,7 +309,8 @@ void CFNumberCreateChecker::checkPreStmt(const CallExpr *CE, // FIXME: Eventually we should handle arbitrary locations. We can do this // by having an enhanced memory model that does low-level typing. - loc::MemRegionVal* LV = dyn_cast<loc::MemRegionVal>(&TheValueExpr); + llvm::Optional<loc::MemRegionVal> LV = + TheValueExpr.getAs<loc::MemRegionVal>(); if (!LV) return; @@ -409,13 +411,14 @@ void CFRetainReleaseChecker::checkPreStmt(const CallExpr *CE, // Get the argument's value. const Expr *Arg = CE->getArg(0); SVal ArgVal = state->getSVal(Arg, C.getLocationContext()); - DefinedSVal *DefArgVal = dyn_cast<DefinedSVal>(&ArgVal); + llvm::Optional<DefinedSVal> DefArgVal = ArgVal.getAs<DefinedSVal>(); if (!DefArgVal) return; // Get a NULL value. SValBuilder &svalBuilder = C.getSValBuilder(); - DefinedSVal zero = cast<DefinedSVal>(svalBuilder.makeZeroVal(Arg->getType())); + DefinedSVal zero = + svalBuilder.makeZeroVal(Arg->getType()).castAs<DefinedSVal>(); // Make an expression asserting that they're equal. DefinedOrUnknownSVal ArgIsNull = svalBuilder.evalEQ(state, zero, *DefArgVal); @@ -619,7 +622,7 @@ void VariadicMethodTypeChecker::checkPreObjCMessage(const ObjCMethodCall &msg, continue; // Ignore pointer constants. - if (isa<loc::ConcreteInt>(msg.getArgSVal(I))) + if (msg.getArgSVal(I).getAs<loc::ConcreteInt>()) continue; // Ignore pointer types annotated with 'NSObject' attribute. @@ -716,12 +719,12 @@ void ObjCLoopChecker::checkPostStmt(const ObjCForCollectionStmt *FCS, ElementVar = State->getSVal(Element, C.getLocationContext()); } - if (!isa<Loc>(ElementVar)) + if (!ElementVar.getAs<Loc>()) return; // Go ahead and assume the value is non-nil. - SVal Val = State->getSVal(cast<Loc>(ElementVar)); - State = State->assume(cast<DefinedOrUnknownSVal>(Val), true); + SVal Val = State->getSVal(ElementVar.castAs<Loc>()); + State = State->assume(Val.castAs<DefinedOrUnknownSVal>(), true); C.addTransition(State); } @@ -745,7 +748,8 @@ static ProgramStateRef assumeExprIsNonNull(const Expr *NonNullExpr, ProgramStateRef State, |