diff options
author | Martin Liska <mliska@suse.cz> | 2022-11-07 08:24:48 +0100 |
---|---|---|
committer | Martin Liska <mliska@suse.cz> | 2022-11-07 08:24:48 +0100 |
commit | 1b09b78ee61bd921ae78ebd0f7905b95b9e1c903 (patch) | |
tree | 9c04b59cdd2cd460f0727501d15402d31ffcf5a4 /libstdc++-v3/testsuite | |
parent | 1eb021edb27e26f95cda63df121f6bc951647599 (diff) | |
parent | c4f8f8afd07680f9e718de1331cd09607bdd9ac8 (diff) | |
download | gcc-1b09b78ee61bd921ae78ebd0f7905b95b9e1c903.zip gcc-1b09b78ee61bd921ae78ebd0f7905b95b9e1c903.tar.gz gcc-1b09b78ee61bd921ae78ebd0f7905b95b9e1c903.tar.bz2 |
Merge branch 'master' into devel/sphinx
Diffstat (limited to 'libstdc++-v3/testsuite')
14 files changed, 897 insertions, 127 deletions
diff --git a/libstdc++-v3/testsuite/18_support/105387.cc b/libstdc++-v3/testsuite/18_support/105387.cc new file mode 100644 index 0000000..c4a2345 --- /dev/null +++ b/libstdc++-v3/testsuite/18_support/105387.cc @@ -0,0 +1,63 @@ +// { dg-do run } + +#include <stdexcept> +#include <cxxabi.h> +#include <testsuite_hooks.h> + +// Test cases for PR libstdc++/105387 + +// This test is to trigger undefined behavior if the bug 105387 is present +// in the code. Note, however, given that the bug is present, this test runs +// into undefined behavior which can also mean that it passes. +// It has been observed to fail quite reliably on x86_64-linux-gnu but only +// fail sporadically on Xtensa, depending on the code placement. +void portable_test() +{ + bool exception_thrown = false; + try { + throw std::runtime_error("test"); + } catch (const char *e) { + VERIFY(false); + } catch (const std::exception &e) { + exception_thrown = true; + } + VERIFY(exception_thrown); +} + +// This test relies on the types defined in the files typeinfo and cxxabi.h +// It is therefore less portable then the test case above but should be +// guaranteed to fail if the implementation has the bug 105387. +// +// This test case checks that __pbase_type_info::__do_catch() behaves +// correctly when called with a non-pointer type info object as argument. +// In particular, __pbase_type_info::__do_catch() should not cast +// the given type object into a pointer type and try to access the +// extended fields. + +void non_portable_test() +{ + // Create a zero-initialized buffer for allocation of the type object + unsigned char buffer [sizeof(__cxxabiv1::__fundamental_type_info) * 2] = {}; + + // Use placement-new to create the fundamental type info object in the + // first half of the buffer. Whenever that type info object will be + // casted to a pointer type info object, the extended fields of the + // pointer type info object will be in the second half of the buffer + // and hence be guaranteed zero. + __cxxabiv1::__fundamental_type_info *p_fund_info + = new(buffer) __cxxabiv1::__fundamental_type_info("fund_type"); + + __cxxabiv1::__pointer_type_info ptr_info("ptr_type", 0, p_fund_info); + + // __do_catch is declared protected in __pointer_type_info, but public in + // type_info, so we upcast it here + std::type_info *abstract_ptr_info = static_cast<std::type_info*>(&ptr_info); + VERIFY(abstract_ptr_info->__do_catch(p_fund_info, 0, 1) == false); +} + +int main() +{ + portable_test(); + non_portable_test(); + return 0; +} diff --git a/libstdc++-v3/testsuite/18_support/105387_memptr.cc b/libstdc++-v3/testsuite/18_support/105387_memptr.cc new file mode 100644 index 0000000..f5612f4 --- /dev/null +++ b/libstdc++-v3/testsuite/18_support/105387_memptr.cc @@ -0,0 +1,25 @@ +#include <testsuite_hooks.h> + +// Test related to PR libstdc++/105387 +// Check that pointer-to-member type exceptions can still be caught with -frtti. +// { dg-require-effective-target rtti } + +void test_catch_ptr_to_member() +{ + bool exception_thrown = false; + struct X { int i; }; + try { + throw &X::i; + } + catch (const int X::*) { + exception_thrown = true; + } + + VERIFY(exception_thrown); +} + +int main() +{ + test_catch_ptr_to_member(); + return 0; +} diff --git a/libstdc++-v3/testsuite/20_util/from_chars/8.cc b/libstdc++-v3/testsuite/20_util/from_chars/8.cc new file mode 100644 index 0000000..ba34c2c --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/from_chars/8.cc @@ -0,0 +1,367 @@ +// Copyright (C) 2020-2022 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +// { dg-options "-std=gnu++2b" } +// { dg-do run { target c++23 } } +// { dg-add-options ieee } + +#include <charconv> +#include <string> +#include <limits> +#include <stdfloat> +#include <cmath> +#include <cstdlib> +#include <testsuite_hooks.h> + +// Test std::from_chars floating-point conversions. + +#if __cpp_lib_to_chars >= 201611L +#if defined(__STDCPP_FLOAT64_T__) && defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY64) +void +test01() +{ + std::string s; + std::float64_t f64; + std::from_chars_result res; + + for (auto fmt : { std::chars_format::fixed, std::chars_format::scientific, + std::chars_format::general, std::chars_format::hex }) + { + s = "Info"; + res = std::from_chars(s.data(), s.data() + s.length(), f64, fmt); + VERIFY( std::isinf(f64) ); + VERIFY( res.ptr == s.data() + 3 ); + VERIFY( res.ec == std::errc{} ); + + s = "-INFIN"; + res = std::from_chars(s.data(), s.data() + s.length(), f64, fmt); + VERIFY( std::isinf(f64) ); + VERIFY( f64 < 0 ); + VERIFY( res.ptr == s.data() + 4 ); + VERIFY( res.ec == std::errc{} ); + + s = "InFiNiTy aNd BeYoNd"; + res = std::from_chars(s.data(), s.data() + s.length(), f64, fmt); + VERIFY( std::isinf(f64) ); + VERIFY( res.ptr == s.data() + 8 ); + VERIFY( res.ec == std::errc{} ); + + s = "nAn"; + res = std::from_chars(s.data(), s.data() + s.length(), f64, fmt); + VERIFY( std::isnan(f64) ); + VERIFY( res.ptr == s.data() + 3 ); + VERIFY( res.ec == std::errc{} ); + + s = "-NAN()"; + res = std::from_chars(s.data(), s.data() + s.length(), f64, fmt); + VERIFY( std::isnan(f64) ); + VERIFY( res.ptr == s.data() + s.length() ); + VERIFY( res.ec == std::errc{} ); + } +} + +void +test02() +{ + std::string s; + std::float64_t f64 = 1.0f64; + std::from_chars_result res; + + s = "0x123"; + res = std::from_chars(s.data(), s.data() + s.length(), f64); + VERIFY( f64 == 0.0f64 ); + VERIFY( res.ptr == s.data() + 1 ); + VERIFY( res.ec == std::errc{} ); + + f64 = 1.0f64; + res = std::from_chars(s.data(), s.data() + s.length(), f64, + std::chars_format::fixed); + VERIFY( f64 == 0.0f64 ); + VERIFY( res.ptr == s.data() + 1 ); + VERIFY( res.ec == std::errc{} ); + + f64 = 1.0f64; + res = std::from_chars(s.data(), s.data() + s.length(), f64, + std::chars_format::scientific); + VERIFY( f64 == 1.0f64 ); + VERIFY( res.ptr == s.data() ); + VERIFY( res.ec == std::errc::invalid_argument ); + + f64 = 1.0f64; + res = std::from_chars(s.data(), s.data() + s.length(), f64, + std::chars_format::general); + VERIFY( f64 == 0.0f64 ); + VERIFY( res.ptr == s.data() + 1 ); + VERIFY( res.ec == std::errc{} ); + + f64 = 1.0f64; + res = std::from_chars(s.data(), s.data() + s.length(), f64, + std::chars_format::hex); + VERIFY( f64 == 0.0f64 ); + VERIFY( res.ptr == s.data() + 1 ); + VERIFY( res.ec == std::errc{} ); +} + +void +test03() +{ + std::string s; + std::float64_t f64 = 1.0f64; + std::from_chars_result res; + + s = "0.5e+2azzz"; + res = std::from_chars(s.data(), s.data() + s.length(), f64); + VERIFY( f64 == 0.5e+2f64 ); + VERIFY( res.ptr == s.data() + s.length() - 1 - 3 ); + VERIFY( res.ec == std::errc{} ); + + res = std::from_chars(s.data(), s.data() + s.length(), f64, + std::chars_format::fixed); + VERIFY( f64 == 0.5f64 ); + VERIFY( res.ptr == s.data() + 3 ); + VERIFY( res.ec == std::errc{} ); + + f64 = 1.0f64; + res = std::from_chars(s.data(), s.data() + s.length(), f64, + std::chars_format::scientific); + VERIFY( f64 == 0.5e+2f64 ); + VERIFY( res.ptr == s.data() + s.length() - 1 - 3 ); + VERIFY( res.ec == std::errc{} ); + + f64 = 1.0f64; + res = std::from_chars(s.data(), s.data() + s.length(), f64, + std::chars_format::general); + VERIFY( f64 == 0.5e+2f64 ); + VERIFY( res.ptr == s.data() + s.length() - 1 - 3 ); + VERIFY( res.ec == std::errc{} ); + + f64 = 1.0; + res = std::from_chars(s.data(), s.data() + s.length(), f64, + std::chars_format::hex); + VERIFY( f64 == 0x0.5Ep0f64 ); + VERIFY( res.ptr == s.data() + 4 ); + VERIFY( res.ec == std::errc{} ); + + s = "1.Ap-2zzz"; + res = std::from_chars(s.data(), s.data() + s.length(), f64, + std::chars_format::hex); + VERIFY( f64 == 0.40625f64 ); + VERIFY( res.ptr == s.data() + s.length() - 3 ); + VERIFY( res.ec == std::errc{} ); +} + +void +test04() +{ + // Huge input strings + std::string s(1000, '0'); + std::float64_t f64 = 1.0f64; + std::from_chars_result res; + res = std::from_chars(s.data(), s.data() + s.length(), f64); + VERIFY( res.ptr == s.data() + s.length() ); + VERIFY( res.ec == std::errc{} ); + VERIFY( f64 == 0.0f64 ); + + s += ".5"; + res = std::from_chars(s.data(), s.data() + s.length(), f64); + VERIFY( res.ptr == s.data() + s.length() ); + VERIFY( res.ec == std::errc{} ); + VERIFY( f64 == 0.5f64 ); + + s += "e2"; + auto len = s.length(); + s += std::string(1000, 'a'); + res = std::from_chars(s.data(), s.data() + s.length(), f64); + VERIFY( res.ptr == s.data() + len ); + VERIFY( res.ec == std::errc{} ); + VERIFY( f64 == 50.f64 ); +} +#endif + +using std::to_string; + +#ifdef __GLIBCXX_TYPE_INT_N_0 +std::string +to_string(unsigned __GLIBCXX_TYPE_INT_N_0 val) +{ + using Limits = std::numeric_limits<unsigned __GLIBCXX_TYPE_INT_N_0>; + std::string s(Limits::digits10+2, '0'); + for (auto iter = s.end(); val != 0; val /= 10) + *--iter = '0' + (val % 10); + return s; +} +#endif + +template<typename FloatT> +void +test_small_num() +{ + std::from_chars_result res; + FloatT flt; + + // Small integer values that are exactly representable + + for (int i = 0; i < 100; ++i) + { + std::string s = to_string(i); + int len = s.length(); + s += "123"; + const char* s1 = s.c_str(); + const char* s1_end = s1 + len; + + for (auto fmt : { std::chars_format::fixed, + std::chars_format::general, + std::chars_format::hex }) + { + if (fmt == std::chars_format::hex && i > 9) + continue; + + res = std::from_chars(s1, s1_end, flt, fmt); + VERIFY( res.ec == std::errc{} ); + VERIFY( res.ptr == s1_end ); + VERIFY( flt == i ); + } + + if (i > 9) + continue; + + // Test single-digit integers with small exponents. + + const char s2[] = { '.', *s1, 'e', '0', '0', '0', '1' }; + const char* s2_end = s2 + sizeof(s2); + + const char s3[] = { *s1, '0', 'e', '-', '0', '0', '1' }; + const char* s3_end = s3 + sizeof(s3); + + for (auto fmt : { std::chars_format::scientific, + std::chars_format::general }) + { + res = std::from_chars(s2, s2_end, flt, fmt); + VERIFY( res.ec == std::errc{} ); + VERIFY( res.ptr == s2_end ); + VERIFY( flt == i ); + + res = std::from_chars(s3, s3_end, flt, fmt); + VERIFY( res.ec == std::errc{} ); + VERIFY( res.ptr == s3_end ); + VERIFY( flt == i ); + } + } +} + +void +test05() +{ +#if defined(__STDCPP_FLOAT32_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32) + test_small_num<std::float32_t>(); +#endif +#if defined(__STDCPP_FLOAT64_T__) && defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY64) + test_small_num<std::float64_t>(); +#endif +#if defined(__STDCPP_FLOAT128_T__) && defined(_GLIBCXX_LDOUBLE_IS_IEEE_BINARY128) + test_small_num<std::float128_t>(); +#endif +} + +template<typename FloatT, typename UIntT> +void +test_max_mantissa() +{ + using Float_limits = std::numeric_limits<FloatT>; + using UInt_limits = std::numeric_limits<UIntT>; + + if (Float_limits::is_iec559 && Float_limits::digits < UInt_limits::digits) + { +#ifdef _GLIBCXX_USE_C99_MATH_TR1 + std::printf("Testing %d-bit float, using %zu-bit integer\n", + Float_limits::digits + (int)std::log2(Float_limits::max_exponent) + 1, + sizeof(UIntT) * __CHAR_BIT__); +#endif + + std::from_chars_result res; + FloatT flt; + + for (int i = 0; i < 10; ++i) + { + // (1 << digits) - 1 is the maximum value of the mantissa + const auto val = ((UIntT)1 << Float_limits::digits) - 1 - i; + std::string s = to_string(val); + auto len = s.length(); + s += "000"; // these should be ignored + for (auto fmt : { std::chars_format::fixed, + std::chars_format::general }) + { + res = std::from_chars(s.data(), s.data() + len, flt, fmt); + VERIFY( res.ec == std::errc{} ); + VERIFY( res.ptr == s.data() + len ); + VERIFY( flt == val ); + } + s.resize(len); + const auto orig_len = len; + s += "e+000"; + len = s.length(); + s += "111"; + for (auto fmt : { std::chars_format::scientific, + std::chars_format::general }) + { + res = std::from_chars(s.data(), s.data() + len, flt, fmt); + VERIFY( res.ec == std::errc{} ); + VERIFY( res.ptr == s.data() + len ); + VERIFY( flt == val ); + + std::string s2 = s.substr(0, len - 5); + s2.insert(s2.begin() + orig_len - 1, '.'); + s2 += "e000000000001"; + res = std::from_chars(s.data(), s.data() + len, flt, fmt); + VERIFY( res.ec == std::errc{} ); + VERIFY( res.ptr == s.data() + len ); + VERIFY( flt == val ); + } + } + } +} + +void +test06() +{ +#if defined(__STDCPP_FLOAT32_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32) + test_max_mantissa<std::float32_t, unsigned long>(); +#endif +#if defined(__STDCPP_FLOAT64_T__) && defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY64) + test_max_mantissa<std::float64_t, unsigned long long>(); +#endif +#if defined(__GLIBCXX_TYPE_INT_N_0) \ + && defined(__STDCPP_FLOAT128_T__) && defined(_GLIBCXX_LDOUBLE_IS_IEEE_BINARY128) + test_max_mantissa<std::float128_t, unsigned __GLIBCXX_TYPE_INT_N_0>(); +#endif +} +#endif + +int +main() +{ +#if __cpp_lib_to_chars >= 201611L +#if defined(__STDCPP_FLOAT64_T__) && defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY64) + test01(); + test02(); + test03(); + test04(); +#endif + test05(); + test06(); +#endif +} diff --git a/libstdc++-v3/testsuite/20_util/to_chars/double.cc b/libstdc++-v3/testsuite/20_util/to_chars/double.cc index 9a965d2..ac9a430 100644 --- a/libstdc++-v3/testsuite/20_util/to_chars/double.cc +++ b/libstdc++-v3/testsuite/20_util/to_chars/double.cc @@ -2821,8 +2821,8 @@ inline constexpr double_to_chars_testcase double_to_chars_test_cases[] = { // Test hexfloat corner cases. {0x1.728p+0, chars_format::hex, "1.728p+0"}, // instead of "2.e5p-1" - {0x0.0000000000001p-1022, chars_format::hex, "0.0000000000001p-1022"}, // instead of "1p-1074", min subnormal - {0x0.fffffffffffffp-1022, chars_format::hex, "0.fffffffffffffp-1022"}, // max subnormal + {0x0.0000000000001p-1022, chars_format::hex, "1p-1074"}, // min subnormal + {0x0.fffffffffffffp-1022, chars_format::hex, "1.ffffffffffffep-1023"}, // max subnormal {0x1p-1022, chars_format::hex, "1p-1022"}, // min normal {0x1.fffffffffffffp+1023, chars_format::hex, "1.fffffffffffffp+1023"}, // max normal diff --git a/libstdc++-v3/testsuite/20_util/to_chars/float.cc b/libstdc++-v3/testsuite/20_util/to_chars/float.cc index bcbd78f..5a5de63 100644 --- a/libstdc++-v3/testsuite/20_util/to_chars/float.cc +++ b/libstdc++-v3/testsuite/20_util/to_chars/float.cc @@ -521,8 +521,8 @@ inline constexpr float_to_chars_testcase float_to_chars_test_cases[] = { // Test hexfloat corner cases. {0x1.728p+0f, chars_format::hex, "1.728p+0"}, // instead of "2.e5p-1" - {0x0.000002p-126f, chars_format::hex, "0.000002p-126"}, // instead of "1p-149", min subnormal - {0x0.fffffep-126f, chars_format::hex, "0.fffffep-126"}, // max subnormal + {0x0.000002p-126f, chars_format::hex, "1p-149"}, // min subnormal + {0x0.fffffep-126f, chars_format::hex, "1.fffffcp-127"}, // max subnormal {0x1p-126f, chars_format::hex, "1p-126"}, // min normal {0x1.fffffep+127f, chars_format::hex, "1.fffffep+127"}, // max normal diff --git a/libstdc++-v3/testsuite/20_util/to_chars/float16_c++23.cc b/libstdc++-v3/testsuite/20_util/to_chars/float16_c++23.cc new file mode 100644 index 0000000..db93537 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/to_chars/float16_c++23.cc @@ -0,0 +1,76 @@ +// Copyright (C) 2022 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +// { dg-options "-std=gnu++2b" } +// { dg-do run { target c++23 } } +// { dg-require-effective-target ieee_floats } +// { dg-require-effective-target size32plus } +// { dg-add-options ieee } + +#include <charconv> +#include <stdfloat> +#include <iostream> +#include <cmath> +#include <testsuite_hooks.h> + +template<typename T> +void +test(std::chars_format fmt = std::chars_format{}) +{ + char str1[128], str2[128], str3[128]; + union U { unsigned short s; T f; } u, v; + for (int i = 0; i <= (unsigned short) ~0; ++i) + { + u.s = i; + auto [ptr1, ec1] = std::to_chars(str1, str1 + sizeof(str1), u.f, fmt); + auto [ptr2, ec2] = std::to_chars(str2, str2 + sizeof(str2), std::float32_t(u.f), fmt); + VERIFY( ec1 == std::errc() && ec2 == std::errc()); +// std::cout << i << ' ' << std::string_view (str1, ptr1) +// << '\t' << std::string_view (str2, ptr2) << '\n'; + if (fmt == std::chars_format::fixed) + { + auto [ptr3, ec3] = std::to_chars(str3, str3 + (ptr1 - str1), u.f, fmt); + VERIFY( ec3 == std::errc() && ptr3 - str3 == ptr1 - str1 ); + auto [ptr4, ec4] = std::to_chars(str3, str3 + (ptr1 - str1 - 1), u.f, fmt); + VERIFY( ec4 != std::errc() ); + } + auto [ptr5, ec5] = std::from_chars(str1, ptr1, v.f, + fmt == std::chars_format{} + ? std::chars_format::general : fmt); + VERIFY( ec5 == std::errc() && ptr5 == ptr1 ); + VERIFY( u.s == v.s || (std::isnan(u.f) && std::isnan(v.f)) ); + } +} + +int +main() +{ +#ifdef __STDCPP_FLOAT16_T__ + test<std::float16_t>(); + test<std::float16_t>(std::chars_format::fixed); + test<std::float16_t>(std::chars_format::scientific); + test<std::float16_t>(std::chars_format::general); + test<std::float16_t>(std::chars_format::hex); +#endif +#ifdef __STDCPP_BFLOAT16_T__ + test<std::bfloat16_t>(); + test<std::bfloat16_t>(std::chars_format::fixed); + test<std::bfloat16_t>(std::chars_format::scientific); + test<std::bfloat16_t>(std::chars_format::general); + test<std::bfloat16_t>(std::chars_format::hex); +#endif +} diff --git a/libstdc++-v3/testsuite/25_algorithms/copy/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/copy/constrained.cc index 98f038a..444dfa7 100644 --- a/libstdc++-v3/testsuite/25_algorithms/copy/constrained.cc +++ b/libstdc++-v3/testsuite/25_algorithms/copy/constrained.cc @@ -226,6 +226,29 @@ test06() VERIFY( ranges::equal(v, (int[]){1,2,3,0}) ); } +void +test07() +{ + struct move_only_output_iterator + { + using value_type = int; + using difference_type = short; + using iterator_category = std::output_iterator_tag; + + move_only_output_iterator() = default; + move_only_output_iterator(move_only_output_iterator&&) = default; + move_only_output_iterator& operator=(move_only_output_iterator&&) = default; + + move_only_output_iterator& operator*() { return *this; } + move_only_output_iterator& operator++() { return *this; } + move_only_output_iterator operator++(int) { return std::move(*this); } + + void operator=(int) { } + }; + + ranges::copy(std::vector<int>{1,2,3}, move_only_output_iterator{}); +} + int main() { @@ -235,4 +258,5 @@ main() test04(); static_assert(test05()); test06(); + test07(); } diff --git a/libstdc++-v3/testsuite/26_numerics/complex/ext_c++23.cc b/libstdc++-v3/testsuite/26_numerics/complex/ext_c++23.cc new file mode 100644 index 0000000..bdc9af0 --- /dev/null +++ b/libstdc++-v3/testsuite/26_numerics/complex/ext_c++23.cc @@ -0,0 +1,89 @@ +// Copyright (C) 2022 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +// { dg-options "-std=gnu++2b" } +// { dg-do link { target c++23 } } + +#include <stdfloat> +#include <complex> + +template <typename T> +__attribute__((__noipa__)) void +test_functions(T *p, std::complex<T> *q) +{ + p[0] = std::abs(q[0]); + p[1] = std::arg(q[1]); + q[2] = std::cos(q[2]); + q[3] = std::cosh(q[3]); + q[4] = std::exp(q[4]); + q[5] = std::log(q[5]); + q[6] = std::sin(q[6]); + q[7] = std::sinh(q[7]); + q[8] = std::sqrt(q[8]); + q[9] = std::tan(q[9]); + q[10] = std::tanh(q[10]); + q[11] = std::pow(q[11], q[19]); + q[12] = std::acos(q[12]); + q[13] = std::asin(q[13]); + q[14] = std::atan(q[14]); + q[15] = std::acosh(q[15]); + q[16] = std::asinh(q[16]); + q[17] = std::atanh(q[17]); + q[18] = std::proj(q[18]); +} + +int +main() +{ +#if defined(__STDCPP_FLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32) + { + std::float16_t p[2] = {}; + std::complex<std::float16_t> q[20] = {}; + test_functions(p, q); + } +#endif +#if defined(__STDCPP_FLOAT32_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32) + { + std::float32_t p[2] = {}; + std::complex<std::float32_t> q[20] = {}; + test_functions(p, q); + } +#endif +#if defined(__STDCPP_FLOAT64_T__) && defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY64) + { + std::float64_t p[2] = {}; + std::complex<std::float64_t> q[20] = {}; + test_functions(p, q); + } +#endif +#if defined(__STDCPP_FLOAT128_T__) \ + && (defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY128) \ + || defined(_GLIBCXX_HAVE_FLOAT128_MATH)) + { + std::float128_t p[2] = {}; + std::complex<std::float128_t> q[20] = {}; + test_functions(p, q); + } +#endif +#if defined(__STDCPP_BFLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32) + { + std::bfloat16_t p[2] = {}; + std::complex<std::bfloat16_t> q[20] = {}; + test_functions(p, q); + } +#endif +} diff --git a/libstdc++-v3/testsuite/26_numerics/headers/cmath/c99_classification_macros_c++23.cc b/libstdc++-v3/testsuite/26_numerics/headers/cmath/c99_classification_macros_c++23.cc index 0fda6a7..193e77b 100644 --- a/libstdc++-v3/testsuite/26_numerics/headers/cmath/c99_classification_macros_c++23.cc +++ b/libstdc++-v3/testsuite/26_numerics/headers/cmath/c99_classification_macros_c++23.cc @@ -15,6 +15,7 @@ // with this library; see the file COPYING3. If not see // <http://www.gnu.org/licenses/>. +// { dg-options "-std=gnu++2b" } // { dg-do link { target c++23 } } // { dg-excess-errors "" { target uclibc } } diff --git a/libstdc++-v3/testsuite/26_numerics/headers/cmath/functions_std_c++23.cc b/libstdc++-v3/testsuite/26_numerics/headers/cmath/functions_std_c++23.cc index 190f8d1..99436b8 100644 --- a/libstdc++-v3/testsuite/26_numerics/headers/cmath/functions_std_c++23.cc +++ b/libstdc++-v3/testsuite/26_numerics/headers/cmath/functions_std_c++23.cc @@ -15,6 +15,7 @@ // with this library; see the file COPYING3. If not see // <http://www.gnu.org/licenses/>. +// { dg-options "-std=gnu++2b" } // { dg-do link { target c++23 } } #include <stdfloat> @@ -22,91 +23,91 @@ template <typename T> __attribute__((__noipa__)) void -test_functions (T *p, int *q, long int *r, long long int *s) +test_functions(T *p, int *q, long int *r, long long int *s) { - p[0] = std::acos (p[0]); - p[1] = std::asin (p[1]); - p[2] = std::atan (p[2]); - p[3] = std::cos (p[3]); - p[4] = std::sin (p[4]); - p[5] = std::tan (p[5]); - p[6] = std::acosh (p[6]); - p[7] = std::asinh (p[7]); - p[8] = std::atanh (p[8]); - p[9] = std::cosh (p[9]); - p[10] = std::sinh (p[10]); - p[11] = std::tanh (p[11]); - p[12] = std::exp (p[12]); - p[13] = std::exp2 (p[13]); - p[14] = std::expm1 (p[14]); - p[15] = std::log (p[15]); - p[16] = std::log10 (p[16]); - p[17] = std::log1p (p[17]); - p[18] = std::log2 (p[18]); - p[19] = std::logb (p[19]); - p[20] = std::cbrt (p[20]); - p[21] = std::fabs (p[21]); - p[22] = std::sqrt (p[22]); - p[23] = std::erf (p[23]); - p[24] = std::erfc (p[24]); - p[25] = std::lgamma (p[25]); - p[26] = std::tgamma (p[26]); - p[27] = std::ceil (p[27]); - p[28] = std::floor (p[28]); - p[29] = std::nearbyint (p[29]); - p[30] = std::rint (p[30]); - p[31] = std::round (p[31]); - p[32] = std::trunc (p[32]); - p[33] = std::atan2 (p[33], p[100]); - p[34] = std::hypot (p[34], p[101]); - p[35] = std::pow (p[35], p[102]); - p[36] = std::fmod (p[36], p[103]); - p[37] = std::remainder (p[37], p[104]); - p[38] = std::copysign (p[38], p[105]); - p[39] = std::nextafter (p[39], p[106]); - p[40] = std::fdim (p[40], p[107]); - p[41] = std::fmax (p[41], p[108]); - p[42] = std::fmin (p[42], p[109]); - p[43] = std::atan2 (p[43], p[110]); - p[44] = std::frexp (p[44], q + 0); - q[1] = std::ilogb (p[45]); - p[46] = std::ldexp (p[46], q[2]); - p[47] = std::modf (p[47], p + 111); - p[48] = std::scalbn (p[48], q[3]); - p[49] = std::scalbln (p[49], r[0]); - p[50] = std::hypot (p[50], p[111], p[112]); - r[1] = std::lrint (p[51]); - s[0] = std::llrint (p[52]); - r[2] = std::lround (p[53]); - s[1] = std::llround (p[54]); - p[55] = std::remquo (p[55], p[113], q + 4); - p[56] = std::fma (p[56], p[114], p[115]); - p[57] = std::lerp (p[57], p[116], p[117]); - p[58] = std::assoc_laguerre (q[5], q[6], p[58]); - p[59] = std::assoc_legendre (q[7], q[8], p[59]); - p[60] = std::beta (p[60], p[118]); - p[61] = std::comp_ellint_1 (p[61]); - p[62] = std::comp_ellint_2 (p[62]); - p[63] = std::comp_ellint_3 (p[63], p[119]); - p[64] = std::cyl_bessel_i (p[64], p[120]); - p[65] = std::cyl_bessel_j (p[65], p[121]); - p[66] = std::cyl_bessel_k (p[66], p[122]); - p[67] = std::cyl_neumann (p[67], p[123]); - p[68] = std::ellint_1 (p[68], p[124]); - p[69] = std::ellint_2 (p[69], p[125]); - p[70] = std::ellint_3 (p[70], p[126], p[127]); - p[71] = std::expint (p[71]); - p[72] = std::hermite (q[9], p[72]); - p[73] = std::laguerre (q[10], p[73]); - p[74] = std::legendre (q[11], p[72]); - p[75] = std::riemann_zeta (p[75]); - p[76] = std::sph_bessel (q[12], p[76]); - p[77] = std::sph_legendre (q[13], q[14], p[77]); - p[78] = std::sph_neumann (q[15], p[78]); + p[0] = std::acos(p[0]); + p[1] = std::asin(p[1]); + p[2] = std::atan(p[2]); + p[3] = std::cos(p[3]); + p[4] = std::sin(p[4]); + p[5] = std::tan(p[5]); + p[6] = std::acosh(p[6]); + p[7] = std::asinh(p[7]); + p[8] = std::atanh(p[8]); + p[9] = std::cosh(p[9]); + p[10] = std::sinh(p[10]); + p[11] = std::tanh(p[11]); + p[12] = std::exp(p[12]); + p[13] = std::exp2(p[13]); + p[14] = std::expm1(p[14]); + p[15] = std::log(p[15]); + p[16] = std::log10(p[16]); + p[17] = std::log1p(p[17]); + p[18] = std::log2(p[18]); + p[19] = std::logb(p[19]); + p[20] = std::cbrt(p[20]); + p[21] = std::fabs(p[21]); + p[22] = std::sqrt(p[22]); + p[23] = std::erf(p[23]); + p[24] = std::erfc(p[24]); + p[25] = std::lgamma(p[25]); + p[26] = std::tgamma(p[26]); + p[27] = std::ceil(p[27]); + p[28] = std::floor(p[28]); + p[29] = std::nearbyint(p[29]); + p[30] = std::rint(p[30]); + p[31] = std::round(p[31]); + p[32] = std::trunc(p[32]); + p[33] = std::atan2(p[33], p[100]); + p[34] = std::hypot(p[34], p[101]); + p[35] = std::pow(p[35], p[102]); + p[36] = std::fmod(p[36], p[103]); + p[37] = std::remainder(p[37], p[104]); + p[38] = std::copysign(p[38], p[105]); + p[39] = std::nextafter(p[39], p[106]); + p[40] = std::fdim(p[40], p[107]); + p[41] = std::fmax(p[41], p[108]); + p[42] = std::fmin(p[42], p[109]); + p[43] = std::atan2(p[43], p[110]); + p[44] = std::frexp(p[44], q + 0); + q[1] = std::ilogb(p[45]); + p[46] = std::ldexp(p[46], q[2]); + p[47] = std::modf(p[47], p + 111); + p[48] = std::scalbn(p[48], q[3]); + p[49] = std::scalbln(p[49], r[0]); + p[50] = std::hypot(p[50], p[111], p[112]); + r[1] = std::lrint(p[51]); + s[0] = std::llrint(p[52]); + r[2] = std::lround(p[53]); + s[1] = std::llround(p[54]); + p[55] = std::remquo(p[55], p[113], q + 4); + p[56] = std::fma(p[56], p[114], p[115]); + p[57] = std::lerp(p[57], p[116], p[117]); + p[58] = std::assoc_laguerre(q[5], q[6], p[58]); + p[59] = std::assoc_legendre(q[7], q[8], p[59]); + p[60] = std::beta(p[60], p[118]); + p[61] = std::comp_ellint_1(p[61]); + p[62] = std::comp_ellint_2(p[62]); + p[63] = std::comp_ellint_3(p[63], p[119]); + p[64] = std::cyl_bessel_i(p[64], p[120]); + p[65] = std::cyl_bessel_j(p[65], p[121]); + p[66] = std::cyl_bessel_k(p[66], p[122]); + p[67] = std::cyl_neumann(p[67], p[123]); + p[68] = std::ellint_1(p[68], p[124]); + p[69] = std::ellint_2(p[69], p[125]); + p[70] = std::ellint_3(p[70], p[126], p[127]); + p[71] = std::expint(p[71]); + p[72] = std::hermite(q[9], p[72]); + p[73] = std::laguerre(q[10], p[73]); + p[74] = std::legendre(q[11], p[72]); + p[75] = std::riemann_zeta(p[75]); + p[76] = std::sph_bessel(q[12], p[76]); + p[77] = std::sph_legendre(q[13], q[14], p[77]); + p[78] = std::sph_neumann(q[15], p[78]); } int -main () +main() { int q[16] = {}; long int r[16] = {}; @@ -114,19 +115,19 @@ main () #if defined(__STDCPP_FLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32) { std::float16_t p[128] = {}; - test_functions (p, q, r, s); + test_functions(p, q, r, s); } #endif #if defined(__STDCPP_FLOAT32_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32) { std::float32_t p[128] = {}; - test_functions (p, q, r, s); + test_functions(p, q, r, s); } #endif #if defined(__STDCPP_FLOAT64_T__) && defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY64) { std::float64_t p[128] = {}; - test_functions (p, q, r, s); + test_functions(p, q, r, s); } #endif #if defined(__STDCPP_FLOAT128_T__) \ @@ -134,13 +135,13 @@ main () || defined(_GLIBCXX_HAVE_FLOAT128_MATH)) { std::float128_t p[128] = {}; - test_functions (p, q, r, s); + test_functions(p, q, r, s); } #endif #if defined(__STDCPP_BFLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32) { std::bfloat16_t p[128] = {}; - test_functions (p, q, r, s); + test_functions(p, q, r, s); } #endif } diff --git a/libstdc++-v3/testsuite/26_numerics/headers/cmath/nextafter_c++23.cc b/libstdc++-v3/testsuite/26_numerics/headers/cmath/nextafter_c++23.cc index 45aa3b7..c105901 100644 --- a/libstdc++-v3/testsuite/26_numerics/headers/cmath/nextafter_c++23.cc +++ b/libstdc++-v3/testsuite/26_numerics/headers/cmath/nextafter_c++23.cc @@ -29,77 +29,79 @@ test () { using lim = std::numeric_limits<T>; T t0 = std::nextafter(T(-0.0), T(2.0)); - VERIFY(t0 == lim::denorm_min()); + VERIFY( t0 == lim::denorm_min() ); T t1 = std::nextafter(T(), T(1.0)); - VERIFY(t1 == lim::denorm_min()); + VERIFY( t1 == lim::denorm_min() ); T t2 = std::nextafter(T(), T()); - VERIFY(t2 == T() && !std::signbit(t2)); + VERIFY( t2 == T() && !std::signbit(t2) ); T t3 = std::nextafter(lim::denorm_min(), T(-2.0)); - VERIFY(t3 == T() && !std::signbit(t3)); + VERIFY( t3 == T() && !std::signbit(t3) ); T t4 = std::nextafter(lim::min(), T(-0.0)); - VERIFY(std::fpclassify(t4) == FP_SUBNORMAL && t4 > T()); + VERIFY( std::fpclassify(t4) == FP_SUBNORMAL && t4 > T() ); T t5 = std::nextafter(t4, T(1.0)); - VERIFY(t5 == lim::min()); + VERIFY( t5 == lim::min() ); T t6 = std::nextafter(lim::min(), lim::infinity()); - VERIFY(std::fpclassify(t6) == FP_NORMAL && t6 > lim::min()); + VERIFY( std::fpclassify(t6) == FP_NORMAL && t6 > lim::min() ); T t7 = std::nextafter(t6, -lim::infinity()); - VERIFY(t7 == lim::min()); + VERIFY( t7 == lim::min() ); T t8 = std::nextafter(T(16.0), T(16.5)); - VERIFY(t8 > t7); + VERIFY( t8 > t7 ); T t9 = std::nextafter(t8, T(15.5)); - VERIFY(t9 == T(16.0)); + VERIFY( t9 == T(16.0) ); T t10 = std::nextafter(lim::max(), T(-0.5)); - VERIFY(std::fpclassify(t10) == FP_NORMAL && t10 < lim::max()); + VERIFY( std::fpclassify(t10) == FP_NORMAL && t10 < lim::max() ); T t11 = std::nextafter(t10, lim::infinity()); - VERIFY(t11 == lim::max()); + VERIFY( t11 == lim::max() ); T t12 = std::nextafter(t11, lim::infinity()); - VERIFY(std::fpclassify(t12) == FP_INFINITE && !std::signbit(t12)); + VERIFY( std::fpclassify(t12) == FP_INFINITE && !std::signbit(t12) ); T t13 = std::nextafter(lim::infinity(), t12); - VERIFY(t13 == t12); + VERIFY( t13 == t12 ); T t14 = std::nextafter(t13, T(1.0)); - VERIFY(t14 == lim::max()); + VERIFY( t14 == lim::max() ); T t15 = std::nextafter(lim::quiet_NaN(), T()); - VERIFY(std::fpclassify(t15) == FP_NAN); + VERIFY( std::fpclassify(t15) == FP_NAN ); T t16 = std::nextafter(T(17.0), lim::quiet_NaN()); - VERIFY(std::fpclassify(t16) == FP_NAN); + VERIFY( std::fpclassify(t16) == FP_NAN ); T t17 = std::nextafter(T(), T(-0.0)); - VERIFY(t17 == T() && std::signbit(t17)); + VERIFY( t17 == T() && std::signbit(t17) ); T t20 = std::nextafter(T(-0.0), T(-2.0)); - VERIFY(t20 == -lim::denorm_min()); + VERIFY( t20 == -lim::denorm_min() ); T t21 = std::nextafter(T(), T(-1.0)); - VERIFY(t21 == -lim::denorm_min()); + VERIFY( t21 == -lim::denorm_min() ); T t22 = std::nextafter(T(-0.0), T(-0.0)); - VERIFY(t22 == T() && std::signbit(t22)); + VERIFY( t22 == T() && std::signbit(t22) ); T t23 = std::nextafter(-lim::denorm_min(), T(2.0)); - VERIFY(t23 == T() && std::signbit(t23)); + VERIFY( t23 == T() && std::signbit(t23) ); T t24 = std::nextafter(-lim::min(), T()); - VERIFY(std::fpclassify(t24) == FP_SUBNORMAL && t24 < T()); + VERIFY( std::fpclassify(t24) == FP_SUBNORMAL && t24 < T() ); T t25 = std::nextafter(t24, T(-1.0)); - VERIFY(t25 == -lim::min()); + VERIFY( t25 == -lim::min() ); T t26 = std::nextafter(-lim::min(), -lim::infinity()); - VERIFY(std::fpclassify(t26) == FP_NORMAL && t26 < -lim::min()); + VERIFY( std::fpclassify(t26) == FP_NORMAL && t26 < -lim::min() ); T t27 = std::nextafter(t26, lim::infinity()); - VERIFY(t27 == -lim::min()); + VERIFY( t27 == -lim::min() ); T t28 = std::nextafter(T(-16.0), T(-16.5)); - VERIFY(t28 < t27); + VERIFY( t28 < t27 ); T t29 = std::nextafter(t28, T(-15.5)); - VERIFY(t29 == T(-16.0)); + VERIFY( t29 == T(-16.0) ); T t30 = std::nextafter(-lim::max(), T(0.5)); - VERIFY(std::fpclassify(t30) == FP_NORMAL && t30 > -lim::max()); + VERIFY( std::fpclassify(t30) == FP_NORMAL && t30 > -lim::max() ); T t31 = std::nextafter(t30, -lim::infinity()); - VERIFY(t31 == -lim::max()); + VERIFY( t31 == -lim::max() ); T t32 = std::nextafter(t31, -lim::infinity()); - VERIFY(std::fpclassify(t32) == FP_INFINITE && std::signbit(t32)); + VERIFY( std::fpclassify(t32) == FP_INFINITE && std::signbit(t32) ); T t33 = std::nextafter(-lim::infinity(), t32); - VERIFY(t33 == t32); + VERIFY( t33 == t32 ); T t34 = std::nextafter(t33, T(-1.0)); - VERIFY(t34 == -lim::max()); + VERIFY( t34 == -lim::max() ); T t35 = std::nextafter(-lim::quiet_NaN(), T()); - VERIFY(std::fpclassify(t35) == FP_NAN); + VERIFY( std::fpclassify(t35) == FP_NAN ); T t36 = std::nextafter(T(-17.0), lim::quiet_NaN()); - VERIFY(std::fpclassify(t36) == FP_NAN); + VERIFY( std::fpclassify(t36) == FP_NAN ); T t37 = std::nextafter(T(-0.0), T()); - VERIFY(t37 == T() && !std::signbit(t37)); + VERIFY( t37 == T() && !std::signbit(t37) ); + static_assert(std::nextafter(T(1.0), T(2.0)) > T(1.0)); + static_assert(std::nextafter(std::nextafter(T(1.0), T(5.0)), T(0.0)) == T(1.0)); } int diff --git a/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/107376.cc b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/107376.cc new file mode 100644 index 0000000..da4f7ad --- /dev/null +++ b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/107376.cc @@ -0,0 +1,76 @@ +// { dg-do run { target c++11 } } +#include <regex> +#include <testsuite_hooks.h> +#include <testsuite_allocator.h> + +template<typename T> +struct Alloc +{ + using value_type = T; + explicit Alloc(int) { } + template<typename U> Alloc(const Alloc&) { } + + T* allocate(std::size_t n) + { return std::allocator<T>().allocate(n); } + void deallocate(T* ptr, std::size_t n) + { std::allocator<T>().deallocate(ptr, n); } + + bool operator==(const Alloc&) const { return true; } + bool operator!=(const Alloc&) const { return false; } +}; + +void +test_non_default_constructible() +{ + using sub_match = std::sub_match<const char*>; + using alloc_type = Alloc<sub_match>; + using match_results = std::match_results<const char*, alloc_type>; + match_results res(alloc_type(1)); + + std::regex_match("x", res, std::regex(".")); // PR libstdc++/107376 +} + +template<typename T> +struct PropAlloc +{ + int id; + + using value_type = T; + explicit PropAlloc(int id) : id(id) { } + template<typename U> PropAlloc(const PropAlloc& a) : id(a.id) { } + + using propagate_on_container_move_assignment = std::true_type; + using propagate_on_container_copy_assignment = std::true_type; + + PropAlloc select_on_container_copy_construction() const + { return PropAlloc(0); } + + T* allocate(std::size_t n) + { return std::allocator<T>().allocate(n); } + void deallocate(T* ptr, std::size_t n) + { std::allocator<T>().deallocate(ptr, n); } + + bool operator==(const PropAlloc& a) const { return id == a.id; } + bool operator!=(const PropAlloc& a) const { return id != a.id; } +}; + +void +test_propagation() +{ + using sub_match = std::sub_match<const char*>; + using alloc_type = PropAlloc<sub_match>; + using match_results = std::match_results<const char*, alloc_type>; + alloc_type alloc(107376); + match_results res(alloc); + + std::regex re("..", std::regex_constants::__polynomial); + std::regex_match("xx", res, re); + + VERIFY( res.get_allocator() == alloc ); +} + +int main() +{ + test_non_default_constructible(); + test_propagation(); +} diff --git a/libstdc++-v3/testsuite/Makefile.in b/libstdc++-v3/testsuite/Makefile.in index 328a036..5081fdf 100644 --- a/libstdc++-v3/testsuite/Makefile.in +++ b/libstdc++-v3/testsuite/Makefile.in @@ -103,7 +103,6 @@ am__aclocal_m4_deps = $(top_srcdir)/../config/acx.m4 \ $(top_srcdir)/../config/multi.m4 \ $(top_srcdir)/../config/no-executables.m4 \ $(top_srcdir)/../config/override.m4 \ - $(top_srcdir)/../config/stdint.m4 \ $(top_srcdir)/../config/toolexeclibdir.m4 \ $(top_srcdir)/../config/unwind_ipinfo.m4 \ $(top_srcdir)/../libtool.m4 $(top_srcdir)/../ltoptions.m4 \ diff --git a/libstdc++-v3/testsuite/experimental/propagate_const/observers/107525.cc b/libstdc++-v3/testsuite/experimental/propagate_const/observers/107525.cc new file mode 100644 index 0000000..e7ecff7 --- /dev/null +++ b/libstdc++-v3/testsuite/experimental/propagate_const/observers/107525.cc @@ -0,0 +1,47 @@ +// { dg-do run { target c++14 } } + +#include <experimental/propagate_const> +#include <testsuite_hooks.h> + +using std::experimental::propagate_const; + +void +test_base_conversion() +{ + struct Base { }; + struct Derived : Base { }; + + static_assert(std::is_convertible<propagate_const<Derived*>, Base*>::value, + "PR libstdc++/107525 - SFINAE breaks conversion operators"); + static_assert(std::is_convertible<const propagate_const<Derived*>, const Base*>::value, + "PR libstdc++/107525 - SFINAE breaks conversion operators"); +} + +void +test_const_conversion() +{ + struct X + { + int* p = nullptr; + + int& operator*() const { return *p; } + int* operator->() const { return p; } + int* get() const { return p; } + + operator int*() { return p; } + operator const int*() const = delete; + }; + + static_assert(!std::is_convertible_v<const X, const int*>, + "Cannot convert const X to const int*"); + // So should not be able to convert const propagate_const<X> to const int*. + static_assert(!std::is_convertible_v<const propagate_const<X>, const int*>, + "So should not be able to convert const propagate_const<X> to " + "const int* (although this is not what LFTSv3 says)"); +} + +int main() +{ + test_base_conversion(); + test_const_conversion(); +} |