-
Notifications
You must be signed in to change notification settings - Fork 3k
Fix for ARMc6 compiler errors #9388
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
Conversation
@@ -850,7 +850,7 @@ void GenericGap::on_read_phy( | |||
) | |||
{ | |||
ble_error_t status = BLE_ERROR_NONE; | |||
if (pal::hci_error_code_t::SUCCESS != hci_status) { | |||
if (pal::hci_error_code_t(pal::hci_error_code_t::SUCCESS) != hci_status) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems like putting in an explicit conversion potentially defeats the point of the type-safety, although I'm not sure as of this C++98 version. Conceptually, at least in newer C++, you'd be activating an explicit conversion, which is a bit like forcing a cast.
I see that just swapping the test to the sane way round clears the problem too:
if (hci_status != pal::hci_error_code_t::SUCCESS) {
Haven't quite understood why yet, but I'll seize on any justification to get people to write their comparisons in the sane order, so I like that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In that order (clang), or either order (other compilers), any integer will be accepted for a comparison:
if (hci_status != 4) // works on any compiler
if (4 != hci_status) // works except on clang
They appear to be able to decide that it wants a SafeEnum<hci_error_code_t, uint8_t>
to compare with, and locates SafeEnum
's implicit conversion constructor to make one. The fact that hci_error_code_t
has no implicit conversion constructor has no bearing, as the comparison operators don't act on hci_error_code_t
.
It appears that clang on any platform can only perform that deduction if the SafeEnum
is the first parameter. This might be a clang bug - afaict first parameter would be important if the operator is a member function, but these aren't, they're friends.
I tried messing a bit to make SafeEnum
's constructor explicit, to force the compiler to locate hci_error_code_t
's implicit from-type constructor instead, making it type-safe, but it didn't seem to want to find it. (Presumably it doesn't try to convert to a derived class to satisfy a need for a base class).
So, the class isn't working as intended. Presumably you could make a macro form that produced a safe enum with the operators and constructors, rather than using the base class, but maybe it can wait until we update to C++14 and just drop it in favour of enum class
, which does everything needed, I think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the report @kjbracey-arm ; that's interesting. As documented in SafeEnum, the main goal was to avoid scope collision between enum of different types so you don't convert a peer_address_type_t into an own_address_type_t as they have slightly different semantics.
Unfortunately we opened a hole in the type safety with comparison operators operating on the base class and not the derived one. Fortunately it can be fixed by rewriting comparison operators to use Target
(the derived class) instead of SafeEnum
(live version). Do you think that's enough ? If so I can issue a patch today.
Note that MSVC is also impacted with operand orders. I need to understand why.
Note: As you expressed it, once C++14 is here we can just use enum class
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually if (4 != hci_status)
works on every compiler. clang only complains if the first parameter is an enum type. Issue raised with clang: https://bugs.llvm.org/show_bug.cgi?id=40329
For now, I think just swap the order - that will retain type safety when/if hci_error_code_t
becomes enum class : uint8_t
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@pan-, ah, the proper-safety fix is simpler than I thought - I was overthinking it. That looks good to me. Go for that.
(But we could still put the comparisons the right way round, on pure taste grounds)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
MSVC's error says something about "predefined operator":
'ble::pal::hci_error_code_t::type' does not define this operator or a conversion to a type acceptable to the predefined operator
I think the automatically predefined member operator!=(other)
for the enum may be getting in the way - that lookup is only activated when left-hand parameter is of that type. But the non-member candidates should all still be there.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
clang folks agreed it was a bug, and it has now been fixed upstream - you can now see it working for "clang (trunk)" in compiler explorer.
@SenRamakri - just reverse the comparison for now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
clang folks agreed it was a bug, and it has now been fixed upstream - you can now see it working for "clang (trunk)" in compiler explorer.
@kjbracey-arm 💯 !
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix visible here for any compiler geeks: llvm-mirror/clang@a7d7e42 (this example is reduced to a test case).
The code modified was clearly marked "FIXME" :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Awesome! It already works in clang (trunk)
on godbolt.
@@ -58,7 +58,7 @@ extern "C" { | |||
/**@{*/ | |||
#if ((defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) && \ | |||
(!defined(__ICC8051__) || (__ICC8051__ == 0))) || \ | |||
defined(__CC_ARM) || defined(__IAR_SYSTEMS_ICC__) | |||
defined(__CC_ARM) || defined(__IAR_SYSTEMS_ICC__) || (defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we really need to write things out this long-windedly? The bit being added is a test for "ARMC6 specifically, not ARMC5".
The whole line could just be
defined(__ARMCC_VERSION) || defined(__IAR_SYSTEMS_ICC__)
__ARMCC_VERSION
is defined by both ARMC5 and ARMC6, so can just test for that where we handle either.
@@ -850,7 +850,7 @@ void GenericGap::on_read_phy( | |||
) | |||
{ | |||
ble_error_t status = BLE_ERROR_NONE; | |||
if (pal::hci_error_code_t::SUCCESS != hci_status) { | |||
if (pal::hci_error_code_t(pal::hci_error_code_t::SUCCESS) != hci_status) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if (pal::hci_error_code_t(pal::hci_error_code_t::SUCCESS) != hci_status) { | |
if (hci_status != pal::hci_error_code_t::SUCCESS) { |
@@ -867,7 +867,7 @@ void GenericGap::on_phy_update_complete( | |||
) | |||
{ | |||
ble_error_t status = BLE_ERROR_NONE; | |||
if (pal::hci_error_code_t::SUCCESS != hci_status) { | |||
if (pal::hci_error_code_t(pal::hci_error_code_t::SUCCESS) != hci_status) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if (pal::hci_error_code_t(pal::hci_error_code_t::SUCCESS) != hci_status) { | |
if (hci_status != pal::hci_error_code_t::SUCCESS) { |
250ae3e
to
2030d03
Compare
@kjbracey-arm @pan- Please review, the comments are addressed. |
Ci started |
Test run: SUCCESSSummary: 12 of 12 test jobs passed |
Description
ARMc6 related fixes under BLE feature
Pull request type
Reviewers
@pan- @kjbracey-arm