[libcxx-commits] [libcxx] [libc++] Refactor the <charconv> tests (PR #227611)
via libcxx-commits
libcxx-commits at lists.llvm.org
Wed Sep 30 02:00:53 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-libcxx
Author: Nikolas Klauser (philnik777)
<details>
<summary>Changes</summary>
---
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
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]
``````````
</details>
https://github.com/llvm/llvm-project/pull/227611
More information about the libcxx-commits
mailing list