-
Notifications
You must be signed in to change notification settings - Fork 6.9k
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
Bluetooth: Avoid use of array compound literals in API #24829
Bluetooth: Avoid use of array compound literals in API #24829
Conversation
All checks passed. Tip: The bot edits this comment instead of posting a new one, so you can check the comment's history to see earlier messages. |
Yes, now we can compile c++ file. |
But we get warnings
|
@a1ien I know. I will revert the const and do the fix a different way. |
9f24a91
to
9aee2e2
Compare
@a1ien Could you please check the updated PR? |
Now it's ok. |
9aee2e2
to
1dbcf35
Compare
Fix BT_BUF_ACL_SIZE in hci_test_app after declaration was moved to hci_raw.h Signed-off-by: Joakim Andersson <joakim.andersson@nordicsemi.no>
Attempt to fix C++ error: taking address of temporary array. According to GCC documentation: In C++, a compound literal designates a temporary object that only lives until the end of its full-expression. Finishing with this recommendation: As an optimization, G++ sometimes gives array compound literals longer lifetimes: when the array either appears outside a function or has a const-qualified type. But it is probably safest just to avoid the use of array compound literals in C++ code. Fix the issue by introducing INIT macros as an alternative, and use these in the inline functions to avoid the use of array compound literals in Bluetooth headers. Signed-off-by: Joakim Andersson <joakim.andersson@nordicsemi.no>
1dbcf35
to
ecfd6d0
Compare
.peer = (_peer), \ | ||
} }) | ||
((struct bt_le_adv_param[]) { \ | ||
BT_LE_ADV_PARAM_INIT(_options, _int_min, _int_max, _peer) \ |
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.
This doesn't work; the cast is still of a temporary. Using a version of samples/bluetooth/peripheral
converted to C++:
/mnt/nordic/zp/zephyr/include/bluetooth/bluetooth.h:526:30: error: taking address of temporary array
526 | ((struct bt_le_adv_param[]) { \
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~
527 | BT_LE_ADV_PARAM_INIT(_options, _int_min, _int_max, _peer) \
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
528 | })
| ~~
/mnt/nordic/zp/zephyr/include/bluetooth/bluetooth.h:539:29: note: in expansion of macro 'BT_LE_ADV_PARAM'
539 | #define BT_LE_ADV_CONN_NAME BT_LE_ADV_PARAM(BT_LE_ADV_OPT_CONNECTABLE | \
| ^~~~~~~~~~~~~~~
../src/main.cxx:260:24: note: in expansion of macro 'BT_LE_ADV_CONN_NAME'
260 | err = bt_le_adv_start(BT_LE_ADV_CONN_NAME, ad, ARRAY_SIZE(ad), NULL, 0);
| ^~~~~~~~~~~~~~~~~~~
The diagnostic goes away if the cast type is changed to const struct bt_le_adv_param[]
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.
@pabigot Thanks. I didn't add the const-qualifier, because the recommendation stated that was best to avoid these constructs altogether for C++. Which is why I added _INIT macros and removed the use in the static inline functions.
C++ code can then include the header, but it must avoid these specific macros.
If I added const to all the places that used this I get a ripple effect of const qualifier being discarded.
If you change your C++ peripheral like this:
struct bt_le_adv_param param = BT_LE_ADV_PARAM_INIT(BT_LE_ADV_OPT_CONNECTABLE |
BT_LE_ADV_OPT_USE_NAME,
BT_GAP_ADV_FAST_INT_MIN_2,
BT_GAP_ADV_FAST_INT_MAX_2,
NULL);
err = bt_le_adv_start(¶m, ad, ARRAY_SIZE(ad), NULL, 0);
You should be good.
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.
OK, I accept that's a workaround so I'll remove my NAK. It'd be nice to have uses of those macros in C++ code produce a diagnostic, but that's not in scope here.
The Zephyr Bluetooth examples are awash in uses of the original (non-init) macro as an argument to functions. A goal of the original solution was to keep the recommended calling code the same for both C and C++ code. Clearly that's not feasible.
We should probably add or convert one of the bluetooth samples to C++ to show how it's supposed to be done.
FWIW include/bluetooth/gatt.h at BT_GATT_CHARACTERISTIC also has an explicit cast of a temporary compound literal being cast to an array. That may not be as easy to fix, but also need not be part of this PR.
giving up on goal of using same idiom for C and C++ code
It can also be changed like this:
which is a far simpler workaround that allows continued use of the helper macros. This should be legal because C++20 section 6.7.7 paragraph 6.1 confirms that binding a reference to a temporary xvalue materialized by decaying (7.3.2) the array prvalue produced by Or, if there's concern that all this does is delay the destruction of the temporary decayed pointer rather than the temporary it points to:
which is still better. |
Attempt to fix C++ error: taking address of temporary array.
According to GCC documentation:
Finishing with this recommendation:
Fix the issue by introducing INIT macros as an alternative, and use
these in the inline functions to avoid the use of array compound
literals in Bluetooth headers.