forked from OSchip/llvm-project
[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
This commit is contained in:
parent
9006b082a5
commit
716b9f7a1a
|
@ -160,7 +160,7 @@ public:
|
|||
/// 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
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue