diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h index 7c5f23b6d466..c3750b2320c8 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h @@ -98,19 +98,12 @@ public: /// Convert to the specified SVal type, asserting that this SVal is of /// the desired type. - template - T castAs() const { - assert(T::classof(*this)); - return *static_cast(this); - } + template T castAs() const { return llvm::cast(*this); } /// Convert to the specified SVal type, returning None if this SVal is /// not of the desired type. - template - Optional getAs() const { - if (!T::classof(*this)) - return None; - return *static_cast(this); + template Optional getAs() const { + return llvm::dyn_cast(*this); } unsigned getRawKind() const { return Kind; } @@ -564,4 +557,28 @@ public: } // namespace ento } // namespace clang +namespace llvm { +template +struct CastInfo< + To, From, + std::enable_if_t::value>> + : public CastIsPossible { + using Self = CastInfo< + To, From, + std::enable_if_t::value>>; + static bool isPossible(const From &V) { + return To::classof(*static_cast(&V)); + } + static Optional castFailed() { return Optional{}; } + static To doCast(const From &f) { + return *static_cast(cast<::clang::ento::SVal>(&f)); + } + static Optional doCastIfPossible(const From &f) { + if (!Self::isPossible(f)) + return Self::castFailed(); + return doCast(f); + } +}; +} // namespace llvm + #endif // LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SVALS_H diff --git a/clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp b/clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp index 2c210fb6cdb9..b143ef93282f 100644 --- a/clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp @@ -446,7 +446,7 @@ void CFNumberChecker::checkPreStmt(const CallExpr *CE, // FIXME: We really should allow ranges of valid theType values, and // bifurcate the state appropriately. - Optional V = TheTypeVal.getAs(); + Optional V = dyn_cast(TheTypeVal); if (!V) return; @@ -907,7 +907,7 @@ static ProgramStateRef checkElementNonNil(CheckerContext &C, // Go ahead and assume the value is non-nil. SVal Val = State->getSVal(*ElementLoc); - return State->assume(Val.castAs(), true); + return State->assume(cast(Val), true); } /// Returns NULL state if the collection is known to contain elements