diff --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst --- a/libcxx/docs/FeatureTestMacroTable.rst +++ b/libcxx/docs/FeatureTestMacroTable.rst @@ -196,7 +196,7 @@ ------------------------------------------------- ----------------- ``__cpp_lib_bounded_array_traits`` ``201902L`` ------------------------------------------------- ----------------- - ``__cpp_lib_char8_t`` ``201811L`` + ``__cpp_lib_char8_t`` ``201907L`` ------------------------------------------------- ----------------- ``__cpp_lib_concepts`` ``202002L`` ------------------------------------------------- ----------------- diff --git a/libcxx/docs/ReleaseNotes.rst b/libcxx/docs/ReleaseNotes.rst --- a/libcxx/docs/ReleaseNotes.rst +++ b/libcxx/docs/ReleaseNotes.rst @@ -49,6 +49,7 @@ - P0618R0 (Deprecating ) - P2418R2 (Add support for ``std::generator``-like types to ``std::format``) - LWG3659 (Consider ``ATOMIC_FLAG_INIT`` undeprecation) +- P1423R3 (char8_t backward compatibility remediation) - Marked the following papers as "Complete" (note that some of those might have been implemented in a previous release but not marked as such): diff --git a/libcxx/docs/Status/Cxx20Papers.csv b/libcxx/docs/Status/Cxx20Papers.csv --- a/libcxx/docs/Status/Cxx20Papers.csv +++ b/libcxx/docs/Status/Cxx20Papers.csv @@ -115,7 +115,7 @@ "`P1208R6 `__","LWG","Adopt source_location for C++20","Cologne","","" "`P1355R2 `__","LWG","Exposing a narrow contract for ceil2","Cologne","|Complete|","9.0" "`P1361R2 `__","LWG","Integration of chrono with text formatting","Cologne","","" -"`P1423R3 `__","LWG","char8_t backward compatibility remediation","Cologne","|In Progress|","" +"`P1423R3 `__","LWG","char8_t backward compatibility remediation","Cologne","|Complete|","15.0" "`P1424R1 `__","LWG","'constexpr' feature macro concerns","Cologne","Superseded by `P1902 `__","" "`P1466R3 `__","LWG","Miscellaneous minor fixes for chrono","Cologne","","" "`P1474R1 `__","LWG","Helpful pointers for ContiguousIterator","Cologne","|Complete|","15.0" diff --git a/libcxx/include/ostream b/libcxx/include/ostream --- a/libcxx/include/ostream +++ b/libcxx/include/ostream @@ -130,6 +130,35 @@ template Stream&& operator<<(Stream&& os, const T& x); +template +basic_ostream& operator<<(basic_ostream&, wchar_t) = delete; // since C++20 +template +basic_ostream& operator<<(basic_ostream&, char8_t) = delete; // since C++20 +template +basic_ostream& operator<<(basic_ostream&, char16_t) = delete; // since C++20 +template +basic_ostream& operator<<(basic_ostream&, char32_t) = delete; // since C++20 +template +basic_ostream& operator<<(basic_ostream&, char8_t) = delete; // since C++20 +template +basic_ostream& operator<<(basic_ostream&, char16_t) = delete; // since C++20 +template +basic_ostream& operator<<(basic_ostream&, char32_t) = delete; // since C++20 +template +basic_ostream& operator<<(basic_ostream&, const wchar_t*) = delete; // since C++20 +template +basic_ostream& operator<<(basic_ostream&, const char8_t*) = delete; // since C++20 +template +basic_ostream& operator<<(basic_ostream&, const char16_t*) = delete; // since C++20 +template +basic_ostream& operator<<(basic_ostream&, const char32_t*) = delete; // since C++20 +template +basic_ostream& operator<<(basic_ostream&, const char8_t*) = delete; // since C++20 +template +basic_ostream& operator<<(basic_ostream&, const char16_t*) = delete; // since C++20 +template +basic_ostream& operator<<(basic_ostream&, const char32_t*) = delete; // since C++20 + } // std */ @@ -1102,6 +1131,57 @@ use_facet >(__os.getloc()).widen('1')); } +#if _LIBCPP_STD_VER > 17 + +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +template +basic_ostream& operator<<(basic_ostream&, wchar_t) = delete; + +template +basic_ostream& operator<<(basic_ostream&, const wchar_t*) = delete; + +template +basic_ostream& operator<<(basic_ostream&, char16_t) = delete; + +template +basic_ostream& operator<<(basic_ostream&, char32_t) = delete; + +template +basic_ostream& operator<<(basic_ostream&, const char16_t*) = delete; + +template +basic_ostream& operator<<(basic_ostream&, const char32_t*) = delete; + +#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS + +#ifndef _LIBCPP_HAS_NO_CHAR8_T +template +basic_ostream& operator<<(basic_ostream&, char8_t) = delete; + +template +basic_ostream& operator<<(basic_ostream&, char8_t) = delete; + +template +basic_ostream& operator<<(basic_ostream&, const char8_t*) = delete; + +template +basic_ostream& operator<<(basic_ostream&, const char8_t*) = delete; +#endif + +template +basic_ostream& operator<<(basic_ostream&, char16_t) = delete; + +template +basic_ostream& operator<<(basic_ostream&, char32_t) = delete; + +template +basic_ostream& operator<<(basic_ostream&, const char16_t*) = delete; + +template +basic_ostream& operator<<(basic_ostream&, const char32_t*) = delete; + +#endif // _LIBCPP_STD_VER > 17 + extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS basic_ostream; #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS basic_ostream; diff --git a/libcxx/include/version b/libcxx/include/version --- a/libcxx/include/version +++ b/libcxx/include/version @@ -47,7 +47,7 @@ __cpp_lib_boyer_moore_searcher 201603L __cpp_lib_byte 201603L __cpp_lib_byteswap 202110L -__cpp_lib_char8_t 201811L +__cpp_lib_char8_t 201907L __cpp_lib_chrono 201611L @@ -308,7 +308,7 @@ // # define __cpp_lib_bitops 201907L # define __cpp_lib_bounded_array_traits 201902L # if !defined(_LIBCPP_HAS_NO_CHAR8_T) -# define __cpp_lib_char8_t 201811L +# define __cpp_lib_char8_t 201907L # endif # define __cpp_lib_concepts 202002L # define __cpp_lib_constexpr_algorithms 201806L diff --git a/libcxx/test/std/input.output/iostream.format/output.streams/ostream/deleted_output_functions.verify.cpp b/libcxx/test/std/input.output/iostream.format/output.streams/ostream/deleted_output_functions.verify.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/input.output/iostream.format/output.streams/ostream/deleted_output_functions.verify.cpp @@ -0,0 +1,55 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 + +// + +#include +#include +#include + +#include "test_macros.h" + +int main() { + std::ostringstream s; + +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + + s << wchar_t(); // expected-error {{overload resolution selected deleted operator '<<'}} + s << std::declval(); // expected-error {{overload resolution selected deleted operator '<<'}} + s << std::declval(); // expected-error {{overload resolution selected deleted operator '<<'}} + + std::wostringstream sw; +# ifndef TEST_HAS_NO_CHAR8_T + sw << char8_t(); // expected-error {{overload resolution selected deleted operator '<<'}} + sw << std::declval(); // expected-error {{overload resolution selected deleted operator '<<'}} + sw << std::declval(); // expected-error {{overload resolution selected deleted operator '<<'}} +# endif + + sw << char16_t(); // expected-error {{overload resolution selected deleted operator '<<'}} + sw << std::declval(); // expected-error {{overload resolution selected deleted operator '<<'}} + sw << std::declval(); // expected-error {{overload resolution selected deleted operator '<<'}} + sw << char32_t(); // expected-error {{overload resolution selected deleted operator '<<'}} + sw << std::declval(); // expected-error {{overload resolution selected deleted operator '<<'}} + sw << std::declval(); // expected-error {{overload resolution selected deleted operator '<<'}} + +#endif // TEST_HAS_NO_WIDE_CHARACTERS + +#ifndef TEST_HAS_NO_CHAR8_T + s << char8_t(); // expected-error {{overload resolution selected deleted operator '<<'}} + s << std::declval(); // expected-error {{overload resolution selected deleted operator '<<'}} + s << std::declval(); // expected-error {{overload resolution selected deleted operator '<<'}} +#endif + s << char16_t(); // expected-error {{overload resolution selected deleted operator '<<'}} + s << std::declval(); // expected-error {{overload resolution selected deleted operator '<<'}} + s << std::declval(); // expected-error {{overload resolution selected deleted operator '<<'}} + s << char32_t(); // expected-error {{overload resolution selected deleted operator '<<'}} + s << std::declval(); // expected-error {{overload resolution selected deleted operator '<<'}} + s << std::declval(); // expected-error {{overload resolution selected deleted operator '<<'}} +} diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/atomic.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/atomic.version.compile.pass.cpp --- a/libcxx/test/std/language.support/support.limits/support.limits.general/atomic.version.compile.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/atomic.version.compile.pass.cpp @@ -24,7 +24,7 @@ __cpp_lib_atomic_shared_ptr 201711L [C++20] __cpp_lib_atomic_value_initialization 201911L [C++20] __cpp_lib_atomic_wait 201907L [C++20] - __cpp_lib_char8_t 201811L [C++20] + __cpp_lib_char8_t 201907L [C++20] */ #include @@ -233,8 +233,8 @@ # ifndef __cpp_lib_char8_t # error "__cpp_lib_char8_t should be defined in c++20" # endif -# if __cpp_lib_char8_t != 201811L -# error "__cpp_lib_char8_t should have the value 201811L in c++20" +# if __cpp_lib_char8_t != 201907L +# error "__cpp_lib_char8_t should have the value 201907L in c++20" # endif # else # ifdef __cpp_lib_char8_t @@ -328,8 +328,8 @@ # ifndef __cpp_lib_char8_t # error "__cpp_lib_char8_t should be defined in c++2b" # endif -# if __cpp_lib_char8_t != 201811L -# error "__cpp_lib_char8_t should have the value 201811L in c++2b" +# if __cpp_lib_char8_t != 201907L +# error "__cpp_lib_char8_t should have the value 201907L in c++2b" # endif # else # ifdef __cpp_lib_char8_t diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/filesystem.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/filesystem.version.compile.pass.cpp --- a/libcxx/test/std/language.support/support.limits/support.limits.general/filesystem.version.compile.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/filesystem.version.compile.pass.cpp @@ -18,7 +18,7 @@ // Test the feature test macros defined by /* Constant Value - __cpp_lib_char8_t 201811L [C++20] + __cpp_lib_char8_t 201907L [C++20] __cpp_lib_filesystem 201703L [C++17] */ @@ -70,8 +70,8 @@ # ifndef __cpp_lib_char8_t # error "__cpp_lib_char8_t should be defined in c++20" # endif -# if __cpp_lib_char8_t != 201811L -# error "__cpp_lib_char8_t should have the value 201811L in c++20" +# if __cpp_lib_char8_t != 201907L +# error "__cpp_lib_char8_t should have the value 201907L in c++20" # endif # else # ifdef __cpp_lib_char8_t @@ -98,8 +98,8 @@ # ifndef __cpp_lib_char8_t # error "__cpp_lib_char8_t should be defined in c++2b" # endif -# if __cpp_lib_char8_t != 201811L -# error "__cpp_lib_char8_t should have the value 201811L in c++2b" +# if __cpp_lib_char8_t != 201907L +# error "__cpp_lib_char8_t should have the value 201907L in c++2b" # endif # else # ifdef __cpp_lib_char8_t diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/istream.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/istream.version.compile.pass.cpp --- a/libcxx/test/std/language.support/support.limits/support.limits.general/istream.version.compile.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/istream.version.compile.pass.cpp @@ -18,7 +18,7 @@ // Test the feature test macros defined by /* Constant Value - __cpp_lib_char8_t 201811L [C++20] + __cpp_lib_char8_t 201907L [C++20] */ #include @@ -48,8 +48,8 @@ # ifndef __cpp_lib_char8_t # error "__cpp_lib_char8_t should be defined in c++20" # endif -# if __cpp_lib_char8_t != 201811L -# error "__cpp_lib_char8_t should have the value 201811L in c++20" +# if __cpp_lib_char8_t != 201907L +# error "__cpp_lib_char8_t should have the value 201907L in c++20" # endif # else # ifdef __cpp_lib_char8_t @@ -63,8 +63,8 @@ # ifndef __cpp_lib_char8_t # error "__cpp_lib_char8_t should be defined in c++2b" # endif -# if __cpp_lib_char8_t != 201811L -# error "__cpp_lib_char8_t should have the value 201811L in c++2b" +# if __cpp_lib_char8_t != 201907L +# error "__cpp_lib_char8_t should have the value 201907L in c++2b" # endif # else # ifdef __cpp_lib_char8_t diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/limits.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/limits.version.compile.pass.cpp --- a/libcxx/test/std/language.support/support.limits/support.limits.general/limits.version.compile.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/limits.version.compile.pass.cpp @@ -16,7 +16,7 @@ // Test the feature test macros defined by /* Constant Value - __cpp_lib_char8_t 201811L [C++20] + __cpp_lib_char8_t 201907L [C++20] */ #include @@ -46,8 +46,8 @@ # ifndef __cpp_lib_char8_t # error "__cpp_lib_char8_t should be defined in c++20" # endif -# if __cpp_lib_char8_t != 201811L -# error "__cpp_lib_char8_t should have the value 201811L in c++20" +# if __cpp_lib_char8_t != 201907L +# error "__cpp_lib_char8_t should have the value 201907L in c++20" # endif # else # ifdef __cpp_lib_char8_t @@ -61,8 +61,8 @@ # ifndef __cpp_lib_char8_t # error "__cpp_lib_char8_t should be defined in c++2b" # endif -# if __cpp_lib_char8_t != 201811L -# error "__cpp_lib_char8_t should have the value 201811L in c++2b" +# if __cpp_lib_char8_t != 201907L +# error "__cpp_lib_char8_t should have the value 201907L in c++2b" # endif # else # ifdef __cpp_lib_char8_t diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/locale.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/locale.version.compile.pass.cpp --- a/libcxx/test/std/language.support/support.limits/support.limits.general/locale.version.compile.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/locale.version.compile.pass.cpp @@ -18,7 +18,7 @@ // Test the feature test macros defined by /* Constant Value - __cpp_lib_char8_t 201811L [C++20] + __cpp_lib_char8_t 201907L [C++20] */ #include @@ -48,8 +48,8 @@ # ifndef __cpp_lib_char8_t # error "__cpp_lib_char8_t should be defined in c++20" # endif -# if __cpp_lib_char8_t != 201811L -# error "__cpp_lib_char8_t should have the value 201811L in c++20" +# if __cpp_lib_char8_t != 201907L +# error "__cpp_lib_char8_t should have the value 201907L in c++20" # endif # else # ifdef __cpp_lib_char8_t @@ -63,8 +63,8 @@ # ifndef __cpp_lib_char8_t # error "__cpp_lib_char8_t should be defined in c++2b" # endif -# if __cpp_lib_char8_t != 201811L -# error "__cpp_lib_char8_t should have the value 201811L in c++2b" +# if __cpp_lib_char8_t != 201907L +# error "__cpp_lib_char8_t should have the value 201907L in c++2b" # endif # else # ifdef __cpp_lib_char8_t diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/ostream.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/ostream.version.compile.pass.cpp --- a/libcxx/test/std/language.support/support.limits/support.limits.general/ostream.version.compile.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/ostream.version.compile.pass.cpp @@ -18,7 +18,7 @@ // Test the feature test macros defined by /* Constant Value - __cpp_lib_char8_t 201811L [C++20] + __cpp_lib_char8_t 201907L [C++20] */ #include @@ -48,8 +48,8 @@ # ifndef __cpp_lib_char8_t # error "__cpp_lib_char8_t should be defined in c++20" # endif -# if __cpp_lib_char8_t != 201811L -# error "__cpp_lib_char8_t should have the value 201811L in c++20" +# if __cpp_lib_char8_t != 201907L +# error "__cpp_lib_char8_t should have the value 201907L in c++20" # endif # else # ifdef __cpp_lib_char8_t @@ -63,8 +63,8 @@ # ifndef __cpp_lib_char8_t # error "__cpp_lib_char8_t should be defined in c++2b" # endif -# if __cpp_lib_char8_t != 201811L -# error "__cpp_lib_char8_t should have the value 201811L in c++2b" +# if __cpp_lib_char8_t != 201907L +# error "__cpp_lib_char8_t should have the value 201907L in c++2b" # endif # else # ifdef __cpp_lib_char8_t diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/string.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/string.version.compile.pass.cpp --- a/libcxx/test/std/language.support/support.limits/support.limits.general/string.version.compile.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/string.version.compile.pass.cpp @@ -17,7 +17,7 @@ /* Constant Value __cpp_lib_allocator_traits_is_always_equal 201411L [C++17] - __cpp_lib_char8_t 201811L [C++20] + __cpp_lib_char8_t 201907L [C++20] __cpp_lib_constexpr_string 201907L [C++20] __cpp_lib_erase_if 202002L [C++20] __cpp_lib_nonmember_container_access 201411L [C++17] @@ -199,8 +199,8 @@ # ifndef __cpp_lib_char8_t # error "__cpp_lib_char8_t should be defined in c++20" # endif -# if __cpp_lib_char8_t != 201811L -# error "__cpp_lib_char8_t should have the value 201811L in c++20" +# if __cpp_lib_char8_t != 201907L +# error "__cpp_lib_char8_t should have the value 201907L in c++20" # endif # else # ifdef __cpp_lib_char8_t @@ -275,8 +275,8 @@ # ifndef __cpp_lib_char8_t # error "__cpp_lib_char8_t should be defined in c++2b" # endif -# if __cpp_lib_char8_t != 201811L -# error "__cpp_lib_char8_t should have the value 201811L in c++2b" +# if __cpp_lib_char8_t != 201907L +# error "__cpp_lib_char8_t should have the value 201907L in c++2b" # endif # else # ifdef __cpp_lib_char8_t diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/string_view.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/string_view.version.compile.pass.cpp --- a/libcxx/test/std/language.support/support.limits/support.limits.general/string_view.version.compile.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/string_view.version.compile.pass.cpp @@ -16,7 +16,7 @@ // Test the feature test macros defined by /* Constant Value - __cpp_lib_char8_t 201811L [C++20] + __cpp_lib_char8_t 201907L [C++20] __cpp_lib_constexpr_string_view 201811L [C++20] __cpp_lib_starts_ends_with 201711L [C++20] __cpp_lib_string_contains 202011L [C++2b] @@ -102,8 +102,8 @@ # ifndef __cpp_lib_char8_t # error "__cpp_lib_char8_t should be defined in c++20" # endif -# if __cpp_lib_char8_t != 201811L -# error "__cpp_lib_char8_t should have the value 201811L in c++20" +# if __cpp_lib_char8_t != 201907L +# error "__cpp_lib_char8_t should have the value 201907L in c++20" # endif # else # ifdef __cpp_lib_char8_t @@ -142,8 +142,8 @@ # ifndef __cpp_lib_char8_t # error "__cpp_lib_char8_t should be defined in c++2b" # endif -# if __cpp_lib_char8_t != 201811L -# error "__cpp_lib_char8_t should have the value 201811L in c++2b" +# if __cpp_lib_char8_t != 201907L +# error "__cpp_lib_char8_t should have the value 201907L in c++2b" # endif # else # ifdef __cpp_lib_char8_t diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp --- a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp @@ -45,7 +45,7 @@ __cpp_lib_boyer_moore_searcher 201603L [C++17] __cpp_lib_byte 201603L [C++17] __cpp_lib_byteswap 202110L [C++2b] - __cpp_lib_char8_t 201811L [C++20] + __cpp_lib_char8_t 201907L [C++20] __cpp_lib_chrono 201611L [C++17] __cpp_lib_chrono_udls 201304L [C++14] __cpp_lib_clamp 201603L [C++17] @@ -2595,8 +2595,8 @@ # ifndef __cpp_lib_char8_t # error "__cpp_lib_char8_t should be defined in c++20" # endif -# if __cpp_lib_char8_t != 201811L -# error "__cpp_lib_char8_t should have the value 201811L in c++20" +# if __cpp_lib_char8_t != 201907L +# error "__cpp_lib_char8_t should have the value 201907L in c++20" # endif # else # ifdef __cpp_lib_char8_t @@ -3814,8 +3814,8 @@ # ifndef __cpp_lib_char8_t # error "__cpp_lib_char8_t should be defined in c++2b" # endif -# if __cpp_lib_char8_t != 201811L -# error "__cpp_lib_char8_t should have the value 201811L in c++2b" +# if __cpp_lib_char8_t != 201907L +# error "__cpp_lib_char8_t should have the value 201907L in c++2b" # endif # else # ifdef __cpp_lib_char8_t diff --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py --- a/libcxx/utils/generate_feature_test_macro_components.py +++ b/libcxx/utils/generate_feature_test_macro_components.py @@ -186,7 +186,7 @@ "headers": ["bit"], }, { "name": "__cpp_lib_char8_t", - "values": { "c++20": 201811 }, + "values": { "c++20": 201907 }, "headers": ["atomic", "filesystem", "istream", "limits", "locale", "ostream", "string", "string_view"], "test_suite_guard": "defined(__cpp_char8_t)", "libcxx_guard": "!defined(_LIBCPP_HAS_NO_CHAR8_T)",