[libcxx-commits] [libcxx] 6880a2a - [libc++] Suppress unsigned-integer-overflow warning in <charconv> (#225801)
via libcxx-commits
libcxx-commits at lists.llvm.org
Tue Oct 13 06:52:30 PDT 2026
Author: hchataing
Date: 2026-10-13T15:52:24+02:00
New Revision: 6880a2a498646d518b580ef8ba34bbca68258984
URL: https://github.com/llvm/llvm-project/commit/6880a2a498646d518b580ef8ba34bbca68258984
DIFF: https://github.com/llvm/llvm-project/commit/6880a2a498646d518b580ef8ba34bbca68258984.diff
LOG: [libc++] Suppress unsigned-integer-overflow warning in <charconv> (#225801)
Invoking __complement with 0 as parameter triggers the unsigned integer
overflow UBSan.
Added:
Modified:
libcxx/include/__charconv/traits.h
libcxx/test/std/utilities/charconv/charconv.from.chars/floating_point.pass.cpp
libcxx/test/std/utilities/charconv/charconv.from.chars/integral.pass.cpp
libcxx/test/std/utilities/charconv/charconv.from.chars/integral.roundtrip.pass.cpp
libcxx/test/std/utilities/charconv/charconv.to.chars/integral.pass.cpp
libcxx/test/support/charconv_test_helpers.h
Removed:
################################################################################
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/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..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
@@ -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,
@@ -19,9 +22,9 @@
#include "test_macros.h"
#include "charconv_test_helpers.h"
-template <typename T>
struct test_basics
{
+ template <typename T>
TEST_CONSTEXPR_CXX23 void operator()()
{
std::from_chars_result r;
@@ -83,9 +86,9 @@ struct test_basics
}
};
-template <typename T>
struct test_signed
{
+ template <typename T>
TEST_CONSTEXPR_CXX23 void operator()()
{
std::from_chars_result r;
@@ -134,13 +137,22 @@ 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);
+ }
}
};
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;
}
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..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,66 +21,62 @@
#include "test_macros.h"
#include "charconv_test_helpers.h"
-template <typename T>
-struct test_basics : roundtrip_test_base<T>
+struct test_basics : roundtrip_test_base
{
- using roundtrip_test_base<T>::test;
-
+ template <typename T>
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);
+ 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(1, b);
- test(-1, b);
- test(xl::lowest(), b);
- test((xl::max)(), b);
- test((xl::max)() / 2, b);
+ 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>
+struct test_signed : roundtrip_test_base
{
- using roundtrip_test_base<T>::test;
-
+ template <typename T>
TEST_CONSTEXPR_CXX23 void operator()()
{
- test(-1);
- test(-12);
- test(-1, 10);
- test(-12, 10);
- test(-21734634, 10);
- test(-2647, 2);
- test(-0xcc1, 16);
+ 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(0, b);
- test(xl::lowest(), b);
- test((xl::max)(), b);
+ 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;
}
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..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,252 +51,246 @@ 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>
+struct test_basics : to_chars_test_base
{
- using to_chars_test_base<T>::test;
- using to_chars_test_base<T>::test_value;
-
+ template <typename T>
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);
+ 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<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>
+struct test_signed : to_chars_test_base
{
- using to_chars_test_base<T>::test;
- using to_chars_test_base<T>::test_value;
-
+ template <typename T>
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);
+ 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<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;
}
diff --git a/libcxx/test/support/charconv_test_helpers.h b/libcxx/test/support/charconv_test_helpers.h
index fcae09478457b6..3d163322a6f4f5 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,10 +79,9 @@ 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>
+ 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;
@@ -102,7 +102,7 @@ struct to_chars_test_base
assert(std::equal(buf, buf + len, expect));
}
- template <typename... Ts>
+ template <typename X, typename... Ts>
TEST_CONSTEXPR_CXX23 void test_value(X v, Ts... args)
{
std::to_chars_result r;
@@ -119,12 +119,12 @@ struct to_chars_test_base
#ifndef TEST_HAS_NO_INT128
if (sizeof(X) == sizeof(__int128_t)) {
- auto a = fromchars128_impl(buf, r.ptr, args...);
+ auto a = fromchars128_impl<X>(buf, r.ptr, args...);
assert(v == a);
} else
#endif
{
- auto a = fromchars_impl(buf, r.ptr, args...);
+ auto a = fromchars_impl<X>(buf, r.ptr, args...);
assert(v == a);
}
@@ -202,6 +202,7 @@ 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>()))
{
@@ -210,6 +211,7 @@ struct to_chars_test_base
#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>()))
{
@@ -219,10 +221,9 @@ struct to_chars_test_base
char buf[150];
};
-template <typename X>
struct roundtrip_test_base
{
- template <typename T, typename... Ts>
+ template <typename X, typename T, typename... Ts>
TEST_CONSTEXPR_CXX23 void test(T v, Ts... args)
{
std::from_chars_result r2;
@@ -269,62 +270,7 @@ struct roundtrip_test_base
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
More information about the libcxx-commits
mailing list