public inbox for libstdc++-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc r13-3412] libstdc++: Redefine __from_chars_alnum_to_val's table
@ 2022-10-20 14:31 Patrick Palka
  0 siblings, 0 replies; only message in thread
From: Patrick Palka @ 2022-10-20 14:31 UTC (permalink / raw)
  To: gcc-cvs, libstdc++-cvs

https://gcc.gnu.org/g:7bf3a4d36a8e59297ea65dd479ffe696f0974303

commit r13-3412-g7bf3a4d36a8e59297ea65dd479ffe696f0974303
Author: Patrick Palka <ppalka@redhat.com>
Date:   Thu Oct 20 10:30:31 2022 -0400

    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.

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<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.

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2022-10-20 14:31 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-10-20 14:31 [gcc r13-3412] libstdc++: Redefine __from_chars_alnum_to_val's table Patrick Palka

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).