Skip to content

Commit 85a8b3a

Browse files
committed
[ADT] Introduce a static_cast_to
1 parent 2141edf commit 85a8b3a

File tree

2 files changed

+91
-0
lines changed

2 files changed

+91
-0
lines changed

llvm/include/llvm/Support/Casting.h

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -816,6 +816,42 @@ template <typename... Types> struct IsaAndPresentCheckPredicate {
816816
return isa_and_present<Types...>(Val);
817817
}
818818
};
819+
820+
//===----------------------------------------------------------------------===//
821+
// Casting Function Objects
822+
//===----------------------------------------------------------------------===//
823+
824+
/// Usable in generic algorithms like map_range
825+
template <typename U> struct StaticCastFunc {
826+
template <typename T> decltype(auto) operator()(T &&Val) const {
827+
return static_cast<U>(Val);
828+
}
829+
};
830+
831+
template <typename U> struct DynCastFunc {
832+
template <typename T> decltype(auto) operator()(T &&Val) const {
833+
return dyn_cast<U>(Val);
834+
}
835+
};
836+
837+
template <typename U> struct CastFunc {
838+
template <typename T> decltype(auto) operator()(T &&Val) const {
839+
return cast<U>(Val);
840+
}
841+
};
842+
843+
template <typename U> struct CastIfPresentFunc {
844+
template <typename T> decltype(auto) operator()(T &&Val) const {
845+
return cast_if_present<U>(Val);
846+
}
847+
};
848+
849+
template <typename U> struct DynCastIfPresentFunc {
850+
template <typename T> decltype(auto) operator()(T &&Val) const {
851+
return dyn_cast_if_present<U>(Val);
852+
}
853+
};
854+
819855
} // namespace detail
820856

821857
/// Function object wrapper for the `llvm::isa` type check. The function call
@@ -841,6 +877,20 @@ template <typename... Types>
841877
inline constexpr detail::IsaAndPresentCheckPredicate<Types...>
842878
IsaAndPresentPred{};
843879

880+
/// Function objects corresponding to the Cast types defined above.
881+
template <typename From>
882+
inline constexpr detail::StaticCastFunc<From> StaticCastTo{};
883+
884+
template <typename From> inline constexpr detail::CastFunc<From> CastTo{};
885+
886+
template <typename From>
887+
inline constexpr detail::CastIfPresentFunc<From> CastIfPresentTo{};
888+
889+
template <typename From>
890+
inline constexpr detail::DynCastIfPresentFunc<From> DynCastIfPresentTo{};
891+
892+
template <typename From> inline constexpr detail::DynCastFunc<From> DynCastTo{};
893+
844894
} // end namespace llvm
845895

846896
#endif // LLVM_SUPPORT_CASTING_H

llvm/unittests/Support/Casting.cpp

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -561,6 +561,47 @@ TEST(CastingTest, assertion_check_unique_ptr) {
561561
<< "Invalid cast of const ref did not cause an abort()";
562562
}
563563

564+
TEST(Casting, StaticCastPredicate) {
565+
uint32_t Value = 1;
566+
567+
EXPECT_TRUE(
568+
(std::is_same_v<decltype(StaticCastTo<uint64_t>(Value)), uint64_t>));
569+
}
570+
571+
TEST(Casting, LLVMRTTIPredicates) {
572+
struct Base {
573+
enum Kind { BK_Base, BK_Derived };
574+
const Kind K;
575+
Base(Kind K = BK_Base) : K(K) {}
576+
Kind getKind() const { return K; }
577+
virtual ~Base() = default;
578+
};
579+
580+
struct Derived : Base {
581+
Derived() : Base(BK_Derived) {}
582+
static bool classof(const Base *B) { return B->getKind() == BK_Derived; }
583+
bool Field = false;
584+
};
585+
586+
Base B;
587+
Derived D;
588+
Base *BD = &D;
589+
Base *Null = nullptr;
590+
591+
// pointers
592+
EXPECT_EQ(DynCastTo<Derived>(BD), &D);
593+
EXPECT_EQ(CastTo<Derived>(BD), &D);
594+
EXPECT_EQ(DynCastTo<Derived>(&B), nullptr);
595+
EXPECT_EQ(CastIfPresentTo<Derived>(BD), &D);
596+
EXPECT_EQ(CastIfPresentTo<Derived>(Null), nullptr);
597+
EXPECT_EQ(DynCastIfPresentTo<Derived>(BD), &D);
598+
EXPECT_EQ(DynCastIfPresentTo<Derived>(Null), nullptr);
599+
600+
Base &R = D;
601+
CastTo<Derived>(R).Field = true;
602+
EXPECT_TRUE(D.Field);
603+
}
604+
564605
} // end namespace assertion_checks
565606
#endif
566607
} // end namespace

0 commit comments

Comments
 (0)