-
Notifications
You must be signed in to change notification settings - Fork 12.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Clang reports that __is_array(T[0])
is true
#54705
Comments
@llvm/issue-subscribers-clang-frontend |
Note, if you use
I have always been curious why we allowed this outside of flexible array members but last time I asked @zygoloid was not sure why. |
N.B. MSVC changed that in v19.32 |
Perhaps it makes more sence to treat Proof-of-concept implementation (Godbolt link): #include <cstddef>
#include <type_traits>
template<class T, bool = std::is_const<const T>::value && !std::is_void<T>::value>
struct ext_is_array_impl { // functions, references, and cv void
static constexpr bool is_array = false;
static constexpr bool is_bounded_array = false;
static constexpr bool is_unbounded_array = false;
};
template<class T, std::size_t N>
struct ext_is_array_impl<T[N], true> {
static constexpr bool is_array = true;
static constexpr bool is_bounded_array = true;
static constexpr bool is_unbounded_array = false;
};
template<class T>
struct ext_is_array_impl<T[], true> {
static constexpr bool is_array = true;
static constexpr bool is_bounded_array = false;
static constexpr bool is_unbounded_array = true;
};
template<class>
struct ext_is_array_impl_extraction_helper {};
template<class T>
struct ext_is_array_impl_extraction_helper<void(*)(T)> { using type = T; };
template<class T>
struct ext_is_array_impl<T, true> { // for non-array objects and extension T[0]
static constexpr bool is_array = !std::is_same<
typename std::remove_cv<T>::type,
typename ext_is_array_impl_extraction_helper<void(*)(T)>::type>::value;
static constexpr bool is_bounded_array = is_array;
static constexpr bool is_unbounded_array = false;
};
template<class T>
constexpr bool ext_is_array_v = ext_is_array_impl<T>::is_array;
template<class T>
constexpr bool ext_is_bounded_array_v = ext_is_array_impl<T>::is_bounded_array;
template<class T>
constexpr bool ext_is_unbounded_array_v = ext_is_array_impl<T>::is_unbounded_array; |
Fixes #54705
Clang currently reports that
__is_array(T[0])
is true, which leads tostd::is_array<T[0]>
being true as well.T[0]
is downright ill-formed: http://eel.is/c++draft/dcl.array#1Since it's ill-formed, I guess Clang is technically conforming, however it still leads to code like this surprisingly compiling with Clang:
So it looks like
T[0]
is neither a bounded array nor an unbounded array, but it is an array, which is quite confusing. I would suggest Clang either:T[0]
since it's ill-formed, orT[0]
is an array from its__is_array
builtin (patch provided for this)Also note that Clang will not match a partial specialization like
template <class T, size_t N> struct foo<T[N]> { ... };
when instantiating it withT[0]
, which seems to support the fact that we really don't want to treatT[0]
as an array type.Here's a potential patch that changes
__is_array(T[0])
tofalse
, but I suspect we may want a deeper fix in the compiler.The text was updated successfully, but these errors were encountered: