Force default char to be signed on all architectures

We assume that `char` is `signed` in various places in the code. In particular, the `Str.StrToInts` test will fail when `char` is not `signed` and names containing special characters will be displayed incorrectly on servers.

Therefore, the compiler flag `-fsigned-char` is set unconditionally instead of only for ARM and ARM64, as we expect `char` to be `signed` on all architectures.

A static assertion is added to ensure at compile time that `char` is `signed` independently from the flag added in `CMakeLists.txt`.

This is necessary at least for ARM, ARM64, PPC, PPC64, and PPC64LE. According to some sources, `char` may also be `unsigned` by default when compiling for Android, although this could not be confirmed with the current Android NDK using Clang.

For the PowerPC architectures, Compiler Explorer can be used to confirm that `char` is not `signed` by default by checking whether the static assertion compiles (see https://godbolt.org/z/9rn5Mrf59) and that the assembly is different with the `-fsigned-char` flag (see https://godbolt.org/z/138zTj3Wa).

Closes #8386.
This commit is contained in:
Robert Müller 2024-06-11 22:11:50 +02:00
parent 4fa55b3463
commit 71b3c8a35b
2 changed files with 8 additions and 5 deletions

View file

@ -291,11 +291,10 @@ if(NOT MSVC AND NOT HAIKU)
add_cxx_compiler_flag_if_supported(OUR_FLAGS -ffloat-store) add_cxx_compiler_flag_if_supported(OUR_FLAGS -ffloat-store)
endif() endif()
# This is needed to get the server to correctly display special characters # We assume that char is signed in various places in the code. In particular,
# on ARM systems. # the Str.StrToInts test will fail when char is not signed and names containing
if("${CMAKE_SYSTEM_PROCESSOR}" MATCHES "arm" OR "${CMAKE_SYSTEM_PROCESSOR}" MATCHES "aarch64") # special characters will be displayed incorrectly on servers.
add_cxx_compiler_flag_if_supported(OUR_FLAGS -fsigned-char) add_cxx_compiler_flag_if_supported(OUR_FLAGS -fsigned-char)
endif()
# Don't insert timestamps into PEs to keep the build reproducible. # Don't insert timestamps into PEs to keep the build reproducible.
if(TARGET_OS STREQUAL "windows") if(TARGET_OS STREQUAL "windows")

View file

@ -9,6 +9,8 @@
#include <base/system.h> #include <base/system.h>
#include <engine/shared/config.h> #include <engine/shared/config.h>
#include <limits>
const char *CTuningParams::ms_apNames[] = const char *CTuningParams::ms_apNames[] =
{ {
#define MACRO_TUNING_PARAM(Name, ScriptName, Value, Description) #ScriptName, #define MACRO_TUNING_PARAM(Name, ScriptName, Value, Description) #ScriptName,
@ -63,6 +65,8 @@ float CTuningParams::GetWeaponFireDelay(int Weapon) const
} }
} }
static_assert(std::numeric_limits<char>::is_signed, "char must be signed for StrToInts to work correctly");
void StrToInts(int *pInts, size_t NumInts, const char *pStr) void StrToInts(int *pInts, size_t NumInts, const char *pStr)
{ {
dbg_assert(NumInts > 0, "StrToInts: NumInts invalid"); dbg_assert(NumInts > 0, "StrToInts: NumInts invalid");