diff --git a/mlir/include/mlir/IR/Attributes.h b/mlir/include/mlir/IR/Attributes.h --- a/mlir/include/mlir/IR/Attributes.h +++ b/mlir/include/mlir/IR/Attributes.h @@ -47,11 +47,11 @@ bool operator!() const { return impl == nullptr; } - template - bool isa() const; - template + /// Casting utility functions. These are deprecated and will be removed, + /// please prefer using the `llvm` namespace variants instead. + template bool isa() const; - template + template bool isa_and_nonnull() const; template U dyn_cast() const; @@ -100,6 +100,9 @@ return impl->getAbstractAttribute(); } + /// Return the internal Attribute implementation. + ImplType *getImpl() const { return impl; } + protected: ImplType *impl{nullptr}; }; @@ -109,34 +112,29 @@ return os; } -template -bool Attribute::isa() const { - assert(impl && "isa<> used on a null attribute."); - return U::classof(*this); -} - -template +template bool Attribute::isa() const { - return isa() || isa(); + return llvm::isa(*this); } -template +template bool Attribute::isa_and_nonnull() const { - return impl && isa(); + return llvm::isa_and_present(*this); } template U Attribute::dyn_cast() const { - return isa() ? U(impl) : U(nullptr); + return llvm::dyn_cast(*this); } + template U Attribute::dyn_cast_or_null() const { - return (impl && isa()) ? U(impl) : U(nullptr); + return llvm::dyn_cast_if_present(*this); } + template U Attribute::cast() const { - assert(isa()); - return U(impl); + return llvm::cast(*this); } inline ::llvm::hash_code hash_value(Attribute arg) { @@ -318,6 +316,31 @@ } }; +/// Add support for llvm style casts. We provide a cast between To and From if +/// From is mlir::Attribute or derives from it. +template +struct CastInfo> || + std::is_base_of_v>> + : NullableValueCastFailed, + DefaultDoCastIfPossible> { + /// Arguments are taken as mlir::Attribute 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::Attribute 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::Attribute attr) { return To(attr.getImpl()); } +}; + } // namespace llvm #endif