Index: mlir/include/mlir/IR/Value.h =================================================================== --- mlir/include/mlir/IR/Value.h +++ mlir/include/mlir/IR/Value.h @@ -88,26 +88,22 @@ template bool isa() const { - assert(*this && "isa<> used on a null type."); - return U::classof(*this); + return llvm::isa(*this); } - template - bool isa() const { - return isa() || isa(); - } template U dyn_cast() const { - return isa() ? U(impl) : U(nullptr); + return llvm::dyn_cast(*this); } + template U dyn_cast_or_null() const { - return (*this && isa()) ? U(impl) : U(nullptr); + return llvm::dyn_cast_if_present(*this); } + template U cast() const { - assert(isa()); - return U(impl); + return llvm::cast(*this); } explicit operator bool() const { return impl; } @@ -560,6 +556,31 @@ } }; +/// Add support for llvm style casts. We provide a cast between To and From if +/// From is mlir::Value or derives from it. +template +struct CastInfo> || + std::is_base_of_v>> + : NullableValueCastFailed, + DefaultDoCastIfPossible> { + /// Arguments are taken as mlir::Value here and not as `From`, because + /// when casting from an intermediate type of the hierarchy to one of its + /// children, the val.getTypeID() inside T::classof will use the static + /// getTypeID of the parent instead of the non-static Type::getTypeID that + /// returns the dynamic ID. This means that T::classof would end up comparing + /// the static TypeID of the children to the static TypeID of its parent, + /// making it impossible to downcast from the parent to the child. + static inline bool isPossible(mlir::Value ty) { + /// Return a constant true instead of a dynamic true when casting to self or + /// up the hierarchy. + return std::is_same_v> || + std::is_base_of_v || To::classof(ty); + } + static inline To doCast(mlir::Value value) { return To(value.getImpl()); } +}; + } // namespace llvm #endif