This revision was automatically updated to reflect the committed changes. Closed by commit rGde6ba9704d0b: [analyzer][Casting] Support isa, cast, dyn_cast of SVals (authored by steakhal).
Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D125709/new/ https://reviews.llvm.org/D125709 Files: clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp Index: clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp +++ clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp @@ -446,7 +446,7 @@ // FIXME: We really should allow ranges of valid theType values, and // bifurcate the state appropriately. - Optional<nonloc::ConcreteInt> V = TheTypeVal.getAs<nonloc::ConcreteInt>(); + Optional<nonloc::ConcreteInt> V = dyn_cast<nonloc::ConcreteInt>(TheTypeVal); if (!V) return; @@ -907,7 +907,7 @@ // Go ahead and assume the value is non-nil. SVal Val = State->getSVal(*ElementLoc); - return State->assume(Val.castAs<DefinedOrUnknownSVal>(), true); + return State->assume(cast<DefinedOrUnknownSVal>(Val), true); } /// Returns NULL state if the collection is known to contain elements Index: clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h =================================================================== --- clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h +++ clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h @@ -98,19 +98,12 @@ /// Convert to the specified SVal type, asserting that this SVal is of /// the desired type. - template<typename T> - T castAs() const { - assert(T::classof(*this)); - return *static_cast<const T *>(this); - } + template <typename T> T castAs() const { return llvm::cast<T>(*this); } /// Convert to the specified SVal type, returning None if this SVal is /// not of the desired type. - template<typename T> - Optional<T> getAs() const { - if (!T::classof(*this)) - return None; - return *static_cast<const T *>(this); + template <typename T> Optional<T> getAs() const { + return llvm::dyn_cast<T>(*this); } unsigned getRawKind() const { return Kind; } @@ -564,4 +557,28 @@ } // namespace ento } // namespace clang +namespace llvm { +template <typename To, typename From> +struct CastInfo< + To, From, + std::enable_if_t<std::is_base_of<::clang::ento::SVal, From>::value>> + : public CastIsPossible<To, ::clang::ento::SVal> { + using Self = CastInfo< + To, From, + std::enable_if_t<std::is_base_of<::clang::ento::SVal, From>::value>>; + static bool isPossible(const From &V) { + return To::classof(*static_cast<const ::clang::ento::SVal *>(&V)); + } + static Optional<To> castFailed() { return Optional<To>{}; } + static To doCast(const From &f) { + return *static_cast<const To *>(cast<::clang::ento::SVal>(&f)); + } + static Optional<To> doCastIfPossible(const From &f) { + if (!Self::isPossible(f)) + return Self::castFailed(); + return doCast(f); + } +}; +} // namespace llvm + #endif // LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SVALS_H
Index: clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp +++ clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp @@ -446,7 +446,7 @@ // FIXME: We really should allow ranges of valid theType values, and // bifurcate the state appropriately. - Optional<nonloc::ConcreteInt> V = TheTypeVal.getAs<nonloc::ConcreteInt>(); + Optional<nonloc::ConcreteInt> V = dyn_cast<nonloc::ConcreteInt>(TheTypeVal); if (!V) return; @@ -907,7 +907,7 @@ // Go ahead and assume the value is non-nil. SVal Val = State->getSVal(*ElementLoc); - return State->assume(Val.castAs<DefinedOrUnknownSVal>(), true); + return State->assume(cast<DefinedOrUnknownSVal>(Val), true); } /// Returns NULL state if the collection is known to contain elements Index: clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h =================================================================== --- clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h +++ clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h @@ -98,19 +98,12 @@ /// Convert to the specified SVal type, asserting that this SVal is of /// the desired type. - template<typename T> - T castAs() const { - assert(T::classof(*this)); - return *static_cast<const T *>(this); - } + template <typename T> T castAs() const { return llvm::cast<T>(*this); } /// Convert to the specified SVal type, returning None if this SVal is /// not of the desired type. - template<typename T> - Optional<T> getAs() const { - if (!T::classof(*this)) - return None; - return *static_cast<const T *>(this); + template <typename T> Optional<T> getAs() const { + return llvm::dyn_cast<T>(*this); } unsigned getRawKind() const { return Kind; } @@ -564,4 +557,28 @@ } // namespace ento } // namespace clang +namespace llvm { +template <typename To, typename From> +struct CastInfo< + To, From, + std::enable_if_t<std::is_base_of<::clang::ento::SVal, From>::value>> + : public CastIsPossible<To, ::clang::ento::SVal> { + using Self = CastInfo< + To, From, + std::enable_if_t<std::is_base_of<::clang::ento::SVal, From>::value>>; + static bool isPossible(const From &V) { + return To::classof(*static_cast<const ::clang::ento::SVal *>(&V)); + } + static Optional<To> castFailed() { return Optional<To>{}; } + static To doCast(const From &f) { + return *static_cast<const To *>(cast<::clang::ento::SVal>(&f)); + } + static Optional<To> doCastIfPossible(const From &f) { + if (!Self::isPossible(f)) + return Self::castFailed(); + return doCast(f); + } +}; +} // namespace llvm + #endif // LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SVALS_H
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits