From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 1888) id 11B323851173; Thu, 20 Oct 2022 14:31:11 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 11B323851173 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1666276271; bh=IXVQ+rBJ+sWjX6LyCQZfKhmE34YuvHL+cdkc+u3tn/A=; h=From:To:Subject:Date:From; b=A5Ant/7wlsqwdwifjP3nfmomgtXKADeKgs5S5hBdr4nJmTv/lD5uTDQO8PruL/e8R 67lwNkNgRuek6MGUK0JtEix3tNha4SulHr3qb+GH8Xe0VtE5qKtkDPyAY2T15nJlbs YDTe68ZjYBev16Iih+HZ3fPexeRFbm6j6vdG2XG8= MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset="utf-8" From: Patrick Palka To: gcc-cvs@gcc.gnu.org, libstdc++-cvs@gcc.gnu.org Subject: [gcc r13-3412] libstdc++: Redefine __from_chars_alnum_to_val's table X-Act-Checkin: gcc X-Git-Author: Patrick Palka X-Git-Refname: refs/heads/master X-Git-Oldrev: f4fda3eec408e1eb12cc966f55f0de396be71597 X-Git-Newrev: 7bf3a4d36a8e59297ea65dd479ffe696f0974303 Message-Id: <20221020143111.11B323851173@sourceware.org> Date: Thu, 20 Oct 2022 14:31:11 +0000 (GMT) List-Id: https://gcc.gnu.org/g:7bf3a4d36a8e59297ea65dd479ffe696f0974303 commit r13-3412-g7bf3a4d36a8e59297ea65dd479ffe696f0974303 Author: Patrick Palka Date: Thu Oct 20 10:30:31 2022 -0400 libstdc++: Redefine __from_chars_alnum_to_val's table After the C++23 constexpr 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. Diff: --- libstdc++-v3/include/std/charconv | 59 +++++++++++++++++++-------------------- 1 file changed, 28 insertions(+), 31 deletions(-) diff --git a/libstdc++-v3/include/std/charconv b/libstdc++-v3/include/std/charconv index 7aefdd3298c..a65fbedc21c 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 + 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 - 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(__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.