Hi,
After r264564, it became possible to perform direct-list-initialization of an
enum in C++1z mode, if the initializer and the enum share the same underlying
type. However, clang crashes on some code which relies on this feature:
// clang++ -std=c++1z
enum class A : unsigned {};
A foo(unsigned x) { return A{x}; }
(We would reject this code in C++11/14 mode.)
The crash occurs in Sema::ImpCastExprToType, while we attempt to perform an
implicit conversion from 'unsigned int' ('x') to 'A'. The issue is that this is
an integral cast in an lvalue-to-rvalue conversion, which Sema asserts is not
possible. I'm not sure why exactly this kind of implicit cast is not allowed.
I'd like to send in a patch to fix this issue, but I'm not confident in my
simplistic fix which simply weakens the assertion in Sema. I'd like to know: is
the assertion really correct (lib/Sema/Sema.cpp:405)? If so, then I'd probably
need to find some other way to perform this conversion. If not, then I'd feel
more confident in my patch.
I've attached the WIP patch for reference.
0001-Sema-Allow-integral-cast-for-lvalue-to-rvalue-conver.patch (3.33 KB)
Hi,
After r264564, it became possible to perform direct-list-initialization of an
enum in C++1z mode, if the initializer and the enum share the same underlying
type. However, clang crashes on some code which relies on this feature:
// clang++ -std=c++1z
enum class A : unsigned {};
A foo(unsigned x) { return A{x}; }
(We would reject this code in C++11/14 mode.)
The crash occurs in Sema::ImpCastExprToType, while we attempt to perform an
implicit conversion from 'unsigned int' ('x') to 'A'. The issue is that this is
an integral cast in an lvalue-to-rvalue conversion, which Sema asserts is not
possible. I'm not sure why exactly this kind of implicit cast is not allowed.
I'd like to send in a patch to fix this issue, but I'm not confident in my
simplistic fix which simply weakens the assertion in Sema. I'd like to know: is
the assertion really correct (lib/Sema/Sema.cpp:405)?
Yes, the assertion is correct
If so, then I'd probably
need to find some other way to perform this conversion.
The right way to perform the conversion is a series of two implicit casts: one of type CK_LValueToRValue, then another of type CK_IntegralCast.
-Eli
Hi,
After r264564, it became possible to perform direct-list-initialization of an
enum in C++1z mode, if the initializer and the enum share the same underlying
type. However, clang crashes on some code which relies on this feature:
// clang++ -std=c++1z
enum class A : unsigned {};
A foo(unsigned x) { return A{x}; }
(We would reject this code in C++11/14 mode.)
The crash occurs in Sema::ImpCastExprToType, while we attempt to perform an
implicit conversion from 'unsigned int' ('x') to 'A'. The issue is that this is
an integral cast in an lvalue-to-rvalue conversion, which Sema asserts is not
possible. I'm not sure why exactly this kind of implicit cast is not allowed.
I'd like to send in a patch to fix this issue, but I'm not confident in my
simplistic fix which simply weakens the assertion in Sema. I'd like to know: is
the assertion really correct (lib/Sema/Sema.cpp:405)?
Yes, the assertion is correct
If so, then I'd probably
need to find some other way to perform this conversion.
The right way to perform the conversion is a series of two implicit casts: one of type CK_LValueToRValue, then another of type CK_IntegralCast.
That makes sense, seeing as 'x' in my example is not an rvalue!
I will try this and send in a patch.
thank you,
vedant