diff options
author | Patrick Palka <ppalka@redhat.com> | 2022-10-20 10:30:31 -0400 |
---|---|---|
committer | Patrick Palka <ppalka@redhat.com> | 2022-10-20 10:30:31 -0400 |
commit | 7bf3a4d36a8e59297ea65dd479ffe696f0974303 (patch) | |
tree | a56d379e4b7cd8a4cde3a28807e3ce3e751c18cd | |
parent | f4fda3eec408e1eb12cc966f55f0de396be71597 (diff) | |
download | gcc-7bf3a4d36a8e59297ea65dd479ffe696f0974303.zip gcc-7bf3a4d36a8e59297ea65dd479ffe696f0974303.tar.gz gcc-7bf3a4d36a8e59297ea65dd479ffe696f0974303.tar.bz2 |
libstdc++: Redefine __from_chars_alnum_to_val's table
After the C++23 constexpr <charconv> patch r13-3313-g378a0f1840e694 we
have some modules testsuite regressions:
FAIL: g++.dg/modules/xtreme-header-4_b.C -std=c++2b (test for excess errors)
FAIL: g++.dg/modules/xtreme-header_b.C -std=c++2b (test for excess errors)
Like with PR105297, the cause seems to be the deduced type of __table
resolving ahead of time to a local class type, which trips up modules.
And unfortunately that PR's minimal workaround of making __tables's
initializer value dependent doesn't help in this case.
So this patch works around this by avoiding using a local class for the
table type. And I suppose we should use a static data member to define
the table once for all dialects (including C++14) instead of having to
define it twice in C++23 mode (once as a static local variable and again
as a variable template for sake of constexpr evaluation).
libstdc++-v3/ChangeLog:
* include/std/charconv (__detail::__from_chars_alnum_to_val_table):
Redefine as a class template containing the members type, value and
_S_make_table. Don't use a local class as the table type.
(__detail::__table): Remove.
(__detail::__from_chars_alnum_to_val): Adjust after the above.
-rw-r--r-- | libstdc++-v3/include/std/charconv | 59 |
1 files changed, 28 insertions, 31 deletions
diff --git a/libstdc++-v3/include/std/charconv b/libstdc++-v3/include/std/charconv index 7aefdd3..a65fbed 100644 --- a/libstdc++-v3/include/std/charconv +++ b/libstdc++-v3/include/std/charconv @@ -413,30 +413,36 @@ namespace __detail return true; } - // Construct and return a lookup table that maps 0-9, A-Z and a-z to their - // corresponding base-36 value and maps all other characters to 127. - constexpr auto - __from_chars_alnum_to_val_table() - { - constexpr unsigned char __lower_letters[27] = "abcdefghijklmnopqrstuvwxyz"; - constexpr unsigned char __upper_letters[27] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; - struct { unsigned char __data[1u << __CHAR_BIT__] = {}; } __table; - for (auto& __entry : __table.__data) - __entry = 127; - for (int __i = 0; __i < 10; ++__i) - __table.__data['0' + __i] = __i; - for (int __i = 0; __i < 26; ++__i) + template<bool _DecOnly> + struct __from_chars_alnum_to_val_table + { + struct type { unsigned char __data[1u << __CHAR_BIT__] = {}; }; + + // Construct and return a lookup table that maps 0-9, A-Z and a-z to their + // corresponding base-36 value and maps all other characters to 127. + static constexpr type + _S_make_table() { - __table.__data[__lower_letters[__i]] = 10 + __i; - __table.__data[__upper_letters[__i]] = 10 + __i; + constexpr unsigned char __lower_letters[27] = "abcdefghijklmnopqrstuvwxyz"; + constexpr unsigned char __upper_letters[27] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + type __table; + for (auto& __entry : __table.__data) + __entry = 127; + for (int __i = 0; __i < 10; ++__i) + __table.__data['0' + __i] = __i; + for (int __i = 0; __i < 26; ++__i) + { + __table.__data[__lower_letters[__i]] = 10 + __i; + __table.__data[__upper_letters[__i]] = 10 + __i; + } + return __table; } - return __table; - } -#if __cpp_lib_constexpr_charconv - template<bool _DecOnly> - inline constexpr auto __table = __from_chars_alnum_to_val_table(); -#endif + // This initializer is made superficially dependent in order + // to prevent the compiler from wastefully constructing the + // table ahead of time when it's not needed. + static constexpr type value = (_DecOnly, _S_make_table()); + }; // If _DecOnly is true: if the character is a decimal digit, then // return its corresponding base-10 value, otherwise return a value >= 127. @@ -449,16 +455,7 @@ namespace __detail if _GLIBCXX17_CONSTEXPR (_DecOnly) return static_cast<unsigned char>(__c - '0'); else - { -#if __cpp_lib_constexpr_charconv - if (std::__is_constant_evaluated()) - return __table<_DecOnly>.__data[__c]; -#endif - // This initializer is deliberately made dependent in order to work - // around modules bug PR105322. - static constexpr auto __table = (_DecOnly, __from_chars_alnum_to_val_table()); - return __table.__data[__c]; - } + return __from_chars_alnum_to_val_table<_DecOnly>::value.__data[__c]; } /// std::from_chars implementation for integers in a power-of-two base. |