steakhal created this revision. steakhal added reviewers: NoQ, martong, Szelethus, balazske, ASDenysPetrov, bzcheeseman. Herald added subscribers: manas, dkrupp, donat.nagy, mikhail.ramalho, a.sidorin, rnkovacs, szepet, baloghadamsoftware, xazax.hun. Herald added a project: All. steakhal requested review of this revision. Herald added a project: clang. Herald added a subscriber: cfe-commits.
This change specializes the LLVM RTTI mechanism for SVals. After this change, we can use the well-known `isa`, `cast`, `dyn_cast`. Examples: // SVal V = ...; // Loc MyLoc = ...; bool IsInteresting = isa<loc::MemRegionVal, loc::GotoLabel>(MyLoc); auto MRV = cast<loc::MemRegionVal>(MyLoc); Optional<loc::MemRegionVal> MaybeMRV = dyn_cast<loc::MemRegionVal>(V) The current `SVal::getAs` and `castAs` member functions are redundant at this point, but I believe that they are still handy. The member function version is terse and reads left-to-right, which IMO is a great plus. However, we should probably add a variadic `isa` member function version to have the same casting API in both cases. I'm not sure, shall I add tests? Thanks for the extensive TMP help @bzcheeseman! Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D125709 Files: clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h 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 @@ -571,4 +571,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 Optional<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/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h =================================================================== --- clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h +++ clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h @@ -571,4 +571,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 Optional<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