From b2ca5fbe1ee78f6045810675a5dda1b4c18fa244 Mon Sep 17 00:00:00 2001 From: Michael Graeb Date: Tue, 13 Aug 2024 18:45:45 +0000 Subject: [PATCH 1/2] Fix warnings from -Wuseless-cast --- cmake/AwsCheckHeaders.cmake | 23 +++++++++++++--- include/aws/common/array_list.inl | 2 +- include/aws/common/math.inl | 44 ++++++++++++++++++++++--------- 3 files changed, 52 insertions(+), 17 deletions(-) diff --git a/cmake/AwsCheckHeaders.cmake b/cmake/AwsCheckHeaders.cmake index 2e62e0ad5..562a3739c 100644 --- a/cmake/AwsCheckHeaders.cmake +++ b/cmake/AwsCheckHeaders.cmake @@ -63,13 +63,22 @@ function(aws_check_headers_internal target std is_cxx) C_STANDARD 99 ) - # Ensure our headers can be included by an application with its warnings set very high + # Ensure our headers can be included by an application with its warnings set very high. + # Most compiler options are universal, but some are C++ only. + set(compiler_options_all "") + set(compiler_options_cxx_only "") if(MSVC) - # MSVC complains about windows' own header files. Use /W4 instead of /Wall - target_compile_options(${HEADER_CHECKER_LIB} PRIVATE /W4 /WX) + # MSVC complains about windows' own header files. Use /W4 instead of /Wall + list(APPEND compiler_options_all /W4 /WX) else() - target_compile_options(${HEADER_CHECKER_LIB} PRIVATE -Wall -Wextra -Wpedantic -Werror) + list(APPEND compiler_options_all -Wall -Wextra -Wpedantic -Werror) + + if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + # -Wuseless-cast requested by https://github.com/awslabs/aws-c-common/issues/973 + list(APPEND compiler_options_cxx_only -Wuseless-cast) + endif() endif() + target_compile_options(${HEADER_CHECKER_LIB} PRIVATE ${compiler_options_all}) foreach(header IN LISTS ARGN) if (NOT ${header} MATCHES "\\.inl$") @@ -78,6 +87,7 @@ function(aws_check_headers_internal target std is_cxx) file(RELATIVE_PATH include_path "${CMAKE_CURRENT_SOURCE_DIR}/include" ${header}) # replace non-alphanumeric characters with underscores string(REGEX REPLACE "[^a-zA-Z0-9]" "_" unique_token ${include_path}) + # test compiling header from a .cpp and .c file (or just .cpp if this header IS_CXX) set(c_file "${HEADER_CHECKER_ROOT}/headerchecker_${unique_token}.c") set(cpp_file "${HEADER_CHECKER_ROOT}/headerchecker_${unique_token}.cpp") # include header twice to check for include-guards @@ -88,6 +98,11 @@ function(aws_check_headers_internal target std is_cxx) file(WRITE "${c_file}" "#include <${include_path}>\n#include <${include_path}>\nint ${unique_token}_c;\n") target_sources(${HEADER_CHECKER_LIB} PUBLIC "${c_file}") endif() + + # for .cpp file, apply C++ only compiler options + if(compiler_options_cxx_only) + set_source_files_properties(${cpp_file} PROPERTIES COMPILE_OPTIONS ${compiler_options_cxx_only}) + endif() endif() endforeach(header) endfunction() diff --git a/include/aws/common/array_list.inl b/include/aws/common/array_list.inl index 42f447e92..5472104c6 100644 --- a/include/aws/common/array_list.inl +++ b/include/aws/common/array_list.inl @@ -123,7 +123,7 @@ AWS_STATIC_IMPL void aws_array_list_clean_up_secure(struct aws_array_list *AWS_RESTRICT list) { AWS_PRECONDITION(AWS_IS_ZEROED(*list) || aws_array_list_is_valid(list)); if (list->alloc && list->data) { - aws_secure_zero((void *)list->data, list->current_size); + aws_secure_zero(list->data, list->current_size); aws_mem_release(list->alloc, list->data); } diff --git a/include/aws/common/math.inl b/include/aws/common/math.inl index 2081fbcca..3910c35a4 100644 --- a/include/aws/common/math.inl +++ b/include/aws/common/math.inl @@ -53,6 +53,22 @@ AWS_EXTERN_C_BEGIN # pragma warning(disable : 4127) /*Disable "conditional expression is constant" */ #endif /* _MSC_VER */ +/* Macros to cast (if necessary) between size_t and uint64_t. + * On x86_64 platforms, size_t is always 64 bits. + * But on __MACH__, size_t's type is unsigned long, while on others it's unsigned long long. + * Some compilers will warn if you don't you cast between them, + * while other compilers (GCC with -Wuseless-cast) warn if you needlessly cast between them. + * So declare macros that do the right thing. */ +#ifdef __MACH__ /* do cast */ +# define AWS_CAST_SIZE_TO_U64 (uint64_t) +# define AWS_CAST_SIZE_PTR_TO_U64 (uint64_t *) +# define AWS_CAST_U64_TO_SIZE (size_t) +#else /* no cast required*/ +# define AWS_CAST_SIZE_TO_U64 +# define AWS_CAST_SIZE_PTR_TO_U64 +# define AWS_CAST_U64_TO_SIZE +#endif + AWS_STATIC_IMPL uint64_t aws_sub_u64_saturating(uint64_t a, uint64_t b) { return a <= b ? 0 : a - b; } @@ -84,9 +100,9 @@ AWS_STATIC_IMPL int aws_sub_u32_checked(uint32_t a, uint32_t b, uint32_t *r) { */ AWS_STATIC_IMPL size_t aws_mul_size_saturating(size_t a, size_t b) { #if SIZE_BITS == 32 - return (size_t)aws_mul_u32_saturating(a, b); + return aws_mul_u32_saturating(a, b); #elif SIZE_BITS == 64 - return (size_t)aws_mul_u64_saturating(a, b); + return AWS_CAST_SIZE_TO_U64 aws_mul_u64_saturating(a, b); #else # error "Target not supported" #endif @@ -98,9 +114,9 @@ AWS_STATIC_IMPL size_t aws_mul_size_saturating(size_t a, size_t b) { */ AWS_STATIC_IMPL int aws_mul_size_checked(size_t a, size_t b, size_t *r) { #if SIZE_BITS == 32 - return aws_mul_u32_checked(a, b, (uint32_t *)r); + return aws_mul_u32_checked(a, b, r); #elif SIZE_BITS == 64 - return aws_mul_u64_checked(a, b, (uint64_t *)r); + return aws_mul_u64_checked(a, b, AWS_CAST_SIZE_PTR_TO_U64 r); #else # error "Target not supported" #endif @@ -111,9 +127,9 @@ AWS_STATIC_IMPL int aws_mul_size_checked(size_t a, size_t b, size_t *r) { */ AWS_STATIC_IMPL size_t aws_add_size_saturating(size_t a, size_t b) { #if SIZE_BITS == 32 - return (size_t)aws_add_u32_saturating(a, b); + return aws_add_u32_saturating(a, b); #elif SIZE_BITS == 64 - return (size_t)aws_add_u64_saturating(a, b); + return AWS_CAST_U64_TO_SIZE aws_add_u64_saturating(a, b); #else # error "Target not supported" #endif @@ -125,9 +141,9 @@ AWS_STATIC_IMPL size_t aws_add_size_saturating(size_t a, size_t b) { */ AWS_STATIC_IMPL int aws_add_size_checked(size_t a, size_t b, size_t *r) { #if SIZE_BITS == 32 - return aws_add_u32_checked(a, b, (uint32_t *)r); + return aws_add_u32_checked(a, b, r); #elif SIZE_BITS == 64 - return aws_add_u64_checked(a, b, (uint64_t *)r); + return aws_add_u64_checked(a, b, AWS_CAST_SIZE_PTR_TO_U64 r); #else # error "Target not supported" #endif @@ -135,9 +151,9 @@ AWS_STATIC_IMPL int aws_add_size_checked(size_t a, size_t b, size_t *r) { AWS_STATIC_IMPL size_t aws_sub_size_saturating(size_t a, size_t b) { #if SIZE_BITS == 32 - return (size_t)aws_sub_u32_saturating(a, b); + return aws_sub_u32_saturating(a, b); #elif SIZE_BITS == 64 - return (size_t)aws_sub_u64_saturating(a, b); + return AWS_CAST_U64_TO_SIZE aws_sub_u64_saturating(a, b); #else # error "Target not supported" #endif @@ -145,9 +161,9 @@ AWS_STATIC_IMPL size_t aws_sub_size_saturating(size_t a, size_t b) { AWS_STATIC_IMPL int aws_sub_size_checked(size_t a, size_t b, size_t *r) { #if SIZE_BITS == 32 - return aws_sub_u32_checked(a, b, (uint32_t *)r); + return aws_sub_u32_checked(a, b, r); #elif SIZE_BITS == 64 - return aws_sub_u64_checked(a, b, (uint64_t *)r); + return aws_sub_u64_checked(a, b, AWS_CAST_SIZE_PTR_TO_U64 r); #else # error "Target not supported" #endif @@ -288,6 +304,10 @@ AWS_STATIC_IMPL double aws_max_double(double a, double b) { return a > b ? a : b; } +#undef AWS_CAST_SIZE_TO_U64 +#undef AWS_CAST_SIZE_PTR_TO_U64 +#undef AWS_CAST_U64_TO_SIZE + AWS_EXTERN_C_END #endif /* AWS_COMMON_MATH_INL */ From d80a18dd4ddeb82b2748ad38056a1d1564a04cee Mon Sep 17 00:00:00 2001 From: Michael Graeb Date: Tue, 13 Aug 2024 20:48:39 +0000 Subject: [PATCH 2/2] easier to just ignore the warning, vs trying to figure out the defines for every platform where size_t is unsigned long --- include/aws/common/math.inl | 51 ++++++++++++++----------------------- 1 file changed, 19 insertions(+), 32 deletions(-) diff --git a/include/aws/common/math.inl b/include/aws/common/math.inl index 3910c35a4..ad3590623 100644 --- a/include/aws/common/math.inl +++ b/include/aws/common/math.inl @@ -51,22 +51,11 @@ AWS_EXTERN_C_BEGIN #ifdef _MSC_VER # pragma warning(push) # pragma warning(disable : 4127) /*Disable "conditional expression is constant" */ -#endif /* _MSC_VER */ - -/* Macros to cast (if necessary) between size_t and uint64_t. - * On x86_64 platforms, size_t is always 64 bits. - * But on __MACH__, size_t's type is unsigned long, while on others it's unsigned long long. - * Some compilers will warn if you don't you cast between them, - * while other compilers (GCC with -Wuseless-cast) warn if you needlessly cast between them. - * So declare macros that do the right thing. */ -#ifdef __MACH__ /* do cast */ -# define AWS_CAST_SIZE_TO_U64 (uint64_t) -# define AWS_CAST_SIZE_PTR_TO_U64 (uint64_t *) -# define AWS_CAST_U64_TO_SIZE (size_t) -#else /* no cast required*/ -# define AWS_CAST_SIZE_TO_U64 -# define AWS_CAST_SIZE_PTR_TO_U64 -# define AWS_CAST_U64_TO_SIZE +#elif defined(__GNUC__) +# pragma GCC diagnostic push +# if defined(__cplusplus) && !defined(__clang__) +# pragma GCC diagnostic ignored "-Wuseless-cast" /* Warning is C++ only (not C), and GCC only (not clang) */ +# endif #endif AWS_STATIC_IMPL uint64_t aws_sub_u64_saturating(uint64_t a, uint64_t b) { @@ -100,9 +89,9 @@ AWS_STATIC_IMPL int aws_sub_u32_checked(uint32_t a, uint32_t b, uint32_t *r) { */ AWS_STATIC_IMPL size_t aws_mul_size_saturating(size_t a, size_t b) { #if SIZE_BITS == 32 - return aws_mul_u32_saturating(a, b); + return (size_t)aws_mul_u32_saturating(a, b); #elif SIZE_BITS == 64 - return AWS_CAST_SIZE_TO_U64 aws_mul_u64_saturating(a, b); + return (size_t)aws_mul_u64_saturating(a, b); #else # error "Target not supported" #endif @@ -114,9 +103,9 @@ AWS_STATIC_IMPL size_t aws_mul_size_saturating(size_t a, size_t b) { */ AWS_STATIC_IMPL int aws_mul_size_checked(size_t a, size_t b, size_t *r) { #if SIZE_BITS == 32 - return aws_mul_u32_checked(a, b, r); + return aws_mul_u32_checked(a, b, (uint32_t *)r); #elif SIZE_BITS == 64 - return aws_mul_u64_checked(a, b, AWS_CAST_SIZE_PTR_TO_U64 r); + return aws_mul_u64_checked(a, b, (uint64_t *)r); #else # error "Target not supported" #endif @@ -127,9 +116,9 @@ AWS_STATIC_IMPL int aws_mul_size_checked(size_t a, size_t b, size_t *r) { */ AWS_STATIC_IMPL size_t aws_add_size_saturating(size_t a, size_t b) { #if SIZE_BITS == 32 - return aws_add_u32_saturating(a, b); + return (size_t)aws_add_u32_saturating(a, b); #elif SIZE_BITS == 64 - return AWS_CAST_U64_TO_SIZE aws_add_u64_saturating(a, b); + return (size_t)aws_add_u64_saturating(a, b); #else # error "Target not supported" #endif @@ -141,9 +130,9 @@ AWS_STATIC_IMPL size_t aws_add_size_saturating(size_t a, size_t b) { */ AWS_STATIC_IMPL int aws_add_size_checked(size_t a, size_t b, size_t *r) { #if SIZE_BITS == 32 - return aws_add_u32_checked(a, b, r); + return aws_add_u32_checked(a, b, (uint32_t *)r); #elif SIZE_BITS == 64 - return aws_add_u64_checked(a, b, AWS_CAST_SIZE_PTR_TO_U64 r); + return aws_add_u64_checked(a, b, (uint64_t *)r); #else # error "Target not supported" #endif @@ -151,9 +140,9 @@ AWS_STATIC_IMPL int aws_add_size_checked(size_t a, size_t b, size_t *r) { AWS_STATIC_IMPL size_t aws_sub_size_saturating(size_t a, size_t b) { #if SIZE_BITS == 32 - return aws_sub_u32_saturating(a, b); + return (size_t)aws_sub_u32_saturating(a, b); #elif SIZE_BITS == 64 - return AWS_CAST_U64_TO_SIZE aws_sub_u64_saturating(a, b); + return (size_t)aws_sub_u64_saturating(a, b); #else # error "Target not supported" #endif @@ -161,9 +150,9 @@ AWS_STATIC_IMPL size_t aws_sub_size_saturating(size_t a, size_t b) { AWS_STATIC_IMPL int aws_sub_size_checked(size_t a, size_t b, size_t *r) { #if SIZE_BITS == 32 - return aws_sub_u32_checked(a, b, r); + return aws_sub_u32_checked(a, b, (uint32_t *)r); #elif SIZE_BITS == 64 - return aws_sub_u64_checked(a, b, AWS_CAST_SIZE_PTR_TO_U64 r); + return aws_sub_u64_checked(a, b, (uint64_t *)r); #else # error "Target not supported" #endif @@ -206,6 +195,8 @@ AWS_STATIC_IMPL int aws_round_up_to_power_of_two(size_t n, size_t *result) { #ifdef _MSC_VER # pragma warning(pop) +#elif defined(__GNUC__) +# pragma GCC diagnostic pop #endif /* _MSC_VER */ AWS_STATIC_IMPL uint8_t aws_min_u8(uint8_t a, uint8_t b) { @@ -304,10 +295,6 @@ AWS_STATIC_IMPL double aws_max_double(double a, double b) { return a > b ? a : b; } -#undef AWS_CAST_SIZE_TO_U64 -#undef AWS_CAST_SIZE_PTR_TO_U64 -#undef AWS_CAST_U64_TO_SIZE - AWS_EXTERN_C_END #endif /* AWS_COMMON_MATH_INL */