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>::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
template <typename T> struct bits {

View File

@ -248,7 +248,8 @@ FMT_BEGIN_NAMESPACE
namespace detail {
#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
#else
# define FMT_CONSTEXPR20
@ -864,6 +865,14 @@ template <typename T = void> struct basic_data {
0x1000000u | ' '};
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 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
@ -901,16 +910,8 @@ FMT_CONSTEXPR20 inline auto count_digits(uint64_t n) -> int {
if (!is_constant_evaluated()) {
// https://github.com/fmtlib/format-benchmark/blob/master/digits10
// Maps bsr(n) to ceil(log10(pow(2, bsr(n) + 1) - 1)).
FMT_STATIC_CONSTEXPR 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};
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]);
auto t = data::bsr2log10[FMT_BUILTIN_CLZLL(n | 1) ^ 63];
return t - (n < data::zero_or_powers_of_10[t]);
}
#endif
return count_digits_fallback(n);

View File

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