Skip to content

Commit 73a940e

Browse files
dcpleungstephanosio
authored andcommitted
lib: os/cbprintf: make char[] work in C++ and tagged arguments
Strings in C++ are usually of type char[] instead of char*. Therefore, this needs to be taken into account when doing tagged arguments or else char[] would be tagged as simple pointer. So fix this by adding a way to get the type of elements in an array to determine if it is a char array. Fixes #46761 Signed-off-by: Daniel Leung <[email protected]>
1 parent 2ddf2fa commit 73a940e

File tree

2 files changed

+78
-1
lines changed

2 files changed

+78
-1
lines changed

include/zephyr/sys/cbprintf_cxx.h

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,5 +252,43 @@ struct z_cbprintf_cxx_remove_cv < const volatile T > {
252252
typedef T type;
253253
};
254254

255+
/* Determine if a type is an array */
256+
template < typename T >
257+
struct z_cbprintf_cxx_is_array {
258+
enum {
259+
value = false
260+
};
261+
};
262+
263+
template < typename T >
264+
struct z_cbprintf_cxx_is_array < T[] > {
265+
enum {
266+
value = true
267+
};
268+
};
269+
270+
template < typename T, size_t N >
271+
struct z_cbprintf_cxx_is_array < T[N] > {
272+
enum {
273+
value = true
274+
};
275+
};
276+
277+
/* Determine the type of elements in an array */
278+
template < typename T >
279+
struct z_cbprintf_cxx_remove_extent {
280+
typedef T type;
281+
};
282+
283+
template < typename T >
284+
struct z_cbprintf_cxx_remove_extent < T[] > {
285+
typedef T type;
286+
};
287+
288+
template < typename T, size_t N >
289+
struct z_cbprintf_cxx_remove_extent < T[N] > {
290+
typedef T type;
291+
};
292+
255293
#endif /* __cplusplus */
256294
#endif /* ZEPHYR_INCLUDE_SYS_CBPRINTF_CXX_H_ */

include/zephyr/sys/cbprintf_internal.h

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -504,6 +504,43 @@ do { \
504504
z_cbprintf_cxx_remove_reference < decltype(arg) > ::type \
505505
> ::type
506506

507+
/*
508+
* Get the type of elements in an array.
509+
*/
510+
#define Z_CBPRINTF_CXX_ARG_ARRAY_TYPE(arg) \
511+
z_cbprintf_cxx_remove_cv < \
512+
z_cbprintf_cxx_remove_extent < decltype(arg) > ::type \
513+
> ::type
514+
515+
/*
516+
* Determine if incoming type is char.
517+
*/
518+
#define Z_CBPRINTF_CXX_ARG_IS_TYPE_CHAR(type) \
519+
(z_cbprintf_cxx_is_same_type < type, \
520+
char > :: value ? \
521+
true : \
522+
(z_cbprintf_cxx_is_same_type < type, \
523+
const char > :: value ? \
524+
true : \
525+
(z_cbprintf_cxx_is_same_type < type, \
526+
volatile char > :: value ? \
527+
true : \
528+
(z_cbprintf_cxx_is_same_type < type, \
529+
const volatile char > :: value ? \
530+
true : \
531+
false))))
532+
533+
/*
534+
* Figure out if this is a char array since (char *) and (char[])
535+
* are of different types in C++.
536+
*/
537+
#define Z_CBPRINTF_CXX_ARG_IS_CHAR_ARRAY(arg) \
538+
(z_cbprintf_cxx_is_array < decltype(arg) > :: value ? \
539+
(Z_CBPRINTF_CXX_ARG_IS_TYPE_CHAR(Z_CBPRINTF_CXX_ARG_ARRAY_TYPE(arg)) ? \
540+
true : \
541+
false) : \
542+
false)
543+
507544
/*
508545
* Note that qualifiers of char * must be explicitly matched
509546
* due to type matching in C++, where remove_cv() does not work.
@@ -560,7 +597,9 @@ do { \
560597
(z_cbprintf_cxx_is_same_type < Z_CBPRINTF_ARG_REMOVE_QUAL(arg), \
561598
const volatile char * > :: value ? \
562599
CBPRINTF_PACKAGE_ARG_TYPE_PTR_CHAR : \
563-
CBPRINTF_PACKAGE_ARG_TYPE_PTR_VOID)))))))))))))))))
600+
(Z_CBPRINTF_CXX_ARG_IS_CHAR_ARRAY(arg) ? \
601+
CBPRINTF_PACKAGE_ARG_TYPE_PTR_CHAR : \
602+
CBPRINTF_PACKAGE_ARG_TYPE_PTR_VOID))))))))))))))))))
564603
#else
565604
#define Z_CBPRINTF_ARG_TYPE(arg) \
566605
_Generic(arg, \

0 commit comments

Comments
 (0)