From fbabe700637e561fc8e403a36d5a9d5d860f9511 Mon Sep 17 00:00:00 2001 From: Krzysztof Chruscinski Date: Fri, 7 May 2021 06:45:44 +0200 Subject: [PATCH] lib: os: cbprintf: Fixes for c++ and coverity Fixes for C++ includes: - avoid calling static inline template function in static assert on certain platforms which consider it non const expression - Add 0 to variable before calling C++ argument storing function to promote a variable. Fix for coverity: - avoid using sizeof(n + 0) by using local variable (gcc extension) Signed-off-by: Krzysztof Chruscinski --- include/sys/cbprintf_cxx.h | 48 ++++++++++++++++++++++++++++ include/sys/cbprintf_internal.h | 56 +++++++++++++++++++++------------ 2 files changed, 84 insertions(+), 20 deletions(-) diff --git a/include/sys/cbprintf_cxx.h b/include/sys/cbprintf_cxx.h index 40333319125..23365811159 100644 --- a/include/sys/cbprintf_cxx.h +++ b/include/sys/cbprintf_cxx.h @@ -52,7 +52,10 @@ static inline int z_cbprintf_cxx_is_pchar(const volatile wchar_t *) template < typename T > static inline int z_cbprintf_cxx_is_pchar(T arg) { + _Pragma("GCC diagnostic push") + _Pragma("GCC diagnostic ignored \"-Wpointer-arith\"") return 0; + _Pragma("GCC diagnostic pop") } /* C++ version for calculating argument size. */ @@ -61,6 +64,11 @@ static inline size_t z_cbprintf_cxx_arg_size(float f) return sizeof(double); } +static inline size_t z_cbprintf_cxx_arg_size(void *p) +{ + return sizeof(void *); +} + template < typename T > static inline size_t z_cbprintf_cxx_arg_size(T arg) { @@ -75,6 +83,46 @@ static inline void z_cbprintf_cxx_store_arg(uint8_t *dst, float arg) z_cbprintf_wcpy((int *)dst, (int *)&d, sizeof(d) / sizeof(int)); } +static inline void z_cbprintf_cxx_store_arg(uint8_t *dst, void *p) +{ + z_cbprintf_wcpy((int *)dst, (int *)&p, sizeof(p) / sizeof(int)); +} + +static inline void z_cbprintf_cxx_store_arg(uint8_t *dst, char arg) +{ + int tmp = arg + 0; + + z_cbprintf_wcpy((int *)dst, &tmp, 1); +} + +static inline void z_cbprintf_cxx_store_arg(uint8_t *dst, unsigned char arg) +{ + int tmp = arg + 0; + + z_cbprintf_wcpy((int *)dst, &tmp, 1); +} + +static inline void z_cbprintf_cxx_store_arg(uint8_t *dst, signed char arg) +{ + int tmp = arg + 0; + + z_cbprintf_wcpy((int *)dst, &tmp, 1); +} + +static inline void z_cbprintf_cxx_store_arg(uint8_t *dst, short arg) +{ + int tmp = arg + 0; + + z_cbprintf_wcpy((int *)dst, &tmp, 1); +} + +static inline void z_cbprintf_cxx_store_arg(uint8_t *dst, unsigned short arg) +{ + int tmp = arg + 0; + + z_cbprintf_wcpy((int *)dst, &tmp, 1); +} + template < typename T > static inline void z_cbprintf_cxx_store_arg(uint8_t *dst, T arg) { diff --git a/include/sys/cbprintf_internal.h b/include/sys/cbprintf_internal.h index b6e9f2a0cd2..39206b5193a 100644 --- a/include/sys/cbprintf_internal.h +++ b/include/sys/cbprintf_internal.h @@ -84,17 +84,18 @@ extern "C" { #ifdef __cplusplus #define Z_CBPRINTF_IS_PCHAR(x) z_cbprintf_cxx_is_pchar(x) #else -#define Z_CBPRINTF_IS_PCHAR(x) _Generic((x), \ - char * : 1, \ - const char * : 1, \ - volatile char * : 1, \ - const volatile char * : 1, \ - wchar_t * : 1, \ - const wchar_t * : 1, \ - volatile wchar_t * : 1, \ - const volatile wchar_t * : 1, \ - default : \ - 0) +#define Z_CBPRINTF_IS_PCHAR(x) \ + _Generic((x) + 0, \ + char * : 1, \ + const char * : 1, \ + volatile char * : 1, \ + const volatile char * : 1, \ + wchar_t * : 1, \ + const wchar_t * : 1, \ + volatile wchar_t * : 1, \ + const volatile wchar_t * : 1, \ + default : \ + 0) #endif /** @brief Calculate number of char * or wchar_t * arguments in the arguments. @@ -120,10 +121,15 @@ extern "C" { * @retval 0 if string can be statically packaged. */ #if Z_C_GENERIC -#define Z_CBPRINTF_MUST_RUNTIME_PACKAGE(skip, ...) \ - COND_CODE_0(NUM_VA_ARGS_LESS_1(__VA_ARGS__), \ +#define Z_CBPRINTF_MUST_RUNTIME_PACKAGE(skip, ...) ({\ + _Pragma("GCC diagnostic push") \ + _Pragma("GCC diagnostic ignored \"-Wpointer-arith\"") \ + int _rv = COND_CODE_0(NUM_VA_ARGS_LESS_1(__VA_ARGS__), \ (0), \ - (((Z_CBPRINTF_HAS_PCHAR_ARGS(__VA_ARGS__) - skip) > 0))) + (((Z_CBPRINTF_HAS_PCHAR_ARGS(__VA_ARGS__) - skip) > 0))); \ + _Pragma("GCC diagnostic pop")\ + _rv; \ +}) #else #define Z_CBPRINTF_MUST_RUNTIME_PACKAGE(skip, ...) 1 #endif @@ -140,13 +146,15 @@ extern "C" { #ifdef __cplusplus #define Z_CBPRINTF_ARG_SIZE(v) z_cbprintf_cxx_arg_size(v) #else -#define Z_CBPRINTF_ARG_SIZE(v) \ - _Generic((v), \ +#define Z_CBPRINTF_ARG_SIZE(v) ({\ + __auto_type _v = (v) + 0; \ + size_t _arg_size = _Generic((v), \ float : sizeof(double), \ default : \ - /* coverity[bad_sizeof] */ \ - sizeof((v) + 0) \ - ) + sizeof((_v)) \ + ); \ + _arg_size; \ +}) #endif /** @brief Promote and store argument in the buffer. @@ -212,14 +220,22 @@ extern "C" { __alignof__((_arg) + 0)), VA_STACK_MIN_ALIGN) #endif -/** @brief Detect long double variable. +/** @brief Detect long double variable as a constant expression. + * + * Macro is used in static assertion. On some platforms C++ static inline + * template function is not a constant expression and cannot be used. In that + * case long double usage will not be detected. * * @param x Argument. * * @return 1 if @p x is a long double, 0 otherwise. */ #ifdef __cplusplus +#if defined(__x86_64__) || defined(__riscv) || defined(__aarch64__) +#define Z_CBPRINTF_IS_LONGDOUBLE(x) 0 +#else #define Z_CBPRINTF_IS_LONGDOUBLE(x) z_cbprintf_cxx_is_longdouble(x) +#endif #else #define Z_CBPRINTF_IS_LONGDOUBLE(x) \ _Generic((x) + 0, long double : 1, default : 0)