public:
using ElementsAttr::ElementsAttr;
+ /// Type trait used to check if the given type T is a potentially valid C++
+ /// floating point type that can be used to access the underlying element
+ /// types of a DenseElementsAttr.
+ // TODO: Use std::disjunction when C++17 is supported.
+ template <typename T> struct is_valid_cpp_fp_type {
+ /// The type is a valid floating point type if it is a builtin floating
+ /// point type, or is a potentially user defined floating point type. The
+ /// latter allows for supporting users that have custom types defined for
+ /// bfloat16/half/etc.
+ static inline constexpr bool value =
+ llvm::is_one_of<T, float, double>::value ||
+ (std::numeric_limits<T>::is_specialized &&
+ !std::numeric_limits<T>::is_integer);
+ };
+
/// Method for support type inquiry through isa, cast and dyn_cast.
static bool classof(Attribute attr);
/// static shape.
template <typename T, typename = typename std::enable_if<
std::numeric_limits<T>::is_integer ||
- llvm::is_one_of<T, float, double>::value>::type>
+ is_valid_cpp_fp_type<T>::value>::type>
static DenseElementsAttr get(const ShapedType &type, ArrayRef<T> values) {
const char *data = reinterpret_cast<const char *>(values.data());
return getRawIntOrFloat(
/// Constructs a dense integer elements attribute from a single element.
template <typename T, typename = typename std::enable_if<
std::numeric_limits<T>::is_integer ||
- llvm::is_one_of<T, float, double>::value ||
+ is_valid_cpp_fp_type<T>::value ||
detail::is_complex_t<T>::value>::type>
static DenseElementsAttr get(const ShapedType &type, T value) {
return get(type, llvm::makeArrayRef(value));
typename = typename std::enable_if<
detail::is_complex_t<T>::value &&
(std::numeric_limits<ElementT>::is_integer ||
- llvm::is_one_of<ElementT, float, double>::value)>::type>
+ is_valid_cpp_fp_type<ElementT>::value)>::type>
static DenseElementsAttr get(const ShapedType &type, ArrayRef<T> values) {
const char *data = reinterpret_cast<const char *>(values.data());
return getRawComplex(type, ArrayRef<char>(data, values.size() * sizeof(T)),
template <typename T, typename = typename std::enable_if<
(!std::is_same<T, bool>::value &&
std::numeric_limits<T>::is_integer) ||
- llvm::is_one_of<T, float, double>::value>::type>
+ is_valid_cpp_fp_type<T>::value>::type>
llvm::iterator_range<ElementIterator<T>> getValues() const {
assert(isValidIntOrFloat(sizeof(T), std::numeric_limits<T>::is_integer,
std::numeric_limits<T>::is_signed));
typename = typename std::enable_if<
detail::is_complex_t<T>::value &&
(std::numeric_limits<ElementT>::is_integer ||
- llvm::is_one_of<ElementT, float, double>::value)>::type>
+ is_valid_cpp_fp_type<ElementT>::value)>::type>
llvm::iterator_range<ElementIterator<T>> getValues() const {
assert(isValidComplex(sizeof(T), std::numeric_limits<ElementT>::is_integer,
std::numeric_limits<ElementT>::is_signed));
template <typename T>
typename std::enable_if<
std::numeric_limits<T>::is_integer ||
- llvm::is_one_of<T, float, double, StringRef>::value ||
+ DenseElementsAttr::is_valid_cpp_fp_type<T>::value ||
+ std::is_same<T, StringRef>::value ||
(detail::is_complex_t<T>::value &&
!llvm::is_one_of<T, std::complex<APInt>,
std::complex<APFloat>>::value),