Fix invalid code and bad codegen (gcc, msvc)

* `static constexpr var` is invalid within `constexpr` function.
 * make lookup tables `static constexpr`
 * instruct msvc to report the true value in `__cplusplus` in _some_ tests to improve test coverage and catch similar problems in the future
This commit is contained in:
Daniela Engert 2021-06-11 12:34:05 +02:00
parent f6b5cc9f84
commit 4c407e3545
No known key found for this signature in database
GPG Key ID: 7B95EE52040C5975
3 changed files with 17 additions and 13 deletions

View File

@ -153,6 +153,9 @@ template <typename T> constexpr const unsigned basic_data<T>::prefixes[];
template <typename T> constexpr const char basic_data<T>::left_padding_shifts[]; template <typename T> constexpr const char basic_data<T>::left_padding_shifts[];
template <typename T> template <typename T>
constexpr const char basic_data<T>::right_padding_shifts[]; constexpr const char basic_data<T>::right_padding_shifts[];
template <typename T> constexpr const uint16_t basic_data<T>::bsr2log10[];
template <typename T>
constexpr const uint64_t basic_data<T>::zero_or_powers_of_10[];
#endif #endif
template <typename T> struct bits { template <typename T> struct bits {

View File

@ -248,7 +248,8 @@ FMT_BEGIN_NAMESPACE
namespace detail { namespace detail {
#if __cplusplus >= 202002L || \ #if __cplusplus >= 202002L || \
(__cplusplus >= 201709L && FMT_GCC_VERSION >= 1002) (__cplusplus >= 201709L && FMT_GCC_VERSION >= 1002) || \
(defined(_MSVC_LANG) && _MSVC_LANG >= 201709L)
# define FMT_CONSTEXPR20 constexpr # define FMT_CONSTEXPR20 constexpr
#else #else
# define FMT_CONSTEXPR20 # define FMT_CONSTEXPR20
@ -864,6 +865,14 @@ template <typename T = void> struct basic_data {
0x1000000u | ' '}; 0x1000000u | ' '};
FMT_API static constexpr const char left_padding_shifts[] = {31, 31, 0, 1, 0}; FMT_API static constexpr const char left_padding_shifts[] = {31, 31, 0, 1, 0};
FMT_API static constexpr const char right_padding_shifts[] = {0, 31, 0, 1, 0}; FMT_API static constexpr const char right_padding_shifts[] = {0, 31, 0, 1, 0};
FMT_API static constexpr const uint16_t bsr2log10[] = {
1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5,
6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10,
10, 11, 11, 11, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 15, 15,
15, 16, 16, 16, 16, 17, 17, 17, 18, 18, 18, 19, 19, 19, 19, 20};
FMT_API static constexpr const uint64_t zero_or_powers_of_10[] = {
0, 0, FMT_POWERS_OF_10(1U), FMT_POWERS_OF_10(1000000000ULL),
10000000000000000000ULL};
}; };
#ifdef FMT_SHARED #ifdef FMT_SHARED
@ -901,16 +910,8 @@ FMT_CONSTEXPR20 inline auto count_digits(uint64_t n) -> int {
if (!is_constant_evaluated()) { if (!is_constant_evaluated()) {
// https://github.com/fmtlib/format-benchmark/blob/master/digits10 // https://github.com/fmtlib/format-benchmark/blob/master/digits10
// Maps bsr(n) to ceil(log10(pow(2, bsr(n) + 1) - 1)). // Maps bsr(n) to ceil(log10(pow(2, bsr(n) + 1) - 1)).
FMT_STATIC_CONSTEXPR uint16_t bsr2log10[] = { auto t = data::bsr2log10[FMT_BUILTIN_CLZLL(n | 1) ^ 63];
1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, return t - (n < data::zero_or_powers_of_10[t]);
6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10,
10, 11, 11, 11, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 15, 15,
15, 16, 16, 16, 16, 17, 17, 17, 18, 18, 18, 19, 19, 19, 19, 20};
auto t = bsr2log10[FMT_BUILTIN_CLZLL(n | 1) ^ 63];
constexpr const uint64_t zero_or_powers_of_10[] = {
0, 0, FMT_POWERS_OF_10(1U), FMT_POWERS_OF_10(1000000000ULL),
10000000000000000000ULL};
return t - (n < zero_or_powers_of_10[t]);
} }
#endif #endif
return count_digits_fallback(n); return count_digits_fallback(n);

View File

@ -99,8 +99,8 @@ if (FMT_CAN_MODULE)
add_fmt_test(module-test MODULE) add_fmt_test(module-test MODULE)
if (MSVC) if (MSVC)
target_compile_options(test-module PRIVATE /utf-8) target_compile_options(test-module PRIVATE /utf-8 /Zc:__cplusplus)
target_compile_options(module-test PRIVATE /utf-8) target_compile_options(module-test PRIVATE /utf-8 /Zc:__cplusplus)
endif () endif ()
endif () endif ()