Skip to content

Commit b0877cd

Browse files
committed
[ADT] Introduce a static_cast_to
1 parent b7e922a commit b0877cd

File tree

3 files changed

+96
-0
lines changed

3 files changed

+96
-0
lines changed

llvm/include/llvm/Support/Casting.h

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -816,6 +816,37 @@ template <typename... Types> struct IsaAndPresentCheckPredicate {
816816
return isa_and_present<Types...>(Val);
817817
}
818818
};
819+
820+
template <typename U> struct StaticCastPredicate {
821+
template <typename T> decltype(auto) operator()(const T &Val) const {
822+
return static_cast<U>(Val);
823+
} // namespace detail
824+
};
825+
826+
template <typename U> struct DynCastPredicate {
827+
template <typename T> decltype(auto) operator()(const T &Val) const {
828+
return dyn_cast<U>(Val);
829+
} // namespace detail
830+
};
831+
832+
template <typename U> struct CastPredicate {
833+
template <typename T> decltype(auto) operator()(const T &Val) const {
834+
return cast<U>(Val);
835+
} // namespace detail
836+
};
837+
838+
template <typename U> struct CastIfPresentPredicate {
839+
template <typename T> decltype(auto) operator()(const T &Val) const {
840+
return cast_if_present<U>(Val);
841+
}
842+
};
843+
844+
template <typename U> struct DynCastIfPresentPredicate {
845+
template <typename T> decltype(auto) operator()(const T &Val) const {
846+
return dyn_cast_if_present<U>(Val);
847+
}
848+
};
849+
819850
} // namespace detail
820851

821852
/// Function object wrapper for the `llvm::isa` type check. The function call
@@ -841,6 +872,22 @@ template <typename... Types>
841872
inline constexpr detail::IsaAndPresentCheckPredicate<Types...>
842873
IsaAndPresentPred{};
843874

875+
template <typename... Types>
876+
inline constexpr detail::StaticCastPredicate<Types...> StaticCastTo{};
877+
878+
template <typename... Types>
879+
inline constexpr detail::CastPredicate<Types...> CastTo{};
880+
881+
template <typename... Types>
882+
inline constexpr detail::CastIfPresentPredicate<Types...> CastIfPresentTo{};
883+
884+
template <typename... Types>
885+
inline constexpr detail::DynCastIfPresentPredicate<Types...>
886+
DynCastIfPresentTo{};
887+
888+
template <typename... Types>
889+
inline constexpr detail::DynCastPredicate<Types...> DynCastTo{};
890+
844891
} // end namespace llvm
845892

846893
#endif // LLVM_SUPPORT_CASTING_H

llvm/unittests/ADT/STLExtrasTest.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "llvm/ADT/STLExtras.h"
1010
#include "llvm/ADT/ArrayRef.h"
1111
#include "llvm/ADT/StringRef.h"
12+
#include "llvm/Support/Casting.h"
1213
#include "gmock/gmock.h"
1314
#include "gtest/gtest.h"
1415

llvm/unittests/Support/Casting.cpp

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "llvm/Support/Casting.h"
10+
#include "llvm/ADT/STLExtras.h"
1011
#include "llvm/IR/User.h"
1112
#include "llvm/Support/Debug.h"
1213
#include "llvm/Support/raw_ostream.h"
@@ -561,6 +562,53 @@ TEST(CastingTest, assertion_check_unique_ptr) {
561562
<< "Invalid cast of const ref did not cause an abort()";
562563
}
563564

565+
TEST(Casting, StaticCastPredicate) {
566+
std::vector<uint32_t> Values{1, 2};
567+
568+
EXPECT_TRUE(
569+
all_of(map_range(Values, StaticCastTo<uint64_t>),
570+
[](const auto &V) { return sizeof(V) == sizeof(uint64_t); }));
571+
}
572+
573+
TEST(Casting, LLVMRTTIPredicates) {
574+
struct Base {
575+
enum Kind { BK_Base, BK_Derived };
576+
const Kind K;
577+
Base(Kind K = BK_Base) : K(K) {}
578+
Kind getKind() const { return K; }
579+
virtual ~Base() = default;
580+
};
581+
582+
struct Derived : public Base {
583+
Derived() : Base(BK_Derived) {}
584+
static bool classof(const Base *B) { return B->getKind() == BK_Derived; }
585+
};
586+
587+
Base B;
588+
Derived D;
589+
590+
std::vector<Base *> RTTI{&B, &D, nullptr};
591+
auto NonNull = drop_end(RTTI);
592+
auto OnlyDerived = drop_begin(NonNull);
593+
auto Casted = map_range(OnlyDerived, CastTo<Derived>);
594+
auto DynCasted = map_range(NonNull, DynCastTo<Derived>);
595+
auto DynCastedIfPresent = map_range(RTTI, DynCastIfPresentTo<Derived>);
596+
auto CastedIfPresent = map_range(drop_begin(RTTI), CastIfPresentTo<Derived>);
597+
598+
auto Same = [](const auto &T) {
599+
const auto &[A, B] = T;
600+
return A == B;
601+
};
602+
EXPECT_TRUE(all_of(zip_longest(Casted, std::vector<Derived *>{&D}), Same));
603+
EXPECT_TRUE(all_of(
604+
zip_longest(DynCasted, std::vector<Derived *>{nullptr, &D}), Same));
605+
EXPECT_TRUE(all_of(zip_longest(DynCastedIfPresent,
606+
std::vector<Derived *>{nullptr, &D, nullptr}),
607+
Same));
608+
EXPECT_TRUE(all_of(
609+
zip_longest(CastedIfPresent, std::vector<Derived *>{&D, nullptr}), Same));
610+
}
611+
564612
} // end namespace assertion_checks
565613
#endif
566614
} // end namespace

0 commit comments

Comments
 (0)