[libcxx-commits] [libcxx] [libc++] Suppress unsigned-integer-overflow warning in <charconv> (PR #225801)
Louis Dionne via libcxx-commits
libcxx-commits at lists.llvm.org
Fri Oct 2 07:28:18 PDT 2026
https://github.com/ldionne updated https://github.com/llvm/llvm-project/pull/225801
>From c21d7876e49900ea78524e2617a0f9a9e987f9e6 Mon Sep 17 00:00:00 2001
From: Henri Chataing <henrichataing at google.com>
Date: Wed, 30 Sep 2026 12:17:39 +0000
Subject: [PATCH 1/3] [libc++] Update charconv tests to use type_algorithms.h
---
.../floating_point.pass.cpp | 24 +-
.../charconv.from.chars/integral.pass.cpp | 213 +++++----
.../integral.roundtrip.pass.cpp | 96 ++---
.../charconv.to.chars/integral.pass.cpp | 408 +++++++++---------
libcxx/test/support/charconv_test_helpers.h | 227 ++++------
5 files changed, 440 insertions(+), 528 deletions(-)
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 a02c7ac466f046..512bda55c7966b 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) {
@@ -325,8 +326,8 @@ void test_fmt_independent(std::chars_format fmt) {
}
}
-template <class F>
struct test_basics {
+ template <class F>
void operator()() {
for (auto fmt : {std::chars_format::scientific,
std::chars_format::fixed,
@@ -335,8 +336,8 @@ struct test_basics {
}
};
-template <class F>
struct test_fixed {
+ template <class F>
void operator()() {
std::from_chars_result r;
F x = 0.25;
@@ -600,8 +601,8 @@ struct test_fixed {
}
};
-template <class F>
struct test_scientific {
+ template <class F>
void operator()() {
std::from_chars_result r;
F x = 0.25;
@@ -874,8 +875,8 @@ struct test_scientific {
}
};
-template <class F>
struct test_general {
+ template <class F>
void operator()() {
std::from_chars_result r;
F x = 0.25;
@@ -1194,8 +1195,8 @@ struct test_general {
}
};
-template <class F>
struct test_hex {
+ template <class F>
void operator()() {
std::from_chars_result r;
F x = 0.25;
@@ -1547,12 +1548,13 @@ void test_random_errors() {
}
int main(int, char**) {
- run<test_basics>(all_floats);
- run<test_scientific>(all_floats);
- run<test_fixed>(all_floats);
- run<test_general>(all_floats);
+ using all_floats = types::type_list<float, double>; // TODO: Add long double
+ types::for_each(all_floats(), test_basics());
+ types::for_each(all_floats(), test_scientific());
+ types::for_each(all_floats(), test_fixed());
+ types::for_each(all_floats(), test_general());
- run<test_hex>(all_floats);
+ types::for_each(all_floats(), test_hex());
test_random_errors();
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 4708da4c38b9b6..f1fe8af9cc424b 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
@@ -19,130 +19,125 @@
#include "test_macros.h"
#include "charconv_test_helpers.h"
-template <typename T>
struct test_basics
{
- 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);
}
+ }
};
-template <typename T>
struct test_signed
{
- 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()
{
- run<test_basics>(integrals);
- run<test_signed>(all_signed);
+ types::for_each(integrals(), test_basics());
+ types::for_each(types::signed_integer_types(), test_signed());
- return true;
+ return true;
}
int main(int, char**) {
diff --git a/libcxx/test/std/utilities/charconv/charconv.from.chars/integral.roundtrip.pass.cpp b/libcxx/test/std/utilities/charconv/charconv.from.chars/integral.roundtrip.pass.cpp
index b1f2c77b34f8af..a4f1a467f55ba8 100644
--- a/libcxx/test/std/utilities/charconv/charconv.from.chars/integral.roundtrip.pass.cpp
+++ b/libcxx/test/std/utilities/charconv/charconv.from.chars/integral.roundtrip.pass.cpp
@@ -21,68 +21,58 @@
#include "test_macros.h"
#include "charconv_test_helpers.h"
-template <typename T>
-struct test_basics : roundtrip_test_base<T>
-{
- using roundtrip_test_base<T>::test;
-
- TEST_CONSTEXPR_CXX23 void operator()()
- {
- test(0);
- test(42);
- test(32768);
- test(0, 10);
- test(42, 10);
- test(32768, 10);
- test(0xf, 16);
- test(0xdeadbeaf, 16);
- test(0755, 8);
-
- for (int b = 2; b < 37; ++b)
- {
- using xl = std::numeric_limits<T>;
-
- test(1, b);
- test(-1, b);
- test(xl::lowest(), b);
- test((xl::max)(), b);
- test((xl::max)() / 2, b);
- }
+struct test_basics : roundtrip_test_base {
+ template <typename T>
+ TEST_CONSTEXPR_CXX23 void operator()() {
+ test<T>(0);
+ test<T>(42);
+ test<T>(32768);
+ test<T>(0, 10);
+ test<T>(42, 10);
+ test<T>(32768, 10);
+ test<T>(0xf, 16);
+ test<T>(0xdeadbeaf, 16);
+ test<T>(0755, 8);
+
+ for (int b = 2; b < 37; ++b) {
+ using xl = std::numeric_limits<T>;
+
+ test<T>(1, b);
+ test<T>(-1, b);
+ test<T>(xl::lowest(), b);
+ test<T>((xl::max)(), b);
+ test<T>((xl::max)() / 2, b);
}
+ }
};
-template <typename T>
-struct test_signed : roundtrip_test_base<T>
-{
- using roundtrip_test_base<T>::test;
-
- TEST_CONSTEXPR_CXX23 void operator()()
- {
- test(-1);
- test(-12);
- test(-1, 10);
- test(-12, 10);
- test(-21734634, 10);
- test(-2647, 2);
- test(-0xcc1, 16);
-
- for (int b = 2; b < 37; ++b)
- {
- using xl = std::numeric_limits<T>;
-
- test(0, b);
- test(xl::lowest(), b);
- test((xl::max)(), b);
- }
+struct test_signed : roundtrip_test_base {
+ template <typename T>
+ TEST_CONSTEXPR_CXX23 void operator()() {
+ test<T>(-1);
+ test<T>(-12);
+ test<T>(-1, 10);
+ test<T>(-12, 10);
+ test<T>(-21734634, 10);
+ test<T>(-2647, 2);
+ test<T>(-0xcc1, 16);
+
+ for (int b = 2; b < 37; ++b) {
+ using xl = std::numeric_limits<T>;
+
+ test<T>(0, b);
+ test<T>(xl::lowest(), b);
+ test<T>((xl::max)(), b);
}
+ }
};
TEST_CONSTEXPR_CXX23 bool test()
{
- run<test_basics>(integrals);
- run<test_signed>(all_signed);
+ types::for_each(integrals(), test_basics());
+ types::for_each(types::signed_integer_types(), test_signed());
- return true;
+ return true;
}
int main(int, char**) {
diff --git a/libcxx/test/std/utilities/charconv/charconv.to.chars/integral.pass.cpp b/libcxx/test/std/utilities/charconv/charconv.to.chars/integral.pass.cpp
index e89b340bdfcbe9..d9291140586c77 100644
--- a/libcxx/test/std/utilities/charconv/charconv.to.chars/integral.pass.cpp
+++ b/libcxx/test/std/utilities/charconv/charconv.to.chars/integral.pass.cpp
@@ -51,254 +51,244 @@ TEST_CONSTEXPR_CXX23 __int128_t make_i128(__int128_t a, __int128_t b, std::int64
}
#endif
-template <typename T>
-struct test_basics : to_chars_test_base<T>
-{
- using to_chars_test_base<T>::test;
- using to_chars_test_base<T>::test_value;
-
- TEST_CONSTEXPR_CXX23 void operator()()
- {
- test(0, "0");
- test(42, "42");
- test(32768, "32768");
- test(0, "0", 10);
- test(42, "42", 10);
- test(32768, "32768", 10);
- test(0xf, "f", 16);
- test(0xdeadbeaf, "deadbeaf", 16);
- test(0755, "755", 8);
+struct test_basics : to_chars_test_base {
+ template <typename T>
+ TEST_CONSTEXPR_CXX23 void operator()() {
+ test<T>(0, "0");
+ test<T>(42, "42");
+ test<T>(32768, "32768");
+ test<T>(0, "0", 10);
+ test<T>(42, "42", 10);
+ test<T>(32768, "32768", 10);
+ test<T>(0xf, "f", 16);
+ test<T>(0xdeadbeaf, "deadbeaf", 16);
+ test<T>(0755, "755", 8);
- // Test each len till len of UINT64_MAX = 20 because to_chars algorithm
- // makes branches based on decimal digits count in the value string
- // representation.
- // Test driver automatically skips values not fitting into source type.
- test(1UL, "1");
- test(12UL, "12");
- test(123UL, "123");
- test(1234UL, "1234");
- test(12345UL, "12345");
- test(123456UL, "123456");
- test(1234567UL, "1234567");
- test(12345678UL, "12345678");
- test(123456789UL, "123456789");
- test(1234567890UL, "1234567890");
- test(12345678901UL, "12345678901");
- test(123456789012UL, "123456789012");
- test(1234567890123UL, "1234567890123");
- test(12345678901234UL, "12345678901234");
- test(123456789012345UL, "123456789012345");
- test(1234567890123456UL, "1234567890123456");
- test(12345678901234567UL, "12345678901234567");
- test(123456789012345678UL, "123456789012345678");
- test(1234567890123456789UL, "1234567890123456789");
- test(12345678901234567890UL, "12345678901234567890");
+ // Test each len till len of UINT64_MAX = 20 because to_chars algorithm
+ // makes branches based on decimal digits count in the value string
+ // representation.
+ // Test driver automatically skips values not fitting into source type.
+ test<T>(1UL, "1");
+ test<T>(12UL, "12");
+ test<T>(123UL, "123");
+ test<T>(1234UL, "1234");
+ test<T>(12345UL, "12345");
+ test<T>(123456UL, "123456");
+ test<T>(1234567UL, "1234567");
+ test<T>(12345678UL, "12345678");
+ test<T>(123456789UL, "123456789");
+ test<T>(1234567890UL, "1234567890");
+ test<T>(12345678901UL, "12345678901");
+ test<T>(123456789012UL, "123456789012");
+ test<T>(1234567890123UL, "1234567890123");
+ test<T>(12345678901234UL, "12345678901234");
+ test<T>(123456789012345UL, "123456789012345");
+ test<T>(1234567890123456UL, "1234567890123456");
+ test<T>(12345678901234567UL, "12345678901234567");
+ test<T>(123456789012345678UL, "123456789012345678");
+ test<T>(1234567890123456789UL, "1234567890123456789");
+ test<T>(12345678901234567890UL, "12345678901234567890");
#ifndef TEST_HAS_NO_INT128
- test(make_u128(12UL, 3456789012345678901UL), "123456789012345678901");
- test(make_u128(123UL, 4567890123456789012UL), "1234567890123456789012");
- test(make_u128(1234UL, 5678901234567890123UL), "12345678901234567890123");
- test(make_u128(12345UL, 6789012345678901234UL), "123456789012345678901234");
- test(make_u128(123456UL, 7890123456789012345UL), "1234567890123456789012345");
- test(make_u128(1234567UL, 8901234567890123456UL), "12345678901234567890123456");
- test(make_u128(12345678UL, 9012345678901234567UL), "123456789012345678901234567");
- test(make_u128(123456789UL, 123456789012345678UL), "1234567890123456789012345678");
- test(make_u128(123UL, 4567890123456UL, 7890123456789UL), "12345678901234567890123456789");
- test(make_u128(1234UL, 5678901234567UL, 8901234567890UL), "123456789012345678901234567890");
- test(make_u128(12345UL, 6789012345678UL, 9012345678901UL), "1234567890123456789012345678901");
- test(make_u128(123456UL, 7890123456789UL, 123456789012UL), "12345678901234567890123456789012");
- test(make_u128(1234567UL, 8901234567890UL, 1234567890123UL), "123456789012345678901234567890123");
- test(make_u128(12345678UL, 9012345678901UL, 2345678901234UL), "1234567890123456789012345678901234");
- test(make_u128(123456789UL, 123456789012UL, 3456789012345UL), "12345678901234567890123456789012345");
- test(make_u128(1234567890UL, 1234567890123UL, 4567890123456UL), "123456789012345678901234567890123456");
- test(make_u128(12345678901UL, 2345678901234UL, 5678901234567UL), "1234567890123456789012345678901234567");
- test(make_u128(123456789012UL, 3456789012345UL, 6789012345678UL), "12345678901234567890123456789012345678");
- test(make_u128(1234567890123UL, 4567890123456UL, 7890123456789UL), "123456789012345678901234567890123456789");
+ test<T>(make_u128(12UL, 3456789012345678901UL), "123456789012345678901");
+ test<T>(make_u128(123UL, 4567890123456789012UL), "1234567890123456789012");
+ test<T>(make_u128(1234UL, 5678901234567890123UL), "12345678901234567890123");
+ test<T>(make_u128(12345UL, 6789012345678901234UL), "123456789012345678901234");
+ test<T>(make_u128(123456UL, 7890123456789012345UL), "1234567890123456789012345");
+ test<T>(make_u128(1234567UL, 8901234567890123456UL), "12345678901234567890123456");
+ test<T>(make_u128(12345678UL, 9012345678901234567UL), "123456789012345678901234567");
+ test<T>(make_u128(123456789UL, 123456789012345678UL), "1234567890123456789012345678");
+ test<T>(make_u128(123UL, 4567890123456UL, 7890123456789UL), "12345678901234567890123456789");
+ test<T>(make_u128(1234UL, 5678901234567UL, 8901234567890UL), "123456789012345678901234567890");
+ test<T>(make_u128(12345UL, 6789012345678UL, 9012345678901UL), "1234567890123456789012345678901");
+ test<T>(make_u128(123456UL, 7890123456789UL, 123456789012UL), "12345678901234567890123456789012");
+ test<T>(make_u128(1234567UL, 8901234567890UL, 1234567890123UL), "123456789012345678901234567890123");
+ test<T>(make_u128(12345678UL, 9012345678901UL, 2345678901234UL), "1234567890123456789012345678901234");
+ test<T>(make_u128(123456789UL, 123456789012UL, 3456789012345UL), "12345678901234567890123456789012345");
+ test<T>(make_u128(1234567890UL, 1234567890123UL, 4567890123456UL), "123456789012345678901234567890123456");
+ test<T>(make_u128(12345678901UL, 2345678901234UL, 5678901234567UL), "1234567890123456789012345678901234567");
+ test<T>(make_u128(123456789012UL, 3456789012345UL, 6789012345678UL), "12345678901234567890123456789012345678");
+ test<T>(make_u128(1234567890123UL, 4567890123456UL, 7890123456789UL), "123456789012345678901234567890123456789");
#endif
// Test special cases with zeros inside a value string representation,
// to_chars algorithm processes them in a special way and should not
// skip trailing zeros
// Test driver automatically skips values not fitting into source type.
- test(0UL, "0");
- test(10UL, "10");
- test(100UL, "100");
- test(1000UL, "1000");
- test(10000UL, "10000");
- test(100000UL, "100000");
- test(1000000UL, "1000000");
- test(10000000UL, "10000000");
- test(100000000UL, "100000000");
- test(1000000000UL, "1000000000");
- test(10000000000UL, "10000000000");
- test(100000000000UL, "100000000000");
- test(1000000000000UL, "1000000000000");
- test(10000000000000UL, "10000000000000");
- test(100000000000000UL, "100000000000000");
- test(1000000000000000UL, "1000000000000000");
- test(10000000000000000UL, "10000000000000000");
- test(100000000000000000UL, "100000000000000000");
- test(1000000000000000000UL, "1000000000000000000");
- test(10000000000000000000UL, "10000000000000000000");
+ test<T>(0UL, "0");
+ test<T>(10UL, "10");
+ test<T>(100UL, "100");
+ test<T>(1000UL, "1000");
+ test<T>(10000UL, "10000");
+ test<T>(100000UL, "100000");
+ test<T>(1000000UL, "1000000");
+ test<T>(10000000UL, "10000000");
+ test<T>(100000000UL, "100000000");
+ test<T>(1000000000UL, "1000000000");
+ test<T>(10000000000UL, "10000000000");
+ test<T>(100000000000UL, "100000000000");
+ test<T>(1000000000000UL, "1000000000000");
+ test<T>(10000000000000UL, "10000000000000");
+ test<T>(100000000000000UL, "100000000000000");
+ test<T>(1000000000000000UL, "1000000000000000");
+ test<T>(10000000000000000UL, "10000000000000000");
+ test<T>(100000000000000000UL, "100000000000000000");
+ test<T>(1000000000000000000UL, "1000000000000000000");
+ test<T>(10000000000000000000UL, "10000000000000000000");
#ifndef TEST_HAS_NO_INT128
- test(make_u128(10UL, 0), "100000000000000000000");
- test(make_u128(100UL, 0), "1000000000000000000000");
- test(make_u128(1000UL, 0), "10000000000000000000000");
- test(make_u128(10000UL, 0), "100000000000000000000000");
- test(make_u128(100000UL, 0), "1000000000000000000000000");
- test(make_u128(1000000UL, 0), "10000000000000000000000000");
- test(make_u128(10000000UL, 0), "100000000000000000000000000");
- test(make_u128(100000000UL, 0), "1000000000000000000000000000");
- test(make_u128(100UL, 0, 0), "10000000000000000000000000000");
- test(make_u128(1000UL, 0, 0), "100000000000000000000000000000");
- test(make_u128(10000UL, 0, 0), "1000000000000000000000000000000");
- test(make_u128(100000UL, 0, 0), "10000000000000000000000000000000");
- test(make_u128(1000000UL, 0, 0), "100000000000000000000000000000000");
- test(make_u128(10000000UL, 0, 0), "1000000000000000000000000000000000");
- test(make_u128(100000000UL, 0, 0), "10000000000000000000000000000000000");
- test(make_u128(1000000000UL, 0, 0), "100000000000000000000000000000000000");
- test(make_u128(10000000000UL, 0, 0), "1000000000000000000000000000000000000");
- test(make_u128(100000000000UL, 0, 0), "10000000000000000000000000000000000000");
- test(make_u128(1000000000000UL, 0, 0), "100000000000000000000000000000000000000");
+ test<T>(make_u128(10UL, 0), "100000000000000000000");
+ test<T>(make_u128(100UL, 0), "1000000000000000000000");
+ test<T>(make_u128(1000UL, 0), "10000000000000000000000");
+ test<T>(make_u128(10000UL, 0), "100000000000000000000000");
+ test<T>(make_u128(100000UL, 0), "1000000000000000000000000");
+ test<T>(make_u128(1000000UL, 0), "10000000000000000000000000");
+ test<T>(make_u128(10000000UL, 0), "100000000000000000000000000");
+ test<T>(make_u128(100000000UL, 0), "1000000000000000000000000000");
+ test<T>(make_u128(100UL, 0, 0), "10000000000000000000000000000");
+ test<T>(make_u128(1000UL, 0, 0), "100000000000000000000000000000");
+ test<T>(make_u128(10000UL, 0, 0), "1000000000000000000000000000000");
+ test<T>(make_u128(100000UL, 0, 0), "10000000000000000000000000000000");
+ test<T>(make_u128(1000000UL, 0, 0), "100000000000000000000000000000000");
+ test<T>(make_u128(10000000UL, 0, 0), "1000000000000000000000000000000000");
+ test<T>(make_u128(100000000UL, 0, 0), "10000000000000000000000000000000000");
+ test<T>(make_u128(1000000000UL, 0, 0), "100000000000000000000000000000000000");
+ test<T>(make_u128(10000000000UL, 0, 0), "1000000000000000000000000000000000000");
+ test<T>(make_u128(100000000000UL, 0, 0), "10000000000000000000000000000000000000");
+ test<T>(make_u128(1000000000000UL, 0, 0), "100000000000000000000000000000000000000");
#endif
for (int b = 2; b < 37; ++b)
{
using xl = std::numeric_limits<T>;
- test_value(1, b);
- test_value(xl::lowest(), b);
- test_value((xl::max)(), b);
- test_value((xl::max)() / 2, b);
+ test_value<T>(1, b);
+ test_value<T>(xl::lowest(), b);
+ test_value<T>((xl::max)(), b);
+ test_value<T>((xl::max)() / 2, b);
}
- }
+ }
};
-template <typename T>
-struct test_signed : to_chars_test_base<T>
-{
- using to_chars_test_base<T>::test;
- using to_chars_test_base<T>::test_value;
-
- TEST_CONSTEXPR_CXX23 void operator()()
- {
- test(-1, "-1");
- test(-12, "-12");
- test(-1, "-1", 10);
- test(-12, "-12", 10);
- test(-21734634, "-21734634", 10);
- test(-2647, "-101001010111", 2);
- test(-0xcc1, "-cc1", 16);
+struct test_signed : to_chars_test_base {
+ template <typename T>
+ TEST_CONSTEXPR_CXX23 void operator()() {
+ test<T>(-1, "-1");
+ test<T>(-12, "-12");
+ test<T>(-1, "-1", 10);
+ test<T>(-12, "-12", 10);
+ test<T>(-21734634, "-21734634", 10);
+ test<T>(-2647, "-101001010111", 2);
+ test<T>(-0xcc1, "-cc1", 16);
- // Test each len till len of INT64_MAX = 19 because to_chars algorithm
- // makes branches based on decimal digits count in the value string
- // representation.
- // Test driver automatically skips values not fitting into source type.
- test(-1L, "-1");
- test(-12L, "-12");
- test(-123L, "-123");
- test(-1234L, "-1234");
- test(-12345L, "-12345");
- test(-123456L, "-123456");
- test(-1234567L, "-1234567");
- test(-12345678L, "-12345678");
- test(-123456789L, "-123456789");
- test(-1234567890L, "-1234567890");
- test(-12345678901L, "-12345678901");
- test(-123456789012L, "-123456789012");
- test(-1234567890123L, "-1234567890123");
- test(-12345678901234L, "-12345678901234");
- test(-123456789012345L, "-123456789012345");
- test(-1234567890123456L, "-1234567890123456");
- test(-12345678901234567L, "-12345678901234567");
- test(-123456789012345678L, "-123456789012345678");
- test(-1234567890123456789L, "-1234567890123456789");
+ // Test each len till len of INT64_MAX = 19 because to_chars algorithm
+ // makes branches based on decimal digits count in the value string
+ // representation.
+ // Test driver automatically skips values not fitting into source type.
+ test<T>(-1L, "-1");
+ test<T>(-12L, "-12");
+ test<T>(-123L, "-123");
+ test<T>(-1234L, "-1234");
+ test<T>(-12345L, "-12345");
+ test<T>(-123456L, "-123456");
+ test<T>(-1234567L, "-1234567");
+ test<T>(-12345678L, "-12345678");
+ test<T>(-123456789L, "-123456789");
+ test<T>(-1234567890L, "-1234567890");
+ test<T>(-12345678901L, "-12345678901");
+ test<T>(-123456789012L, "-123456789012");
+ test<T>(-1234567890123L, "-1234567890123");
+ test<T>(-12345678901234L, "-12345678901234");
+ test<T>(-123456789012345L, "-123456789012345");
+ test<T>(-1234567890123456L, "-1234567890123456");
+ test<T>(-12345678901234567L, "-12345678901234567");
+ test<T>(-123456789012345678L, "-123456789012345678");
+ test<T>(-1234567890123456789L, "-1234567890123456789");
#ifndef TEST_HAS_NO_INT128
- test(make_i128(-1L, 2345678901234567890L), "-12345678901234567890");
- test(make_i128(-12L, 3456789012345678901L), "-123456789012345678901");
- test(make_i128(-123L, 4567890123456789012L), "-1234567890123456789012");
- test(make_i128(-1234L, 5678901234567890123L), "-12345678901234567890123");
- test(make_i128(-12345L, 6789012345678901234L), "-123456789012345678901234");
- test(make_i128(-123456L, 7890123456789012345L), "-1234567890123456789012345");
- test(make_i128(-1234567L, 8901234567890123456L), "-12345678901234567890123456");
- test(make_i128(-12345678L, 9012345678901234567L), "-123456789012345678901234567");
- test(make_i128(-123456789L, 123456789012345678L), "-1234567890123456789012345678");
- test(make_i128(-1234567890L, 1234567890123456789L), "-12345678901234567890123456789");
- test(make_i128(-123L, 4567890123456L, 7890123456789L), "-12345678901234567890123456789");
- test(make_i128(-1234L, 5678901234567L, 8901234567890L), "-123456789012345678901234567890");
- test(make_i128(-12345L, 6789012345678L, 9012345678901L), "-1234567890123456789012345678901");
- test(make_i128(-123456L, 7890123456789L, 123456789012L), "-12345678901234567890123456789012");
- test(make_i128(-1234567L, 8901234567890L, 1234567890123L), "-123456789012345678901234567890123");
- test(make_i128(-12345678L, 9012345678901L, 2345678901234L), "-1234567890123456789012345678901234");
- test(make_i128(-123456789L, 123456789012L, 3456789012345L), "-12345678901234567890123456789012345");
- test(make_i128(-1234567890L, 1234567890123L, 4567890123456L), "-123456789012345678901234567890123456");
- test(make_i128(-12345678901L, 2345678901234L, 5678901234567L), "-1234567890123456789012345678901234567");
- test(make_i128(-123456789012L, 3456789012345L, 6789012345678L), "-12345678901234567890123456789012345678");
- test(make_i128(-1234567890123L, 4567890123456L, 7890123456789L), "-123456789012345678901234567890123456789");
+ test<T>(make_i128(-1L, 2345678901234567890L), "-12345678901234567890");
+ test<T>(make_i128(-12L, 3456789012345678901L), "-123456789012345678901");
+ test<T>(make_i128(-123L, 4567890123456789012L), "-1234567890123456789012");
+ test<T>(make_i128(-1234L, 5678901234567890123L), "-12345678901234567890123");
+ test<T>(make_i128(-12345L, 6789012345678901234L), "-123456789012345678901234");
+ test<T>(make_i128(-123456L, 7890123456789012345L), "-1234567890123456789012345");
+ test<T>(make_i128(-1234567L, 8901234567890123456L), "-12345678901234567890123456");
+ test<T>(make_i128(-12345678L, 9012345678901234567L), "-123456789012345678901234567");
+ test<T>(make_i128(-123456789L, 123456789012345678L), "-1234567890123456789012345678");
+ test<T>(make_i128(-1234567890L, 1234567890123456789L), "-12345678901234567890123456789");
+ test<T>(make_i128(-123L, 4567890123456L, 7890123456789L), "-12345678901234567890123456789");
+ test<T>(make_i128(-1234L, 5678901234567L, 8901234567890L), "-123456789012345678901234567890");
+ test<T>(make_i128(-12345L, 6789012345678L, 9012345678901L), "-1234567890123456789012345678901");
+ test<T>(make_i128(-123456L, 7890123456789L, 123456789012L), "-12345678901234567890123456789012");
+ test<T>(make_i128(-1234567L, 8901234567890L, 1234567890123L), "-123456789012345678901234567890123");
+ test<T>(make_i128(-12345678L, 9012345678901L, 2345678901234L), "-1234567890123456789012345678901234");
+ test<T>(make_i128(-123456789L, 123456789012L, 3456789012345L), "-12345678901234567890123456789012345");
+ test<T>(make_i128(-1234567890L, 1234567890123L, 4567890123456L), "-123456789012345678901234567890123456");
+ test<T>(make_i128(-12345678901L, 2345678901234L, 5678901234567L), "-1234567890123456789012345678901234567");
+ test<T>(make_i128(-123456789012L, 3456789012345L, 6789012345678L), "-12345678901234567890123456789012345678");
+ test<T>(make_i128(-1234567890123L, 4567890123456L, 7890123456789L), "-123456789012345678901234567890123456789");
#endif
// Test special cases with zeros inside a value string representation,
// to_chars algorithm processes them in a special way and should not
// skip trailing zeros
// Test driver automatically skips values not fitting into source type.
- test(-10L, "-10");
- test(-100L, "-100");
- test(-1000L, "-1000");
- test(-10000L, "-10000");
- test(-100000L, "-100000");
- test(-1000000L, "-1000000");
- test(-10000000L, "-10000000");
- test(-100000000L, "-100000000");
- test(-1000000000L, "-1000000000");
- test(-10000000000L, "-10000000000");
- test(-100000000000L, "-100000000000");
- test(-1000000000000L, "-1000000000000");
- test(-10000000000000L, "-10000000000000");
- test(-100000000000000L, "-100000000000000");
- test(-1000000000000000L, "-1000000000000000");
- test(-10000000000000000L, "-10000000000000000");
- test(-100000000000000000L, "-100000000000000000");
- test(-1000000000000000000L, "-1000000000000000000");
+ test<T>(-10L, "-10");
+ test<T>(-100L, "-100");
+ test<T>(-1000L, "-1000");
+ test<T>(-10000L, "-10000");
+ test<T>(-100000L, "-100000");
+ test<T>(-1000000L, "-1000000");
+ test<T>(-10000000L, "-10000000");
+ test<T>(-100000000L, "-100000000");
+ test<T>(-1000000000L, "-1000000000");
+ test<T>(-10000000000L, "-10000000000");
+ test<T>(-100000000000L, "-100000000000");
+ test<T>(-1000000000000L, "-1000000000000");
+ test<T>(-10000000000000L, "-10000000000000");
+ test<T>(-100000000000000L, "-100000000000000");
+ test<T>(-1000000000000000L, "-1000000000000000");
+ test<T>(-10000000000000000L, "-10000000000000000");
+ test<T>(-100000000000000000L, "-100000000000000000");
+ test<T>(-1000000000000000000L, "-1000000000000000000");
#ifndef TEST_HAS_NO_INT128
- test(make_i128(-1L, 0L), "-10000000000000000000");
- test(make_i128(-10L, 0L), "-100000000000000000000");
- test(make_i128(-100L, 0L), "-1000000000000000000000");
- test(make_i128(-1000L, 0L), "-10000000000000000000000");
- test(make_i128(-10000L, 0L), "-100000000000000000000000");
- test(make_i128(-100000L, 0L), "-1000000000000000000000000");
- test(make_i128(-1000000L, 0L), "-10000000000000000000000000");
- test(make_i128(-10000000L, 0L), "-100000000000000000000000000");
- test(make_i128(-100000000L, 0L), "-1000000000000000000000000000");
- test(make_i128(-1000000000L, 0L), "-10000000000000000000000000000");
- test(make_i128(-100L, 0L, 0L), "-10000000000000000000000000000");
- test(make_i128(-1000L, 0L, 0L), "-100000000000000000000000000000");
- test(make_i128(-10000L, 0L, 0L), "-1000000000000000000000000000000");
- test(make_i128(-100000L, 0L, 0L), "-10000000000000000000000000000000");
- test(make_i128(-1000000L, 0L, 0L), "-100000000000000000000000000000000");
- test(make_i128(-10000000L, 0L, 0L), "-1000000000000000000000000000000000");
- test(make_i128(-100000000L, 0L, 0L), "-10000000000000000000000000000000000");
- test(make_i128(-1000000000L, 0L, 0L), "-100000000000000000000000000000000000");
- test(make_i128(-10000000000L, 0L, 0L), "-1000000000000000000000000000000000000");
- test(make_i128(-100000000000L, 0L, 0L), "-10000000000000000000000000000000000000");
- test(make_i128(-1000000000000L, 0L, 0L), "-100000000000000000000000000000000000000");
+ test<T>(make_i128(-1L, 0L), "-10000000000000000000");
+ test<T>(make_i128(-10L, 0L), "-100000000000000000000");
+ test<T>(make_i128(-100L, 0L), "-1000000000000000000000");
+ test<T>(make_i128(-1000L, 0L), "-10000000000000000000000");
+ test<T>(make_i128(-10000L, 0L), "-100000000000000000000000");
+ test<T>(make_i128(-100000L, 0L), "-1000000000000000000000000");
+ test<T>(make_i128(-1000000L, 0L), "-10000000000000000000000000");
+ test<T>(make_i128(-10000000L, 0L), "-100000000000000000000000000");
+ test<T>(make_i128(-100000000L, 0L), "-1000000000000000000000000000");
+ test<T>(make_i128(-1000000000L, 0L), "-10000000000000000000000000000");
+ test<T>(make_i128(-100L, 0L, 0L), "-10000000000000000000000000000");
+ test<T>(make_i128(-1000L, 0L, 0L), "-100000000000000000000000000000");
+ test<T>(make_i128(-10000L, 0L, 0L), "-1000000000000000000000000000000");
+ test<T>(make_i128(-100000L, 0L, 0L), "-10000000000000000000000000000000");
+ test<T>(make_i128(-1000000L, 0L, 0L), "-100000000000000000000000000000000");
+ test<T>(make_i128(-10000000L, 0L, 0L), "-1000000000000000000000000000000000");
+ test<T>(make_i128(-100000000L, 0L, 0L), "-10000000000000000000000000000000000");
+ test<T>(make_i128(-1000000000L, 0L, 0L), "-100000000000000000000000000000000000");
+ test<T>(make_i128(-10000000000L, 0L, 0L), "-1000000000000000000000000000000000000");
+ test<T>(make_i128(-100000000000L, 0L, 0L), "-10000000000000000000000000000000000000");
+ test<T>(make_i128(-1000000000000L, 0L, 0L), "-100000000000000000000000000000000000000");
#endif
for (int b = 2; b < 37; ++b)
{
using xl = std::numeric_limits<T>;
- test_value(0, b);
- test_value(xl::lowest(), b);
- test_value((xl::max)(), b);
+ test_value<T>(0, b);
+ test_value<T>(xl::lowest(), b);
+ test_value<T>((xl::max)(), b);
}
- }
+ }
};
TEST_CONSTEXPR_CXX23 bool test()
{
- run<test_basics>(integrals);
- run<test_signed>(all_signed);
+ types::for_each(integrals(), test_basics());
+ types::for_each(types::signed_integer_types(), test_signed());
- return true;
+ return true;
}
int main(int, char**)
diff --git a/libcxx/test/support/charconv_test_helpers.h b/libcxx/test/support/charconv_test_helpers.h
index fcae09478457b6..7cd14204ddb00a 100644
--- a/libcxx/test/support/charconv_test_helpers.h
+++ b/libcxx/test/support/charconv_test_helpers.h
@@ -21,6 +21,7 @@
#include <type_traits>
#include "test_macros.h"
+#include "type_algorithms.h"
#if TEST_STD_VER < 11
#error This file requires C++11
@@ -78,61 +79,58 @@ fits_in(T v)
return _fits_in<X>(v, is_non_narrowing<X>(v), std::is_signed<T>(), std::is_signed<X>());
}
-template <typename X>
struct to_chars_test_base
{
- template <typename T, std::size_t N, typename... Ts>
- TEST_CONSTEXPR_CXX23 void test(T v, char const (&expect)[N], Ts... args)
- {
- std::to_chars_result r;
-
- constexpr std::size_t len = N - 1;
- static_assert(len > 0, "expected output won't be empty");
-
- if (!fits_in<X>(v))
- return;
-
- r = std::to_chars(buf, buf + len - 1, X(v), args...);
- assert(r.ptr == buf + len - 1);
- assert(r.ec == std::errc::value_too_large);
-
- r = std::to_chars(buf, buf + sizeof(buf), X(v), args...);
- assert(r.ptr == buf + len);
- assert(r.ec == std::errc{});
- assert(std::equal(buf, buf + len, expect));
- }
-
- template <typename... Ts>
- TEST_CONSTEXPR_CXX23 void test_value(X v, Ts... args)
- {
- std::to_chars_result r;
-
- // Poison the buffer for testing whether a successful std::to_chars
- // doesn't modify data beyond r.ptr. Use unsigned values to avoid
- // overflowing char when it's signed.
- std::iota(buf, buf + sizeof(buf), static_cast<unsigned char>(1));
- r = std::to_chars(buf, buf + sizeof(buf), v, args...);
- assert(r.ec == std::errc{});
- for (std::size_t i = r.ptr - buf; i < sizeof(buf); ++i)
- assert(static_cast<unsigned char>(buf[i]) == i + 1);
- *r.ptr = '\0';
+ template <typename X, typename T, std::size_t N, typename... Ts>
+ TEST_CONSTEXPR_CXX23 void test(T v, char const (&expect)[N], Ts... args) {
+ std::to_chars_result r;
+
+ constexpr std::size_t len = N - 1;
+ static_assert(len > 0, "expected output won't be empty");
+
+ if (!fits_in<X>(v))
+ return;
+
+ r = std::to_chars(buf, buf + len - 1, X(v), args...);
+ assert(r.ptr == buf + len - 1);
+ assert(r.ec == std::errc::value_too_large);
+
+ r = std::to_chars(buf, buf + sizeof(buf), X(v), args...);
+ assert(r.ptr == buf + len);
+ assert(r.ec == std::errc{});
+ assert(std::equal(buf, buf + len, expect));
+ }
+
+ template <typename X, typename... Ts>
+ TEST_CONSTEXPR_CXX23 void test_value(X v, Ts... args) {
+ std::to_chars_result r;
+
+ // Poison the buffer for testing whether a successful std::to_chars
+ // doesn't modify data beyond r.ptr. Use unsigned values to avoid
+ // overflowing char when it's signed.
+ std::iota(buf, buf + sizeof(buf), static_cast<unsigned char>(1));
+ r = std::to_chars(buf, buf + sizeof(buf), v, args...);
+ assert(r.ec == std::errc{});
+ for (std::size_t i = r.ptr - buf; i < sizeof(buf); ++i)
+ assert(static_cast<unsigned char>(buf[i]) == i + 1);
+ *r.ptr = '\0';
#ifndef TEST_HAS_NO_INT128
if (sizeof(X) == sizeof(__int128_t)) {
- auto a = fromchars128_impl(buf, r.ptr, args...);
- assert(v == a);
+ auto a = fromchars128_impl<X>(buf, r.ptr, args...);
+ assert(v == a);
} else
#endif
{
- auto a = fromchars_impl(buf, r.ptr, args...);
- assert(v == a);
+ auto a = fromchars_impl<X>(buf, r.ptr, args...);
+ assert(v == a);
}
auto ep = r.ptr - 1;
r = std::to_chars(buf, ep, v, args...);
assert(r.ptr == ep);
assert(r.ec == std::errc::value_too_large);
- }
+ }
private:
static TEST_CONSTEXPR_CXX23 long long fromchars_impl(char const* p, char const* ep, int base, true_type)
@@ -202,129 +200,66 @@ struct to_chars_test_base
return r;
}
+ template <typename X>
static TEST_CONSTEXPR_CXX23 auto fromchars128_impl(char const* p, char const* ep, int base = 10)
- -> decltype(fromchars128_impl(p, ep, base, std::is_signed<X>()))
- {
- return fromchars128_impl(p, ep, base, std::is_signed<X>());
+ -> decltype(fromchars128_impl(p, ep, base, std::is_signed<X>())) {
+ return fromchars128_impl(p, ep, base, std::is_signed<X>());
}
#endif
+ template <typename X>
static TEST_CONSTEXPR_CXX23 auto fromchars_impl(char const* p, char const* ep, int base = 10)
- -> decltype(fromchars_impl(p, ep, base, std::is_signed<X>()))
- {
- return fromchars_impl(p, ep, base, std::is_signed<X>());
+ -> decltype(fromchars_impl(p, ep, base, std::is_signed<X>())) {
+ return fromchars_impl(p, ep, base, std::is_signed<X>());
}
char buf[150];
};
-template <typename X>
struct roundtrip_test_base
{
- template <typename T, typename... Ts>
- TEST_CONSTEXPR_CXX23 void test(T v, Ts... args)
- {
- std::from_chars_result r2;
- std::to_chars_result r;
- X x = 0xc;
-
- if (fits_in<X>(v))
- {
- r = std::to_chars(buf, buf + sizeof(buf), v, args...);
- assert(r.ec == std::errc{});
-
- r2 = std::from_chars(buf, r.ptr, x, args...);
- assert(r2.ptr == r.ptr);
- assert(x == X(v));
- }
- else
- {
- r = std::to_chars(buf, buf + sizeof(buf), v, args...);
- assert(r.ec == std::errc{});
-
- r2 = std::from_chars(buf, r.ptr, x, args...);
-
- TEST_DIAGNOSTIC_PUSH
- TEST_MSVC_DIAGNOSTIC_IGNORED(4127) // conditional expression is constant
-
- if (std::is_signed<T>::value && v < 0 && std::is_unsigned<X>::value)
- {
- assert(x == 0xc);
- assert(r2.ptr == buf);
- assert(r2.ec == std::errc::invalid_argument);
- }
- else
- {
- assert(x == 0xc);
- assert(r2.ptr == r.ptr);
- assert(r2.ec == std::errc::result_out_of_range);
- }
-
- TEST_DIAGNOSTIC_POP
- }
+ template <typename X, typename T, typename... Ts>
+ TEST_CONSTEXPR_CXX23 void test(T v, Ts... args) {
+ std::from_chars_result r2;
+ std::to_chars_result r;
+ X x = 0xc;
+
+ if (fits_in<X>(v)) {
+ r = std::to_chars(buf, buf + sizeof(buf), v, args...);
+ assert(r.ec == std::errc{});
+
+ r2 = std::from_chars(buf, r.ptr, x, args...);
+ assert(r2.ptr == r.ptr);
+ assert(x == X(v));
+ } else {
+ r = std::to_chars(buf, buf + sizeof(buf), v, args...);
+ assert(r.ec == std::errc{});
+
+ r2 = std::from_chars(buf, r.ptr, x, args...);
+
+ TEST_DIAGNOSTIC_PUSH
+ TEST_MSVC_DIAGNOSTIC_IGNORED(4127) // conditional expression is constant
+
+ if (std::is_signed<T>::value && v < 0 && std::is_unsigned<X>::value) {
+ assert(x == 0xc);
+ assert(r2.ptr == buf);
+ assert(r2.ec == std::errc::invalid_argument);
+ } else {
+ assert(x == 0xc);
+ assert(r2.ptr == r.ptr);
+ assert(r2.ec == std::errc::result_out_of_range);
+ }
+
+ TEST_DIAGNOSTIC_POP
}
+ }
private:
char buf[150];
};
-template <typename... T>
-struct type_list
-{
-};
-
-template <typename L1, typename L2>
-struct type_concat;
-
-template <typename... Xs, typename... Ys>
-struct type_concat<type_list<Xs...>, type_list<Ys...>>
-{
- using type = type_list<Xs..., Ys...>;
-};
-
-template <typename L1, typename L2>
-using concat_t = typename type_concat<L1, L2>::type;
-
-template <typename L1, typename L2>
-constexpr auto concat(L1, L2) -> concat_t<L1, L2>
-{
- return {};
-}
-
-auto all_signed = type_list<
- char,
- signed char,
- short,
- int,
- long,
- long long
-#ifndef TEST_HAS_NO_INT128
- ,
- __int128_t
-#endif
- >();
-auto all_unsigned = type_list<
- unsigned char,
- unsigned short,
- unsigned int,
- unsigned long,
- unsigned long long
-#ifndef TEST_HAS_NO_INT128
- ,
- __uint128_t
-#endif
- >();
-auto integrals = concat(all_signed, all_unsigned);
-
-auto all_floats = type_list< float, double >(); //TODO: Add long double
-
-template <template <typename> class Fn, typename... Ts>
-TEST_CONSTEXPR_CXX23 void
-run(type_list<Ts...>)
-{
- int ls[sizeof...(Ts)] = {(Fn<Ts>{}(), 0)...};
- (void)ls;
-}
+using integrals =
+ types::concatenate_t<types::type_list<char>, types::signed_integer_types, types::unsigned_integer_types>;
#endif // SUPPORT_CHARCONV_TEST_HELPERS_H
>From 76b9f3db97e175c75c87b923d8ebee0f0b4cd75d Mon Sep 17 00:00:00 2001
From: Henri Chataing <henrichataing at google.com>
Date: Wed, 23 Sep 2026 14:51:23 +0000
Subject: [PATCH 2/3] [libc++] Suppress unsigned-integer-overflow warning in
<charconv>
Invoking __complement with 0 as parameter triggers this runtime error:
> include/c++/v1/__charconv/traits.h:181:19: runtime error: unsigned integer overflow: 18446744073709551615 + 1 cannot be represented in type 'unsigned long'
> SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior include/c++/v1/__charconv/traits.h:181:19
---
libcxx/include/__charconv/traits.h | 3 ++-
.../charconv/charconv.from.chars/integral.pass.cpp | 12 ++++++++++++
2 files changed, 14 insertions(+), 1 deletion(-)
diff --git a/libcxx/include/__charconv/traits.h b/libcxx/include/__charconv/traits.h
index b8c840d1ebe326..a13c30a19c23dc 100644
--- a/libcxx/include/__charconv/traits.h
+++ b/libcxx/include/__charconv/traits.h
@@ -155,7 +155,8 @@ struct _LIBCPP_HIDDEN __traits : __traits_base<_Tp> {
} // namespace __itoa
template <typename _Tp>
-inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI _Tp __complement(_Tp __x) {
+inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK _Tp
+__complement(_Tp __x) {
static_assert(is_unsigned<_Tp>::value, "cast to unsigned first");
return _Tp(~__x + 1);
}
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 f1fe8af9cc424b..0ece8bdc8bbfa3 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
@@ -8,6 +8,9 @@
// UNSUPPORTED: c++03, c++11, c++14
+// FIXME: Enable this for all tests once possible
+// ADDITIONAL_COMPILE_FLAGS(ubsan): -fsanitize=unsigned-integer-overflow
+
// <charconv>
// constexpr from_chars_result from_chars(const char* first, const char* last,
@@ -129,6 +132,15 @@ struct test_signed
// the member ec is equal to errc::invalid_argument.
assert(r.ec == std::errc::invalid_argument);
}
+
+ {
+ // Ensure "-0" does not trigger unsigned integer overflow.
+ char s[] = "-0";
+ r = std::from_chars(s, s + sizeof(s), x);
+ assert(r.ec == std::errc{});
+ assert(r.ptr == s + 2);
+ assert(x == 0);
+ }
}
};
>From 82cdbe02b7fab5f9d4883c74dda28bca56f1a5fa Mon Sep 17 00:00:00 2001
From: Louis Dionne <ldionne.2 at gmail.com>
Date: Fri, 2 Oct 2026 10:27:51 -0400
Subject: [PATCH 3/3] Undo unrelated formatting changes
---
.../charconv.from.chars/integral.pass.cpp | 231 ++++++++---------
.../integral.roundtrip.pass.cpp | 92 +++----
.../charconv.to.chars/integral.pass.cpp | 232 +++++++++---------
libcxx/test/support/charconv_test_helpers.h | 163 ++++++------
4 files changed, 372 insertions(+), 346 deletions(-)
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 0ece8bdc8bbfa3..ab6f6724cfc887 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
@@ -24,132 +24,137 @@
struct test_basics
{
- template <typename T>
- TEST_CONSTEXPR_CXX23 void operator()() {
- std::from_chars_result r;
- T x;
-
+ template <typename T>
+ TEST_CONSTEXPR_CXX23 void operator()()
{
- 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()() {
- 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);
- }
-
+ template <typename T>
+ TEST_CONSTEXPR_CXX23 void operator()()
{
- // Ensure "-0" does not trigger unsigned integer overflow.
- char s[] = "-0";
- r = std::from_chars(s, s + sizeof(s), x);
- assert(r.ec == std::errc{});
- assert(r.ptr == s + 2);
- assert(x == 0);
+ 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);
+ }
+
+ {
+ // Ensure "-0" does not trigger unsigned integer overflow.
+ char s[] = "-0";
+ r = std::from_chars(s, s + sizeof(s), x);
+ assert(r.ec == std::errc{});
+ assert(r.ptr == s + 2);
+ assert(x == 0);
+ }
}
- }
};
TEST_CONSTEXPR_CXX23 bool test()
{
- types::for_each(integrals(), test_basics());
- types::for_each(types::signed_integer_types(), test_signed());
+ types::for_each(integrals(), test_basics());
+ types::for_each(types::signed_integer_types(), test_signed());
- return true;
+ return true;
}
int main(int, char**) {
diff --git a/libcxx/test/std/utilities/charconv/charconv.from.chars/integral.roundtrip.pass.cpp b/libcxx/test/std/utilities/charconv/charconv.from.chars/integral.roundtrip.pass.cpp
index a4f1a467f55ba8..a9681202ba400f 100644
--- a/libcxx/test/std/utilities/charconv/charconv.from.chars/integral.roundtrip.pass.cpp
+++ b/libcxx/test/std/utilities/charconv/charconv.from.chars/integral.roundtrip.pass.cpp
@@ -21,58 +21,64 @@
#include "test_macros.h"
#include "charconv_test_helpers.h"
-struct test_basics : roundtrip_test_base {
- template <typename T>
- TEST_CONSTEXPR_CXX23 void operator()() {
- test<T>(0);
- test<T>(42);
- test<T>(32768);
- test<T>(0, 10);
- test<T>(42, 10);
- test<T>(32768, 10);
- test<T>(0xf, 16);
- test<T>(0xdeadbeaf, 16);
- test<T>(0755, 8);
-
- for (int b = 2; b < 37; ++b) {
- using xl = std::numeric_limits<T>;
-
- test<T>(1, b);
- test<T>(-1, b);
- test<T>(xl::lowest(), b);
- test<T>((xl::max)(), b);
- test<T>((xl::max)() / 2, b);
+struct test_basics : roundtrip_test_base
+{
+ template <typename T>
+ TEST_CONSTEXPR_CXX23 void operator()()
+ {
+ test<T>(0);
+ test<T>(42);
+ test<T>(32768);
+ test<T>(0, 10);
+ test<T>(42, 10);
+ test<T>(32768, 10);
+ test<T>(0xf, 16);
+ test<T>(0xdeadbeaf, 16);
+ test<T>(0755, 8);
+
+ for (int b = 2; b < 37; ++b)
+ {
+ using xl = std::numeric_limits<T>;
+
+ test<T>(1, b);
+ test<T>(-1, b);
+ test<T>(xl::lowest(), b);
+ test<T>((xl::max)(), b);
+ test<T>((xl::max)() / 2, b);
+ }
}
- }
};
-struct test_signed : roundtrip_test_base {
- template <typename T>
- TEST_CONSTEXPR_CXX23 void operator()() {
- test<T>(-1);
- test<T>(-12);
- test<T>(-1, 10);
- test<T>(-12, 10);
- test<T>(-21734634, 10);
- test<T>(-2647, 2);
- test<T>(-0xcc1, 16);
-
- for (int b = 2; b < 37; ++b) {
- using xl = std::numeric_limits<T>;
-
- test<T>(0, b);
- test<T>(xl::lowest(), b);
- test<T>((xl::max)(), b);
+struct test_signed : roundtrip_test_base
+{
+ template <typename T>
+ TEST_CONSTEXPR_CXX23 void operator()()
+ {
+ test<T>(-1);
+ test<T>(-12);
+ test<T>(-1, 10);
+ test<T>(-12, 10);
+ test<T>(-21734634, 10);
+ test<T>(-2647, 2);
+ test<T>(-0xcc1, 16);
+
+ for (int b = 2; b < 37; ++b)
+ {
+ using xl = std::numeric_limits<T>;
+
+ test<T>(0, b);
+ test<T>(xl::lowest(), b);
+ test<T>((xl::max)(), b);
+ }
}
- }
};
TEST_CONSTEXPR_CXX23 bool test()
{
- types::for_each(integrals(), test_basics());
- types::for_each(types::signed_integer_types(), test_signed());
+ types::for_each(integrals(), test_basics());
+ types::for_each(types::signed_integer_types(), test_signed());
- return true;
+ return true;
}
int main(int, char**) {
diff --git a/libcxx/test/std/utilities/charconv/charconv.to.chars/integral.pass.cpp b/libcxx/test/std/utilities/charconv/charconv.to.chars/integral.pass.cpp
index d9291140586c77..4d07ad78d5d8f8 100644
--- a/libcxx/test/std/utilities/charconv/charconv.to.chars/integral.pass.cpp
+++ b/libcxx/test/std/utilities/charconv/charconv.to.chars/integral.pass.cpp
@@ -51,63 +51,65 @@ TEST_CONSTEXPR_CXX23 __int128_t make_i128(__int128_t a, __int128_t b, std::int64
}
#endif
-struct test_basics : to_chars_test_base {
- template <typename T>
- TEST_CONSTEXPR_CXX23 void operator()() {
- test<T>(0, "0");
- test<T>(42, "42");
- test<T>(32768, "32768");
- test<T>(0, "0", 10);
- test<T>(42, "42", 10);
- test<T>(32768, "32768", 10);
- test<T>(0xf, "f", 16);
- test<T>(0xdeadbeaf, "deadbeaf", 16);
- test<T>(0755, "755", 8);
+struct test_basics : to_chars_test_base
+{
+ template <typename T>
+ TEST_CONSTEXPR_CXX23 void operator()()
+ {
+ test<T>(0, "0");
+ test<T>(42, "42");
+ test<T>(32768, "32768");
+ test<T>(0, "0", 10);
+ test<T>(42, "42", 10);
+ test<T>(32768, "32768", 10);
+ test<T>(0xf, "f", 16);
+ test<T>(0xdeadbeaf, "deadbeaf", 16);
+ test<T>(0755, "755", 8);
- // Test each len till len of UINT64_MAX = 20 because to_chars algorithm
- // makes branches based on decimal digits count in the value string
- // representation.
- // Test driver automatically skips values not fitting into source type.
- test<T>(1UL, "1");
- test<T>(12UL, "12");
- test<T>(123UL, "123");
- test<T>(1234UL, "1234");
- test<T>(12345UL, "12345");
- test<T>(123456UL, "123456");
- test<T>(1234567UL, "1234567");
- test<T>(12345678UL, "12345678");
- test<T>(123456789UL, "123456789");
- test<T>(1234567890UL, "1234567890");
- test<T>(12345678901UL, "12345678901");
- test<T>(123456789012UL, "123456789012");
- test<T>(1234567890123UL, "1234567890123");
- test<T>(12345678901234UL, "12345678901234");
- test<T>(123456789012345UL, "123456789012345");
- test<T>(1234567890123456UL, "1234567890123456");
- test<T>(12345678901234567UL, "12345678901234567");
- test<T>(123456789012345678UL, "123456789012345678");
- test<T>(1234567890123456789UL, "1234567890123456789");
- test<T>(12345678901234567890UL, "12345678901234567890");
+ // Test each len till len of UINT64_MAX = 20 because to_chars algorithm
+ // makes branches based on decimal digits count in the value string
+ // representation.
+ // Test driver automatically skips values not fitting into source type.
+ test<T>(1UL, "1");
+ test<T>(12UL, "12");
+ test<T>(123UL, "123");
+ test<T>(1234UL, "1234");
+ test<T>(12345UL, "12345");
+ test<T>(123456UL, "123456");
+ test<T>(1234567UL, "1234567");
+ test<T>(12345678UL, "12345678");
+ test<T>(123456789UL, "123456789");
+ test<T>(1234567890UL, "1234567890");
+ test<T>(12345678901UL, "12345678901");
+ test<T>(123456789012UL, "123456789012");
+ test<T>(1234567890123UL, "1234567890123");
+ test<T>(12345678901234UL, "12345678901234");
+ test<T>(123456789012345UL, "123456789012345");
+ test<T>(1234567890123456UL, "1234567890123456");
+ test<T>(12345678901234567UL, "12345678901234567");
+ test<T>(123456789012345678UL, "123456789012345678");
+ test<T>(1234567890123456789UL, "1234567890123456789");
+ test<T>(12345678901234567890UL, "12345678901234567890");
#ifndef TEST_HAS_NO_INT128
- test<T>(make_u128(12UL, 3456789012345678901UL), "123456789012345678901");
- test<T>(make_u128(123UL, 4567890123456789012UL), "1234567890123456789012");
- test<T>(make_u128(1234UL, 5678901234567890123UL), "12345678901234567890123");
- test<T>(make_u128(12345UL, 6789012345678901234UL), "123456789012345678901234");
- test<T>(make_u128(123456UL, 7890123456789012345UL), "1234567890123456789012345");
- test<T>(make_u128(1234567UL, 8901234567890123456UL), "12345678901234567890123456");
- test<T>(make_u128(12345678UL, 9012345678901234567UL), "123456789012345678901234567");
- test<T>(make_u128(123456789UL, 123456789012345678UL), "1234567890123456789012345678");
- test<T>(make_u128(123UL, 4567890123456UL, 7890123456789UL), "12345678901234567890123456789");
- test<T>(make_u128(1234UL, 5678901234567UL, 8901234567890UL), "123456789012345678901234567890");
- test<T>(make_u128(12345UL, 6789012345678UL, 9012345678901UL), "1234567890123456789012345678901");
- test<T>(make_u128(123456UL, 7890123456789UL, 123456789012UL), "12345678901234567890123456789012");
- test<T>(make_u128(1234567UL, 8901234567890UL, 1234567890123UL), "123456789012345678901234567890123");
- test<T>(make_u128(12345678UL, 9012345678901UL, 2345678901234UL), "1234567890123456789012345678901234");
- test<T>(make_u128(123456789UL, 123456789012UL, 3456789012345UL), "12345678901234567890123456789012345");
- test<T>(make_u128(1234567890UL, 1234567890123UL, 4567890123456UL), "123456789012345678901234567890123456");
- test<T>(make_u128(12345678901UL, 2345678901234UL, 5678901234567UL), "1234567890123456789012345678901234567");
- test<T>(make_u128(123456789012UL, 3456789012345UL, 6789012345678UL), "12345678901234567890123456789012345678");
- test<T>(make_u128(1234567890123UL, 4567890123456UL, 7890123456789UL), "123456789012345678901234567890123456789");
+ test<T>(make_u128(12UL, 3456789012345678901UL), "123456789012345678901");
+ test<T>(make_u128(123UL, 4567890123456789012UL), "1234567890123456789012");
+ test<T>(make_u128(1234UL, 5678901234567890123UL), "12345678901234567890123");
+ test<T>(make_u128(12345UL, 6789012345678901234UL), "123456789012345678901234");
+ test<T>(make_u128(123456UL, 7890123456789012345UL), "1234567890123456789012345");
+ test<T>(make_u128(1234567UL, 8901234567890123456UL), "12345678901234567890123456");
+ test<T>(make_u128(12345678UL, 9012345678901234567UL), "123456789012345678901234567");
+ test<T>(make_u128(123456789UL, 123456789012345678UL), "1234567890123456789012345678");
+ test<T>(make_u128(123UL, 4567890123456UL, 7890123456789UL), "12345678901234567890123456789");
+ test<T>(make_u128(1234UL, 5678901234567UL, 8901234567890UL), "123456789012345678901234567890");
+ test<T>(make_u128(12345UL, 6789012345678UL, 9012345678901UL), "1234567890123456789012345678901");
+ test<T>(make_u128(123456UL, 7890123456789UL, 123456789012UL), "12345678901234567890123456789012");
+ test<T>(make_u128(1234567UL, 8901234567890UL, 1234567890123UL), "123456789012345678901234567890123");
+ test<T>(make_u128(12345678UL, 9012345678901UL, 2345678901234UL), "1234567890123456789012345678901234");
+ test<T>(make_u128(123456789UL, 123456789012UL, 3456789012345UL), "12345678901234567890123456789012345");
+ test<T>(make_u128(1234567890UL, 1234567890123UL, 4567890123456UL), "123456789012345678901234567890123456");
+ test<T>(make_u128(12345678901UL, 2345678901234UL, 5678901234567UL), "1234567890123456789012345678901234567");
+ test<T>(make_u128(123456789012UL, 3456789012345UL, 6789012345678UL), "12345678901234567890123456789012345678");
+ test<T>(make_u128(1234567890123UL, 4567890123456UL, 7890123456789UL), "123456789012345678901234567890123456789");
#endif
// Test special cases with zeros inside a value string representation,
@@ -165,65 +167,67 @@ struct test_basics : to_chars_test_base {
test_value<T>((xl::max)(), b);
test_value<T>((xl::max)() / 2, b);
}
- }
+ }
};
-struct test_signed : to_chars_test_base {
- template <typename T>
- TEST_CONSTEXPR_CXX23 void operator()() {
- test<T>(-1, "-1");
- test<T>(-12, "-12");
- test<T>(-1, "-1", 10);
- test<T>(-12, "-12", 10);
- test<T>(-21734634, "-21734634", 10);
- test<T>(-2647, "-101001010111", 2);
- test<T>(-0xcc1, "-cc1", 16);
+struct test_signed : to_chars_test_base
+{
+ template <typename T>
+ TEST_CONSTEXPR_CXX23 void operator()()
+ {
+ test<T>(-1, "-1");
+ test<T>(-12, "-12");
+ test<T>(-1, "-1", 10);
+ test<T>(-12, "-12", 10);
+ test<T>(-21734634, "-21734634", 10);
+ test<T>(-2647, "-101001010111", 2);
+ test<T>(-0xcc1, "-cc1", 16);
- // Test each len till len of INT64_MAX = 19 because to_chars algorithm
- // makes branches based on decimal digits count in the value string
- // representation.
- // Test driver automatically skips values not fitting into source type.
- test<T>(-1L, "-1");
- test<T>(-12L, "-12");
- test<T>(-123L, "-123");
- test<T>(-1234L, "-1234");
- test<T>(-12345L, "-12345");
- test<T>(-123456L, "-123456");
- test<T>(-1234567L, "-1234567");
- test<T>(-12345678L, "-12345678");
- test<T>(-123456789L, "-123456789");
- test<T>(-1234567890L, "-1234567890");
- test<T>(-12345678901L, "-12345678901");
- test<T>(-123456789012L, "-123456789012");
- test<T>(-1234567890123L, "-1234567890123");
- test<T>(-12345678901234L, "-12345678901234");
- test<T>(-123456789012345L, "-123456789012345");
- test<T>(-1234567890123456L, "-1234567890123456");
- test<T>(-12345678901234567L, "-12345678901234567");
- test<T>(-123456789012345678L, "-123456789012345678");
- test<T>(-1234567890123456789L, "-1234567890123456789");
+ // Test each len till len of INT64_MAX = 19 because to_chars algorithm
+ // makes branches based on decimal digits count in the value string
+ // representation.
+ // Test driver automatically skips values not fitting into source type.
+ test<T>(-1L, "-1");
+ test<T>(-12L, "-12");
+ test<T>(-123L, "-123");
+ test<T>(-1234L, "-1234");
+ test<T>(-12345L, "-12345");
+ test<T>(-123456L, "-123456");
+ test<T>(-1234567L, "-1234567");
+ test<T>(-12345678L, "-12345678");
+ test<T>(-123456789L, "-123456789");
+ test<T>(-1234567890L, "-1234567890");
+ test<T>(-12345678901L, "-12345678901");
+ test<T>(-123456789012L, "-123456789012");
+ test<T>(-1234567890123L, "-1234567890123");
+ test<T>(-12345678901234L, "-12345678901234");
+ test<T>(-123456789012345L, "-123456789012345");
+ test<T>(-1234567890123456L, "-1234567890123456");
+ test<T>(-12345678901234567L, "-12345678901234567");
+ test<T>(-123456789012345678L, "-123456789012345678");
+ test<T>(-1234567890123456789L, "-1234567890123456789");
#ifndef TEST_HAS_NO_INT128
- test<T>(make_i128(-1L, 2345678901234567890L), "-12345678901234567890");
- test<T>(make_i128(-12L, 3456789012345678901L), "-123456789012345678901");
- test<T>(make_i128(-123L, 4567890123456789012L), "-1234567890123456789012");
- test<T>(make_i128(-1234L, 5678901234567890123L), "-12345678901234567890123");
- test<T>(make_i128(-12345L, 6789012345678901234L), "-123456789012345678901234");
- test<T>(make_i128(-123456L, 7890123456789012345L), "-1234567890123456789012345");
- test<T>(make_i128(-1234567L, 8901234567890123456L), "-12345678901234567890123456");
- test<T>(make_i128(-12345678L, 9012345678901234567L), "-123456789012345678901234567");
- test<T>(make_i128(-123456789L, 123456789012345678L), "-1234567890123456789012345678");
- test<T>(make_i128(-1234567890L, 1234567890123456789L), "-12345678901234567890123456789");
- test<T>(make_i128(-123L, 4567890123456L, 7890123456789L), "-12345678901234567890123456789");
- test<T>(make_i128(-1234L, 5678901234567L, 8901234567890L), "-123456789012345678901234567890");
- test<T>(make_i128(-12345L, 6789012345678L, 9012345678901L), "-1234567890123456789012345678901");
- test<T>(make_i128(-123456L, 7890123456789L, 123456789012L), "-12345678901234567890123456789012");
- test<T>(make_i128(-1234567L, 8901234567890L, 1234567890123L), "-123456789012345678901234567890123");
- test<T>(make_i128(-12345678L, 9012345678901L, 2345678901234L), "-1234567890123456789012345678901234");
- test<T>(make_i128(-123456789L, 123456789012L, 3456789012345L), "-12345678901234567890123456789012345");
- test<T>(make_i128(-1234567890L, 1234567890123L, 4567890123456L), "-123456789012345678901234567890123456");
- test<T>(make_i128(-12345678901L, 2345678901234L, 5678901234567L), "-1234567890123456789012345678901234567");
- test<T>(make_i128(-123456789012L, 3456789012345L, 6789012345678L), "-12345678901234567890123456789012345678");
- test<T>(make_i128(-1234567890123L, 4567890123456L, 7890123456789L), "-123456789012345678901234567890123456789");
+ test<T>(make_i128(-1L, 2345678901234567890L), "-12345678901234567890");
+ test<T>(make_i128(-12L, 3456789012345678901L), "-123456789012345678901");
+ test<T>(make_i128(-123L, 4567890123456789012L), "-1234567890123456789012");
+ test<T>(make_i128(-1234L, 5678901234567890123L), "-12345678901234567890123");
+ test<T>(make_i128(-12345L, 6789012345678901234L), "-123456789012345678901234");
+ test<T>(make_i128(-123456L, 7890123456789012345L), "-1234567890123456789012345");
+ test<T>(make_i128(-1234567L, 8901234567890123456L), "-12345678901234567890123456");
+ test<T>(make_i128(-12345678L, 9012345678901234567L), "-123456789012345678901234567");
+ test<T>(make_i128(-123456789L, 123456789012345678L), "-1234567890123456789012345678");
+ test<T>(make_i128(-1234567890L, 1234567890123456789L), "-12345678901234567890123456789");
+ test<T>(make_i128(-123L, 4567890123456L, 7890123456789L), "-12345678901234567890123456789");
+ test<T>(make_i128(-1234L, 5678901234567L, 8901234567890L), "-123456789012345678901234567890");
+ test<T>(make_i128(-12345L, 6789012345678L, 9012345678901L), "-1234567890123456789012345678901");
+ test<T>(make_i128(-123456L, 7890123456789L, 123456789012L), "-12345678901234567890123456789012");
+ test<T>(make_i128(-1234567L, 8901234567890L, 1234567890123L), "-123456789012345678901234567890123");
+ test<T>(make_i128(-12345678L, 9012345678901L, 2345678901234L), "-1234567890123456789012345678901234");
+ test<T>(make_i128(-123456789L, 123456789012L, 3456789012345L), "-12345678901234567890123456789012345");
+ test<T>(make_i128(-1234567890L, 1234567890123L, 4567890123456L), "-123456789012345678901234567890123456");
+ test<T>(make_i128(-12345678901L, 2345678901234L, 5678901234567L), "-1234567890123456789012345678901234567");
+ test<T>(make_i128(-123456789012L, 3456789012345L, 6789012345678L), "-12345678901234567890123456789012345678");
+ test<T>(make_i128(-1234567890123L, 4567890123456L, 7890123456789L), "-123456789012345678901234567890123456789");
#endif
// Test special cases with zeros inside a value string representation,
@@ -280,15 +284,15 @@ struct test_signed : to_chars_test_base {
test_value<T>(xl::lowest(), b);
test_value<T>((xl::max)(), b);
}
- }
+ }
};
TEST_CONSTEXPR_CXX23 bool test()
{
- types::for_each(integrals(), test_basics());
- types::for_each(types::signed_integer_types(), test_signed());
+ types::for_each(integrals(), test_basics());
+ types::for_each(types::signed_integer_types(), test_signed());
- return true;
+ return true;
}
int main(int, char**)
diff --git a/libcxx/test/support/charconv_test_helpers.h b/libcxx/test/support/charconv_test_helpers.h
index 7cd14204ddb00a..3d163322a6f4f5 100644
--- a/libcxx/test/support/charconv_test_helpers.h
+++ b/libcxx/test/support/charconv_test_helpers.h
@@ -81,56 +81,58 @@ fits_in(T v)
struct to_chars_test_base
{
- template <typename X, typename T, std::size_t N, typename... Ts>
- TEST_CONSTEXPR_CXX23 void test(T v, char const (&expect)[N], Ts... args) {
- std::to_chars_result r;
-
- constexpr std::size_t len = N - 1;
- static_assert(len > 0, "expected output won't be empty");
-
- if (!fits_in<X>(v))
- return;
-
- r = std::to_chars(buf, buf + len - 1, X(v), args...);
- assert(r.ptr == buf + len - 1);
- assert(r.ec == std::errc::value_too_large);
-
- r = std::to_chars(buf, buf + sizeof(buf), X(v), args...);
- assert(r.ptr == buf + len);
- assert(r.ec == std::errc{});
- assert(std::equal(buf, buf + len, expect));
- }
-
- template <typename X, typename... Ts>
- TEST_CONSTEXPR_CXX23 void test_value(X v, Ts... args) {
- std::to_chars_result r;
-
- // Poison the buffer for testing whether a successful std::to_chars
- // doesn't modify data beyond r.ptr. Use unsigned values to avoid
- // overflowing char when it's signed.
- std::iota(buf, buf + sizeof(buf), static_cast<unsigned char>(1));
- r = std::to_chars(buf, buf + sizeof(buf), v, args...);
- assert(r.ec == std::errc{});
- for (std::size_t i = r.ptr - buf; i < sizeof(buf); ++i)
- assert(static_cast<unsigned char>(buf[i]) == i + 1);
- *r.ptr = '\0';
+ template <typename X, typename T, std::size_t N, typename... Ts>
+ TEST_CONSTEXPR_CXX23 void test(T v, char const (&expect)[N], Ts... args)
+ {
+ std::to_chars_result r;
+
+ constexpr std::size_t len = N - 1;
+ static_assert(len > 0, "expected output won't be empty");
+
+ if (!fits_in<X>(v))
+ return;
+
+ r = std::to_chars(buf, buf + len - 1, X(v), args...);
+ assert(r.ptr == buf + len - 1);
+ assert(r.ec == std::errc::value_too_large);
+
+ r = std::to_chars(buf, buf + sizeof(buf), X(v), args...);
+ assert(r.ptr == buf + len);
+ assert(r.ec == std::errc{});
+ assert(std::equal(buf, buf + len, expect));
+ }
+
+ template <typename X, typename... Ts>
+ TEST_CONSTEXPR_CXX23 void test_value(X v, Ts... args)
+ {
+ std::to_chars_result r;
+
+ // Poison the buffer for testing whether a successful std::to_chars
+ // doesn't modify data beyond r.ptr. Use unsigned values to avoid
+ // overflowing char when it's signed.
+ std::iota(buf, buf + sizeof(buf), static_cast<unsigned char>(1));
+ r = std::to_chars(buf, buf + sizeof(buf), v, args...);
+ assert(r.ec == std::errc{});
+ for (std::size_t i = r.ptr - buf; i < sizeof(buf); ++i)
+ assert(static_cast<unsigned char>(buf[i]) == i + 1);
+ *r.ptr = '\0';
#ifndef TEST_HAS_NO_INT128
if (sizeof(X) == sizeof(__int128_t)) {
- auto a = fromchars128_impl<X>(buf, r.ptr, args...);
- assert(v == a);
+ auto a = fromchars128_impl<X>(buf, r.ptr, args...);
+ assert(v == a);
} else
#endif
{
- auto a = fromchars_impl<X>(buf, r.ptr, args...);
- assert(v == a);
+ auto a = fromchars_impl<X>(buf, r.ptr, args...);
+ assert(v == a);
}
auto ep = r.ptr - 1;
r = std::to_chars(buf, ep, v, args...);
assert(r.ptr == ep);
assert(r.ec == std::errc::value_too_large);
- }
+ }
private:
static TEST_CONSTEXPR_CXX23 long long fromchars_impl(char const* p, char const* ep, int base, true_type)
@@ -202,16 +204,18 @@ struct to_chars_test_base
template <typename X>
static TEST_CONSTEXPR_CXX23 auto fromchars128_impl(char const* p, char const* ep, int base = 10)
- -> decltype(fromchars128_impl(p, ep, base, std::is_signed<X>())) {
- return fromchars128_impl(p, ep, base, std::is_signed<X>());
+ -> decltype(fromchars128_impl(p, ep, base, std::is_signed<X>()))
+ {
+ return fromchars128_impl(p, ep, base, std::is_signed<X>());
}
#endif
template <typename X>
static TEST_CONSTEXPR_CXX23 auto fromchars_impl(char const* p, char const* ep, int base = 10)
- -> decltype(fromchars_impl(p, ep, base, std::is_signed<X>())) {
- return fromchars_impl(p, ep, base, std::is_signed<X>());
+ -> decltype(fromchars_impl(p, ep, base, std::is_signed<X>()))
+ {
+ return fromchars_impl(p, ep, base, std::is_signed<X>());
}
char buf[150];
@@ -219,41 +223,48 @@ struct to_chars_test_base
struct roundtrip_test_base
{
- template <typename X, typename T, typename... Ts>
- TEST_CONSTEXPR_CXX23 void test(T v, Ts... args) {
- std::from_chars_result r2;
- std::to_chars_result r;
- X x = 0xc;
-
- if (fits_in<X>(v)) {
- r = std::to_chars(buf, buf + sizeof(buf), v, args...);
- assert(r.ec == std::errc{});
-
- r2 = std::from_chars(buf, r.ptr, x, args...);
- assert(r2.ptr == r.ptr);
- assert(x == X(v));
- } else {
- r = std::to_chars(buf, buf + sizeof(buf), v, args...);
- assert(r.ec == std::errc{});
-
- r2 = std::from_chars(buf, r.ptr, x, args...);
-
- TEST_DIAGNOSTIC_PUSH
- TEST_MSVC_DIAGNOSTIC_IGNORED(4127) // conditional expression is constant
-
- if (std::is_signed<T>::value && v < 0 && std::is_unsigned<X>::value) {
- assert(x == 0xc);
- assert(r2.ptr == buf);
- assert(r2.ec == std::errc::invalid_argument);
- } else {
- assert(x == 0xc);
- assert(r2.ptr == r.ptr);
- assert(r2.ec == std::errc::result_out_of_range);
- }
-
- TEST_DIAGNOSTIC_POP
+ template <typename X, typename T, typename... Ts>
+ TEST_CONSTEXPR_CXX23 void test(T v, Ts... args)
+ {
+ std::from_chars_result r2;
+ std::to_chars_result r;
+ X x = 0xc;
+
+ if (fits_in<X>(v))
+ {
+ r = std::to_chars(buf, buf + sizeof(buf), v, args...);
+ assert(r.ec == std::errc{});
+
+ r2 = std::from_chars(buf, r.ptr, x, args...);
+ assert(r2.ptr == r.ptr);
+ assert(x == X(v));
+ }
+ else
+ {
+ r = std::to_chars(buf, buf + sizeof(buf), v, args...);
+ assert(r.ec == std::errc{});
+
+ r2 = std::from_chars(buf, r.ptr, x, args...);
+
+ TEST_DIAGNOSTIC_PUSH
+ TEST_MSVC_DIAGNOSTIC_IGNORED(4127) // conditional expression is constant
+
+ if (std::is_signed<T>::value && v < 0 && std::is_unsigned<X>::value)
+ {
+ assert(x == 0xc);
+ assert(r2.ptr == buf);
+ assert(r2.ec == std::errc::invalid_argument);
+ }
+ else
+ {
+ assert(x == 0xc);
+ assert(r2.ptr == r.ptr);
+ assert(r2.ec == std::errc::result_out_of_range);
+ }
+
+ TEST_DIAGNOSTIC_POP
+ }
}
- }
private:
char buf[150];
More information about the libcxx-commits
mailing list