Skip to content

[libc++] Refactor the <charconv> tests - #227611

Open
philnik777 wants to merge 1 commit into
llvm:mainfrom
philnik777:refactor_charconv_tests
Open

philnik777 wants to merge 1 commit into
llvm:mainfrom
philnik777:refactor_charconv_tests

Conversation

@philnik777

@philnik777 philnik777 commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

This does a few things:

  • code inside charconv_test_helpers.h that is only used in a single test is moved into the test
  • the type algorithms are used instead of a custom implementation
  • .verify.cpp tests are instead SFINAE tested

Using the type algorithms is an important fix here, since the custom implementation resulted in only ever constant evaluating some functions.

@philnik777
philnik777 requested a review from a team as a code owner September 30, 2026 08:59
@llvmorg-github-actions llvmorg-github-actions Bot added the libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi. label Sep 30, 2026
@llvmorg-github-actions

Copy link
Copy Markdown

@llvm/pr-subscribers-libcxx

Author: Nikolas Klauser (philnik777)

Changes

Patch is 119.59 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/227611.diff

7 Files Affected:

  • (modified) libcxx/test/std/utilities/charconv/charconv.from.chars/floating_point.pass.cpp (+930-932)
  • (removed) libcxx/test/std/utilities/charconv/charconv.from.chars/integral.bool.verify.cpp (-32)
  • (modified) libcxx/test/std/utilities/charconv/charconv.from.chars/integral.pass.cpp (+22-6)
  • (modified) libcxx/test/std/utilities/charconv/charconv.from.chars/integral.roundtrip.pass.cpp (+84-58)
  • (removed) libcxx/test/std/utilities/charconv/charconv.to.chars/integral.bool.verify.cpp (-32)
  • (modified) libcxx/test/std/utilities/charconv/charconv.to.chars/integral.pass.cpp (+367-232)
  • (modified) libcxx/test/support/charconv_test_helpers.h (+6-265)
diff --git a/libcxx/test/std/utilities/charconv/charconv.from.chars/floating_point.pass.cpp b/libcxx/test/std/utilities/charconv/charconv.from.chars/floating_point.pass.cpp
index a02c7ac466f04..fa223785d758d 100644
--- a/libcxx/test/std/utilities/charconv/charconv.from.chars/floating_point.pass.cpp
+++ b/libcxx/test/std/utilities/charconv/charconv.from.chars/floating_point.pass.cpp
@@ -17,6 +17,7 @@
 //                              double& value, chars_format fmt = chars_format::general)
 
 #include <array>
+#include <cassert>
 #include <charconv>
 #include <cmath>
 #include <cstring>
@@ -24,8 +25,8 @@
 #include <stdexcept>
 #include <system_error>
 
-#include "charconv_test_helpers.h"
 #include "test_macros.h"
+#include "type_algorithms.h"
 
 template <class F>
 void test_infinity(std::chars_format fmt) {
@@ -326,1193 +327,1183 @@ void test_fmt_independent(std::chars_format fmt) {
 }
 
 template <class F>
-struct test_basics {
-  void operator()() {
-    for (auto fmt : {std::chars_format::scientific,
-                     std::chars_format::fixed,
-                     /*std::chars_format::hex,*/ std::chars_format::general})
-      test_fmt_independent<F>(fmt);
-  }
-};
+void test_basics() {
+  for (auto fmt : {std::chars_format::scientific,
+                   std::chars_format::fixed,
+                   /*std::chars_format::hex,*/ std::chars_format::general})
+    test_fmt_independent<F>(fmt);
+}
 
 template <class F>
-struct test_fixed {
-  void operator()() {
-    std::from_chars_result r;
-    F x = 0.25;
+void test_fixed() {
+  std::from_chars_result r;
+  F x = 0.25;
 
-    // *** Failures
+  // *** Failures
 
-    { // Starts with invalid character
-      std::array s = {' ', '1'};
-      for (auto c : "abcdefghijklmnopqrstuvwxyz"
-                    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
-                    "`~!@#$%^&*()_=[]{}\\|;:'\",/<>? \t\v\r\n") {
-        s[0] = c;
-        r    = std::from_chars(s.data(), s.data() + s.size(), x, std::chars_format::fixed);
+  { // Starts with invalid character
+    std::array s = {' ', '1'};
+    for (auto c : "abcdefghijklmnopqrstuvwxyz"
+                  "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+                  "`~!@#$%^&*()_=[]{}\\|;:'\",/<>? \t\v\r\n") {
+      s[0] = c;
+      r    = std::from_chars(s.data(), s.data() + s.size(), x, std::chars_format::fixed);
 
-        assert(r.ec == std::errc::invalid_argument);
-        assert(r.ptr == s.data());
-        assert(x == F(0.25));
-      }
+      assert(r.ec == std::errc::invalid_argument);
+      assert(r.ptr == s.data());
+      assert(x == F(0.25));
     }
+  }
 
-    // *** Success
+  // *** Success
 
-    { // number followed by non-numeric values
-      const char* s = "001x";
+  { // number followed by non-numeric values
+    const char* s = "001x";
 
-      // the expected form of the subject sequence is a nonempty sequence of
-      // decimal digits optionally containing a decimal-point character, then
-      // an optional exponent part as defined in 6.4.4.3, excluding any digit
-      // separators (6.4.4.2); (C23 7.24.1.5)
-      r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed);
-      assert(r.ec == std::errc{});
-      assert(r.ptr == s + 3);
-      assert(x == F(1.0));
-    }
-    { // no leading digit
-      const char* s = ".5";
+    // the expected form of the subject sequence is a nonempty sequence of
+    // decimal digits optionally containing a decimal-point character, then
+    // an optional exponent part as defined in 6.4.4.3, excluding any digit
+    // separators (6.4.4.2); (C23 7.24.1.5)
+    r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed);
+    assert(r.ec == std::errc{});
+    assert(r.ptr == s + 3);
+    assert(x == F(1.0));
+  }
+  { // no leading digit
+    const char* s = ".5";
+
+    // the expected form of the subject sequence is a nonempty sequence of
+    // decimal digits optionally containing a decimal-point character, then
+    // an optional exponent part as defined in 6.4.4.3, excluding any digit
+    // separators (6.4.4.2); (C23 7.24.1.5)
+    r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed);
+    assert(r.ec == std::errc{});
+    assert(r.ptr == s + 2);
+    assert(x == F(0.5));
+  }
+  { // negative sign and no leading digit
+    const char* s = "-.5";
+
+    // the expected form of the subject sequence is a nonempty sequence of
+    // decimal digits optionally containing a decimal-point character, then
+    // an optional exponent part as defined in 6.4.4.3, excluding any digit
+    // separators (6.4.4.2); (C23 7.24.1.5)
+    r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed);
+    assert(r.ec == std::errc{});
+    assert(r.ptr == s + 3);
+    assert(x == F(-0.5));
+  }
 
-      // the expected form of the subject sequence is a nonempty sequence of
-      // decimal digits optionally containing a decimal-point character, then
-      // an optional exponent part as defined in 6.4.4.3, excluding any digit
-      // separators (6.4.4.2); (C23 7.24.1.5)
-      r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed);
-      assert(r.ec == std::errc{});
-      assert(r.ptr == s + 2);
-      assert(x == F(0.5));
-    }
-    { // negative sign and no leading digit
-      const char* s = "-.5";
+  { // double decimal point
+    const char* s = "1.25.78";
 
-      // the expected form of the subject sequence is a nonempty sequence of
-      // decimal digits optionally containing a decimal-point character, then
-      // an optional exponent part as defined in 6.4.4.3, excluding any digit
-      // separators (6.4.4.2); (C23 7.24.1.5)
-      r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed);
-      assert(r.ec == std::errc{});
-      assert(r.ptr == s + 3);
-      assert(x == F(-0.5));
-    }
+    // This number is halfway between two float values.
+    r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed);
+    assert(r.ec == std::errc{});
+    assert(r.ptr == s + 4);
+    assert(x == F(1.25));
+  }
+  { // exponent no sign
+    const char* s = "1.5e10";
+    r             = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed);
+
+    assert(r.ec == std::errc{});
+    assert(r.ptr == s + 3);
+    assert(x == F(1.5));
+  }
+  { // exponent capitalized no sign
+    const char* s = "1.5E10";
+    r             = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed);
+
+    assert(r.ec == std::errc{});
+    assert(r.ptr == s + 3);
+    assert(x == F(1.5));
+  }
+  { // exponent + sign
+    const char* s = "1.5e+10";
+    r             = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed);
+
+    assert(r.ec == std::errc{});
+    assert(r.ptr == s + 3);
+    assert(x == F(1.5));
+  }
+  { // exponent - sign
+    const char* s = "1.5e-10";
+    r             = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed);
+
+    assert(r.ec == std::errc{});
+    assert(r.ptr == s + 3);
+    assert(x == F(1.5));
+  }
+  { // Exponent no number
+    const char* s = "1.5e";
 
-    { // double decimal point
-      const char* s = "1.25.78";
+    r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed);
+    assert(r.ec == std::errc{});
+    assert(r.ptr == s + 3);
+    assert(x == F(1.5));
+  }
+  { // Exponent sign no number
+    {
+      const char* s = "1.5e+";
 
-      // This number is halfway between two float values.
       r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed);
       assert(r.ec == std::errc{});
-      assert(r.ptr == s + 4);
-      assert(x == F(1.25));
+      assert(r.ptr == s + 3);
+      assert(x == F(1.5));
     }
-    { // exponent no sign
-      const char* s = "1.5e10";
-      r             = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed);
+    {
+      const char* s = "1.5e-";
 
+      r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed);
       assert(r.ec == std::errc{});
       assert(r.ptr == s + 3);
       assert(x == F(1.5));
     }
-    { // exponent capitalized no sign
-      const char* s = "1.5E10";
-      r             = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed);
+  }
+  { // Exponent with whitespace
+    {
+      const char* s = "1.5e +1";
 
+      r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed);
       assert(r.ec == std::errc{});
       assert(r.ptr == s + 3);
       assert(x == F(1.5));
     }
-    { // exponent + sign
-      const char* s = "1.5e+10";
-      r             = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed);
+    {
+      const char* s = "1.5e+ 1";
 
+      r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed);
       assert(r.ec == std::errc{});
       assert(r.ptr == s + 3);
       assert(x == F(1.5));
     }
-    { // exponent - sign
-      const char* s = "1.5e-10";
-      r             = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed);
+    {
+      const char* s = "1.5e -1";
 
+      r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed);
       assert(r.ec == std::errc{});
       assert(r.ptr == s + 3);
       assert(x == F(1.5));
     }
-    { // Exponent no number
-      const char* s = "1.5e";
+    {
+      const char* s = "1.5e- 1";
 
       r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed);
       assert(r.ec == std::errc{});
       assert(r.ptr == s + 3);
       assert(x == F(1.5));
     }
-    { // Exponent sign no number
-      {
-        const char* s = "1.5e+";
-
-        r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed);
-        assert(r.ec == std::errc{});
-        assert(r.ptr == s + 3);
-        assert(x == F(1.5));
-      }
-      {
-        const char* s = "1.5e-";
-
-        r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed);
-        assert(r.ec == std::errc{});
-        assert(r.ptr == s + 3);
-        assert(x == F(1.5));
-      }
-    }
-    { // Exponent with whitespace
-      {
-        const char* s = "1.5e +1";
-
-        r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed);
-        assert(r.ec == std::errc{});
-        assert(r.ptr == s + 3);
-        assert(x == F(1.5));
-      }
-      {
-        const char* s = "1.5e+ 1";
-
-        r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed);
-        assert(r.ec == std::errc{});
-        assert(r.ptr == s + 3);
-        assert(x == F(1.5));
-      }
-      {
-        const char* s = "1.5e -1";
-
-        r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed);
-        assert(r.ec == std::errc{});
-        assert(r.ptr == s + 3);
-        assert(x == F(1.5));
-      }
-      {
-        const char* s = "1.5e- 1";
-
-        r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed);
-        assert(r.ec == std::errc{});
-        assert(r.ptr == s + 3);
-        assert(x == F(1.5));
-      }
-    }
-    { // double exponent
-      const char* s = "1.25e0e12";
-      r             = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed);
+  }
+  { // double exponent
+    const char* s = "1.25e0e12";
+    r             = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed);
 
+    assert(r.ec == std::errc{});
+    assert(r.ptr == s + 4);
+    assert(x == F(1.25));
+  }
+  { // Exponent double sign
+    {
+      const char* s = "1.25e++12";
+
+      r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed);
       assert(r.ec == std::errc{});
       assert(r.ptr == s + 4);
       assert(x == F(1.25));
     }
-    { // Exponent double sign
-      {
-        const char* s = "1.25e++12";
-
-        r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed);
-        assert(r.ec == std::errc{});
-        assert(r.ptr == s + 4);
-        assert(x == F(1.25));
-      }
-      {
-        const char* s = "1.25e+-12";
-
-        r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed);
-        assert(r.ec == std::errc{});
-        assert(r.ptr == s + 4);
-        assert(x == F(1.25));
-      }
-      {
-        const char* s = "1.25e-+12";
-
-        r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed);
-        assert(r.ec == std::errc{});
-        assert(r.ptr == s + 4);
-        assert(x == F(1.25));
-      }
-      {
-        const char* s = "1.25e--12";
-
-        r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed);
-        assert(r.ec == std::errc{});
-        assert(r.ptr == s + 4);
-        assert(x == F(1.25));
-      }
-    }
-    { // exponent hex prefix
-      const char* s = "1.25e0x12";
+    {
+      const char* s = "1.25e+-12";
 
       r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed);
       assert(r.ec == std::errc{});
       assert(r.ptr == s + 4);
       assert(x == F(1.25));
     }
-    { // This number is halfway between two float values.
-      const char* s = "20040229";
+    {
+      const char* s = "1.25e-+12";
 
       r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed);
       assert(r.ec == std::errc{});
-      assert(r.ptr == s + 8);
-      assert(x == F(20040229));
+      assert(r.ptr == s + 4);
+      assert(x == F(1.25));
     }
-    { // Shifting mantissa exponent and no exponent
-      const char* s = "123.456";
+    {
+      const char* s = "1.25e--12";
 
       r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed);
       assert(r.ec == std::errc{});
-      assert(r.ptr == s + 7);
-      assert(x == F(1.23456e2));
+      assert(r.ptr == s + 4);
+      assert(x == F(1.25));
     }
-    { // Shifting mantissa exponent and an exponent
-      const char* s = "123.456e3";
-      r             = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed);
+  }
+  { // exponent hex prefix
+    const char* s = "1.25e0x12";
 
+    r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed);
+    assert(r.ec == std::errc{});
+    assert(r.ptr == s + 4);
+    assert(x == F(1.25));
+  }
+  { // This number is halfway between two float values.
+    const char* s = "20040229";
+
+    r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed);
+    assert(r.ec == std::errc{});
+    assert(r.ptr == s + 8);
+    assert(x == F(20040229));
+  }
+  { // Shifting mantissa exponent and no exponent
+    const char* s = "123.456";
+
+    r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed);
+    assert(r.ec == std::errc{});
+    assert(r.ptr == s + 7);
+    assert(x == F(1.23456e2));
+  }
+  { // Shifting mantissa exponent and an exponent
+    const char* s = "123.456e3";
+    r             = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed);
+
+    assert(r.ec == std::errc{});
+    assert(r.ptr == s + 7);
+    assert(x == F(123.456));
+  }
+  { // Mantissa overflow
+    {
+      const char* s = "0.111111111111111111111111111111111111111111";
+
+      r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed);
       assert(r.ec == std::errc{});
-      assert(r.ptr == s + 7);
-      assert(x == F(123.456));
-    }
-    { // Mantissa overflow
-      {
-        const char* s = "0.111111111111111111111111111111111111111111";
-
-        r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed);
-        assert(r.ec == std::errc{});
-        assert(r.ptr == s + std::strlen(s));
-        assert(x == F(0.111111111111111111111111111111111111111111));
-      }
-      {
-        const char* s = "111111111111.111111111111111111111111111111111111111111";
-
-        r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed);
-        assert(r.ec == std::errc{});
-        assert(r.ptr == s + std::strlen(s));
-        assert(x == F(111111111111.111111111111111111111111111111111111111111));
-      }
-    }
-    { // Negative value
-      const char* s = "-0.25";
+      assert(r.ptr == s + std::strlen(s));
+      assert(x == F(0.111111111111111111111111111111111111111111));
+    }
+    {
+      const char* s = "111111111111.111111111111111111111111111111111111111111";
 
       r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed);
       assert(r.ec == std::errc{});
       assert(r.ptr == s + std::strlen(s));
-      assert(x == F(-0.25));
+      assert(x == F(111111111111.111111111111111111111111111111111111111111));
     }
   }
-};
+  { // Negative value
+    const char* s = "-0.25";
+
+    r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed);
+    assert(r.ec == std::errc{});
+    assert(r.ptr == s + std::strlen(s));
+    assert(x == F(-0.25));
+  }
+}
 
 template <class F>
-struct test_scientific {
-  void operator()() {
-    std::from_chars_result r;
-    F x = 0.25;
+void test_scientific() {
+  std::from_chars_result r;
+  F x = 0.25;
 
-    // *** Failures
+  // *** Failures
 
-    { // Starts with invalid character
-      std::array s = {' ', '1', 'e', '0'};
-      for (auto c : "abcdefghijklmnopqrstuvwxyz"
-                    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
-                    "`~!@#$%^&*()_=[]{}\\|;:'\",/<>? \t\v\r\n") {
-        s[0] = c;
-        r    = std::from_chars(s.data(), s.data() + s.size(), x, std::chars_format::scientific);
+  { // Starts with invalid character
+    std::array s = {' ', '1', 'e', '0'};
+    for (auto c : "abcdefghijklmnopqrstuvwxyz"
+                  "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+                  "`~!@#$%^&*()_=[]{}\\|;:'\",/<>? \t\v\r\n") {
+      s[0] = c;
+      r    = std::from_chars(s.data(), s.data() + s.size(), x, std::chars_format::scientific);
 
-        assert(r.ec == std::errc::invalid_argument);
-        assert(r.ptr == s.data());
-        assert(x == F(0.25));
-      }
+      assert(r.ec == std::errc::invalid_argument);
+      assert(r.ptr == s.data());
+      assert(x == F(0.25));
     }
-    { // No exponent
-      const char* s = "1.23";
-      r             = std::from_chars(s, s + strlen(s), x, std::chars_format::scientific);
+  }
+  { // No exponent
+    const char* s = "1.23";
+    r             = std::from_chars(s, s + strlen(s), x, std::chars_format::scientific);
 
+    assert(r.ec == std::errc::invalid_argument);
+    assert(r.ptr == s);
+    assert(x == F(0.25));
+  }
+  { // Exponent no number
+    const char* s = "1.23e";
+    r             = std::from_chars(s, s + strlen(s), x, std::chars_format::scientific);
+
+    assert(r.ec == std::errc::invalid_argument);
+    assert(r.ptr == s);
+    assert(x == F(0.25));
+  }
+  { // Exponent sign no number
+    {
+      const char* s = "1.5e+";
+
+      r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::scientific);
       assert(r.ec == std::errc::invalid_argument);
       assert(r.ptr == s);
       assert(x == F(0.25));
     }
-    { // Exponent no number
-      const char* s = "1.23e";
-      r             = std::from_chars(s, s + strlen(s), x, std::chars_format::scientific);
+    {
+      const char* s = "1.5e-";
 
+      r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::scientific);
       assert(r.ec == std::errc::invalid_argument);
       assert(r.ptr == s);
       assert(x == F(0.25));
     }
-    { // Exponent sign no number
-      {
-        const char* s = "1.5e+";
-
-        r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::scientific);
-        assert(r.ec == std::errc::invalid_argument);
-        assert(r.ptr == s);
-        assert(x == F(0.25));
-      }
-      {
-        const char* s = "1.5e-";
-
-        r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::scientific);
-        assert(r.ec == std::errc::invalid_argument);
-        assert(r.ptr == s);
-        assert(x == F(0.25));
-      }
-    }
-    { // Exponent with whitespace
-      {
-        const char* s = "1.5e +1";
-
-        r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::scientific);
-        assert(r.ec == std::errc::invalid_argument);
-        assert(r.ptr == s);
-        assert(x == F(0.25));
-      }
-      {
-        const char* s = "1.5e+ 1";
-
-        r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::scientific);
-        assert(r.ec == std::errc::invalid_argument);
-        assert(r.ptr == s);
-        assert(x == F(0.25));
-  ...
[truncated]

@github-actions

Copy link
Copy Markdown

⚠️ C/C++ code formatter, clang-format found issues in your code. ⚠️

You can test this locally with the following command:
git-clang-format --diff origin/main HEAD --extensions cpp,h -- libcxx/test/std/utilities/charconv/charconv.from.chars/floating_point.pass.cpp libcxx/test/std/utilities/charconv/charconv.from.chars/integral.pass.cpp libcxx/test/std/utilities/charconv/charconv.from.chars/integral.roundtrip.pass.cpp libcxx/test/std/utilities/charconv/charconv.to.chars/integral.pass.cpp libcxx/test/support/charconv_test_helpers.h --diff_from_common_commit

⚠️
The reproduction instructions above might return results for more than one PR
in a stack if you are using a stacked PR workflow. You can limit the results by
changing origin/main to the base branch/commit you want to compare against.
⚠️

View the diff from clang-format here.
diff --git a/libcxx/test/std/utilities/charconv/charconv.from.chars/integral.pass.cpp b/libcxx/test/std/utilities/charconv/charconv.from.chars/integral.pass.cpp
index 1e0aaebb1..0a32dd079 100644
--- a/libcxx/test/std/utilities/charconv/charconv.from.chars/integral.pass.cpp
+++ b/libcxx/test/std/utilities/charconv/charconv.from.chars/integral.pass.cpp
@@ -37,120 +37,115 @@ static_assert(!has_from_chars<char*, char*, bool&, int>);
 
 struct test_basics
 {
-    template <typename T>
-    TEST_CONSTEXPR_CXX23 void operator()()
+  template <typename T>
+  TEST_CONSTEXPR_CXX23 void operator()() {
+    std::from_chars_result r;
+    T x;
+
+    {
+      char s[] = "001x";
+
+      // the expected form of the subject sequence is a sequence of
+      // letters and digits representing an integer with the radix
+      // specified by base (C11 7.22.1.4/3)
+      r = std::from_chars(s, s + sizeof(s), x);
+      assert(r.ec == std::errc{});
+      assert(r.ptr == s + 3);
+      assert(x == 1);
+    }
+
     {
-        std::from_chars_result r;
-        T x;
-
-        {
-            char s[] = "001x";
-
-            // the expected form of the subject sequence is a sequence of
-            // letters and digits representing an integer with the radix
-            // specified by base (C11 7.22.1.4/3)
-            r = std::from_chars(s, s + sizeof(s), x);
-            assert(r.ec == std::errc{});
-            assert(r.ptr == s + 3);
-            assert(x == 1);
-        }
-
-        {
-            // The string has more characters than valid in an 128-bit value.
-            char s[] = "0X7BAtSGHDkEIXZgQRfYChLpOzRnM ";
-
-            // The letters from a (or A) through z (or Z) are ascribed the
-            // values 10 through 35; (C11 7.22.1.4/3)
-            r = std::from_chars(s, s + sizeof(s), x, 36);
-            assert(r.ec == std::errc::result_out_of_range);
-            // The member ptr of the return value points to the first character
-            // not matching the pattern
-            assert(r.ptr == s + sizeof(s) - 2);
-            assert(x == 1);
-
-            // no "0x" or "0X" prefix shall appear if the value of base is 16
-            r = std::from_chars(s, s + sizeof(s), x, 16);
-            assert(r.ec == std::errc{});
-            assert(r.ptr == s + 1);
-            assert(x == 0);
-
-            // only letters and digits whose ascribed values are less than that
-            // of base are permitted. (C11 7.22.1.4/3)
-            r = std::from_chars(s + 2, s + sizeof(s), x, 12);
-            // If the parsed value is not in the range representable by the type
-            // of value,
-            if (!fits_in<T>(1150))
-            {
-                // value is unmodified and
-                assert(x == 0);
-                // the member ec of the return value is equal to
-                // errc::result_out_of_range
-                assert(r.ec == std::errc::result_out_of_range);
-            }
-            else
-            {
-                // Otherwise, value is set to the parsed value,
-                assert(x == 1150);
-                // and the member ec is value-initialized.
-                assert(r.ec == std::errc{});
-            }
-            assert(r.ptr == s + 5);
-        }
+      // The string has more characters than valid in an 128-bit value.
+      char s[] = "0X7BAtSGHDkEIXZgQRfYChLpOzRnM ";
+
+      // The letters from a (or A) through z (or Z) are ascribed the
+      // values 10 through 35; (C11 7.22.1.4/3)
+      r = std::from_chars(s, s + sizeof(s), x, 36);
+      assert(r.ec == std::errc::result_out_of_range);
+      // The member ptr of the return value points to the first character
+      // not matching the pattern
+      assert(r.ptr == s + sizeof(s) - 2);
+      assert(x == 1);
+
+      // no "0x" or "0X" prefix shall appear if the value of base is 16
+      r = std::from_chars(s, s + sizeof(s), x, 16);
+      assert(r.ec == std::errc{});
+      assert(r.ptr == s + 1);
+      assert(x == 0);
+
+      // only letters and digits whose ascribed values are less than that
+      // of base are permitted. (C11 7.22.1.4/3)
+      r = std::from_chars(s + 2, s + sizeof(s), x, 12);
+      // If the parsed value is not in the range representable by the type
+      // of value,
+      if (!fits_in<T>(1150)) {
+        // value is unmodified and
+        assert(x == 0);
+        // the member ec of the return value is equal to
+        // errc::result_out_of_range
+        assert(r.ec == std::errc::result_out_of_range);
+      } else {
+        // Otherwise, value is set to the parsed value,
+        assert(x == 1150);
+        // and the member ec is value-initialized.
+        assert(r.ec == std::errc{});
+      }
+      assert(r.ptr == s + 5);
     }
+  }
 };
 
 struct test_signed
 {
-    template <typename T>
-    TEST_CONSTEXPR_CXX23 void operator()()
+  template <typename T>
+  TEST_CONSTEXPR_CXX23 void operator()() {
+    std::from_chars_result r;
+    T x = 42;
+
+    {
+      // If the pattern allows for an optional sign,
+      // but the string has no digit characters following the sign,
+      char s[] = "- 9+12";
+      r        = std::from_chars(s, s + sizeof(s), x);
+      // value is unmodified,
+      assert(x == 42);
+      // no characters match the pattern.
+      assert(r.ptr == s);
+      assert(r.ec == std::errc::invalid_argument);
+    }
+
+    {
+      char s[] = "9+12";
+      r        = std::from_chars(s, s + sizeof(s), x);
+      assert(r.ec == std::errc{});
+      // The member ptr of the return value points to the first character
+      // not matching the pattern,
+      assert(r.ptr == s + 1);
+      assert(x == 9);
+    }
+
+    {
+      char s[] = "12";
+      r        = std::from_chars(s, s + 2, x);
+      assert(r.ec == std::errc{});
+      // or has the value last if all characters match.
+      assert(r.ptr == s + 2);
+      assert(x == 12);
+    }
+
     {
-        std::from_chars_result r;
-        T x = 42;
-
-        {
-            // If the pattern allows for an optional sign,
-            // but the string has no digit characters following the sign,
-            char s[] = "- 9+12";
-            r = std::from_chars(s, s + sizeof(s), x);
-            // value is unmodified,
-            assert(x == 42);
-            // no characters match the pattern.
-            assert(r.ptr == s);
-            assert(r.ec == std::errc::invalid_argument);
-        }
-
-        {
-            char s[] = "9+12";
-            r = std::from_chars(s, s + sizeof(s), x);
-            assert(r.ec == std::errc{});
-            // The member ptr of the return value points to the first character
-            // not matching the pattern,
-            assert(r.ptr == s + 1);
-            assert(x == 9);
-        }
-
-        {
-            char s[] = "12";
-            r = std::from_chars(s, s + 2, x);
-            assert(r.ec == std::errc{});
-            // or has the value last if all characters match.
-            assert(r.ptr == s + 2);
-            assert(x == 12);
-        }
-
-        {
-            // '-' is the only sign that may appear
-            char s[] = "+30";
-            // If no characters match the pattern,
-            r = std::from_chars(s, s + sizeof(s), x);
-            // value is unmodified,
-            assert(x == 12);
-            // the member ptr of the return value is first and
-            assert(r.ptr == s);
-            // the member ec is equal to errc::invalid_argument.
-            assert(r.ec == std::errc::invalid_argument);
-        }
+      // '-' is the only sign that may appear
+      char s[] = "+30";
+      // If no characters match the pattern,
+      r = std::from_chars(s, s + sizeof(s), x);
+      // value is unmodified,
+      assert(x == 12);
+      // the member ptr of the return value is first and
+      assert(r.ptr == s);
+      // the member ec is equal to errc::invalid_argument.
+      assert(r.ec == std::errc::invalid_argument);
     }
+  }
 };
 
 TEST_CONSTEXPR_CXX23 bool test()
diff --git a/libcxx/test/support/charconv_test_helpers.h b/libcxx/test/support/charconv_test_helpers.h
index 51c579e79..91313e66f 100644
--- a/libcxx/test/support/charconv_test_helpers.h
+++ b/libcxx/test/support/charconv_test_helpers.h
@@ -20,45 +20,33 @@
 #endif
 
 template <typename To, typename From>
-constexpr auto
-is_non_narrowing(From a) -> decltype(To{a}, std::true_type())
-{
-    return {};
+constexpr auto is_non_narrowing(From a) -> decltype(To{a}, std::true_type()) {
+  return {};
 }
 
 template <typename To>
-constexpr auto
-is_non_narrowing(...) -> std::false_type
-{
-    return {};
+constexpr auto is_non_narrowing(...) -> std::false_type {
+  return {};
 }
 
 template <typename X, typename T>
-constexpr bool
-_fits_in(T, std::true_type /* non-narrowing*/, ...)
-{
-    return true;
+constexpr bool _fits_in(T, std::true_type /* non-narrowing*/, ...) {
+  return true;
 }
 
 template <typename X, typename T, typename xl = std::numeric_limits<X>>
-constexpr bool
-_fits_in(T v, std::false_type, std::true_type /* T signed*/, std::true_type /* X signed */)
-{
-    return xl::lowest() <= v && v <= (xl::max)();
+constexpr bool _fits_in(T v, std::false_type, std::true_type /* T signed*/, std::true_type /* X signed */) {
+  return xl::lowest() <= v && v <= (xl::max)();
 }
 
 template <typename X, typename T, typename xl = std::numeric_limits<X>>
-constexpr bool
-_fits_in(T v, std::false_type, std::true_type /* T signed */, std::false_type /* X unsigned*/)
-{
-    return 0 <= v && typename std::make_unsigned<T>::type(v) <= (xl::max)();
+constexpr bool _fits_in(T v, std::false_type, std::true_type /* T signed */, std::false_type /* X unsigned*/) {
+  return 0 <= v && typename std::make_unsigned<T>::type(v) <= (xl::max)();
 }
 
 template <typename X, typename T, typename xl = std::numeric_limits<X>>
-constexpr bool
-_fits_in(T v, std::false_type, std::false_type /* T unsigned */, ...)
-{
-    return v <= typename std::make_unsigned<X>::type((xl::max)());
+constexpr bool _fits_in(T v, std::false_type, std::false_type /* T unsigned */, ...) {
+  return v <= typename std::make_unsigned<X>::type((xl::max)());
 }
 
 template <typename X, typename T>

@philnik777
philnik777 force-pushed the refactor_charconv_tests branch from f1139ec to bccfd44 Compare September 30, 2026 12:31
@philnik777 philnik777 self-assigned this Sep 30, 2026
@ldionne

ldionne commented Sep 30, 2026

Copy link
Copy Markdown
Member

I think we should rebase this on top of #225801 once it lands.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants