diff --git a/libcxx/docs/Status/Cxx2bPapers.csv b/libcxx/docs/Status/Cxx2bPapers.csv index db94ba0099336..4df0bfcddbf7a 100644 --- a/libcxx/docs/Status/Cxx2bPapers.csv +++ b/libcxx/docs/Status/Cxx2bPapers.csv @@ -21,5 +21,5 @@ "`P1951R1 `__","LWG","Default Arguments for pair Forwarding Constructor","June 2021","","" "`P1989R2 `__","LWG","Range constructor for std::string_view","June 2021","","" "`P2136R3 `__","LWG","invoke_r","June 2021","","" -"`P2166R1 `__","LWG","A Proposal to Prohibit std::basic_string and std::basic_string_view construction from nullptr","June 2021","","" +"`P2166R1 `__","LWG","A Proposal to Prohibit std::basic_string and std::basic_string_view construction from nullptr","June 2021","|Complete|","13.0" "","","","","","" \ No newline at end of file diff --git a/libcxx/include/string b/libcxx/include/string index 3917c07a1f744..4940021b0c68a 100644 --- a/libcxx/include/string +++ b/libcxx/include/string @@ -110,6 +110,7 @@ public: explicit basic_string(const T& t, const Allocator& a = Allocator()); // C++17 basic_string(const value_type* s, const allocator_type& a = allocator_type()); basic_string(const value_type* s, size_type n, const allocator_type& a = allocator_type()); + basic_string(nullptr_t) = delete; // C++2b basic_string(size_type n, value_type c, const allocator_type& a = allocator_type()); template basic_string(InputIterator begin, InputIterator end, @@ -130,6 +131,7 @@ public: allocator_type::propagate_on_container_move_assignment::value || allocator_type::is_always_equal::value ); // C++17 basic_string& operator=(const value_type* s); + basic_string& operator=(nullptr_t) = delete; // C++2b basic_string& operator=(value_type c); basic_string& operator=(initializer_list); @@ -843,6 +845,10 @@ public: _LIBCPP_INLINE_VISIBILITY basic_string(const _CharT* __s, const _Allocator& __a); +#if _LIBCPP_STD_VER > 20 + basic_string(nullptr_t) = delete; +#endif + _LIBCPP_INLINE_VISIBILITY basic_string(const _CharT* __s, size_type __n); _LIBCPP_INLINE_VISIBILITY @@ -906,6 +912,9 @@ public: basic_string& operator=(initializer_list __il) {return assign(__il.begin(), __il.size());} #endif _LIBCPP_INLINE_VISIBILITY basic_string& operator=(const value_type* __s) {return assign(__s);} +#if _LIBCPP_STD_VER > 20 + basic_string& operator=(nullptr_t) = delete; +#endif basic_string& operator=(value_type __c); #if _LIBCPP_DEBUG_LEVEL == 2 diff --git a/libcxx/include/string_view b/libcxx/include/string_view index ddca14e239fcb..2c94cb85269fb 100644 --- a/libcxx/include/string_view +++ b/libcxx/include/string_view @@ -83,6 +83,7 @@ namespace std { basic_string_view& operator=(const basic_string_view&) noexcept = default; template constexpr basic_string_view(const charT* str); + basic_string_view(nullptr_t) = delete; // C++2b constexpr basic_string_view(const charT* str, size_type len); // 7.4, basic_string_view iterator support @@ -273,6 +274,10 @@ public: basic_string_view(const _CharT* __s) : __data(__s), __size(_VSTD::__char_traits_length_checked<_Traits>(__s)) {} +#if _LIBCPP_STD_VER > 20 + basic_string_view(nullptr_t) = delete; +#endif + // [string.view.iterators], iterators _LIBCPP_CONSTEXPR _LIBCPP_INLINE_VISIBILITY const_iterator begin() const _NOEXCEPT { return cbegin(); } diff --git a/libcxx/test/libcxx/debug/db_string_view.pass.cpp b/libcxx/test/libcxx/debug/db_string_view.pass.cpp index c2285f09d3cd3..b38bc3186ba88 100644 --- a/libcxx/test/libcxx/debug/db_string_view.pass.cpp +++ b/libcxx/test/libcxx/debug/db_string_view.pass.cpp @@ -21,18 +21,22 @@ #include "debug_mode_helper.h" void test_null_argument() { - EXPECT_DEATH(std::string_view(nullptr)); - EXPECT_DEATH(std::string_view(NULL)); + // C++2b prohibits construction of string_view from nullptr_t. + const char* nullp = nullptr; + const char* null = NULL; + (void)nullp; + (void)null; + EXPECT_DEATH((std::string_view(nullp))); + EXPECT_DEATH((std::string_view(null))); EXPECT_DEATH(std::string_view(static_cast(0))); { std::string_view v; - EXPECT_DEATH(((void)(v == nullptr))); - EXPECT_DEATH(((void)(nullptr == v))); + EXPECT_DEATH(((void)(v == nullp))); + EXPECT_DEATH(((void)(nullp == v))); } } -int main(int, char**) -{ +int main(int, char**) { test_null_argument(); return 0; diff --git a/libcxx/test/std/strings/basic.string/string.cons/nullptr.compile.pass.cpp b/libcxx/test/std/strings/basic.string/string.cons/nullptr.compile.pass.cpp new file mode 100644 index 0000000000000..3b6a00ec135d4 --- /dev/null +++ b/libcxx/test/std/strings/basic.string/string.cons/nullptr.compile.pass.cpp @@ -0,0 +1,21 @@ +//===----------------------------------------------------------------------===// +// +// 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, c++20 + +// + +// basic_string(nullptr_t) = delete; // C++2b +// basic_string& operator=(nullptr_t) = delete; // C++2b + +#include +#include + +static_assert(!std::is_convertible_v); +static_assert(!std::is_constructible_v); +static_assert(!std::is_assignable_v); diff --git a/libcxx/test/std/strings/string.view/string.view.cons/nullptr.compile.pass.cpp b/libcxx/test/std/strings/string.view/string.view.cons/nullptr.compile.pass.cpp new file mode 100644 index 0000000000000..2517e77a16d49 --- /dev/null +++ b/libcxx/test/std/strings/string.view/string.view.cons/nullptr.compile.pass.cpp @@ -0,0 +1,20 @@ +//===----------------------------------------------------------------------===// +// +// 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, c++20 + +// + +// basic_string_view(nullptr_t) = delete; // C++2b + +#include +#include + +static_assert(!std::is_convertible_v); +static_assert(!std::is_constructible_v); +static_assert(!std::is_assignable_v);