aboutsummaryrefslogtreecommitdiff
path: root/libstdc++-v3/testsuite
diff options
context:
space:
mode:
authorTomasz Kamiński <tkaminsk@redhat.com>2025-03-10 16:51:57 +0100
committerTomasz Kamiński <tkaminsk@redhat.com>2025-03-13 10:57:35 +0100
commit22847ef193670e761ed205a4a6f0a694b939d4e4 (patch)
tree57a658f338af4b527beceafbe634f51e287c927e /libstdc++-v3/testsuite
parent77ef91d7159613c0cfc2920ddd5a32952c61ff5b (diff)
downloadgcc-22847ef193670e761ed205a4a6f0a694b939d4e4.zip
gcc-22847ef193670e761ed205a4a6f0a694b939d4e4.tar.gz
gcc-22847ef193670e761ed205a4a6f0a694b939d4e4.tar.bz2
libstdc++: Hide 128-bit int and float types behind handle for basic_format_arg visitation [PR108053]
Implement visit_format_arg and basic_format_arg::visit function, in terms of _M_visit_user member functions, that wraps any type stored inside basic_format_arg, that is not specified in the standard, into the handle. This affects __int128, unsigned __int128, PowerPC specific __ieee128 and __ibm128, and _Float128 for architectures where long double is not 128bits. The bfloat16, _Float16, _Float32, _Float32, and _Float128 for 128bits long double are not are not addressed, as they are transformed into a standard floating point types. For internal purposes __format::__visit_format_arg function is used, that provides an unmodified access to stored object. PR libstdc++/108053 libstdc++-v3/ChangeLog: * include/std/format (basic_format_arg::_M_visit_user): Helper function for wrapping extension types into handle. (visit_format_arg): Call `_M_visit_user` instead of `_M_visit`. (basic_format_arg::visit): As above. (__format::__visit_format_arg): Provides direct access to values stored in basic_format_arg. (__format::__int_from_arg): Use __format::__visit_format_arg instead of std::visit_format_arg. (_Formatting_scanner::_M_format_arg): As above. (_Checking_scanner::__do_vformat_to): As above. * testsuite/std/format/arguments/args.cc: New tests. * testsuite/std/format/string.cc: Test for using __int128 as width/precision. Reviewed-by: Jonathan Wakely <jwakely@redhat.com> Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
Diffstat (limited to 'libstdc++-v3/testsuite')
-rw-r--r--libstdc++-v3/testsuite/std/format/arguments/args.cc73
-rw-r--r--libstdc++-v3/testsuite/std/format/string.cc10
2 files changed, 81 insertions, 2 deletions
diff --git a/libstdc++-v3/testsuite/std/format/arguments/args.cc b/libstdc++-v3/testsuite/std/format/arguments/args.cc
index 2cea0a1..4c50bc7 100644
--- a/libstdc++-v3/testsuite/std/format/arguments/args.cc
+++ b/libstdc++-v3/testsuite/std/format/arguments/args.cc
@@ -148,9 +148,82 @@ test_member_visit()
#endif
}
+template<typename T>
+void test_visited_as_handle()
+{
+ T v{};
+ auto store = std::make_format_args(v);
+ std::format_args args = store;
+
+ constexpr auto is_handle = [](auto arg) {
+ return std::is_same_v<decltype(arg), decltype(args.get(0))::handle>;
+ };
+ VERIFY( std::visit_format_arg(is_handle, args.get(0)) );
+#if __cpp_lib_format >= 202306L // C++26 adds std::basic_format_arg::visit
+ VERIFY( args.get(0).visit(is_handle) );
+#endif
+}
+
+template<typename E, typename S>
+void test_visited_as()
+{
+ auto v = static_cast<S>(1.0);
+ auto store = std::make_format_args(v);
+ std::format_args args = store;
+
+ auto is_expected_val = [v](auto arg) {
+ if constexpr (std::is_same_v<decltype(arg), E>)
+ return arg == static_cast<E>(v);
+ return false;
+ };
+ VERIFY( std::visit_format_arg(is_expected_val, args.get(0)) );
+#if __cpp_lib_format >= 202306L // C++26 adds std::basic_format_arg::visit
+ VERIFY( args.get(0).visit(is_expected_val) );
+#endif
+}
+
+template<typename T>
+concept can_format = std::is_default_constructible_v<std::formatter<T, char>>;
+
int main()
{
test_empty();
test_args();
test_member_visit();
+
+#ifdef __SIZEOF_INT128__
+ test_visited_as_handle<__int128>();
+ test_visited_as_handle<unsigned __int128>();
+#endif
+// TODO: This should be visited as handle.
+#ifdef __STDCPP_FLOAT16_T__
+ if constexpr (can_format<_Float16>)
+ test_visited_as<float, _Float16>();
+#endif
+#ifdef __STDCPP_BFLOAT16_T__
+ if constexpr (can_format<__gnu_cxx::__bfloat16_t>)
+ test_visited_as<float, __gnu_cxx::__bfloat16_t>();
+#endif
+#ifdef __FLT32_DIG__
+ if constexpr (can_format<_Float32>)
+ test_visited_as<float, _Float32>();
+#endif
+#ifdef __FLT64_DIG__
+ if constexpr (can_format<_Float64>)
+ test_visited_as<double, _Float64>();
+#endif
+#ifdef __FLT128_DIG__
+ if constexpr (can_format<_Float128>)
+# ifdef _GLIBCXX_LDOUBLE_IS_IEEE_BINARY128
+ test_visited_as<long double, _Float128>();
+# else
+ test_visited_as_handle<_Float128>();
+# endif
+#endif
+#ifdef _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT
+ if constexpr (!std::is_same_v<__ieee128, long double>)
+ test_visited_as_handle<__ieee128>();
+ if constexpr (!std::is_same_v<__ibm128, long double>)
+ test_visited_as_handle<__ibm128>();
+#endif
}
diff --git a/libstdc++-v3/testsuite/std/format/string.cc b/libstdc++-v3/testsuite/std/format/string.cc
index d5f3050..ee987a1 100644
--- a/libstdc++-v3/testsuite/std/format/string.cc
+++ b/libstdc++-v3/testsuite/std/format/string.cc
@@ -113,11 +113,14 @@ test_format_spec()
VERIFY( ! is_format_string_for("{:0c}", 'c') );
VERIFY( ! is_format_string_for("{:0s}", true) );
- // Dynamic width arg must be an integer type.
+ // Dynamic width arg must be a standar integer type.
VERIFY( ! is_format_string_for("{:{}d}", 1, 1.5) );
VERIFY( ! is_format_string_for("{:{}d}", 1, true) );
VERIFY( ! is_format_string_for("{:{}d}", 1, "str") );
VERIFY( ! is_format_string_for("{:{}d}", 1, nullptr) );
+#ifdef __SIZEOF_INT128__
+ VERIFY( ! is_format_string_for("{:{}d}", 1, static_cast<__int128>(1)) );
+#endif
// Precision only valid for string and floating-point types.
VERIFY( ! is_format_string_for("{:.3d}", 1) );
@@ -126,11 +129,14 @@ test_format_spec()
VERIFY( ! is_format_string_for("{:3.3s}", 'c') );
VERIFY( ! is_format_string_for("{:3.3p}", nullptr) );
- // Dynamic precision arg must be an integer type.
+ // Dynamic precision arg must be a standard integer type.
VERIFY( ! is_format_string_for("{:.{}f}", 1.0, 1.5) );
VERIFY( ! is_format_string_for("{:.{}f}", 1.0, true) );
VERIFY( ! is_format_string_for("{:.{}f}", 1.0, "str") );
VERIFY( ! is_format_string_for("{:.{}f}", 1.0, nullptr) );
+#ifdef __SIZEOF_INT128__
+ VERIFY( ! is_format_string_for("{:{}f}", 1.0, static_cast<unsigned __int128>(1)) );
+#endif
// Invalid presentation types for integers.
VERIFY( ! is_format_string_for("{:f}", 1) );