Skip to content

Commit 0ebb22b

Browse files
committed
[Support][Casting] Add predicates for isa* functions
Expose function objects that call into `llvm::isa` and `llvm::isa_and_present`, such that these type checks can be used as predicates in generic algorithms. Before this change, `llvm::isa*` functions cannot be easily used without knowing both the argument type and the checked types, which leads to them being wrapped in lambdas. For example: ```c++ llvm::all_of(myTypes, [](auto type) { return llvm::isa<VectorType>(type); }); ``` With this PR the example above becomes: ```c++ llvm::all_of(myTypes, llvm::IsaPred<VectorType>); ``` As an alternative solution, I considered redefining `isa*` as function objects, but I decided against doing that because it would create assymetry with other cast *functions* and could break code that depends on them being actual functions.
1 parent b29301c commit 0ebb22b

File tree

2 files changed

+60
-0
lines changed

2 files changed

+60
-0
lines changed

llvm/include/llvm/Support/Casting.h

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -801,6 +801,52 @@ template <class X, class Y>
801801
return unique_dyn_cast_or_null<X, Y>(Val);
802802
}
803803

804+
//===----------------------------------------------------------------------===//
805+
// Isa Predicates
806+
//===----------------------------------------------------------------------===//
807+
808+
/// These are wrappers over isa* function that allow them to be used in generic
809+
/// algorithms such as `llvm:all_of`, `llvm::none_of`, etc. This is accomplished
810+
/// by exposing the isa* functions through function objects with a generic
811+
/// function call operator.
812+
813+
namespace detail {
814+
template <typename... Types> struct IsaCheckPredicate {
815+
template <typename T> bool operator()(const T &Val) const {
816+
return isa<Types...>(Val);
817+
}
818+
};
819+
820+
template <typename... Types> struct IsaAndPresentCheckPredicate {
821+
template <typename T> bool operator()(const T &Val) const {
822+
return isa_and_present<Types...>(Val);
823+
}
824+
};
825+
} // namespace detail
826+
827+
/// Function object wrapper for the `llvm::isa` type check. The function call
828+
/// operator returns true when the value can be cast to any type in `Types`.
829+
/// Example:
830+
/// ```
831+
/// SmallVector<Type> myTypes = ...;
832+
/// if (llvm::all_of(myTypes, llvm::IsaPred<VectorType>))
833+
/// ...
834+
/// ```
835+
template <typename... Types>
836+
inline constexpr detail::IsaCheckPredicate<Types...> IsaPred{};
837+
838+
/// Function object wrapper for the `llvm::isa_and_present` type check. The
839+
/// function call operator returns true when the value can be cast to any type
840+
/// in `Types`, or if the value is not present (e.g., nullptr). Example:
841+
/// ```
842+
/// SmallVector<Type> myTypes = ...;
843+
/// if (llvm::all_of(myTypes, llvm::IsaAndPresnetPred<VectorType>))
844+
/// ...
845+
/// ```
846+
template <typename... Types>
847+
inline constexpr detail::IsaAndPresentCheckPredicate<Types...>
848+
IsaAndPresentPred{};
849+
804850
} // end namespace llvm
805851

806852
#endif // LLVM_SUPPORT_CASTING_H

llvm/unittests/Support/Casting.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,20 @@ TEST(CastingTest, dyn_cast_if_present) {
282282
EXPECT_FALSE(t4.hasValue);
283283
}
284284

285+
TEST(CastingTest, isa_check_predicates) {
286+
auto IsaFoo = IsaPred<foo>;
287+
auto IsaAndPresentFoo = IsaAndPresentPred<foo>;
288+
EXPECT_TRUE(IsaFoo(B1));
289+
EXPECT_TRUE(IsaFoo(B2));
290+
EXPECT_TRUE(IsaFoo(B3));
291+
EXPECT_TRUE(IsaPred<foo>(B4));
292+
EXPECT_TRUE((IsaPred<foo, bar>(B4)));
293+
EXPECT_TRUE(IsaAndPresentFoo(B2));
294+
EXPECT_TRUE(IsaAndPresentFoo(B4));
295+
EXPECT_FALSE(IsaAndPresentPred<foo>(fub()));
296+
EXPECT_FALSE((IsaAndPresentPred<foo, bar>(fub())));
297+
}
298+
285299
std::unique_ptr<derived> newd() { return std::make_unique<derived>(); }
286300
std::unique_ptr<base> newb() { return std::make_unique<derived>(); }
287301

0 commit comments

Comments
 (0)