[llvm] 716b9f7 - [LLVM][Support/ADT] Add assert for isPresent to dyn_cast.
via llvm-commits
llvm-commits at lists.llvm.org
Tue Sep 6 13:59:05 PDT 2022
Author: bzcheeseman
Date: 2022-09-06T13:58:56-07:00
New Revision: 716b9f7a1a3ce7db89993c15855d8b89a35fc4fc
URL: https://github.com/llvm/llvm-project/commit/716b9f7a1a3ce7db89993c15855d8b89a35fc4fc
DIFF: https://github.com/llvm/llvm-project/commit/716b9f7a1a3ce7db89993c15855d8b89a35fc4fc.diff
LOG: [LLVM][Support/ADT] Add assert for isPresent to dyn_cast.
This change adds an assert to dyn_cast that the value passed-in is present. In the past, this relied on the isa_impl assertion (which still works in many cases) but which we can tighten up for a better QoI.
The PointerUnion change is because it seems like (based on the call sites) the semantics of the member dyn_cast are actually dyn_cast_if_present.
Reviewed By: rriddle
Differential Revision: https://reviews.llvm.org/D133221
Added:
Modified:
llvm/include/llvm/ADT/PointerUnion.h
llvm/include/llvm/Support/Casting.h
llvm/unittests/ADT/PointerUnionTest.cpp
Removed:
################################################################################
diff --git a/llvm/include/llvm/ADT/PointerUnion.h b/llvm/include/llvm/ADT/PointerUnion.h
index f01db09dd765b..061c4000fcb35 100644
--- a/llvm/include/llvm/ADT/PointerUnion.h
+++ b/llvm/include/llvm/ADT/PointerUnion.h
@@ -160,7 +160,7 @@ class PointerUnion
/// Returns the current pointer if it is of the specified pointer type,
/// otherwise returns null.
template <typename T> inline T dyn_cast() const {
- return llvm::dyn_cast<T>(*this);
+ return llvm::dyn_cast_if_present<T>(*this);
}
/// If the union is set to the first pointer type get an address pointing to
diff --git a/llvm/include/llvm/Support/Casting.h b/llvm/include/llvm/Support/Casting.h
index cf9c7c0efbf14..8a2fa94f9ccad 100644
--- a/llvm/include/llvm/Support/Casting.h
+++ b/llvm/include/llvm/Support/Casting.h
@@ -585,47 +585,18 @@ template <typename To, typename From>
return CastInfo<To, std::unique_ptr<From>>::doCast(std::move(Val));
}
-/// dyn_cast<X> - Return the argument parameter cast to the specified type. This
-/// casting operator returns null if the argument is of the wrong type, so it
-/// can be used to test for a type as well as cast if successful. The value
-/// passed in must be present, if not, use dyn_cast_if_present. This should be
-/// used in the context of an if statement like this:
-///
-/// if (const Instruction *I = dyn_cast<Instruction>(myVal)) { ... }
-
-template <typename To, typename From>
-[[nodiscard]] inline decltype(auto) dyn_cast(const From &Val) {
- return CastInfo<To, const From>::doCastIfPossible(Val);
-}
-
-template <typename To, typename From>
-[[nodiscard]] inline decltype(auto) dyn_cast(From &Val) {
- return CastInfo<To, From>::doCastIfPossible(Val);
-}
-
-template <typename To, typename From>
-[[nodiscard]] inline decltype(auto) dyn_cast(From *Val) {
- return CastInfo<To, From *>::doCastIfPossible(Val);
-}
-
-template <typename To, typename From>
-[[nodiscard]] inline decltype(auto) dyn_cast(std::unique_ptr<From> &&Val) {
- return CastInfo<To, std::unique_ptr<From>>::doCastIfPossible(std::move(Val));
-}
-
//===----------------------------------------------------------------------===//
// ValueIsPresent
//===----------------------------------------------------------------------===//
template <typename T>
-constexpr bool IsNullable = std::is_pointer<T>::value ||
- std::is_constructible<T, std::nullptr_t>::value;
+constexpr bool IsNullable =
+ std::is_pointer_v<T> || std::is_constructible_v<T, std::nullptr_t>;
/// ValueIsPresent provides a way to check if a value is, well, present. For
-/// pointers, this is the equivalent of checking against nullptr, for
-/// Optionals this is the equivalent of checking hasValue(). It also
-/// provides a method for unwrapping a value (think dereferencing a
-/// pointer).
+/// pointers, this is the equivalent of checking against nullptr, for Optionals
+/// this is the equivalent of checking hasValue(). It also provides a method for
+/// unwrapping a value (think calling .value() on an optional).
// Generic values can't *not* be present.
template <typename T, typename Enable = void> struct ValueIsPresent {
@@ -646,7 +617,7 @@ template <typename T> struct ValueIsPresent<Optional<T>> {
template <typename T>
struct ValueIsPresent<T, std::enable_if_t<IsNullable<T>>> {
using UnwrappedType = T;
- static inline bool isPresent(const T &t) { return t != nullptr; }
+ static inline bool isPresent(const T &t) { return t != T(nullptr); }
static inline decltype(auto) unwrapValue(T &t) { return t; }
};
@@ -664,6 +635,39 @@ template <typename T> inline decltype(auto) unwrapValue(T &t) {
}
} // namespace detail
+/// dyn_cast<X> - Return the argument parameter cast to the specified type. This
+/// casting operator returns null if the argument is of the wrong type, so it
+/// can be used to test for a type as well as cast if successful. The value
+/// passed in must be present, if not, use dyn_cast_if_present. This should be
+/// used in the context of an if statement like this:
+///
+/// if (const Instruction *I = dyn_cast<Instruction>(myVal)) { ... }
+
+template <typename To, typename From>
+[[nodiscard]] inline decltype(auto) dyn_cast(const From &Val) {
+ assert(detail::isPresent(Val) && "dyn_cast on a non-existent value");
+ return CastInfo<To, const From>::doCastIfPossible(Val);
+}
+
+template <typename To, typename From>
+[[nodiscard]] inline decltype(auto) dyn_cast(From &Val) {
+ assert(detail::isPresent(Val) && "dyn_cast on a non-existent value");
+ return CastInfo<To, From>::doCastIfPossible(Val);
+}
+
+template <typename To, typename From>
+[[nodiscard]] inline decltype(auto) dyn_cast(From *Val) {
+ assert(detail::isPresent(Val) && "dyn_cast on a non-existent value");
+ return CastInfo<To, From *>::doCastIfPossible(Val);
+}
+
+template <typename To, typename From>
+[[nodiscard]] inline decltype(auto) dyn_cast(std::unique_ptr<From> &&Val) {
+ assert(detail::isPresent(Val) && "dyn_cast on a non-existent value");
+ return CastInfo<To, std::unique_ptr<From>>::doCastIfPossible(
+ std::forward<std::unique_ptr<From> &&>(Val));
+}
+
/// isa_and_present<X> - Functionally identical to isa, except that a null value
/// is accepted.
template <typename... X, class Y>
diff --git a/llvm/unittests/ADT/PointerUnionTest.cpp b/llvm/unittests/ADT/PointerUnionTest.cpp
index e12a3ec4e4d4f..180ae45931ccb 100644
--- a/llvm/unittests/ADT/PointerUnionTest.cpp
+++ b/llvm/unittests/ADT/PointerUnionTest.cpp
@@ -227,8 +227,8 @@ TEST_F(PointerUnionTest, NewCastInfra) {
EXPECT_EQ(dyn_cast<float *>(b), nullptr);
EXPECT_EQ(dyn_cast<int *>(c), &i);
EXPECT_EQ(dyn_cast<float *>(c), nullptr);
- EXPECT_EQ(dyn_cast<int *>(n), nullptr);
- EXPECT_EQ(dyn_cast<float *>(n), nullptr);
+ EXPECT_EQ(dyn_cast_if_present<int *>(n), nullptr);
+ EXPECT_EQ(dyn_cast_if_present<float *>(n), nullptr);
EXPECT_EQ(dyn_cast<int *>(i3), &i);
EXPECT_EQ(dyn_cast<float *>(i3), nullptr);
EXPECT_EQ(dyn_cast<long long *>(i3), nullptr);
@@ -254,22 +254,22 @@ TEST_F(PointerUnionTest, NewCastInfra) {
EXPECT_EQ(dyn_cast<float *>(d4), nullptr);
EXPECT_EQ(dyn_cast<long long *>(d4), nullptr);
EXPECT_EQ(dyn_cast<double *>(d4), &d);
- EXPECT_EQ(dyn_cast<int *>(i4null), nullptr);
- EXPECT_EQ(dyn_cast<float *>(i4null), nullptr);
- EXPECT_EQ(dyn_cast<long long *>(i4null), nullptr);
- EXPECT_EQ(dyn_cast<double *>(i4null), nullptr);
- EXPECT_EQ(dyn_cast<int *>(f4null), nullptr);
- EXPECT_EQ(dyn_cast<float *>(f4null), nullptr);
- EXPECT_EQ(dyn_cast<long long *>(f4null), nullptr);
- EXPECT_EQ(dyn_cast<double *>(f4null), nullptr);
- EXPECT_EQ(dyn_cast<int *>(l4null), nullptr);
- EXPECT_EQ(dyn_cast<float *>(l4null), nullptr);
- EXPECT_EQ(dyn_cast<long long *>(l4null), nullptr);
- EXPECT_EQ(dyn_cast<double *>(l4null), nullptr);
- EXPECT_EQ(dyn_cast<int *>(d4null), nullptr);
- EXPECT_EQ(dyn_cast<float *>(d4null), nullptr);
- EXPECT_EQ(dyn_cast<long long *>(d4null), nullptr);
- EXPECT_EQ(dyn_cast<double *>(d4null), nullptr);
+ EXPECT_EQ(dyn_cast_if_present<int *>(i4null), nullptr);
+ EXPECT_EQ(dyn_cast_if_present<float *>(i4null), nullptr);
+ EXPECT_EQ(dyn_cast_if_present<long long *>(i4null), nullptr);
+ EXPECT_EQ(dyn_cast_if_present<double *>(i4null), nullptr);
+ EXPECT_EQ(dyn_cast_if_present<int *>(f4null), nullptr);
+ EXPECT_EQ(dyn_cast_if_present<float *>(f4null), nullptr);
+ EXPECT_EQ(dyn_cast_if_present<long long *>(f4null), nullptr);
+ EXPECT_EQ(dyn_cast_if_present<double *>(f4null), nullptr);
+ EXPECT_EQ(dyn_cast_if_present<int *>(l4null), nullptr);
+ EXPECT_EQ(dyn_cast_if_present<float *>(l4null), nullptr);
+ EXPECT_EQ(dyn_cast_if_present<long long *>(l4null), nullptr);
+ EXPECT_EQ(dyn_cast_if_present<double *>(l4null), nullptr);
+ EXPECT_EQ(dyn_cast_if_present<int *>(d4null), nullptr);
+ EXPECT_EQ(dyn_cast_if_present<float *>(d4null), nullptr);
+ EXPECT_EQ(dyn_cast_if_present<long long *>(d4null), nullptr);
+ EXPECT_EQ(dyn_cast_if_present<double *>(d4null), nullptr);
// test for const
const PU4 constd4(&d);
More information about the llvm-commits
mailing list