From 375122a03b870ed00f2c4c452d8c939e2039ffec Mon Sep 17 00:00:00 2001 From: Dimitry Andric Date: Sun, 22 Jan 2017 16:52:53 +0000 Subject: [PATCH] Vendor import of libc++ release_40 branch r292732: https://llvm.org/svn/llvm-project/libcxx/branches/release_40@292732 --- include/__config | 12 ++ include/array | 14 +- include/new | 7 +- include/string | 1 + include/typeinfo | 5 +- src/new.cpp | 180 +++++++++--------- .../containers/sequences/array/at.pass.cpp | 15 ++ .../sequences/array/front_back.pass.cpp | 26 ++- .../sequences/array/indexing.pass.cpp | 15 ++ .../last_write_time.pass.cpp | 92 ++++++--- .../support.rtti/type.info/type_info.pass.cpp | 14 ++ .../string.cons/brace_assignment.pass.cpp | 36 ++++ .../string.cons/string_view.pass.cpp | 22 +++ 13 files changed, 309 insertions(+), 130 deletions(-) create mode 100644 test/std/strings/basic.string/string.cons/brace_assignment.pass.cpp diff --git a/include/__config b/include/__config index b30b15c6fdb9..973f13bc9394 100644 --- a/include/__config +++ b/include/__config @@ -835,6 +835,18 @@ template struct __static_assert_check {}; #define _DECLARE_C99_LDBL_MATH 1 #endif +#if defined(__APPLE__) +# if !defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && \ + defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) +# define __MAC_OS_X_VERSION_MIN_REQUIRED __ENVIROMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ +# endif +# if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) +# if __MAC_OS_X_VERSION_MIN_REQUIRED < 1060 +# define _LIBCPP_HAS_NO_ALIGNED_ALLOCATION +# endif +# endif +#endif // defined(__APPLE__) + #if defined(__APPLE__) || defined(__FreeBSD__) #define _LIBCPP_HAS_DEFAULTRUNELOCALE #endif diff --git a/include/array b/include/array index eee9405dbeff..165ffad6b8b1 100644 --- a/include/array +++ b/include/array @@ -185,14 +185,17 @@ struct _LIBCPP_TEMPLATE_VIS array _LIBCPP_CONSTEXPR bool empty() const _NOEXCEPT {return _Size == 0;} // element access: - _LIBCPP_INLINE_VISIBILITY reference operator[](size_type __n) {return __elems_[__n];} - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 const_reference operator[](size_type __n) const {return __elems_[__n];} - reference at(size_type __n); + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 + reference operator[](size_type __n) {return __elems_[__n];} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 + const_reference operator[](size_type __n) const {return __elems_[__n];} + + _LIBCPP_CONSTEXPR_AFTER_CXX14 reference at(size_type __n); _LIBCPP_CONSTEXPR_AFTER_CXX11 const_reference at(size_type __n) const; - _LIBCPP_INLINE_VISIBILITY reference front() {return __elems_[0];} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 reference front() {return __elems_[0];} _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 const_reference front() const {return __elems_[0];} - _LIBCPP_INLINE_VISIBILITY reference back() {return __elems_[_Size > 0 ? _Size-1 : 0];} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 reference back() {return __elems_[_Size > 0 ? _Size-1 : 0];} _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 const_reference back() const {return __elems_[_Size > 0 ? _Size-1 : 0];} _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 @@ -202,6 +205,7 @@ struct _LIBCPP_TEMPLATE_VIS array }; template +_LIBCPP_CONSTEXPR_AFTER_CXX14 typename array<_Tp, _Size>::reference array<_Tp, _Size>::at(size_type __n) { diff --git a/include/new b/include/new index 6589f16b7a16..86428f281dc1 100644 --- a/include/new +++ b/include/new @@ -101,8 +101,9 @@ void operator delete[](void* ptr, void*) noexcept; # define _LIBCPP_HAS_NO_SIZED_DEALLOCATION #endif -#if !(defined(_LIBCPP_BUILDING_NEW) || _LIBCPP_STD_VER > 14 || \ - (defined(__cpp_aligned_new) && __cpp_aligned_new >= 201606)) +#if !defined(_LIBCPP_HAS_NO_ALIGNED_ALLOCATION) && \ + (!(defined(_LIBCPP_BUILDING_NEW) || _LIBCPP_STD_VER > 14 || \ + (defined(__cpp_aligned_new) && __cpp_aligned_new >= 201606))) # define _LIBCPP_HAS_NO_ALIGNED_ALLOCATION #endif @@ -144,7 +145,7 @@ public: #endif // defined(_LIBCPP_BUILDING_NEW) || (_LIBCPP_STD_VER > 11) -#ifndef _LIBCPP_HAS_NO_ALIGNED_ALLOCATION +#if !defined(_LIBCPP_HAS_NO_ALIGNED_ALLOCATION) || _LIBCPP_STD_VER > 14 #ifndef _LIBCPP_CXX03_LANG enum class _LIBCPP_ENUM_VIS align_val_t : size_t { }; #else diff --git a/include/string b/include/string index 136a5fb8949d..7d7994eaca1b 100644 --- a/include/string +++ b/include/string @@ -818,6 +818,7 @@ public: operator __self_view() const _NOEXCEPT { return __self_view(data(), size()); } basic_string& operator=(const basic_string& __str); + template _LIBCPP_INLINE_VISIBILITY basic_string& operator=(__self_view __sv) {return assign(__sv);} #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES diff --git a/include/typeinfo b/include/typeinfo index 9b21da6b9341..fdc25c81e94f 100644 --- a/include/typeinfo +++ b/include/typeinfo @@ -95,12 +95,13 @@ protected: uintptr_t __type_name; _LIBCPP_INLINE_VISIBILITY - type_info(const char* __n) : __type_name(reinterpret_cast(__n)) {} + explicit type_info(const char* __n) + : __type_name(reinterpret_cast(__n)) {} #else const char *__type_name; _LIBCPP_INLINE_VISIBILITY - type_info(const char* __n) : __type_name(__n) {} + explicit type_info(const char* __n) : __type_name(__n) {} #endif public: diff --git a/src/new.cpp b/src/new.cpp index 2ef8939fdcb3..b1e8ee324d84 100644 --- a/src/new.cpp +++ b/src/new.cpp @@ -63,6 +63,96 @@ operator new(std::size_t size) _THROW_BAD_ALLOC return p; } +_LIBCPP_WEAK +void* +operator new(size_t size, const std::nothrow_t&) _NOEXCEPT +{ + void* p = 0; +#ifndef _LIBCPP_NO_EXCEPTIONS + try + { +#endif // _LIBCPP_NO_EXCEPTIONS + p = ::operator new(size); +#ifndef _LIBCPP_NO_EXCEPTIONS + } + catch (...) + { + } +#endif // _LIBCPP_NO_EXCEPTIONS + return p; +} + +_LIBCPP_WEAK +void* +operator new[](size_t size) _THROW_BAD_ALLOC +{ + return ::operator new(size); +} + +_LIBCPP_WEAK +void* +operator new[](size_t size, const std::nothrow_t&) _NOEXCEPT +{ + void* p = 0; +#ifndef _LIBCPP_NO_EXCEPTIONS + try + { +#endif // _LIBCPP_NO_EXCEPTIONS + p = ::operator new[](size); +#ifndef _LIBCPP_NO_EXCEPTIONS + } + catch (...) + { + } +#endif // _LIBCPP_NO_EXCEPTIONS + return p; +} + +_LIBCPP_WEAK +void +operator delete(void* ptr) _NOEXCEPT +{ + if (ptr) + ::free(ptr); +} + +_LIBCPP_WEAK +void +operator delete(void* ptr, const std::nothrow_t&) _NOEXCEPT +{ + ::operator delete(ptr); +} + +_LIBCPP_WEAK +void +operator delete(void* ptr, size_t) _NOEXCEPT +{ + ::operator delete(ptr); +} + +_LIBCPP_WEAK +void +operator delete[] (void* ptr) _NOEXCEPT +{ + ::operator delete(ptr); +} + +_LIBCPP_WEAK +void +operator delete[] (void* ptr, const std::nothrow_t&) _NOEXCEPT +{ + ::operator delete[](ptr); +} + +_LIBCPP_WEAK +void +operator delete[] (void* ptr, size_t) _NOEXCEPT +{ + ::operator delete[](ptr); +} + +#if !defined(_LIBCPP_HAS_NO_ALIGNED_ALLOCATION) + _LIBCPP_WEAK void * operator new(std::size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC @@ -95,25 +185,6 @@ operator new(std::size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC return p; } -_LIBCPP_WEAK -void* -operator new(size_t size, const std::nothrow_t&) _NOEXCEPT -{ - void* p = 0; -#ifndef _LIBCPP_NO_EXCEPTIONS - try - { -#endif // _LIBCPP_NO_EXCEPTIONS - p = ::operator new(size); -#ifndef _LIBCPP_NO_EXCEPTIONS - } - catch (...) - { - } -#endif // _LIBCPP_NO_EXCEPTIONS - return p; -} - _LIBCPP_WEAK void* operator new(size_t size, std::align_val_t alignment, const std::nothrow_t&) _NOEXCEPT @@ -133,13 +204,6 @@ operator new(size_t size, std::align_val_t alignment, const std::nothrow_t&) _NO return p; } -_LIBCPP_WEAK -void* -operator new[](size_t size) _THROW_BAD_ALLOC -{ - return ::operator new(size); -} - _LIBCPP_WEAK void* operator new[](size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC @@ -147,25 +211,6 @@ operator new[](size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC return ::operator new(size, alignment); } -_LIBCPP_WEAK -void* -operator new[](size_t size, const std::nothrow_t&) _NOEXCEPT -{ - void* p = 0; -#ifndef _LIBCPP_NO_EXCEPTIONS - try - { -#endif // _LIBCPP_NO_EXCEPTIONS - p = ::operator new[](size); -#ifndef _LIBCPP_NO_EXCEPTIONS - } - catch (...) - { - } -#endif // _LIBCPP_NO_EXCEPTIONS - return p; -} - _LIBCPP_WEAK void* operator new[](size_t size, std::align_val_t alignment, const std::nothrow_t&) _NOEXCEPT @@ -185,14 +230,6 @@ operator new[](size_t size, std::align_val_t alignment, const std::nothrow_t&) _ return p; } -_LIBCPP_WEAK -void -operator delete(void* ptr) _NOEXCEPT -{ - if (ptr) - ::free(ptr); -} - _LIBCPP_WEAK void operator delete(void* ptr, std::align_val_t) _NOEXCEPT @@ -205,13 +242,6 @@ operator delete(void* ptr, std::align_val_t) _NOEXCEPT #endif } -_LIBCPP_WEAK -void -operator delete(void* ptr, const std::nothrow_t&) _NOEXCEPT -{ - ::operator delete(ptr); -} - _LIBCPP_WEAK void operator delete(void* ptr, std::align_val_t alignment, const std::nothrow_t&) _NOEXCEPT @@ -219,13 +249,6 @@ operator delete(void* ptr, std::align_val_t alignment, const std::nothrow_t&) _N ::operator delete(ptr, alignment); } -_LIBCPP_WEAK -void -operator delete(void* ptr, size_t) _NOEXCEPT -{ - ::operator delete(ptr); -} - _LIBCPP_WEAK void operator delete(void* ptr, size_t, std::align_val_t alignment) _NOEXCEPT @@ -233,13 +256,6 @@ operator delete(void* ptr, size_t, std::align_val_t alignment) _NOEXCEPT ::operator delete(ptr, alignment); } -_LIBCPP_WEAK -void -operator delete[] (void* ptr) _NOEXCEPT -{ - ::operator delete(ptr); -} - _LIBCPP_WEAK void operator delete[] (void* ptr, std::align_val_t alignment) _NOEXCEPT @@ -247,13 +263,6 @@ operator delete[] (void* ptr, std::align_val_t alignment) _NOEXCEPT ::operator delete(ptr, alignment); } -_LIBCPP_WEAK -void -operator delete[] (void* ptr, const std::nothrow_t&) _NOEXCEPT -{ - ::operator delete[](ptr); -} - _LIBCPP_WEAK void operator delete[] (void* ptr, std::align_val_t alignment, const std::nothrow_t&) _NOEXCEPT @@ -261,13 +270,6 @@ operator delete[] (void* ptr, std::align_val_t alignment, const std::nothrow_t&) ::operator delete[](ptr, alignment); } -_LIBCPP_WEAK -void -operator delete[] (void* ptr, size_t) _NOEXCEPT -{ - ::operator delete[](ptr); -} - _LIBCPP_WEAK void operator delete[] (void* ptr, size_t, std::align_val_t alignment) _NOEXCEPT @@ -275,6 +277,8 @@ operator delete[] (void* ptr, size_t, std::align_val_t alignment) _NOEXCEPT ::operator delete[](ptr, alignment); } +#endif // !defined(_LIBCPP_HAS_NO_ALIGNED_ALLOCATION) + #endif // !__GLIBCXX__ namespace std diff --git a/test/std/containers/sequences/array/at.pass.cpp b/test/std/containers/sequences/array/at.pass.cpp index 29483153d4ab..8e7ff6dff702 100644 --- a/test/std/containers/sequences/array/at.pass.cpp +++ b/test/std/containers/sequences/array/at.pass.cpp @@ -23,6 +23,14 @@ // Disable the missing braces warning for this reason. #include "disable_missing_braces_warning.h" +#if TEST_STD_VER > 14 +constexpr bool check_idx( size_t idx, double val ) +{ + std::array arr = {1, 2, 3.5}; + return arr.at(idx) == val; +} +#endif + int main() { { @@ -82,4 +90,11 @@ int main() } #endif +#if TEST_STD_VER > 14 + { + static_assert (check_idx(0, 1), ""); + static_assert (check_idx(1, 2), ""); + static_assert (check_idx(2, 3.5), ""); + } +#endif } diff --git a/test/std/containers/sequences/array/front_back.pass.cpp b/test/std/containers/sequences/array/front_back.pass.cpp index 7d53b8265e96..239fda5c99d8 100644 --- a/test/std/containers/sequences/array/front_back.pass.cpp +++ b/test/std/containers/sequences/array/front_back.pass.cpp @@ -9,10 +9,10 @@ // -// reference front(); -// reference back(); +// reference front(); // constexpr in C++17 +// reference back(); // constexpr in C++17 // const_reference front(); // constexpr in C++14 -// const_reference back(); // constexpr in C++14 +// const_reference back(); // constexpr in C++14 #include #include @@ -23,6 +23,20 @@ // Disable the missing braces warning for this reason. #include "disable_missing_braces_warning.h" +#if TEST_STD_VER > 14 +constexpr bool check_front( double val ) +{ + std::array arr = {1, 2, 3.5}; + return arr.front() == val; +} + +constexpr bool check_back( double val ) +{ + std::array arr = {1, 2, 3.5}; + return arr.back() == val; +} +#endif + int main() { { @@ -65,4 +79,10 @@ int main() } #endif +#if TEST_STD_VER > 14 + { + static_assert (check_front(1), ""); + static_assert (check_back (3.5), ""); + } +#endif } diff --git a/test/std/containers/sequences/array/indexing.pass.cpp b/test/std/containers/sequences/array/indexing.pass.cpp index 64d2716a7592..6cb7941d92c5 100644 --- a/test/std/containers/sequences/array/indexing.pass.cpp +++ b/test/std/containers/sequences/array/indexing.pass.cpp @@ -23,6 +23,14 @@ // Disable the missing braces warning for this reason. #include "disable_missing_braces_warning.h" +#if TEST_STD_VER > 14 +constexpr bool check_idx( size_t idx, double val ) +{ + std::array arr = {1, 2, 3.5}; + return arr[idx] == val; +} +#endif + int main() { { @@ -63,4 +71,11 @@ int main() } #endif +#if TEST_STD_VER > 14 + { + static_assert (check_idx(0, 1), ""); + static_assert (check_idx(1, 2), ""); + static_assert (check_idx(2, 3.5), ""); + } +#endif } diff --git a/test/std/experimental/filesystem/fs.op.funcs/fs.op.last_write_time/last_write_time.pass.cpp b/test/std/experimental/filesystem/fs.op.funcs/fs.op.last_write_time/last_write_time.pass.cpp index 50407b0399f9..ed25649531b9 100644 --- a/test/std/experimental/filesystem/fs.op.funcs/fs.op.last_write_time/last_write_time.pass.cpp +++ b/test/std/experimental/filesystem/fs.op.funcs/fs.op.last_write_time/last_write_time.pass.cpp @@ -72,14 +72,61 @@ std::pair GetSymlinkTimes(path const& p) { return {st.st_atime, st.st_mtime}; } -inline bool TimeIsRepresentableAsTimeT(file_time_type tp) { +namespace { +bool TestSupportsNegativeTimes() { + using namespace std::chrono; + std::error_code ec; + std::time_t old_write_time, new_write_time; + { // WARNING: Do not assert in this scope. + scoped_test_env env; + const path file = env.create_file("file", 42); + old_write_time = LastWriteTime(file); + file_time_type tp(seconds(-5)); + fs::last_write_time(file, tp, ec); + new_write_time = LastWriteTime(file); + } + return !ec && new_write_time <= -5; +} + +bool TestSupportsMaxTime() { + using namespace std::chrono; + using Lim = std::numeric_limits; + auto max_sec = duration_cast(file_time_type::max().time_since_epoch()).count(); + if (max_sec > Lim::max()) return false; + std::error_code ec; + std::time_t old_write_time, new_write_time; + { // WARNING: Do not assert in this scope. + scoped_test_env env; + const path file = env.create_file("file", 42); + old_write_time = LastWriteTime(file); + file_time_type tp = file_time_type::max(); + fs::last_write_time(file, tp, ec); + new_write_time = LastWriteTime(file); + } + return !ec && new_write_time > max_sec - 1; +} + +static const bool SupportsNegativeTimes = TestSupportsNegativeTimes(); +static const bool SupportsMaxTime = TestSupportsMaxTime(); + +} // end namespace + +// Check if a time point is representable on a given filesystem. Check that: +// (A) 'tp' is representable as a time_t +// (B) 'tp' is non-negative or the filesystem supports negative times. +// (C) 'tp' is not 'file_time_type::max()' or the filesystem supports the max +// value. +inline bool TimeIsRepresentableByFilesystem(file_time_type tp) { using namespace std::chrono; using Lim = std::numeric_limits; auto sec = duration_cast(tp.time_since_epoch()).count(); - return (sec >= Lim::min() && sec <= Lim::max()); + auto microsec = duration_cast(tp.time_since_epoch()).count(); + if (sec < Lim::min() || sec > Lim::max()) return false; + else if (microsec < 0 && !SupportsNegativeTimes) return false; + else if (tp == file_time_type::max() && !SupportsMaxTime) return false; + return true; } - TEST_SUITE(exists_test_suite) TEST_CASE(signature_test) @@ -214,15 +261,17 @@ TEST_CASE(set_last_write_time_dynamic_env_test) file_time_type got_time = last_write_time(TC.p); - TEST_CHECK(got_time != old_time); - if (TC.new_time < epoch_time) { - TEST_CHECK(got_time <= TC.new_time); - TEST_CHECK(got_time > TC.new_time - Sec(1)); - } else { - TEST_CHECK(got_time <= TC.new_time + Sec(1)); - TEST_CHECK(got_time >= TC.new_time - Sec(1)); + if (TimeIsRepresentableByFilesystem(TC.new_time)) { + TEST_CHECK(got_time != old_time); + if (TC.new_time < epoch_time) { + TEST_CHECK(got_time <= TC.new_time); + TEST_CHECK(got_time > TC.new_time - Sec(1)); + } else { + TEST_CHECK(got_time <= TC.new_time + Sec(1)); + TEST_CHECK(got_time >= TC.new_time - Sec(1)); + } + TEST_CHECK(LastAccessTime(TC.p) == old_times.first); } - TEST_CHECK(LastAccessTime(TC.p) == old_times.first); } } @@ -269,17 +318,12 @@ TEST_CASE(test_write_min_time) const path p = env.create_file("file", 42); std::error_code ec = GetTestEC(); - file_time_type last_time = last_write_time(p); file_time_type new_time = file_time_type::min(); last_write_time(p, new_time, ec); file_time_type tt = last_write_time(p); - if (!TimeIsRepresentableAsTimeT(new_time)) { - TEST_CHECK(ec); - TEST_CHECK(ec != GetTestEC()); - TEST_CHECK(tt == last_time); - } else { + if (TimeIsRepresentableByFilesystem(new_time)) { TEST_CHECK(!ec); TEST_CHECK(tt >= new_time); TEST_CHECK(tt < new_time + Sec(1)); @@ -287,18 +331,13 @@ TEST_CASE(test_write_min_time) ec = GetTestEC(); last_write_time(p, Clock::now()); - last_time = last_write_time(p); new_time = file_time_type::min() + MicroSec(1); last_write_time(p, new_time, ec); tt = last_write_time(p); - if (!TimeIsRepresentableAsTimeT(new_time)) { - TEST_CHECK(ec); - TEST_CHECK(ec != GetTestEC()); - TEST_CHECK(tt == last_time); - } else { + if (TimeIsRepresentableByFilesystem(new_time)) { TEST_CHECK(!ec); TEST_CHECK(tt >= new_time); TEST_CHECK(tt < new_time + Sec(1)); @@ -317,18 +356,13 @@ TEST_CASE(test_write_min_max_time) const path p = env.create_file("file", 42); std::error_code ec = GetTestEC(); - file_time_type last_time = last_write_time(p); file_time_type new_time = file_time_type::max(); ec = GetTestEC(); last_write_time(p, new_time, ec); file_time_type tt = last_write_time(p); - if (!TimeIsRepresentableAsTimeT(new_time)) { - TEST_CHECK(ec); - TEST_CHECK(ec != GetTestEC()); - TEST_CHECK(tt == last_time); - } else { + if (TimeIsRepresentableByFilesystem(new_time)) { TEST_CHECK(!ec); TEST_CHECK(tt > new_time - Sec(1)); TEST_CHECK(tt <= new_time); diff --git a/test/std/language.support/support.rtti/type.info/type_info.pass.cpp b/test/std/language.support/support.rtti/type.info/type_info.pass.cpp index 2616865e6da9..74c1c0c7df99 100644 --- a/test/std/language.support/support.rtti/type.info/type_info.pass.cpp +++ b/test/std/language.support/support.rtti/type.info/type_info.pass.cpp @@ -10,11 +10,16 @@ // test type_info #include +#include #include #include +bool test_constructor_explicit(std::type_info const&) { return false; } +bool test_constructor_explicit(std::string const&) { return true; } + int main() { + { const std::type_info& t1 = typeid(int); const std::type_info& t2 = typeid(int); assert(t1 == t2); @@ -23,4 +28,13 @@ int main() assert(!t1.before(t2)); assert(strcmp(t1.name(), t2.name()) == 0); assert(strcmp(t1.name(), t3.name()) != 0); + } + { + // type_info has a protected constructor taking a string literal. This + // constructor is not intended for users. However it still participates + // in overload resolution, so we need to ensure that it is marked explicit + // to avoid ambiguous conversions. + // See: https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=216201 + assert(test_constructor_explicit("abc")); + } } diff --git a/test/std/strings/basic.string/string.cons/brace_assignment.pass.cpp b/test/std/strings/basic.string/string.cons/brace_assignment.pass.cpp new file mode 100644 index 000000000000..8b498f1787bd --- /dev/null +++ b/test/std/strings/basic.string/string.cons/brace_assignment.pass.cpp @@ -0,0 +1,36 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03 + +// + +// basic_string& +// operator=(basic_string&& str); + +#include +#include + +#include "test_macros.h" + +int main() +{ + // Test that assignment from {} and {ptr, len} are allowed and are not + // ambiguous. + { + std::string s = "hello world"; + s = {}; + assert(s.empty()); + } + { + std::string s = "hello world"; + s = {"abc", 2}; + assert(s == "ab"); + } +} diff --git a/test/std/strings/basic.string/string.cons/string_view.pass.cpp b/test/std/strings/basic.string/string.cons/string_view.pass.cpp index d0e1a1699a22..78ceae70e2d1 100644 --- a/test/std/strings/basic.string/string.cons/string_view.pass.cpp +++ b/test/std/strings/basic.string/string.cons/string_view.pass.cpp @@ -28,12 +28,23 @@ test(std::basic_string_view sv) typedef std::basic_string, test_allocator > S; typedef typename S::traits_type T; typedef typename S::allocator_type A; + { S s2(sv); LIBCPP_ASSERT(s2.__invariants()); assert(s2.size() == sv.size()); assert(T::compare(s2.data(), sv.data(), sv.size()) == 0); assert(s2.get_allocator() == A()); assert(s2.capacity() >= s2.size()); + } + { + S s2; + s2 = sv; + LIBCPP_ASSERT(s2.__invariants()); + assert(s2.size() == sv.size()); + assert(T::compare(s2.data(), sv.data(), sv.size()) == 0); + assert(s2.get_allocator() == A()); + assert(s2.capacity() >= s2.size()); + } } template @@ -42,12 +53,23 @@ test(std::basic_string_view sv, const A& a) { typedef std::basic_string, A> S; typedef typename S::traits_type T; + { S s2(sv, a); LIBCPP_ASSERT(s2.__invariants()); assert(s2.size() == sv.size()); assert(T::compare(s2.data(), sv.data(), sv.size()) == 0); assert(s2.get_allocator() == a); assert(s2.capacity() >= s2.size()); + } + { + S s2(a); + s2 = sv; + LIBCPP_ASSERT(s2.__invariants()); + assert(s2.size() == sv.size()); + assert(T::compare(s2.data(), sv.data(), sv.size()) == 0); + assert(s2.get_allocator() == a); + assert(s2.capacity() >= s2.size()); + } } int main()