From d77882e66779f69e0497050e1e9e4c1bada589e8 Mon Sep 17 00:00:00 2001 From: Tom Stellard Date: Tue, 26 Jul 2022 21:46:53 -0700 Subject: [PATCH 001/323] Drop 'git' from version string --- llvm/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/CMakeLists.txt b/llvm/CMakeLists.txt index 45399dc0537e1..c264bbeca0266 100644 --- a/llvm/CMakeLists.txt +++ b/llvm/CMakeLists.txt @@ -25,7 +25,7 @@ if(NOT DEFINED LLVM_VERSION_PATCH) set(LLVM_VERSION_PATCH 0) endif() if(NOT DEFINED LLVM_VERSION_SUFFIX) - set(LLVM_VERSION_SUFFIX git) + set(LLVM_VERSION_SUFFIX) endif() if (NOT PACKAGE_VERSION) From 99f7f1ad7a8ee58f7e4be8e1586aed164639ec1b Mon Sep 17 00:00:00 2001 From: Tom Stellard Date: Wed, 27 Jul 2022 12:31:40 -0700 Subject: [PATCH 002/323] workflows: Fix version check for X.0.0 releases (cherry picked from commit 51ba98d058c24632b86b79af5a4ddf6c5ab4e614) --- .github/workflows/version-check.py | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/.github/workflows/version-check.py b/.github/workflows/version-check.py index 74c061ee9e95f..11591312c2819 100755 --- a/.github/workflows/version-check.py +++ b/.github/workflows/version-check.py @@ -10,13 +10,21 @@ tag = repo.git.describe(tags = True, abbrev=0) m = re.match('llvmorg-([0-9]+)\.([0-9]+)\.([0-9]+)', tag) -if not m: - print("error: Tag is not valid: ", tag) - sys.exit(1) -expected_major = m.group(1) -expected_minor = m.group(2) -expected_patch = int(m.group(3)) + 1 +if m: + expected_major = m.group(1) + expected_minor = m.group(2) + expected_patch = int(m.group(3)) + 1 +else: + # If the previous tag is llvmorg-X-init, then we should be at version X.0.0. + m = re.match('llvmorg-([0-9]+)-init', tag) + if not m: + print("error: Tag is not valid: ", tag) + sys.exit(1) + expected_major = m.group(1) + expected_minor = 0 + expected_patch = 0 + expected_version = f"{expected_major}.{expected_minor}.{expected_patch}" m = re.match("[0-9]+\.[0-9]+\.[0-9]+", version) From 37007475ca1b345b4c5d340e228bcd7a62732d81 Mon Sep 17 00:00:00 2001 From: Tom Stellard Date: Wed, 27 Jul 2022 15:23:24 -0700 Subject: [PATCH 003/323] workflows: Use macos-11 runners macos-10.15 is deprecated and will be removed. (cherry picked from commit d9e02a30b16ea65a7da87913c40af03e22c9571f) --- .github/workflows/llvm-project-tests.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.github/workflows/llvm-project-tests.yml b/.github/workflows/llvm-project-tests.yml index 4910ddbe5cfd4..78bb4a88bafe9 100644 --- a/.github/workflows/llvm-project-tests.yml +++ b/.github/workflows/llvm-project-tests.yml @@ -39,9 +39,7 @@ jobs: - windows-2019 # We're using a specific version of macOS due to: # https://github.com/actions/virtual-environments/issues/5900 - # We need addtional testing to see if our workaround works for - # new macOS builds. - - macOS-10.15 + - macOS-11 steps: - name: Setup Windows if: startsWith(matrix.os, 'windows') @@ -74,7 +72,7 @@ jobs: env: # Workaround for https://github.com/actions/virtual-environments/issues/5900. # This should be a no-op for non-mac OSes - PKG_CONFIG_PATH: /usr/local/Homebrew/Library/Homebrew/os/mac/pkgconfig//11 + PKG_CONFIG_PATH: /usr/local/Homebrew/Library/Homebrew/os/mac/pkgconfig//12 with: cmake_args: '-GNinja -DLLVM_ENABLE_PROJECTS="${{ inputs.projects }}" -DCMAKE_BUILD_TYPE=Release -DLLDB_INCLUDE_TESTS=OFF -DCMAKE_C_COMPILER_LAUNCHER=sccache -DCMAKE_CXX_COMPILER_LAUNCHER=sccache' build_target: '${{ inputs.build_target }}' From 2647f7274782e4a529d7c3a9920de86ddfe72324 Mon Sep 17 00:00:00 2001 From: Sebastian Neubauer Date: Thu, 28 Jul 2022 14:34:59 +0200 Subject: [PATCH 004/323] [CMake][OpenMP] Remove wrong backslash outdir is defined in the line above, it will not exist in the install command, so it should not be escaped. (cherry picked from commit 50716ba2b337afe46ac256cc91673dc27356a776) --- openmp/runtime/src/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmp/runtime/src/CMakeLists.txt b/openmp/runtime/src/CMakeLists.txt index 02f65aac0d40e..9bc8837d0377d 100644 --- a/openmp/runtime/src/CMakeLists.txt +++ b/openmp/runtime/src/CMakeLists.txt @@ -380,7 +380,7 @@ else() extend_path(outdir "${CMAKE_INSTALL_PREFIX}" "${OPENMP_INSTALL_LIBDIR}") install(CODE "execute_process(COMMAND \"\${CMAKE_COMMAND}\" -E create_symlink \"${LIBOMP_LIB_FILE}\" \"${alias}${LIBOMP_LIBRARY_SUFFIX}\" WORKING_DIRECTORY - \"\$ENV{DESTDIR}\${outdir}\")") + \"\$ENV{DESTDIR}${outdir}\")") endforeach() endif() endif() From c74059c5da05cc6fd90afb3a5657bc12a1bb6d81 Mon Sep 17 00:00:00 2001 From: Nikolas Klauser Date: Wed, 27 Jul 2022 14:41:40 +0200 Subject: [PATCH 005/323] [libc++] Implement P1004R2 (constexpr std::vector) Reviewed By: #libc, ldionne Spies: mgorny, var-const, ormris, philnik, miscco, hiraditya, steven_wu, jkorous, ldionne, christof, libcxx-commits Differential Revision: https://reviews.llvm.org/D68365 (cherry picked from commit 98d3d5b5da66e3cf7807c23a0294280bb796466b) --- libcxx/docs/ReleaseNotes.rst | 1 + libcxx/docs/Status/Cxx20Papers.csv | 2 +- libcxx/include/__algorithm/fill.h | 2 + libcxx/include/__algorithm/fill_n.h | 2 + libcxx/include/__bit_reference | 243 ++++---- libcxx/include/__memory/construct_at.h | 3 +- libcxx/include/__memory/pointer_traits.h | 2 +- .../__memory/uninitialized_algorithms.h | 7 +- libcxx/include/__split_buffer | 134 +++-- libcxx/include/memory | 26 +- libcxx/include/vector | 557 +++++++++++------- libcxx/src/include/sso_allocator.h | 5 + .../map/map.cons/copy_assign.pass.cpp | 2 + .../vector.bool/assign_copy.pass.cpp | 13 +- .../assign_initializer_list.pass.cpp | 13 +- .../vector.bool/assign_move.pass.cpp | 13 +- .../sequences/vector.bool/capacity.pass.cpp | 13 +- .../sequences/vector.bool/compare.pass.cpp | 11 +- .../vector.bool/const_reference.pass.cpp | 5 +- .../vector.bool/construct_default.pass.cpp | 19 +- .../vector.bool/construct_iter_iter.pass.cpp | 16 +- .../construct_iter_iter_alloc.pass.cpp | 16 +- .../vector.bool/construct_size.pass.cpp | 24 +- .../vector.bool/construct_size_value.pass.cpp | 16 +- .../construct_size_value_alloc.pass.cpp | 19 +- .../sequences/vector.bool/copy.pass.cpp | 16 +- .../sequences/vector.bool/copy_alloc.pass.cpp | 16 +- .../sequences/vector.bool/emplace.pass.cpp | 13 +- .../vector.bool/emplace_back.pass.cpp | 13 +- .../sequences/vector.bool/empty.pass.cpp | 13 +- .../vector.bool/enabled_hash.pass.cpp | 15 +- .../sequences/vector.bool/erase_iter.pass.cpp | 13 +- .../vector.bool/erase_iter_iter.pass.cpp | 13 +- .../sequences/vector.bool/find.pass.cpp | 13 +- .../vector.bool/get_allocator.pass.cpp | 11 +- .../vector.bool/initializer_list.pass.cpp | 13 +- .../initializer_list_alloc.pass.cpp | 13 +- .../insert_iter_initializer_list.pass.cpp | 13 +- .../insert_iter_iter_iter.pass.cpp | 13 +- .../insert_iter_size_value.pass.cpp | 13 +- .../vector.bool/insert_iter_value.pass.cpp | 13 +- .../sequences/vector.bool/iterators.pass.cpp | 17 +- .../sequences/vector.bool/move.pass.cpp | 13 +- .../sequences/vector.bool/move_alloc.pass.cpp | 13 +- .../op_equal_initializer_list.pass.cpp | 13 +- .../sequences/vector.bool/push_back.pass.cpp | 13 +- .../vector.bool/reference.swap.pass.cpp | 13 +- .../reference/assign_bool.pass.cpp | 5 +- .../reference/assign_copy.pass.cpp | 7 +- .../vector.bool/reference/ctor_copy.pass.cpp | 7 +- .../vector.bool/reference/flip.pass.cpp | 7 +- .../reference/operator_bool.pass.cpp | 7 +- .../sequences/vector.bool/reserve.pass.cpp | 15 +- .../vector.bool/resize_size.pass.cpp | 13 +- .../vector.bool/resize_size_value.pass.cpp | 13 +- .../vector.bool/shrink_to_fit.pass.cpp | 13 +- .../sequences/vector.bool/size.pass.cpp | 13 +- .../sequences/vector.bool/swap.pass.cpp | 13 +- .../vector.bool/vector_bool.pass.cpp | 13 +- .../sequences/vector/access.pass.cpp | 34 +- .../sequences/vector/compare.pass.cpp | 11 +- .../vector/constant_initialization.pass.cpp | 23 + .../sequences/vector/contiguous.pass.cpp | 15 +- .../sequences/vector/get_allocator.pass.cpp | 11 +- .../sequences/vector/iterators.pass.cpp | 13 +- .../vector/reverse_iterators.pass.cpp | 13 +- .../vector/vector.capacity/capacity.pass.cpp | 13 +- .../vector/vector.capacity/empty.pass.cpp | 14 +- .../vector/vector.capacity/max_size.pass.cpp | 12 +- .../vector/vector.capacity/reserve.pass.cpp | 20 +- .../vector.capacity/resize_size.pass.cpp | 14 +- .../resize_size_value.pass.cpp | 14 +- .../vector.capacity/shrink_to_fit.pass.cpp | 16 +- .../vector/vector.capacity/size.pass.cpp | 11 +- .../vector/vector.capacity/swap.pass.cpp | 14 +- .../vector/vector.cons/assign_copy.pass.cpp | 14 +- .../assign_initializer_list.pass.cpp | 16 +- .../vector.cons/assign_iter_iter.pass.cpp | 7 +- .../vector/vector.cons/assign_move.pass.cpp | 14 +- .../vector.cons/assign_size_value.pass.cpp | 18 +- .../vector.cons/construct_default.pass.cpp | 20 +- .../vector.cons/construct_iter_iter.pass.cpp | 24 +- .../construct_iter_iter_alloc.pass.cpp | 23 +- .../vector.cons/construct_size.pass.cpp | 22 +- .../vector.cons/construct_size_value.pass.cpp | 16 +- .../construct_size_value_alloc.pass.cpp | 16 +- .../vector/vector.cons/copy.pass.cpp | 16 +- .../vector/vector.cons/copy_alloc.pass.cpp | 16 +- .../vector/vector.cons/deduct.pass.cpp | 11 +- .../vector.cons/default.recursive.pass.cpp | 2 +- .../vector.cons/default_noexcept.pass.cpp | 14 +- .../vector/vector.cons/dtor_noexcept.pass.cpp | 13 +- .../vector.cons/initializer_list.pass.cpp | 13 +- .../initializer_list_alloc.pass.cpp | 13 +- .../vector/vector.cons/move.pass.cpp | 13 +- .../vector/vector.cons/move_alloc.pass.cpp | 13 +- .../vector.cons/move_assign_noexcept.pass.cpp | 2 +- .../op_equal_initializer_list.pass.cpp | 13 +- .../vector/vector.data/data.pass.cpp | 21 +- .../vector/vector.data/data_const.pass.cpp | 21 +- .../vector/vector.erasure/erase.pass.cpp | 16 +- .../vector/vector.erasure/erase_if.pass.cpp | 17 +- .../vector/vector.modifiers/clear.pass.cpp | 13 +- .../vector/vector.modifiers/emplace.pass.cpp | 23 +- .../vector.modifiers/emplace_back.pass.cpp | 23 +- .../vector.modifiers/emplace_extra.pass.cpp | 14 +- .../vector.modifiers/erase_iter.pass.cpp | 29 +- .../vector.modifiers/erase_iter_iter.pass.cpp | 29 +- .../insert_iter_initializer_list.pass.cpp | 17 +- .../insert_iter_iter_iter.pass.cpp | 13 +- .../insert_iter_lvalue.pass.cpp | 14 +- .../insert_iter_rvalue.pass.cpp | 13 +- .../insert_iter_size_value.pass.cpp | 13 +- .../vector/vector.modifiers/pop_back.pass.cpp | 13 +- .../vector.modifiers/push_back.pass.cpp | 13 +- .../push_back_rvalue.pass.cpp | 13 +- .../vector/vector.special/swap.pass.cpp | 13 +- .../end.to.end/oneshot_func.pass.cpp | 2 + libcxx/test/support/allocators.h | 21 +- libcxx/test/support/asan_testing.h | 10 +- libcxx/test/support/poisoned_hash_helper.h | 6 +- libcxx/test/support/test_allocator.h | 23 +- 122 files changed, 1817 insertions(+), 736 deletions(-) create mode 100644 libcxx/test/std/containers/sequences/vector/constant_initialization.pass.cpp diff --git a/libcxx/docs/ReleaseNotes.rst b/libcxx/docs/ReleaseNotes.rst index 96e98fd5c9ab3..c717ea2682b54 100644 --- a/libcxx/docs/ReleaseNotes.rst +++ b/libcxx/docs/ReleaseNotes.rst @@ -50,6 +50,7 @@ almost complete. The ``ranges`` library is considered experimental. Implemented Papers ------------------ +- P1004R2 - Making ``std::vector`` constexpr - P0627R6 - Function to mark unreachable code - P1165R1 - Make stateful allocator propagation more consistent for ``operator+(basic_string)`` - P0674R1 - Support arrays in ``make_shared`` and ``allocate_shared`` diff --git a/libcxx/docs/Status/Cxx20Papers.csv b/libcxx/docs/Status/Cxx20Papers.csv index 703c4a54c27e9..f335d1b984a25 100644 --- a/libcxx/docs/Status/Cxx20Papers.csv +++ b/libcxx/docs/Status/Cxx20Papers.csv @@ -107,7 +107,7 @@ "`P0660R10 `__","LWG","Stop Token and Joining Thread, Rev 10","Cologne","","" "`P0784R7 `__","CWG","More constexpr containers","Cologne","|Complete|","12.0" "`P0980R1 `__","LWG","Making std::string constexpr","Cologne","|Complete|","15.0" -"`P1004R2 `__","LWG","Making std::vector constexpr","Cologne","","" +"`P1004R2 `__","LWG","Making std::vector constexpr","Cologne","|Complete|","15.0" "`P1035R7 `__","LWG","Input Range Adaptors","Cologne","","" "`P1065R2 `__","LWG","Constexpr INVOKE","Cologne","|Complete|","12.0" "`P1135R6 `__","LWG","The C++20 Synchronization Library","Cologne","|Complete|","11.0" diff --git a/libcxx/include/__algorithm/fill.h b/libcxx/include/__algorithm/fill.h index ec9968fdb8b34..901ba4e68689a 100644 --- a/libcxx/include/__algorithm/fill.h +++ b/libcxx/include/__algorithm/fill.h @@ -20,6 +20,8 @@ _LIBCPP_BEGIN_NAMESPACE_STD +// fill isn't specialized for std::memset, because the compiler already optimizes the loop to a call to std::memset. + template inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 void diff --git a/libcxx/include/__algorithm/fill_n.h b/libcxx/include/__algorithm/fill_n.h index 7482a4188dd51..6c5e44efde9b0 100644 --- a/libcxx/include/__algorithm/fill_n.h +++ b/libcxx/include/__algorithm/fill_n.h @@ -19,6 +19,8 @@ _LIBCPP_BEGIN_NAMESPACE_STD +// fill_n isn't specialized for std::memset, because the compiler already optimizes the loop to a call to std::memset. + template inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 _OutputIterator diff --git a/libcxx/include/__bit_reference b/libcxx/include/__bit_reference index f54cb6c16f48e..60f57d665a1cb 100644 --- a/libcxx/include/__bit_reference +++ b/libcxx/include/__bit_reference @@ -10,10 +10,13 @@ #ifndef _LIBCPP___BIT_REFERENCE #define _LIBCPP___BIT_REFERENCE +#include <__algorithm/copy_n.h> +#include <__algorithm/fill_n.h> #include <__algorithm/min.h> #include <__bits> #include <__config> #include <__iterator/iterator_traits.h> +#include <__memory/construct_at.h> #include <__memory/pointer_traits.h> #include #include @@ -51,15 +54,15 @@ class __bit_reference friend class __bit_const_reference<_Cp>; friend class __bit_iterator<_Cp, false>; public: - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 __bit_reference(const __bit_reference&) = default; - _LIBCPP_INLINE_VISIBILITY operator bool() const _NOEXCEPT + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 operator bool() const _NOEXCEPT {return static_cast(*__seg_ & __mask_);} - _LIBCPP_INLINE_VISIBILITY bool operator ~() const _NOEXCEPT + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 bool operator ~() const _NOEXCEPT {return !static_cast(*this);} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 __bit_reference& operator=(bool __x) _NOEXCEPT { if (__x) @@ -70,7 +73,7 @@ public: } #if _LIBCPP_STD_VER > 20 - _LIBCPP_HIDE_FROM_ABI const __bit_reference& operator=(bool __x) const noexcept { + _LIBCPP_HIDE_FROM_ABI constexpr const __bit_reference& operator=(bool __x) const noexcept { if (__x) *__seg_ |= __mask_; else @@ -79,15 +82,15 @@ public: } #endif - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 __bit_reference& operator=(const __bit_reference& __x) _NOEXCEPT {return operator=(static_cast(__x));} - _LIBCPP_INLINE_VISIBILITY void flip() _NOEXCEPT {*__seg_ ^= __mask_;} - _LIBCPP_INLINE_VISIBILITY __bit_iterator<_Cp, false> operator&() const _NOEXCEPT + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 void flip() _NOEXCEPT {*__seg_ ^= __mask_;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 __bit_iterator<_Cp, false> operator&() const _NOEXCEPT {return __bit_iterator<_Cp, false>(__seg_, static_cast(__libcpp_ctz(__mask_)));} private: - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 explicit __bit_reference(__storage_pointer __s, __storage_type __m) _NOEXCEPT : __seg_(__s), __mask_(__m) {} }; @@ -98,7 +101,7 @@ class __bit_reference<_Cp, false> }; template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 void swap(__bit_reference<_Cp> __x, __bit_reference<_Cp> __y) _NOEXCEPT { @@ -108,7 +111,7 @@ swap(__bit_reference<_Cp> __x, __bit_reference<_Cp> __y) _NOEXCEPT } template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 void swap(__bit_reference<_Cp> __x, __bit_reference<_Dp> __y) _NOEXCEPT { @@ -118,7 +121,7 @@ swap(__bit_reference<_Cp> __x, __bit_reference<_Dp> __y) _NOEXCEPT } template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 void swap(__bit_reference<_Cp> __x, bool& __y) _NOEXCEPT { @@ -128,7 +131,7 @@ swap(__bit_reference<_Cp> __x, bool& __y) _NOEXCEPT } template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 void swap(bool& __x, __bit_reference<_Cp> __y) _NOEXCEPT { @@ -152,14 +155,14 @@ public: _LIBCPP_INLINE_VISIBILITY __bit_const_reference(const __bit_const_reference&) = default; - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 __bit_const_reference(const __bit_reference<_Cp>& __x) _NOEXCEPT : __seg_(__x.__seg_), __mask_(__x.__mask_) {} _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR operator bool() const _NOEXCEPT {return static_cast(*__seg_ & __mask_);} - _LIBCPP_INLINE_VISIBILITY __bit_iterator<_Cp, true> operator&() const _NOEXCEPT + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 __bit_iterator<_Cp, true> operator&() const _NOEXCEPT {return __bit_iterator<_Cp, true>(__seg_, static_cast(__libcpp_ctz(__mask_)));} private: _LIBCPP_INLINE_VISIBILITY @@ -173,12 +176,12 @@ private: // find template -__bit_iterator<_Cp, _IsConst> +_LIBCPP_CONSTEXPR_AFTER_CXX17 __bit_iterator<_Cp, _IsConst> __find_bool_true(__bit_iterator<_Cp, _IsConst> __first, typename _Cp::size_type __n) { typedef __bit_iterator<_Cp, _IsConst> _It; typedef typename _It::__storage_type __storage_type; - static const int __bits_per_word = _It::__bits_per_word; + const int __bits_per_word = _It::__bits_per_word; // do first partial word if (__first.__ctz_ != 0) { @@ -209,7 +212,7 @@ __find_bool_true(__bit_iterator<_Cp, _IsConst> __first, typename _Cp::size_type } template -__bit_iterator<_Cp, _IsConst> +_LIBCPP_CONSTEXPR_AFTER_CXX17 __bit_iterator<_Cp, _IsConst> __find_bool_false(__bit_iterator<_Cp, _IsConst> __first, typename _Cp::size_type __n) { typedef __bit_iterator<_Cp, _IsConst> _It; @@ -248,7 +251,7 @@ __find_bool_false(__bit_iterator<_Cp, _IsConst> __first, typename _Cp::size_type } template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 __bit_iterator<_Cp, _IsConst> find(__bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, const _Tp& __value) { @@ -334,7 +337,7 @@ count(__bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __las // fill_n template -void +_LIBCPP_CONSTEXPR_AFTER_CXX17 void __fill_n_false(__bit_iterator<_Cp, false> __first, typename _Cp::size_type __n) { typedef __bit_iterator<_Cp, false> _It; @@ -352,7 +355,7 @@ __fill_n_false(__bit_iterator<_Cp, false> __first, typename _Cp::size_type __n) } // do middle whole words __storage_type __nw = __n / __bits_per_word; - _VSTD::memset(_VSTD::__to_address(__first.__seg_), 0, __nw * sizeof(__storage_type)); + std::fill_n(std::__to_address(__first.__seg_), __nw, 0); __n -= __nw * __bits_per_word; // do last partial word if (__n > 0) @@ -364,7 +367,7 @@ __fill_n_false(__bit_iterator<_Cp, false> __first, typename _Cp::size_type __n) } template -void +_LIBCPP_CONSTEXPR_AFTER_CXX17 void __fill_n_true(__bit_iterator<_Cp, false> __first, typename _Cp::size_type __n) { typedef __bit_iterator<_Cp, false> _It; @@ -382,7 +385,8 @@ __fill_n_true(__bit_iterator<_Cp, false> __first, typename _Cp::size_type __n) } // do middle whole words __storage_type __nw = __n / __bits_per_word; - _VSTD::memset(_VSTD::__to_address(__first.__seg_), -1, __nw * sizeof(__storage_type)); + // __storage_type is always an unsigned type, so -1 sets all bits + std::fill_n(std::__to_address(__first.__seg_), __nw, static_cast<__storage_type>(-1)); __n -= __nw * __bits_per_word; // do last partial word if (__n > 0) @@ -394,7 +398,7 @@ __fill_n_true(__bit_iterator<_Cp, false> __first, typename _Cp::size_type __n) } template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 void fill_n(__bit_iterator<_Cp, false> __first, typename _Cp::size_type __n, bool __value) { @@ -410,7 +414,7 @@ fill_n(__bit_iterator<_Cp, false> __first, typename _Cp::size_type __n, bool __v // fill template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 void fill(__bit_iterator<_Cp, false> __first, __bit_iterator<_Cp, false> __last, bool __value) { @@ -420,6 +424,7 @@ fill(__bit_iterator<_Cp, false> __first, __bit_iterator<_Cp, false> __last, bool // copy template +_LIBCPP_CONSTEXPR_AFTER_CXX17 __bit_iterator<_Cp, false> __copy_aligned(__bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, __bit_iterator<_Cp, false> __result) @@ -449,9 +454,7 @@ __copy_aligned(__bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsCon // __first.__ctz_ == 0; // do middle words __storage_type __nw = __n / __bits_per_word; - _VSTD::memmove(_VSTD::__to_address(__result.__seg_), - _VSTD::__to_address(__first.__seg_), - __nw * sizeof(__storage_type)); + std::copy_n(std::__to_address(__first.__seg_), __nw, std::__to_address(__result.__seg_)); __n -= __nw * __bits_per_word; __result.__seg_ += __nw; // do last word @@ -469,6 +472,7 @@ __copy_aligned(__bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsCon } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 __bit_iterator<_Cp, false> __copy_unaligned(__bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, __bit_iterator<_Cp, false> __result) @@ -476,7 +480,7 @@ __copy_unaligned(__bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsC typedef __bit_iterator<_Cp, _IsConst> _In; typedef typename _In::difference_type difference_type; typedef typename _In::__storage_type __storage_type; - static const int __bits_per_word = _In::__bits_per_word; + const int __bits_per_word = _In::__bits_per_word; difference_type __n = __last - __first; if (__n > 0) { @@ -547,7 +551,7 @@ __copy_unaligned(__bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsC } template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 __bit_iterator<_Cp, false> copy(__bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, __bit_iterator<_Cp, false> __result) { @@ -559,7 +563,7 @@ copy(__bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last // copy_backward template -__bit_iterator<_Cp, false> +_LIBCPP_CONSTEXPR_AFTER_CXX17 __bit_iterator<_Cp, false> __copy_backward_aligned(__bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, __bit_iterator<_Cp, false> __result) { @@ -590,9 +594,7 @@ __copy_backward_aligned(__bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_C __storage_type __nw = __n / __bits_per_word; __result.__seg_ -= __nw; __last.__seg_ -= __nw; - _VSTD::memmove(_VSTD::__to_address(__result.__seg_), - _VSTD::__to_address(__last.__seg_), - __nw * sizeof(__storage_type)); + std::copy_n(std::__to_address(__last.__seg_), __nw, std::__to_address(__result.__seg_)); __n -= __nw * __bits_per_word; // do last word if (__n > 0) @@ -608,7 +610,7 @@ __copy_backward_aligned(__bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_C } template -__bit_iterator<_Cp, false> +_LIBCPP_CONSTEXPR_AFTER_CXX17 __bit_iterator<_Cp, false> __copy_backward_unaligned(__bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, __bit_iterator<_Cp, false> __result) { @@ -694,7 +696,7 @@ __copy_backward_unaligned(__bit_iterator<_Cp, _IsConst> __first, __bit_iterator< } template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 __bit_iterator<_Cp, false> copy_backward(__bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, __bit_iterator<_Cp, false> __result) { @@ -901,14 +903,19 @@ struct __bit_array difference_type __size_; __storage_type __word_[_Np]; - _LIBCPP_INLINE_VISIBILITY static difference_type capacity() + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 static difference_type capacity() {return static_cast(_Np * __bits_per_word);} - _LIBCPP_INLINE_VISIBILITY explicit __bit_array(difference_type __s) : __size_(__s) {} - _LIBCPP_INLINE_VISIBILITY iterator begin() + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 explicit __bit_array(difference_type __s) : __size_(__s) { + if (__libcpp_is_constant_evaluated()) { + for (size_t __i = 0; __i != __bit_array<_Cp>::_Np; ++__i) + std::__construct_at(__word_ + __i, 0); + } + } + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 iterator begin() { return iterator(pointer_traits<__storage_pointer>::pointer_to(__word_[0]), 0); } - _LIBCPP_INLINE_VISIBILITY iterator end() + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 iterator end() { return iterator(pointer_traits<__storage_pointer>::pointer_to(__word_[0]) + __size_ / __bits_per_word, static_cast(__size_ % __bits_per_word)); @@ -916,7 +923,7 @@ struct __bit_array }; template -__bit_iterator<_Cp, false> +_LIBCPP_CONSTEXPR_AFTER_CXX17 __bit_iterator<_Cp, false> rotate(__bit_iterator<_Cp, false> __first, __bit_iterator<_Cp, false> __middle, __bit_iterator<_Cp, false> __last) { typedef __bit_iterator<_Cp, false> _I1; @@ -967,14 +974,14 @@ rotate(__bit_iterator<_Cp, false> __first, __bit_iterator<_Cp, false> __middle, // equal template -bool +_LIBCPP_CONSTEXPR_AFTER_CXX17 bool __equal_unaligned(__bit_iterator<_Cp, _IC1> __first1, __bit_iterator<_Cp, _IC1> __last1, __bit_iterator<_Cp, _IC2> __first2) { typedef __bit_iterator<_Cp, _IC1> _It; typedef typename _It::difference_type difference_type; typedef typename _It::__storage_type __storage_type; - static const int __bits_per_word = _It::__bits_per_word; + const int __bits_per_word = _It::__bits_per_word; difference_type __n = __last1 - __first1; if (__n > 0) { @@ -1049,14 +1056,14 @@ __equal_unaligned(__bit_iterator<_Cp, _IC1> __first1, __bit_iterator<_Cp, _IC1> } template -bool +_LIBCPP_CONSTEXPR_AFTER_CXX17 bool __equal_aligned(__bit_iterator<_Cp, _IC1> __first1, __bit_iterator<_Cp, _IC1> __last1, __bit_iterator<_Cp, _IC2> __first2) { typedef __bit_iterator<_Cp, _IC1> _It; typedef typename _It::difference_type difference_type; typedef typename _It::__storage_type __storage_type; - static const int __bits_per_word = _It::__bits_per_word; + const int __bits_per_word = _It::__bits_per_word; difference_type __n = __last1 - __first1; if (__n > 0) { @@ -1092,7 +1099,7 @@ __equal_aligned(__bit_iterator<_Cp, _IC1> __first1, __bit_iterator<_Cp, _IC1> __ } template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 bool equal(__bit_iterator<_Cp, _IC1> __first1, __bit_iterator<_Cp, _IC1> __last1, __bit_iterator<_Cp, _IC2> __first2) { @@ -1126,7 +1133,7 @@ private: unsigned __ctz_; public: - _LIBCPP_INLINE_VISIBILITY __bit_iterator() _NOEXCEPT + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 __bit_iterator() _NOEXCEPT #if _LIBCPP_STD_VER > 11 : __seg_(nullptr), __ctz_(0) #endif @@ -1137,7 +1144,7 @@ public: // When _IsConst=true, this is a converting constructor; // the copy and move constructors are implicitly generated // and trivial. - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 __bit_iterator(const __bit_iterator<_Cp, false>& __it) _NOEXCEPT : __seg_(__it.__seg_), __ctz_(__it.__ctz_) {} @@ -1146,19 +1153,19 @@ public: // the implicit generation of a defaulted one is deprecated. // When _IsConst=true, the assignment operators are // implicitly generated and trivial. - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 __bit_iterator& operator=(const _If<_IsConst, struct __private_nat, __bit_iterator>& __it) { __seg_ = __it.__seg_; __ctz_ = __it.__ctz_; return *this; } - _LIBCPP_INLINE_VISIBILITY reference operator*() const _NOEXCEPT { + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 reference operator*() const _NOEXCEPT { return typename conditional<_IsConst, __bit_const_reference<_Cp>, __bit_reference<_Cp> > ::type(__seg_, __storage_type(1) << __ctz_); } - _LIBCPP_INLINE_VISIBILITY __bit_iterator& operator++() + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 __bit_iterator& operator++() { if (__ctz_ != __bits_per_word-1) ++__ctz_; @@ -1170,14 +1177,14 @@ public: return *this; } - _LIBCPP_INLINE_VISIBILITY __bit_iterator operator++(int) + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 __bit_iterator operator++(int) { __bit_iterator __tmp = *this; ++(*this); return __tmp; } - _LIBCPP_INLINE_VISIBILITY __bit_iterator& operator--() + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 __bit_iterator& operator--() { if (__ctz_ != 0) --__ctz_; @@ -1189,14 +1196,14 @@ public: return *this; } - _LIBCPP_INLINE_VISIBILITY __bit_iterator operator--(int) + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 __bit_iterator operator--(int) { __bit_iterator __tmp = *this; --(*this); return __tmp; } - _LIBCPP_INLINE_VISIBILITY __bit_iterator& operator+=(difference_type __n) + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 __bit_iterator& operator+=(difference_type __n) { if (__n >= 0) __seg_ += (__n + __ctz_) / __bits_per_word; @@ -1208,54 +1215,54 @@ public: return *this; } - _LIBCPP_INLINE_VISIBILITY __bit_iterator& operator-=(difference_type __n) + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 __bit_iterator& operator-=(difference_type __n) { return *this += -__n; } - _LIBCPP_INLINE_VISIBILITY __bit_iterator operator+(difference_type __n) const + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 __bit_iterator operator+(difference_type __n) const { __bit_iterator __t(*this); __t += __n; return __t; } - _LIBCPP_INLINE_VISIBILITY __bit_iterator operator-(difference_type __n) const + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 __bit_iterator operator-(difference_type __n) const { __bit_iterator __t(*this); __t -= __n; return __t; } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 friend __bit_iterator operator+(difference_type __n, const __bit_iterator& __it) {return __it + __n;} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 friend difference_type operator-(const __bit_iterator& __x, const __bit_iterator& __y) {return (__x.__seg_ - __y.__seg_) * __bits_per_word + __x.__ctz_ - __y.__ctz_;} - _LIBCPP_INLINE_VISIBILITY reference operator[](difference_type __n) const {return *(*this + __n);} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 reference operator[](difference_type __n) const {return *(*this + __n);} - _LIBCPP_INLINE_VISIBILITY friend bool operator==(const __bit_iterator& __x, const __bit_iterator& __y) + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 friend bool operator==(const __bit_iterator& __x, const __bit_iterator& __y) {return __x.__seg_ == __y.__seg_ && __x.__ctz_ == __y.__ctz_;} - _LIBCPP_INLINE_VISIBILITY friend bool operator!=(const __bit_iterator& __x, const __bit_iterator& __y) + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 friend bool operator!=(const __bit_iterator& __x, const __bit_iterator& __y) {return !(__x == __y);} - _LIBCPP_INLINE_VISIBILITY friend bool operator<(const __bit_iterator& __x, const __bit_iterator& __y) + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 friend bool operator<(const __bit_iterator& __x, const __bit_iterator& __y) {return __x.__seg_ < __y.__seg_ || (__x.__seg_ == __y.__seg_ && __x.__ctz_ < __y.__ctz_);} - _LIBCPP_INLINE_VISIBILITY friend bool operator>(const __bit_iterator& __x, const __bit_iterator& __y) + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 friend bool operator>(const __bit_iterator& __x, const __bit_iterator& __y) {return __y < __x;} - _LIBCPP_INLINE_VISIBILITY friend bool operator<=(const __bit_iterator& __x, const __bit_iterator& __y) + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 friend bool operator<=(const __bit_iterator& __x, const __bit_iterator& __y) {return !(__y < __x);} - _LIBCPP_INLINE_VISIBILITY friend bool operator>=(const __bit_iterator& __x, const __bit_iterator& __y) + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 friend bool operator>=(const __bit_iterator& __x, const __bit_iterator& __y) {return !(__x < __y);} private: - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 explicit __bit_iterator(__storage_pointer __s, unsigned __ctz) _NOEXCEPT : __seg_(__s), __ctz_(__ctz) {} @@ -1265,26 +1272,44 @@ private: friend class __bit_const_reference<_Cp>; friend class __bit_iterator<_Cp, true>; template friend struct __bit_array; - template friend void __fill_n_false(__bit_iterator<_Dp, false> __first, typename _Dp::size_type __n); - template friend void __fill_n_true(__bit_iterator<_Dp, false> __first, typename _Dp::size_type __n); - template friend __bit_iterator<_Dp, false> __copy_aligned(__bit_iterator<_Dp, _IC> __first, - __bit_iterator<_Dp, _IC> __last, - __bit_iterator<_Dp, false> __result); - template friend __bit_iterator<_Dp, false> __copy_unaligned(__bit_iterator<_Dp, _IC> __first, - __bit_iterator<_Dp, _IC> __last, - __bit_iterator<_Dp, false> __result); - template friend __bit_iterator<_Dp, false> copy(__bit_iterator<_Dp, _IC> __first, - __bit_iterator<_Dp, _IC> __last, - __bit_iterator<_Dp, false> __result); - template friend __bit_iterator<_Dp, false> __copy_backward_aligned(__bit_iterator<_Dp, _IC> __first, - __bit_iterator<_Dp, _IC> __last, - __bit_iterator<_Dp, false> __result); - template friend __bit_iterator<_Dp, false> __copy_backward_unaligned(__bit_iterator<_Dp, _IC> __first, - __bit_iterator<_Dp, _IC> __last, - __bit_iterator<_Dp, false> __result); - template friend __bit_iterator<_Dp, false> copy_backward(__bit_iterator<_Dp, _IC> __first, - __bit_iterator<_Dp, _IC> __last, - __bit_iterator<_Dp, false> __result); + template + _LIBCPP_CONSTEXPR_AFTER_CXX17 + friend void __fill_n_false(__bit_iterator<_Dp, false> __first, typename _Dp::size_type __n); + + template + _LIBCPP_CONSTEXPR_AFTER_CXX17 + friend void __fill_n_true(__bit_iterator<_Dp, false> __first, typename _Dp::size_type __n); + + template + _LIBCPP_CONSTEXPR_AFTER_CXX17 + friend __bit_iterator<_Dp, false> __copy_aligned(__bit_iterator<_Dp, _IC> __first, + __bit_iterator<_Dp, _IC> __last, + __bit_iterator<_Dp, false> __result); + template + _LIBCPP_CONSTEXPR_AFTER_CXX17 + friend __bit_iterator<_Dp, false> __copy_unaligned(__bit_iterator<_Dp, _IC> __first, + __bit_iterator<_Dp, _IC> __last, + __bit_iterator<_Dp, false> __result); + template + _LIBCPP_CONSTEXPR_AFTER_CXX17 + friend __bit_iterator<_Dp, false> copy(__bit_iterator<_Dp, _IC> __first, + __bit_iterator<_Dp, _IC> __last, + __bit_iterator<_Dp, false> __result); + template + _LIBCPP_CONSTEXPR_AFTER_CXX17 + friend __bit_iterator<_Dp, false> __copy_backward_aligned(__bit_iterator<_Dp, _IC> __first, + __bit_iterator<_Dp, _IC> __last, + __bit_iterator<_Dp, false> __result); + template + _LIBCPP_CONSTEXPR_AFTER_CXX17 + friend __bit_iterator<_Dp, false> __copy_backward_unaligned(__bit_iterator<_Dp, _IC> __first, + __bit_iterator<_Dp, _IC> __last, + __bit_iterator<_Dp, false> __result); + template + _LIBCPP_CONSTEXPR_AFTER_CXX17 + friend __bit_iterator<_Dp, false> copy_backward(__bit_iterator<_Dp, _IC> __first, + __bit_iterator<_Dp, _IC> __last, + __bit_iterator<_Dp, false> __result); template friend __bit_iterator<__C2, false> __swap_ranges_aligned(__bit_iterator<__C1, false>, __bit_iterator<__C1, false>, __bit_iterator<__C2, false>); @@ -1294,22 +1319,32 @@ private: template friend __bit_iterator<__C2, false> swap_ranges(__bit_iterator<__C1, false>, __bit_iterator<__C1, false>, __bit_iterator<__C2, false>); - template friend __bit_iterator<_Dp, false> rotate(__bit_iterator<_Dp, false>, - __bit_iterator<_Dp, false>, - __bit_iterator<_Dp, false>); - template friend bool __equal_aligned(__bit_iterator<_Dp, _IC1>, - __bit_iterator<_Dp, _IC1>, - __bit_iterator<_Dp, _IC2>); - template friend bool __equal_unaligned(__bit_iterator<_Dp, _IC1>, - __bit_iterator<_Dp, _IC1>, - __bit_iterator<_Dp, _IC2>); - template friend bool equal(__bit_iterator<_Dp, _IC1>, - __bit_iterator<_Dp, _IC1>, - __bit_iterator<_Dp, _IC2>); - template friend __bit_iterator<_Dp, _IC> __find_bool_true(__bit_iterator<_Dp, _IC>, - typename _Dp::size_type); - template friend __bit_iterator<_Dp, _IC> __find_bool_false(__bit_iterator<_Dp, _IC>, - typename _Dp::size_type); + template + _LIBCPP_CONSTEXPR_AFTER_CXX17 + friend __bit_iterator<_Dp, false> rotate(__bit_iterator<_Dp, false>, + __bit_iterator<_Dp, false>, + __bit_iterator<_Dp, false>); + template + _LIBCPP_CONSTEXPR_AFTER_CXX17 + friend bool __equal_aligned(__bit_iterator<_Dp, _IC1>, + __bit_iterator<_Dp, _IC1>, + __bit_iterator<_Dp, _IC2>); + template + _LIBCPP_CONSTEXPR_AFTER_CXX17 + friend bool __equal_unaligned(__bit_iterator<_Dp, _IC1>, + __bit_iterator<_Dp, _IC1>, + __bit_iterator<_Dp, _IC2>); + template + _LIBCPP_CONSTEXPR_AFTER_CXX17 + friend bool equal(__bit_iterator<_Dp, _IC1>, + __bit_iterator<_Dp, _IC1>, + __bit_iterator<_Dp, _IC2>); + template + _LIBCPP_CONSTEXPR_AFTER_CXX17 + friend __bit_iterator<_Dp, _IC> __find_bool_true(__bit_iterator<_Dp, _IC>, typename _Dp::size_type); + template + _LIBCPP_CONSTEXPR_AFTER_CXX17 + friend __bit_iterator<_Dp, _IC> __find_bool_false(__bit_iterator<_Dp, _IC>, typename _Dp::size_type); template friend typename __bit_iterator<_Dp, _IC>::difference_type __count_bool_true(__bit_iterator<_Dp, _IC>, typename _Dp::size_type); template friend typename __bit_iterator<_Dp, _IC>::difference_type diff --git a/libcxx/include/__memory/construct_at.h b/libcxx/include/__memory/construct_at.h index bfa20a149d51c..f5985b7731fda 100644 --- a/libcxx/include/__memory/construct_at.h +++ b/libcxx/include/__memory/construct_at.h @@ -42,7 +42,8 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Tp* __construct_at(_Tp* __location, _Ar #if _LIBCPP_STD_VER > 17 return std::construct_at(__location, std::forward<_Args>(__args)...); #else - return ::new (std::__voidify(*__location)) _Tp(std::forward<_Args>(__args)...); + return _LIBCPP_ASSERT(__location != nullptr, "null pointer given to construct_at"), + ::new (std::__voidify(*__location)) _Tp(std::forward<_Args>(__args)...); #endif } diff --git a/libcxx/include/__memory/pointer_traits.h b/libcxx/include/__memory/pointer_traits.h index 2549e4be7df12..c4cd56a21feab 100644 --- a/libcxx/include/__memory/pointer_traits.h +++ b/libcxx/include/__memory/pointer_traits.h @@ -122,7 +122,7 @@ struct _LIBCPP_TEMPLATE_VIS pointer_traits private: struct __nat {}; public: - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 static pointer pointer_to(typename conditional::value, __nat, element_type>::type& __r) {return pointer::pointer_to(__r);} diff --git a/libcxx/include/__memory/uninitialized_algorithms.h b/libcxx/include/__memory/uninitialized_algorithms.h index 72b6890c22251..4f3d4e90cb6e2 100644 --- a/libcxx/include/__memory/uninitialized_algorithms.h +++ b/libcxx/include/__memory/uninitialized_algorithms.h @@ -509,10 +509,11 @@ __allocator_destroy(_Alloc& __alloc, _Iter __first, _Sent __last) { template class _AllocatorDestroyRangeReverse { public: - _LIBCPP_HIDE_FROM_ABI _AllocatorDestroyRangeReverse(_Alloc& __alloc, _Iter& __first, _Iter& __last) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 + _AllocatorDestroyRangeReverse(_Alloc& __alloc, _Iter& __first, _Iter& __last) : __alloc_(__alloc), __first_(__first), __last_(__last) {} - _LIBCPP_CONSTEXPR_AFTER_CXX11 void operator()() const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 void operator()() const { std::__allocator_destroy(__alloc_, std::reverse_iterator<_Iter>(__last_), std::reverse_iterator<_Iter>(__first_)); } @@ -621,7 +622,7 @@ template < class _Type = typename iterator_traits<_Iter1>::value_type, class = __enable_if_t::value && is_trivially_move_assignable<_Type>::value && __allocator_has_trivial_move_construct<_Alloc, _Type>::value> > -_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 _Iter1 +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 _Iter2 __uninitialized_allocator_move_if_noexcept(_Alloc&, _Iter1 __first1, _Iter1 __last1, _Iter2 __first2) { if (__libcpp_is_constant_evaluated()) { while (__first1 != __last1) { diff --git a/libcxx/include/__split_buffer b/libcxx/include/__split_buffer index f781674662175..4d40732a75cf0 100644 --- a/libcxx/include/__split_buffer +++ b/libcxx/include/__split_buffer @@ -62,107 +62,107 @@ public: typedef typename add_lvalue_reference::type __alloc_ref; typedef typename add_lvalue_reference::type __alloc_const_ref; - _LIBCPP_INLINE_VISIBILITY __alloc_rr& __alloc() _NOEXCEPT {return __end_cap_.second();} - _LIBCPP_INLINE_VISIBILITY const __alloc_rr& __alloc() const _NOEXCEPT {return __end_cap_.second();} - _LIBCPP_INLINE_VISIBILITY pointer& __end_cap() _NOEXCEPT {return __end_cap_.first();} - _LIBCPP_INLINE_VISIBILITY const pointer& __end_cap() const _NOEXCEPT {return __end_cap_.first();} + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY __alloc_rr& __alloc() _NOEXCEPT {return __end_cap_.second();} + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY const __alloc_rr& __alloc() const _NOEXCEPT {return __end_cap_.second();} + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY pointer& __end_cap() _NOEXCEPT {return __end_cap_.first();} + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY const pointer& __end_cap() const _NOEXCEPT {return __end_cap_.first();} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY __split_buffer() _NOEXCEPT_(is_nothrow_default_constructible::value); - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY explicit __split_buffer(__alloc_rr& __a); - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY explicit __split_buffer(const __alloc_rr& __a); - __split_buffer(size_type __cap, size_type __start, __alloc_rr& __a); - ~__split_buffer(); + _LIBCPP_CONSTEXPR_AFTER_CXX17 __split_buffer(size_type __cap, size_type __start, __alloc_rr& __a); + _LIBCPP_CONSTEXPR_AFTER_CXX17 ~__split_buffer(); - __split_buffer(__split_buffer&& __c) + _LIBCPP_CONSTEXPR_AFTER_CXX17 __split_buffer(__split_buffer&& __c) _NOEXCEPT_(is_nothrow_move_constructible::value); - __split_buffer(__split_buffer&& __c, const __alloc_rr& __a); - __split_buffer& operator=(__split_buffer&& __c) + _LIBCPP_CONSTEXPR_AFTER_CXX17 __split_buffer(__split_buffer&& __c, const __alloc_rr& __a); + _LIBCPP_CONSTEXPR_AFTER_CXX17 __split_buffer& operator=(__split_buffer&& __c) _NOEXCEPT_((__alloc_traits::propagate_on_container_move_assignment::value && is_nothrow_move_assignable::value) || !__alloc_traits::propagate_on_container_move_assignment::value); - _LIBCPP_INLINE_VISIBILITY iterator begin() _NOEXCEPT {return __begin_;} - _LIBCPP_INLINE_VISIBILITY const_iterator begin() const _NOEXCEPT {return __begin_;} - _LIBCPP_INLINE_VISIBILITY iterator end() _NOEXCEPT {return __end_;} - _LIBCPP_INLINE_VISIBILITY const_iterator end() const _NOEXCEPT {return __end_;} + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY iterator begin() _NOEXCEPT {return __begin_;} + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY const_iterator begin() const _NOEXCEPT {return __begin_;} + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY iterator end() _NOEXCEPT {return __end_;} + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY const_iterator end() const _NOEXCEPT {return __end_;} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY void clear() _NOEXCEPT {__destruct_at_end(__begin_);} - _LIBCPP_INLINE_VISIBILITY size_type size() const {return static_cast(__end_ - __begin_);} - _LIBCPP_INLINE_VISIBILITY bool empty() const {return __end_ == __begin_;} - _LIBCPP_INLINE_VISIBILITY size_type capacity() const {return static_cast(__end_cap() - __first_);} - _LIBCPP_INLINE_VISIBILITY size_type __front_spare() const {return static_cast(__begin_ - __first_);} - _LIBCPP_INLINE_VISIBILITY size_type __back_spare() const {return static_cast(__end_cap() - __end_);} - - _LIBCPP_INLINE_VISIBILITY reference front() {return *__begin_;} - _LIBCPP_INLINE_VISIBILITY const_reference front() const {return *__begin_;} - _LIBCPP_INLINE_VISIBILITY reference back() {return *(__end_ - 1);} - _LIBCPP_INLINE_VISIBILITY const_reference back() const {return *(__end_ - 1);} - - void reserve(size_type __n); - void shrink_to_fit() _NOEXCEPT; - void push_front(const_reference __x); - _LIBCPP_INLINE_VISIBILITY void push_back(const_reference __x); - void push_front(value_type&& __x); - void push_back(value_type&& __x); + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY size_type size() const {return static_cast(__end_ - __begin_);} + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY bool empty() const {return __end_ == __begin_;} + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY size_type capacity() const {return static_cast(__end_cap() - __first_);} + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY size_type __front_spare() const {return static_cast(__begin_ - __first_);} + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY size_type __back_spare() const {return static_cast(__end_cap() - __end_);} + + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY reference front() {return *__begin_;} + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY const_reference front() const {return *__begin_;} + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY reference back() {return *(__end_ - 1);} + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY const_reference back() const {return *(__end_ - 1);} + + _LIBCPP_CONSTEXPR_AFTER_CXX17 void reserve(size_type __n); + _LIBCPP_CONSTEXPR_AFTER_CXX17 void shrink_to_fit() _NOEXCEPT; + _LIBCPP_CONSTEXPR_AFTER_CXX17 void push_front(const_reference __x); + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY void push_back(const_reference __x); + _LIBCPP_CONSTEXPR_AFTER_CXX17 void push_front(value_type&& __x); + _LIBCPP_CONSTEXPR_AFTER_CXX17 void push_back(value_type&& __x); template - void emplace_back(_Args&&... __args); + _LIBCPP_CONSTEXPR_AFTER_CXX17 void emplace_back(_Args&&... __args); - _LIBCPP_INLINE_VISIBILITY void pop_front() {__destruct_at_begin(__begin_+1);} - _LIBCPP_INLINE_VISIBILITY void pop_back() {__destruct_at_end(__end_-1);} + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY void pop_front() {__destruct_at_begin(__begin_+1);} + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY void pop_back() {__destruct_at_end(__end_-1);} - void __construct_at_end(size_type __n); - void __construct_at_end(size_type __n, const_reference __x); + _LIBCPP_CONSTEXPR_AFTER_CXX17 void __construct_at_end(size_type __n); + _LIBCPP_CONSTEXPR_AFTER_CXX17 void __construct_at_end(size_type __n, const_reference __x); template - __enable_if_t<__is_exactly_cpp17_input_iterator<_InputIter>::value> + _LIBCPP_CONSTEXPR_AFTER_CXX17 __enable_if_t<__is_exactly_cpp17_input_iterator<_InputIter>::value> __construct_at_end(_InputIter __first, _InputIter __last); template - __enable_if_t<__is_cpp17_forward_iterator<_ForwardIterator>::value> + _LIBCPP_CONSTEXPR_AFTER_CXX17 __enable_if_t<__is_cpp17_forward_iterator<_ForwardIterator>::value> __construct_at_end(_ForwardIterator __first, _ForwardIterator __last); - _LIBCPP_INLINE_VISIBILITY void __destruct_at_begin(pointer __new_begin) + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY void __destruct_at_begin(pointer __new_begin) {__destruct_at_begin(__new_begin, is_trivially_destructible());} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY void __destruct_at_begin(pointer __new_begin, false_type); - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY void __destruct_at_begin(pointer __new_begin, true_type); - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY void __destruct_at_end(pointer __new_last) _NOEXCEPT {__destruct_at_end(__new_last, false_type());} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY void __destruct_at_end(pointer __new_last, false_type) _NOEXCEPT; - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY void __destruct_at_end(pointer __new_last, true_type) _NOEXCEPT; - void swap(__split_buffer& __x) + _LIBCPP_CONSTEXPR_AFTER_CXX17 void swap(__split_buffer& __x) _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value|| __is_nothrow_swappable<__alloc_rr>::value); - bool __invariants() const; + _LIBCPP_CONSTEXPR_AFTER_CXX17 bool __invariants() const; private: - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY void __move_assign_alloc(__split_buffer& __c, true_type) _NOEXCEPT_(is_nothrow_move_assignable::value) { __alloc() = _VSTD::move(__c.__alloc()); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY void __move_assign_alloc(__split_buffer&, false_type) _NOEXCEPT {} struct _ConstructTransaction { - explicit _ConstructTransaction(pointer* __p, size_type __n) _NOEXCEPT + _LIBCPP_CONSTEXPR_AFTER_CXX17 explicit _ConstructTransaction(pointer* __p, size_type __n) _NOEXCEPT : __pos_(*__p), __end_(*__p + __n), __dest_(__p) { } - ~_ConstructTransaction() { + _LIBCPP_CONSTEXPR_AFTER_CXX17 ~_ConstructTransaction() { *__dest_ = __pos_; } pointer __pos_; @@ -173,6 +173,7 @@ private: }; template +_LIBCPP_CONSTEXPR_AFTER_CXX17 bool __split_buffer<_Tp, _Allocator>::__invariants() const { @@ -203,6 +204,7 @@ __split_buffer<_Tp, _Allocator>::__invariants() const // Precondition: size() + __n <= capacity() // Postcondition: size() == size() + __n template +_LIBCPP_CONSTEXPR_AFTER_CXX17 void __split_buffer<_Tp, _Allocator>::__construct_at_end(size_type __n) { @@ -219,6 +221,7 @@ __split_buffer<_Tp, _Allocator>::__construct_at_end(size_type __n) // Postcondition: size() == old size() + __n // Postcondition: [i] == __x for all i in [size() - __n, __n) template +_LIBCPP_CONSTEXPR_AFTER_CXX17 void __split_buffer<_Tp, _Allocator>::__construct_at_end(size_type __n, const_reference __x) { @@ -231,7 +234,7 @@ __split_buffer<_Tp, _Allocator>::__construct_at_end(size_type __n, const_referen template template -__enable_if_t<__is_exactly_cpp17_input_iterator<_InputIter>::value> +_LIBCPP_CONSTEXPR_AFTER_CXX17 __enable_if_t<__is_exactly_cpp17_input_iterator<_InputIter>::value> __split_buffer<_Tp, _Allocator>::__construct_at_end(_InputIter __first, _InputIter __last) { __alloc_rr& __a = this->__alloc(); @@ -254,7 +257,7 @@ __split_buffer<_Tp, _Allocator>::__construct_at_end(_InputIter __first, _InputIt template template -__enable_if_t<__is_cpp17_forward_iterator<_ForwardIterator>::value> +_LIBCPP_CONSTEXPR_AFTER_CXX17 __enable_if_t<__is_cpp17_forward_iterator<_ForwardIterator>::value> __split_buffer<_Tp, _Allocator>::__construct_at_end(_ForwardIterator __first, _ForwardIterator __last) { _ConstructTransaction __tx(&this->__end_, _VSTD::distance(__first, __last)); @@ -265,6 +268,7 @@ __split_buffer<_Tp, _Allocator>::__construct_at_end(_ForwardIterator __first, _F } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 inline void __split_buffer<_Tp, _Allocator>::__destruct_at_begin(pointer __new_begin, false_type) @@ -274,6 +278,7 @@ __split_buffer<_Tp, _Allocator>::__destruct_at_begin(pointer __new_begin, false_ } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 inline void __split_buffer<_Tp, _Allocator>::__destruct_at_begin(pointer __new_begin, true_type) @@ -282,6 +287,7 @@ __split_buffer<_Tp, _Allocator>::__destruct_at_begin(pointer __new_begin, true_t } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 inline _LIBCPP_INLINE_VISIBILITY void __split_buffer<_Tp, _Allocator>::__destruct_at_end(pointer __new_last, false_type) _NOEXCEPT @@ -291,6 +297,7 @@ __split_buffer<_Tp, _Allocator>::__destruct_at_end(pointer __new_last, false_typ } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 inline _LIBCPP_INLINE_VISIBILITY void __split_buffer<_Tp, _Allocator>::__destruct_at_end(pointer __new_last, true_type) _NOEXCEPT @@ -299,6 +306,7 @@ __split_buffer<_Tp, _Allocator>::__destruct_at_end(pointer __new_last, true_type } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 __split_buffer<_Tp, _Allocator>::__split_buffer(size_type __cap, size_type __start, __alloc_rr& __a) : __end_cap_(nullptr, __a) { @@ -314,6 +322,7 @@ __split_buffer<_Tp, _Allocator>::__split_buffer(size_type __cap, size_type __sta } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 inline __split_buffer<_Tp, _Allocator>::__split_buffer() _NOEXCEPT_(is_nothrow_default_constructible::value) @@ -322,6 +331,7 @@ __split_buffer<_Tp, _Allocator>::__split_buffer() } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 inline __split_buffer<_Tp, _Allocator>::__split_buffer(__alloc_rr& __a) : __first_(nullptr), __begin_(nullptr), __end_(nullptr), __end_cap_(nullptr, __a) @@ -329,6 +339,7 @@ __split_buffer<_Tp, _Allocator>::__split_buffer(__alloc_rr& __a) } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 inline __split_buffer<_Tp, _Allocator>::__split_buffer(const __alloc_rr& __a) : __first_(nullptr), __begin_(nullptr), __end_(nullptr), __end_cap_(nullptr, __a) @@ -336,6 +347,7 @@ __split_buffer<_Tp, _Allocator>::__split_buffer(const __alloc_rr& __a) } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 __split_buffer<_Tp, _Allocator>::~__split_buffer() { clear(); @@ -344,6 +356,7 @@ __split_buffer<_Tp, _Allocator>::~__split_buffer() } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 __split_buffer<_Tp, _Allocator>::__split_buffer(__split_buffer&& __c) _NOEXCEPT_(is_nothrow_move_constructible::value) : __first_(_VSTD::move(__c.__first_)), @@ -358,6 +371,7 @@ __split_buffer<_Tp, _Allocator>::__split_buffer(__split_buffer&& __c) } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 __split_buffer<_Tp, _Allocator>::__split_buffer(__split_buffer&& __c, const __alloc_rr& __a) : __end_cap_(nullptr, __a) { @@ -384,6 +398,7 @@ __split_buffer<_Tp, _Allocator>::__split_buffer(__split_buffer&& __c, const __al } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 __split_buffer<_Tp, _Allocator>& __split_buffer<_Tp, _Allocator>::operator=(__split_buffer&& __c) _NOEXCEPT_((__alloc_traits::propagate_on_container_move_assignment::value && @@ -404,6 +419,7 @@ __split_buffer<_Tp, _Allocator>::operator=(__split_buffer&& __c) } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 void __split_buffer<_Tp, _Allocator>::swap(__split_buffer& __x) _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value|| @@ -417,6 +433,7 @@ __split_buffer<_Tp, _Allocator>::swap(__split_buffer& __x) } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 void __split_buffer<_Tp, _Allocator>::reserve(size_type __n) { @@ -433,6 +450,7 @@ __split_buffer<_Tp, _Allocator>::reserve(size_type __n) } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 void __split_buffer<_Tp, _Allocator>::shrink_to_fit() _NOEXCEPT { @@ -460,6 +478,7 @@ __split_buffer<_Tp, _Allocator>::shrink_to_fit() _NOEXCEPT } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 void __split_buffer<_Tp, _Allocator>::push_front(const_reference __x) { @@ -489,6 +508,7 @@ __split_buffer<_Tp, _Allocator>::push_front(const_reference __x) } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 void __split_buffer<_Tp, _Allocator>::push_front(value_type&& __x) { @@ -519,6 +539,7 @@ __split_buffer<_Tp, _Allocator>::push_front(value_type&& __x) } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 inline _LIBCPP_INLINE_VISIBILITY void __split_buffer<_Tp, _Allocator>::push_back(const_reference __x) @@ -549,6 +570,7 @@ __split_buffer<_Tp, _Allocator>::push_back(const_reference __x) } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 void __split_buffer<_Tp, _Allocator>::push_back(value_type&& __x) { @@ -580,6 +602,7 @@ __split_buffer<_Tp, _Allocator>::push_back(value_type&& __x) template template +_LIBCPP_CONSTEXPR_AFTER_CXX17 void __split_buffer<_Tp, _Allocator>::emplace_back(_Args&&... __args) { @@ -610,6 +633,7 @@ __split_buffer<_Tp, _Allocator>::emplace_back(_Args&&... __args) } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 inline _LIBCPP_INLINE_VISIBILITY void swap(__split_buffer<_Tp, _Allocator>& __x, __split_buffer<_Tp, _Allocator>& __y) diff --git a/libcxx/include/memory b/libcxx/include/memory index 56f8159fbd445..a986d76c8b4ef 100644 --- a/libcxx/include/memory +++ b/libcxx/include/memory @@ -838,6 +838,8 @@ template */ +#include <__algorithm/copy.h> +#include <__algorithm/move.h> #include <__assert> // all public C++ headers provide the assertion handler #include <__config> #include <__memory/addressof.h> @@ -941,21 +943,31 @@ template struct __temp_value { typedef allocator_traits<_Alloc> _Traits; +#ifdef _LIBCPP_CXX03_LANG typename aligned_storage::type __v; +#else + union { _Tp __v; }; +#endif _Alloc &__a; - _Tp *__addr() { return reinterpret_cast<_Tp *>(addressof(__v)); } - _Tp & get() { return *__addr(); } + _LIBCPP_CONSTEXPR_AFTER_CXX17 _Tp *__addr() { +#ifdef _LIBCPP_CXX03_LANG + return reinterpret_cast<_Tp*>(std::addressof(__v)); +#else + return std::addressof(__v); +#endif + } + + _LIBCPP_CONSTEXPR_AFTER_CXX17 _Tp & get() { return *__addr(); } template _LIBCPP_NO_CFI - __temp_value(_Alloc &__alloc, _Args&& ... __args) : __a(__alloc) { - _Traits::construct(__a, reinterpret_cast<_Tp*>(addressof(__v)), - _VSTD::forward<_Args>(__args)...); + _LIBCPP_CONSTEXPR_AFTER_CXX17 __temp_value(_Alloc &__alloc, _Args&& ... __args) : __a(__alloc) { + _Traits::construct(__a, __addr(), std::forward<_Args>(__args)...); } - ~__temp_value() { _Traits::destroy(__a, __addr()); } - }; + _LIBCPP_CONSTEXPR_AFTER_CXX17 ~__temp_value() { _Traits::destroy(__a, __addr()); } +}; template struct __is_allocator : false_type {}; diff --git a/libcxx/include/vector b/libcxx/include/vector index 30030f85e43c3..252a0f051ff54 100644 --- a/libcxx/include/vector +++ b/libcxx/include/vector @@ -360,12 +360,12 @@ public: static_assert((is_same::value), "Allocator::value_type must be same type as value_type"); - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY vector() _NOEXCEPT_(is_nothrow_default_constructible::value) { _VSTD::__debug_db_insert_c(this); } - _LIBCPP_INLINE_VISIBILITY explicit vector(const allocator_type& __a) + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY explicit vector(const allocator_type& __a) #if _LIBCPP_STD_VER <= 14 _NOEXCEPT_(is_nothrow_copy_constructible::value) #else @@ -375,13 +375,14 @@ public: { _VSTD::__debug_db_insert_c(this); } - explicit vector(size_type __n); + _LIBCPP_CONSTEXPR_AFTER_CXX17 explicit vector(size_type __n); #if _LIBCPP_STD_VER > 11 - explicit vector(size_type __n, const allocator_type& __a); + _LIBCPP_CONSTEXPR_AFTER_CXX17 explicit vector(size_type __n, const allocator_type& __a); #endif - vector(size_type __n, const value_type& __x); + _LIBCPP_CONSTEXPR_AFTER_CXX17 vector(size_type __n, const value_type& __x); template ::value> > + _LIBCPP_CONSTEXPR_AFTER_CXX17 vector(size_type __n, const value_type& __x, const allocator_type& __a) : __end_cap_(nullptr, __a) { @@ -394,6 +395,7 @@ public: } template + _LIBCPP_CONSTEXPR_AFTER_CXX17 vector(_InputIterator __first, typename enable_if<__is_exactly_cpp17_input_iterator<_InputIterator>::value && is_constructible< @@ -401,12 +403,14 @@ public: typename iterator_traits<_InputIterator>::reference>::value, _InputIterator>::type __last); template + _LIBCPP_CONSTEXPR_AFTER_CXX17 vector(_InputIterator __first, _InputIterator __last, const allocator_type& __a, typename enable_if<__is_exactly_cpp17_input_iterator<_InputIterator>::value && is_constructible< value_type, typename iterator_traits<_InputIterator>::reference>::value>::type* = 0); template + _LIBCPP_CONSTEXPR_AFTER_CXX17 vector(_ForwardIterator __first, typename enable_if<__is_cpp17_forward_iterator<_ForwardIterator>::value && is_constructible< @@ -414,13 +418,14 @@ public: typename iterator_traits<_ForwardIterator>::reference>::value, _ForwardIterator>::type __last); template + _LIBCPP_CONSTEXPR_AFTER_CXX17 vector(_ForwardIterator __first, _ForwardIterator __last, const allocator_type& __a, typename enable_if<__is_cpp17_forward_iterator<_ForwardIterator>::value && is_constructible< value_type, typename iterator_traits<_ForwardIterator>::reference>::value>::type* = 0); - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY ~vector() { __annotate_delete(); @@ -433,24 +438,24 @@ public: } } - vector(const vector& __x); - vector(const vector& __x, const __type_identity_t& __a); - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 vector(const vector& __x); + _LIBCPP_CONSTEXPR_AFTER_CXX17 vector(const vector& __x, const __type_identity_t& __a); + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY vector& operator=(const vector& __x); #ifndef _LIBCPP_CXX03_LANG - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY vector(initializer_list __il); - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY vector(initializer_list __il, const allocator_type& __a); - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY vector& operator=(initializer_list __il) {assign(__il.begin(), __il.end()); return *this;} #endif // !_LIBCPP_CXX03_LANG - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY vector(vector&& __x) #if _LIBCPP_STD_VER > 14 noexcept; @@ -458,14 +463,14 @@ public: _NOEXCEPT_(is_nothrow_move_constructible::value); #endif - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY vector(vector&& __x, const __type_identity_t& __a); - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY vector& operator=(vector&& __x) _NOEXCEPT_((__noexcept_move_assign_container<_Allocator, __alloc_traits>::value)); template - typename enable_if <__is_exactly_cpp17_input_iterator<_InputIterator>::value && + _LIBCPP_CONSTEXPR_AFTER_CXX17 typename enable_if <__is_exactly_cpp17_input_iterator<_InputIterator>::value && is_constructible< value_type, typename iterator_traits<_InputIterator>::reference>::value, @@ -473,6 +478,7 @@ public: >::type assign(_InputIterator __first, _InputIterator __last); template + _LIBCPP_CONSTEXPR_AFTER_CXX17 typename enable_if < __is_cpp17_forward_iterator<_ForwardIterator>::value && @@ -483,119 +489,120 @@ public: >::type assign(_ForwardIterator __first, _ForwardIterator __last); - void assign(size_type __n, const_reference __u); + _LIBCPP_CONSTEXPR_AFTER_CXX17 void assign(size_type __n, const_reference __u); #ifndef _LIBCPP_CXX03_LANG - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY void assign(initializer_list __il) {assign(__il.begin(), __il.end());} #endif - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY allocator_type get_allocator() const _NOEXCEPT {return this->__alloc();} - _LIBCPP_INLINE_VISIBILITY iterator begin() _NOEXCEPT; - _LIBCPP_INLINE_VISIBILITY const_iterator begin() const _NOEXCEPT; - _LIBCPP_INLINE_VISIBILITY iterator end() _NOEXCEPT; - _LIBCPP_INLINE_VISIBILITY const_iterator end() const _NOEXCEPT; + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY iterator begin() _NOEXCEPT; + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY const_iterator begin() const _NOEXCEPT; + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY iterator end() _NOEXCEPT; + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY const_iterator end() const _NOEXCEPT; - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY reverse_iterator rbegin() _NOEXCEPT {return reverse_iterator(end());} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY const_reverse_iterator rbegin() const _NOEXCEPT {return const_reverse_iterator(end());} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY reverse_iterator rend() _NOEXCEPT {return reverse_iterator(begin());} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY const_reverse_iterator rend() const _NOEXCEPT {return const_reverse_iterator(begin());} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY const_iterator cbegin() const _NOEXCEPT {return begin();} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY const_iterator cend() const _NOEXCEPT {return end();} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY const_reverse_iterator crbegin() const _NOEXCEPT {return rbegin();} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY const_reverse_iterator crend() const _NOEXCEPT {return rend();} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY size_type size() const _NOEXCEPT {return static_cast(this->__end_ - this->__begin_);} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY size_type capacity() const _NOEXCEPT {return static_cast(__end_cap() - this->__begin_);} - _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY + _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY bool empty() const _NOEXCEPT {return this->__begin_ == this->__end_;} - size_type max_size() const _NOEXCEPT; - void reserve(size_type __n); - void shrink_to_fit() _NOEXCEPT; + _LIBCPP_CONSTEXPR_AFTER_CXX17 size_type max_size() const _NOEXCEPT; + _LIBCPP_CONSTEXPR_AFTER_CXX17 void reserve(size_type __n); + _LIBCPP_CONSTEXPR_AFTER_CXX17 void shrink_to_fit() _NOEXCEPT; - _LIBCPP_INLINE_VISIBILITY reference operator[](size_type __n) _NOEXCEPT; - _LIBCPP_INLINE_VISIBILITY const_reference operator[](size_type __n) const _NOEXCEPT; - reference at(size_type __n); - const_reference at(size_type __n) const; + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY reference operator[](size_type __n) _NOEXCEPT; + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY const_reference operator[](size_type __n) const _NOEXCEPT; + _LIBCPP_CONSTEXPR_AFTER_CXX17 reference at(size_type __n); + _LIBCPP_CONSTEXPR_AFTER_CXX17 const_reference at(size_type __n) const; - _LIBCPP_INLINE_VISIBILITY reference front() _NOEXCEPT + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY reference front() _NOEXCEPT { _LIBCPP_ASSERT(!empty(), "front() called on an empty vector"); return *this->__begin_; } - _LIBCPP_INLINE_VISIBILITY const_reference front() const _NOEXCEPT + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY const_reference front() const _NOEXCEPT { _LIBCPP_ASSERT(!empty(), "front() called on an empty vector"); return *this->__begin_; } - _LIBCPP_INLINE_VISIBILITY reference back() _NOEXCEPT + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY reference back() _NOEXCEPT { _LIBCPP_ASSERT(!empty(), "back() called on an empty vector"); return *(this->__end_ - 1); } - _LIBCPP_INLINE_VISIBILITY const_reference back() const _NOEXCEPT + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY const_reference back() const _NOEXCEPT { _LIBCPP_ASSERT(!empty(), "back() called on an empty vector"); return *(this->__end_ - 1); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY value_type* data() _NOEXCEPT {return _VSTD::__to_address(this->__begin_);} - _LIBCPP_INLINE_VISIBILITY + + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY const value_type* data() const _NOEXCEPT {return _VSTD::__to_address(this->__begin_);} - _LIBCPP_INLINE_VISIBILITY void push_back(const_reference __x); + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY void push_back(const_reference __x); - _LIBCPP_INLINE_VISIBILITY void push_back(value_type&& __x); + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY void push_back(value_type&& __x); template - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY #if _LIBCPP_STD_VER > 14 reference emplace_back(_Args&&... __args); #else void emplace_back(_Args&&... __args); #endif - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY void pop_back(); - iterator insert(const_iterator __position, const_reference __x); + _LIBCPP_CONSTEXPR_AFTER_CXX17 iterator insert(const_iterator __position, const_reference __x); - iterator insert(const_iterator __position, value_type&& __x); + _LIBCPP_CONSTEXPR_AFTER_CXX17 iterator insert(const_iterator __position, value_type&& __x); template - iterator emplace(const_iterator __position, _Args&&... __args); + _LIBCPP_CONSTEXPR_AFTER_CXX17 iterator emplace(const_iterator __position, _Args&&... __args); - iterator insert(const_iterator __position, size_type __n, const_reference __x); + _LIBCPP_CONSTEXPR_AFTER_CXX17 iterator insert(const_iterator __position, size_type __n, const_reference __x); template - typename enable_if <__is_exactly_cpp17_input_iterator<_InputIterator>::value && + _LIBCPP_CONSTEXPR_AFTER_CXX17 typename enable_if <__is_exactly_cpp17_input_iterator<_InputIterator>::value && is_constructible< value_type, typename iterator_traits<_InputIterator>::reference>::value, @@ -603,6 +610,7 @@ public: >::type insert(const_iterator __position, _InputIterator __first, _InputIterator __last); template + _LIBCPP_CONSTEXPR_AFTER_CXX17 typename enable_if < __is_cpp17_forward_iterator<_ForwardIterator>::value && @@ -614,15 +622,15 @@ public: insert(const_iterator __position, _ForwardIterator __first, _ForwardIterator __last); #ifndef _LIBCPP_CXX03_LANG - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY iterator insert(const_iterator __position, initializer_list __il) {return insert(__position, __il.begin(), __il.end());} #endif - _LIBCPP_INLINE_VISIBILITY iterator erase(const_iterator __position); - iterator erase(const_iterator __first, const_iterator __last); + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY iterator erase(const_iterator __position); + _LIBCPP_CONSTEXPR_AFTER_CXX17 iterator erase(const_iterator __first, const_iterator __last); - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY void clear() _NOEXCEPT { size_type __old_size = size(); @@ -631,10 +639,10 @@ public: std::__debug_db_invalidate_all(this); } - void resize(size_type __sz); - void resize(size_type __sz, const_reference __x); + _LIBCPP_CONSTEXPR_AFTER_CXX17 void resize(size_type __sz); + _LIBCPP_CONSTEXPR_AFTER_CXX17 void resize(size_type __sz, const_reference __x); - void swap(vector&) + _LIBCPP_CONSTEXPR_AFTER_CXX17 void swap(vector&) #if _LIBCPP_STD_VER >= 14 _NOEXCEPT; #else @@ -642,7 +650,7 @@ public: __is_nothrow_swappable::value); #endif - bool __invariants() const; + _LIBCPP_CONSTEXPR_AFTER_CXX17 bool __invariants() const; #ifdef _LIBCPP_ENABLE_DEBUG_MODE @@ -661,7 +669,6 @@ private: _LIBCPP_INLINE_VISIBILITY void __invalidate_iterators_past(pointer __new_last); - // Allocate space for __n objects // throws length_error if __n > max_size() // throws (probably bad_alloc) if memory run out @@ -669,7 +676,7 @@ private: // Precondition: __n > 0 // Postcondition: capacity() >= __n // Postcondition: size() == 0 - _LIBCPP_HIDE_FROM_ABI void __vallocate(size_type __n) { + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI void __vallocate(size_type __n) { if (__n > max_size()) __throw_length_error(); auto __allocation = std::__allocate_at_least(__alloc(), __n); @@ -679,46 +686,48 @@ private: __annotate_new(0); } - void __vdeallocate() _NOEXCEPT; - _LIBCPP_INLINE_VISIBILITY size_type __recommend(size_type __new_size) const; - void __construct_at_end(size_type __n); - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 void __vdeallocate() _NOEXCEPT; + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY size_type __recommend(size_type __new_size) const; + _LIBCPP_CONSTEXPR_AFTER_CXX17 void __construct_at_end(size_type __n); + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY void __construct_at_end(size_type __n, const_reference __x); template + _LIBCPP_CONSTEXPR_AFTER_CXX17 typename enable_if < __is_cpp17_forward_iterator<_ForwardIterator>::value, void >::type __construct_at_end(_ForwardIterator __first, _ForwardIterator __last, size_type __n); - void __append(size_type __n); - void __append(size_type __n, const_reference __x); - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 void __append(size_type __n); + _LIBCPP_CONSTEXPR_AFTER_CXX17 void __append(size_type __n, const_reference __x); + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY iterator __make_iter(pointer __p) _NOEXCEPT; - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY const_iterator __make_iter(const_pointer __p) const _NOEXCEPT; - void __swap_out_circular_buffer(__split_buffer& __v); - pointer __swap_out_circular_buffer(__split_buffer& __v, pointer __p); - void __move_range(pointer __from_s, pointer __from_e, pointer __to); - void __move_assign(vector& __c, true_type) + _LIBCPP_CONSTEXPR_AFTER_CXX17 void __swap_out_circular_buffer(__split_buffer& __v); + _LIBCPP_CONSTEXPR_AFTER_CXX17 pointer __swap_out_circular_buffer(__split_buffer& __v, pointer __p); + _LIBCPP_CONSTEXPR_AFTER_CXX17 void __move_range(pointer __from_s, pointer __from_e, pointer __to); + _LIBCPP_CONSTEXPR_AFTER_CXX17 void __move_assign(vector& __c, true_type) _NOEXCEPT_(is_nothrow_move_assignable::value); - void __move_assign(vector& __c, false_type) + _LIBCPP_CONSTEXPR_AFTER_CXX17 void __move_assign(vector& __c, false_type) _NOEXCEPT_(__alloc_traits::is_always_equal::value); - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY void __destruct_at_end(pointer __new_last) _NOEXCEPT { - __invalidate_iterators_past(__new_last); + if (!__libcpp_is_constant_evaluated()) + __invalidate_iterators_past(__new_last); size_type __old_size = size(); __base_destruct_at_end(__new_last); __annotate_shrink(__old_size); } template - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY inline void __push_back_slow_path(_Up&& __x); template - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY inline void __emplace_back_slow_path(_Args&&... __args); // The following functions are no-ops outside of AddressSanitizer mode. @@ -726,39 +735,40 @@ private: // may not meet the AddressSanitizer alignment constraints. // See the documentation for __sanitizer_annotate_contiguous_container for more details. #ifndef _LIBCPP_HAS_NO_ASAN + _LIBCPP_CONSTEXPR_AFTER_CXX17 void __annotate_contiguous_container(const void *__beg, const void *__end, const void *__old_mid, const void *__new_mid) const { - if (__beg && is_same::value) + if (!__libcpp_is_constant_evaluated() && __beg && is_same::value) __sanitizer_annotate_contiguous_container(__beg, __end, __old_mid, __new_mid); } #else - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY void __annotate_contiguous_container(const void*, const void*, const void*, const void*) const _NOEXCEPT {} #endif - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY void __annotate_new(size_type __current_size) const _NOEXCEPT { __annotate_contiguous_container(data(), data() + capacity(), data() + capacity(), data() + __current_size); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY void __annotate_delete() const _NOEXCEPT { __annotate_contiguous_container(data(), data() + capacity(), data() + size(), data() + capacity()); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY void __annotate_increase(size_type __n) const _NOEXCEPT { __annotate_contiguous_container(data(), data() + capacity(), data() + size(), data() + size() + __n); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY void __annotate_shrink(size_type __old_size) const _NOEXCEPT { __annotate_contiguous_container(data(), data() + capacity(), @@ -766,13 +776,14 @@ private: } struct _ConstructTransaction { + _LIBCPP_CONSTEXPR_AFTER_CXX17 explicit _ConstructTransaction(vector &__v, size_type __n) : __v_(__v), __pos_(__v.__end_), __new_end_(__v.__end_ + __n) { #ifndef _LIBCPP_HAS_NO_ASAN __v_.__annotate_increase(__n); #endif } - ~_ConstructTransaction() { + _LIBCPP_CONSTEXPR_AFTER_CXX17 ~_ConstructTransaction() { __v_.__end_ = __pos_; #ifndef _LIBCPP_HAS_NO_ASAN if (__pos_ != __new_end_) { @@ -791,7 +802,7 @@ private: }; template - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY void __construct_one_at_end(_Args&& ...__args) { _ConstructTransaction __tx(*this, 1); __alloc_traits::construct(this->__alloc(), _VSTD::__to_address(__tx.__pos_), @@ -799,23 +810,23 @@ private: ++__tx.__pos_; } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY allocator_type& __alloc() _NOEXCEPT {return this->__end_cap_.second();} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY const allocator_type& __alloc() const _NOEXCEPT {return this->__end_cap_.second();} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY pointer& __end_cap() _NOEXCEPT {return this->__end_cap_.first();} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY const pointer& __end_cap() const _NOEXCEPT {return this->__end_cap_.first();} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY void __clear() _NOEXCEPT {__base_destruct_at_end(this->__begin_);} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY void __base_destruct_at_end(pointer __new_last) _NOEXCEPT { pointer __soon_to_be_end = this->__end_; while (__new_last != __soon_to_be_end) @@ -823,12 +834,12 @@ private: this->__end_ = __new_last; } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY void __copy_assign_alloc(const vector& __c) {__copy_assign_alloc(__c, integral_constant());} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY void __move_assign_alloc(vector& __c) _NOEXCEPT_( !__alloc_traits::propagate_on_container_move_assignment::value || @@ -846,7 +857,7 @@ private: _VSTD::__throw_out_of_range("vector"); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY void __copy_assign_alloc(const vector& __c, true_type) { if (__alloc() != __c.__alloc()) @@ -858,18 +869,18 @@ private: __alloc() = __c.__alloc(); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY void __copy_assign_alloc(const vector&, false_type) {} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY void __move_assign_alloc(vector& __c, true_type) _NOEXCEPT_(is_nothrow_move_assignable::value) { __alloc() = _VSTD::move(__c.__alloc()); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY void __move_assign_alloc(vector&, false_type) _NOEXCEPT {} @@ -894,6 +905,7 @@ vector(_InputIterator, _InputIterator, _Alloc) #endif template +_LIBCPP_CONSTEXPR_AFTER_CXX17 void vector<_Tp, _Allocator>::__swap_out_circular_buffer(__split_buffer& __v) { @@ -911,6 +923,7 @@ vector<_Tp, _Allocator>::__swap_out_circular_buffer(__split_buffer +_LIBCPP_CONSTEXPR_AFTER_CXX17 typename vector<_Tp, _Allocator>::pointer vector<_Tp, _Allocator>::__swap_out_circular_buffer(__split_buffer& __v, pointer __p) { @@ -931,6 +944,7 @@ vector<_Tp, _Allocator>::__swap_out_circular_buffer(__split_buffer +_LIBCPP_CONSTEXPR_AFTER_CXX17 void vector<_Tp, _Allocator>::__vdeallocate() _NOEXCEPT { @@ -943,6 +957,7 @@ vector<_Tp, _Allocator>::__vdeallocate() _NOEXCEPT } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 typename vector<_Tp, _Allocator>::size_type vector<_Tp, _Allocator>::max_size() const _NOEXCEPT { @@ -952,6 +967,7 @@ vector<_Tp, _Allocator>::max_size() const _NOEXCEPT // Precondition: __new_size > capacity() template +_LIBCPP_CONSTEXPR_AFTER_CXX17 inline _LIBCPP_INLINE_VISIBILITY typename vector<_Tp, _Allocator>::size_type vector<_Tp, _Allocator>::__recommend(size_type __new_size) const @@ -971,6 +987,7 @@ vector<_Tp, _Allocator>::__recommend(size_type __new_size) const // Precondition: size() + __n <= capacity() // Postcondition: size() == size() + __n template +_LIBCPP_CONSTEXPR_AFTER_CXX17 void vector<_Tp, _Allocator>::__construct_at_end(size_type __n) { @@ -988,6 +1005,7 @@ vector<_Tp, _Allocator>::__construct_at_end(size_type __n) // Postcondition: size() == old size() + __n // Postcondition: [i] == __x for all i in [size() - __n, __n) template +_LIBCPP_CONSTEXPR_AFTER_CXX17 inline void vector<_Tp, _Allocator>::__construct_at_end(size_type __n, const_reference __x) @@ -1001,6 +1019,7 @@ vector<_Tp, _Allocator>::__construct_at_end(size_type __n, const_reference __x) template template +_LIBCPP_CONSTEXPR_AFTER_CXX17 typename enable_if < __is_cpp17_forward_iterator<_ForwardIterator>::value, @@ -1017,6 +1036,7 @@ vector<_Tp, _Allocator>::__construct_at_end(_ForwardIterator __first, _ForwardIt // Postcondition: size() == size() + __n // Exception safety: strong. template +_LIBCPP_CONSTEXPR_AFTER_CXX17 void vector<_Tp, _Allocator>::__append(size_type __n) { @@ -1036,6 +1056,7 @@ vector<_Tp, _Allocator>::__append(size_type __n) // Postcondition: size() == size() + __n // Exception safety: strong. template +_LIBCPP_CONSTEXPR_AFTER_CXX17 void vector<_Tp, _Allocator>::__append(size_type __n, const_reference __x) { @@ -1051,6 +1072,7 @@ vector<_Tp, _Allocator>::__append(size_type __n, const_reference __x) } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 vector<_Tp, _Allocator>::vector(size_type __n) { _VSTD::__debug_db_insert_c(this); @@ -1063,6 +1085,7 @@ vector<_Tp, _Allocator>::vector(size_type __n) #if _LIBCPP_STD_VER > 11 template +_LIBCPP_CONSTEXPR_AFTER_CXX17 vector<_Tp, _Allocator>::vector(size_type __n, const allocator_type& __a) : __end_cap_(nullptr, __a) { @@ -1076,6 +1099,7 @@ vector<_Tp, _Allocator>::vector(size_type __n, const allocator_type& __a) #endif template +_LIBCPP_CONSTEXPR_AFTER_CXX17 vector<_Tp, _Allocator>::vector(size_type __n, const value_type& __x) { _VSTD::__debug_db_insert_c(this); @@ -1088,6 +1112,7 @@ vector<_Tp, _Allocator>::vector(size_type __n, const value_type& __x) template template +_LIBCPP_CONSTEXPR_AFTER_CXX17 vector<_Tp, _Allocator>::vector(_InputIterator __first, typename enable_if<__is_exactly_cpp17_input_iterator<_InputIterator>::value && is_constructible< @@ -1102,6 +1127,7 @@ vector<_Tp, _Allocator>::vector(_InputIterator __first, template template +_LIBCPP_CONSTEXPR_AFTER_CXX17 vector<_Tp, _Allocator>::vector(_InputIterator __first, _InputIterator __last, const allocator_type& __a, typename enable_if<__is_exactly_cpp17_input_iterator<_InputIterator>::value && is_constructible< @@ -1116,6 +1142,7 @@ vector<_Tp, _Allocator>::vector(_InputIterator __first, _InputIterator __last, c template template +_LIBCPP_CONSTEXPR_AFTER_CXX17 vector<_Tp, _Allocator>::vector(_ForwardIterator __first, typename enable_if<__is_cpp17_forward_iterator<_ForwardIterator>::value && is_constructible< @@ -1134,6 +1161,7 @@ vector<_Tp, _Allocator>::vector(_ForwardIterator __first, template template +_LIBCPP_CONSTEXPR_AFTER_CXX17 vector<_Tp, _Allocator>::vector(_ForwardIterator __first, _ForwardIterator __last, const allocator_type& __a, typename enable_if<__is_cpp17_forward_iterator<_ForwardIterator>::value && is_constructible< @@ -1151,6 +1179,7 @@ vector<_Tp, _Allocator>::vector(_ForwardIterator __first, _ForwardIterator __las } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 vector<_Tp, _Allocator>::vector(const vector& __x) : __end_cap_(nullptr, __alloc_traits::select_on_container_copy_construction(__x.__alloc())) { @@ -1164,6 +1193,7 @@ vector<_Tp, _Allocator>::vector(const vector& __x) } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 vector<_Tp, _Allocator>::vector(const vector& __x, const __type_identity_t& __a) : __end_cap_(nullptr, __a) { @@ -1177,6 +1207,7 @@ vector<_Tp, _Allocator>::vector(const vector& __x, const __type_identity_t +_LIBCPP_CONSTEXPR_AFTER_CXX17 inline _LIBCPP_INLINE_VISIBILITY vector<_Tp, _Allocator>::vector(vector&& __x) #if _LIBCPP_STD_VER > 14 @@ -1195,6 +1226,7 @@ vector<_Tp, _Allocator>::vector(vector&& __x) } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 inline _LIBCPP_INLINE_VISIBILITY vector<_Tp, _Allocator>::vector(vector&& __x, const __type_identity_t& __a) : __end_cap_(nullptr, __a) @@ -1218,6 +1250,7 @@ vector<_Tp, _Allocator>::vector(vector&& __x, const __type_identity_t +_LIBCPP_CONSTEXPR_AFTER_CXX17 inline _LIBCPP_INLINE_VISIBILITY vector<_Tp, _Allocator>::vector(initializer_list __il) { @@ -1230,6 +1263,7 @@ vector<_Tp, _Allocator>::vector(initializer_list __il) } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 inline _LIBCPP_INLINE_VISIBILITY vector<_Tp, _Allocator>::vector(initializer_list __il, const allocator_type& __a) : __end_cap_(nullptr, __a) @@ -1245,6 +1279,7 @@ vector<_Tp, _Allocator>::vector(initializer_list __il, const allocat #endif // _LIBCPP_CXX03_LANG template +_LIBCPP_CONSTEXPR_AFTER_CXX17 inline _LIBCPP_INLINE_VISIBILITY vector<_Tp, _Allocator>& vector<_Tp, _Allocator>::operator=(vector&& __x) @@ -1256,6 +1291,7 @@ vector<_Tp, _Allocator>::operator=(vector&& __x) } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 void vector<_Tp, _Allocator>::__move_assign(vector& __c, false_type) _NOEXCEPT_(__alloc_traits::is_always_equal::value) @@ -1270,6 +1306,7 @@ vector<_Tp, _Allocator>::__move_assign(vector& __c, false_type) } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 void vector<_Tp, _Allocator>::__move_assign(vector& __c, true_type) _NOEXCEPT_(is_nothrow_move_assignable::value) @@ -1284,6 +1321,7 @@ vector<_Tp, _Allocator>::__move_assign(vector& __c, true_type) } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 inline _LIBCPP_INLINE_VISIBILITY vector<_Tp, _Allocator>& vector<_Tp, _Allocator>::operator=(const vector& __x) @@ -1298,7 +1336,7 @@ vector<_Tp, _Allocator>::operator=(const vector& __x) template template -typename enable_if <__is_exactly_cpp17_input_iterator<_InputIterator>::value && +_LIBCPP_CONSTEXPR_AFTER_CXX17 typename enable_if <__is_exactly_cpp17_input_iterator<_InputIterator>::value && is_constructible< _Tp, typename iterator_traits<_InputIterator>::reference>::value, @@ -1313,6 +1351,7 @@ vector<_Tp, _Allocator>::assign(_InputIterator __first, _InputIterator __last) template template +_LIBCPP_CONSTEXPR_AFTER_CXX17 typename enable_if < __is_cpp17_forward_iterator<_ForwardIterator>::value && @@ -1350,6 +1389,7 @@ vector<_Tp, _Allocator>::assign(_ForwardIterator __first, _ForwardIterator __las } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 void vector<_Tp, _Allocator>::assign(size_type __n, const_reference __u) { @@ -1372,6 +1412,7 @@ vector<_Tp, _Allocator>::assign(size_type __n, const_reference __u) } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 inline _LIBCPP_INLINE_VISIBILITY typename vector<_Tp, _Allocator>::iterator vector<_Tp, _Allocator>::begin() _NOEXCEPT @@ -1380,6 +1421,7 @@ vector<_Tp, _Allocator>::begin() _NOEXCEPT } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 inline _LIBCPP_INLINE_VISIBILITY typename vector<_Tp, _Allocator>::const_iterator vector<_Tp, _Allocator>::begin() const _NOEXCEPT @@ -1388,6 +1430,7 @@ vector<_Tp, _Allocator>::begin() const _NOEXCEPT } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 inline _LIBCPP_INLINE_VISIBILITY typename vector<_Tp, _Allocator>::iterator vector<_Tp, _Allocator>::end() _NOEXCEPT @@ -1396,6 +1439,7 @@ vector<_Tp, _Allocator>::end() _NOEXCEPT } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 inline _LIBCPP_INLINE_VISIBILITY typename vector<_Tp, _Allocator>::const_iterator vector<_Tp, _Allocator>::end() const _NOEXCEPT @@ -1404,6 +1448,7 @@ vector<_Tp, _Allocator>::end() const _NOEXCEPT } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 inline _LIBCPP_INLINE_VISIBILITY typename vector<_Tp, _Allocator>::reference vector<_Tp, _Allocator>::operator[](size_type __n) _NOEXCEPT @@ -1413,6 +1458,7 @@ vector<_Tp, _Allocator>::operator[](size_type __n) _NOEXCEPT } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 inline _LIBCPP_INLINE_VISIBILITY typename vector<_Tp, _Allocator>::const_reference vector<_Tp, _Allocator>::operator[](size_type __n) const _NOEXCEPT @@ -1422,6 +1468,7 @@ vector<_Tp, _Allocator>::operator[](size_type __n) const _NOEXCEPT } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 typename vector<_Tp, _Allocator>::reference vector<_Tp, _Allocator>::at(size_type __n) { @@ -1431,6 +1478,7 @@ vector<_Tp, _Allocator>::at(size_type __n) } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 typename vector<_Tp, _Allocator>::const_reference vector<_Tp, _Allocator>::at(size_type __n) const { @@ -1440,6 +1488,7 @@ vector<_Tp, _Allocator>::at(size_type __n) const } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 void vector<_Tp, _Allocator>::reserve(size_type __n) { @@ -1454,6 +1503,7 @@ vector<_Tp, _Allocator>::reserve(size_type __n) } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 void vector<_Tp, _Allocator>::shrink_to_fit() _NOEXCEPT { @@ -1477,6 +1527,7 @@ vector<_Tp, _Allocator>::shrink_to_fit() _NOEXCEPT template template +_LIBCPP_CONSTEXPR_AFTER_CXX17 void vector<_Tp, _Allocator>::__push_back_slow_path(_Up&& __x) { @@ -1489,6 +1540,7 @@ vector<_Tp, _Allocator>::__push_back_slow_path(_Up&& __x) } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 inline _LIBCPP_INLINE_VISIBILITY void vector<_Tp, _Allocator>::push_back(const_reference __x) @@ -1502,6 +1554,7 @@ vector<_Tp, _Allocator>::push_back(const_reference __x) } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 inline _LIBCPP_INLINE_VISIBILITY void vector<_Tp, _Allocator>::push_back(value_type&& __x) @@ -1516,6 +1569,7 @@ vector<_Tp, _Allocator>::push_back(value_type&& __x) template template +_LIBCPP_CONSTEXPR_AFTER_CXX17 void vector<_Tp, _Allocator>::__emplace_back_slow_path(_Args&&... __args) { @@ -1529,6 +1583,7 @@ vector<_Tp, _Allocator>::__emplace_back_slow_path(_Args&&... __args) template template +_LIBCPP_CONSTEXPR_AFTER_CXX17 inline #if _LIBCPP_STD_VER > 14 typename vector<_Tp, _Allocator>::reference @@ -1549,6 +1604,7 @@ vector<_Tp, _Allocator>::emplace_back(_Args&&... __args) } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 inline void vector<_Tp, _Allocator>::pop_back() @@ -1558,6 +1614,7 @@ vector<_Tp, _Allocator>::pop_back() } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 inline _LIBCPP_INLINE_VISIBILITY typename vector<_Tp, _Allocator>::iterator vector<_Tp, _Allocator>::erase(const_iterator __position) @@ -1569,12 +1626,14 @@ vector<_Tp, _Allocator>::erase(const_iterator __position) difference_type __ps = __position - cbegin(); pointer __p = this->__begin_ + __ps; this->__destruct_at_end(_VSTD::move(__p + 1, this->__end_, __p)); - this->__invalidate_iterators_past(__p-1); + if (!__libcpp_is_constant_evaluated()) + this->__invalidate_iterators_past(__p - 1); iterator __r = iterator(this, __p); return __r; } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 typename vector<_Tp, _Allocator>::iterator vector<_Tp, _Allocator>::erase(const_iterator __first, const_iterator __last) { @@ -1587,13 +1646,15 @@ vector<_Tp, _Allocator>::erase(const_iterator __first, const_iterator __last) pointer __p = this->__begin_ + (__first - begin()); if (__first != __last) { this->__destruct_at_end(_VSTD::move(__p + (__last - __first), this->__end_, __p)); - this->__invalidate_iterators_past(__p - 1); + if (!__libcpp_is_constant_evaluated()) + this->__invalidate_iterators_past(__p - 1); } iterator __r = iterator(this, __p); return __r; } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 void vector<_Tp, _Allocator>::__move_range(pointer __from_s, pointer __from_e, pointer __to) { @@ -1613,13 +1674,15 @@ vector<_Tp, _Allocator>::__move_range(pointer __from_s, pointer __from_e, pointe } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 typename vector<_Tp, _Allocator>::iterator vector<_Tp, _Allocator>::insert(const_iterator __position, const_reference __x) { _LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(_VSTD::addressof(__position)) == this, "vector::insert(iterator, x) called with an iterator not referring to this vector"); pointer __p = this->__begin_ + (__position - begin()); - if (this->__end_ < this->__end_cap()) + // We can't compare unrelated pointers inside constant expressions + if (!__libcpp_is_constant_evaluated() && this->__end_ < this->__end_cap()) { if (__p == this->__end_) { @@ -1645,6 +1708,7 @@ vector<_Tp, _Allocator>::insert(const_iterator __position, const_reference __x) } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 typename vector<_Tp, _Allocator>::iterator vector<_Tp, _Allocator>::insert(const_iterator __position, value_type&& __x) { @@ -1675,6 +1739,7 @@ vector<_Tp, _Allocator>::insert(const_iterator __position, value_type&& __x) template template +_LIBCPP_CONSTEXPR_AFTER_CXX17 typename vector<_Tp, _Allocator>::iterator vector<_Tp, _Allocator>::emplace(const_iterator __position, _Args&&... __args) { @@ -1705,6 +1770,7 @@ vector<_Tp, _Allocator>::emplace(const_iterator __position, _Args&&... __args) } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 typename vector<_Tp, _Allocator>::iterator vector<_Tp, _Allocator>::insert(const_iterator __position, size_type __n, const_reference __x) { @@ -1713,7 +1779,8 @@ vector<_Tp, _Allocator>::insert(const_iterator __position, size_type __n, const_ pointer __p = this->__begin_ + (__position - begin()); if (__n > 0) { - if (__n <= static_cast(this->__end_cap() - this->__end_)) + // We can't compare unrelated pointers inside constant expressions + if (!__libcpp_is_constant_evaluated() && __n <= static_cast(this->__end_cap() - this->__end_)) { size_type __old_n = __n; pointer __old_last = this->__end_; @@ -1745,7 +1812,7 @@ vector<_Tp, _Allocator>::insert(const_iterator __position, size_type __n, const_ template template -typename enable_if <__is_exactly_cpp17_input_iterator<_InputIterator>::value && +_LIBCPP_CONSTEXPR_AFTER_CXX17 typename enable_if <__is_exactly_cpp17_input_iterator<_InputIterator>::value && is_constructible< _Tp, typename iterator_traits<_InputIterator>::reference>::value, @@ -1793,6 +1860,7 @@ vector<_Tp, _Allocator>::insert(const_iterator __position, _InputIterator __firs template template +_LIBCPP_CONSTEXPR_AFTER_CXX17 typename enable_if < __is_cpp17_forward_iterator<_ForwardIterator>::value && @@ -1841,6 +1909,7 @@ vector<_Tp, _Allocator>::insert(const_iterator __position, _ForwardIterator __fi } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 void vector<_Tp, _Allocator>::resize(size_type __sz) { @@ -1852,6 +1921,7 @@ vector<_Tp, _Allocator>::resize(size_type __sz) } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 void vector<_Tp, _Allocator>::resize(size_type __sz, const_reference __x) { @@ -1863,6 +1933,7 @@ vector<_Tp, _Allocator>::resize(size_type __sz, const_reference __x) } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 void vector<_Tp, _Allocator>::swap(vector& __x) #if _LIBCPP_STD_VER >= 14 @@ -1885,6 +1956,7 @@ vector<_Tp, _Allocator>::swap(vector& __x) } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 bool vector<_Tp, _Allocator>::__invariants() const { @@ -2007,81 +2079,81 @@ public: typedef __bit_const_reference const_reference; #endif private: - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 size_type& __cap() _NOEXCEPT {return __cap_alloc_.first();} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 const size_type& __cap() const _NOEXCEPT {return __cap_alloc_.first();} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 __storage_allocator& __alloc() _NOEXCEPT {return __cap_alloc_.second();} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 const __storage_allocator& __alloc() const _NOEXCEPT {return __cap_alloc_.second();} static const unsigned __bits_per_word = static_cast(sizeof(__storage_type) * CHAR_BIT); - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 static size_type __internal_cap_to_external(size_type __n) _NOEXCEPT {return __n * __bits_per_word;} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 static size_type __external_cap_to_internal(size_type __n) _NOEXCEPT {return (__n - 1) / __bits_per_word + 1;} public: - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 vector() _NOEXCEPT_(is_nothrow_default_constructible::value); - _LIBCPP_INLINE_VISIBILITY explicit vector(const allocator_type& __a) + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 explicit vector(const allocator_type& __a) #if _LIBCPP_STD_VER <= 14 _NOEXCEPT_(is_nothrow_copy_constructible::value); #else _NOEXCEPT; #endif - ~vector(); - explicit vector(size_type __n); + _LIBCPP_CONSTEXPR_AFTER_CXX17 ~vector(); + _LIBCPP_CONSTEXPR_AFTER_CXX17 explicit vector(size_type __n); #if _LIBCPP_STD_VER > 11 - explicit vector(size_type __n, const allocator_type& __a); + _LIBCPP_CONSTEXPR_AFTER_CXX17 explicit vector(size_type __n, const allocator_type& __a); #endif - vector(size_type __n, const value_type& __v); - vector(size_type __n, const value_type& __v, const allocator_type& __a); + _LIBCPP_CONSTEXPR_AFTER_CXX17 vector(size_type __n, const value_type& __v); + _LIBCPP_CONSTEXPR_AFTER_CXX17 vector(size_type __n, const value_type& __v, const allocator_type& __a); template - vector(_InputIterator __first, _InputIterator __last, + _LIBCPP_CONSTEXPR_AFTER_CXX17 vector(_InputIterator __first, _InputIterator __last, typename enable_if<__is_exactly_cpp17_input_iterator<_InputIterator>::value>::type* = 0); template - vector(_InputIterator __first, _InputIterator __last, const allocator_type& __a, + _LIBCPP_CONSTEXPR_AFTER_CXX17 vector(_InputIterator __first, _InputIterator __last, const allocator_type& __a, typename enable_if<__is_exactly_cpp17_input_iterator<_InputIterator>::value>::type* = 0); template - vector(_ForwardIterator __first, _ForwardIterator __last, + _LIBCPP_CONSTEXPR_AFTER_CXX17 vector(_ForwardIterator __first, _ForwardIterator __last, typename enable_if<__is_cpp17_forward_iterator<_ForwardIterator>::value>::type* = 0); template - vector(_ForwardIterator __first, _ForwardIterator __last, const allocator_type& __a, + _LIBCPP_CONSTEXPR_AFTER_CXX17 vector(_ForwardIterator __first, _ForwardIterator __last, const allocator_type& __a, typename enable_if<__is_cpp17_forward_iterator<_ForwardIterator>::value>::type* = 0); - vector(const vector& __v); - vector(const vector& __v, const allocator_type& __a); - vector& operator=(const vector& __v); + _LIBCPP_CONSTEXPR_AFTER_CXX17 vector(const vector& __v); + _LIBCPP_CONSTEXPR_AFTER_CXX17 vector(const vector& __v, const allocator_type& __a); + _LIBCPP_CONSTEXPR_AFTER_CXX17 vector& operator=(const vector& __v); #ifndef _LIBCPP_CXX03_LANG - vector(initializer_list __il); - vector(initializer_list __il, const allocator_type& __a); + _LIBCPP_CONSTEXPR_AFTER_CXX17 vector(initializer_list __il); + _LIBCPP_CONSTEXPR_AFTER_CXX17 vector(initializer_list __il, const allocator_type& __a); - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 vector& operator=(initializer_list __il) {assign(__il.begin(), __il.end()); return *this;} #endif // !_LIBCPP_CXX03_LANG - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 vector(vector&& __v) #if _LIBCPP_STD_VER > 14 noexcept; #else _NOEXCEPT_(is_nothrow_move_constructible::value); #endif - vector(vector&& __v, const __type_identity_t& __a); - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 vector(vector&& __v, const __type_identity_t& __a); + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 vector& operator=(vector&& __v) _NOEXCEPT_((__noexcept_move_assign_container<_Allocator, __alloc_traits>::value)); @@ -2089,93 +2161,93 @@ public: typename enable_if <__is_exactly_cpp17_input_iterator<_InputIterator>::value, void >::type - assign(_InputIterator __first, _InputIterator __last); + _LIBCPP_CONSTEXPR_AFTER_CXX17 assign(_InputIterator __first, _InputIterator __last); template typename enable_if < __is_cpp17_forward_iterator<_ForwardIterator>::value, void >::type - assign(_ForwardIterator __first, _ForwardIterator __last); + _LIBCPP_CONSTEXPR_AFTER_CXX17 assign(_ForwardIterator __first, _ForwardIterator __last); - void assign(size_type __n, const value_type& __x); + _LIBCPP_CONSTEXPR_AFTER_CXX17 void assign(size_type __n, const value_type& __x); #ifndef _LIBCPP_CXX03_LANG - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 void assign(initializer_list __il) {assign(__il.begin(), __il.end());} #endif - _LIBCPP_INLINE_VISIBILITY allocator_type get_allocator() const _NOEXCEPT + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 allocator_type get_allocator() const _NOEXCEPT {return allocator_type(this->__alloc());} - size_type max_size() const _NOEXCEPT; - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 size_type max_size() const _NOEXCEPT; + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 size_type capacity() const _NOEXCEPT {return __internal_cap_to_external(__cap());} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 size_type size() const _NOEXCEPT {return __size_;} - _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY + _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 bool empty() const _NOEXCEPT {return __size_ == 0;} - void reserve(size_type __n); - void shrink_to_fit() _NOEXCEPT; + _LIBCPP_CONSTEXPR_AFTER_CXX17 void reserve(size_type __n); + _LIBCPP_CONSTEXPR_AFTER_CXX17 void shrink_to_fit() _NOEXCEPT; - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 iterator begin() _NOEXCEPT {return __make_iter(0);} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 const_iterator begin() const _NOEXCEPT {return __make_iter(0);} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 iterator end() _NOEXCEPT {return __make_iter(__size_);} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 const_iterator end() const _NOEXCEPT {return __make_iter(__size_);} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 reverse_iterator rbegin() _NOEXCEPT {return reverse_iterator(end());} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 const_reverse_iterator rbegin() const _NOEXCEPT {return const_reverse_iterator(end());} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 reverse_iterator rend() _NOEXCEPT {return reverse_iterator(begin());} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 const_reverse_iterator rend() const _NOEXCEPT {return const_reverse_iterator(begin());} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 const_iterator cbegin() const _NOEXCEPT {return __make_iter(0);} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 const_iterator cend() const _NOEXCEPT {return __make_iter(__size_);} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 const_reverse_iterator crbegin() const _NOEXCEPT {return rbegin();} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 const_reverse_iterator crend() const _NOEXCEPT {return rend();} - _LIBCPP_INLINE_VISIBILITY reference operator[](size_type __n) {return __make_ref(__n);} - _LIBCPP_INLINE_VISIBILITY const_reference operator[](size_type __n) const {return __make_ref(__n);} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 reference operator[](size_type __n) {return __make_ref(__n);} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 const_reference operator[](size_type __n) const {return __make_ref(__n);} reference at(size_type __n); const_reference at(size_type __n) const; - _LIBCPP_INLINE_VISIBILITY reference front() {return __make_ref(0);} - _LIBCPP_INLINE_VISIBILITY const_reference front() const {return __make_ref(0);} - _LIBCPP_INLINE_VISIBILITY reference back() {return __make_ref(__size_ - 1);} - _LIBCPP_INLINE_VISIBILITY const_reference back() const {return __make_ref(__size_ - 1);} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 reference front() {return __make_ref(0);} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 const_reference front() const {return __make_ref(0);} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 reference back() {return __make_ref(__size_ - 1);} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 const_reference back() const {return __make_ref(__size_ - 1);} - void push_back(const value_type& __x); + _LIBCPP_CONSTEXPR_AFTER_CXX17 void push_back(const value_type& __x); #if _LIBCPP_STD_VER > 11 template #if _LIBCPP_STD_VER > 14 - _LIBCPP_INLINE_VISIBILITY reference emplace_back(_Args&&... __args) + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 reference emplace_back(_Args&&... __args) #else _LIBCPP_INLINE_VISIBILITY void emplace_back(_Args&&... __args) #endif @@ -2187,54 +2259,54 @@ public: } #endif - _LIBCPP_INLINE_VISIBILITY void pop_back() {--__size_;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 void pop_back() {--__size_;} #if _LIBCPP_STD_VER > 11 template - _LIBCPP_INLINE_VISIBILITY iterator emplace(const_iterator __position, _Args&&... __args) + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 iterator emplace(const_iterator __position, _Args&&... __args) { return insert ( __position, value_type ( _VSTD::forward<_Args>(__args)... )); } #endif - iterator insert(const_iterator __position, const value_type& __x); - iterator insert(const_iterator __position, size_type __n, const value_type& __x); + _LIBCPP_CONSTEXPR_AFTER_CXX17 iterator insert(const_iterator __position, const value_type& __x); + _LIBCPP_CONSTEXPR_AFTER_CXX17 iterator insert(const_iterator __position, size_type __n, const value_type& __x); template typename enable_if <__is_exactly_cpp17_input_iterator<_InputIterator>::value, iterator >::type - insert(const_iterator __position, _InputIterator __first, _InputIterator __last); + _LIBCPP_CONSTEXPR_AFTER_CXX17 insert(const_iterator __position, _InputIterator __first, _InputIterator __last); template typename enable_if < __is_cpp17_forward_iterator<_ForwardIterator>::value, iterator >::type - insert(const_iterator __position, _ForwardIterator __first, _ForwardIterator __last); + _LIBCPP_CONSTEXPR_AFTER_CXX17 insert(const_iterator __position, _ForwardIterator __first, _ForwardIterator __last); #ifndef _LIBCPP_CXX03_LANG - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 iterator insert(const_iterator __position, initializer_list __il) {return insert(__position, __il.begin(), __il.end());} #endif - _LIBCPP_INLINE_VISIBILITY iterator erase(const_iterator __position); - iterator erase(const_iterator __first, const_iterator __last); + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 iterator erase(const_iterator __position); + _LIBCPP_CONSTEXPR_AFTER_CXX17 iterator erase(const_iterator __first, const_iterator __last); - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 void clear() _NOEXCEPT {__size_ = 0;} - void swap(vector&) + _LIBCPP_CONSTEXPR_AFTER_CXX17 void swap(vector&) #if _LIBCPP_STD_VER >= 14 _NOEXCEPT; #else _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || __is_nothrow_swappable::value); #endif - static void swap(reference __x, reference __y) _NOEXCEPT { _VSTD::swap(__x, __y); } + _LIBCPP_CONSTEXPR_AFTER_CXX17 static void swap(reference __x, reference __y) _NOEXCEPT { _VSTD::swap(__x, __y); } - void resize(size_type __sz, value_type __x = false); - void flip() _NOEXCEPT; + _LIBCPP_CONSTEXPR_AFTER_CXX17 void resize(size_type __sz, value_type __x = false); + _LIBCPP_CONSTEXPR_AFTER_CXX17 void flip() _NOEXCEPT; - bool __invariants() const; + _LIBCPP_CONSTEXPR_AFTER_CXX17 bool __invariants() const; private: _LIBCPP_NORETURN _LIBCPP_HIDE_FROM_ABI @@ -2254,52 +2326,56 @@ private: // Precondition: __n > 0 // Postcondition: capacity() >= __n // Postcondition: size() == 0 - _LIBCPP_HIDE_FROM_ABI void __vallocate(size_type __n) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 void __vallocate(size_type __n) { if (__n > max_size()) __throw_length_error(); auto __allocation = std::__allocate_at_least(__alloc(), __external_cap_to_internal(__n)); __begin_ = __allocation.ptr; __size_ = 0; __cap() = __allocation.count; + if (__libcpp_is_constant_evaluated()) { + for (size_type __i = 0; __i != __cap(); ++__i) + std::__construct_at(std::__to_address(__begin_) + __i); + } } - void __vdeallocate() _NOEXCEPT; - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 void __vdeallocate() _NOEXCEPT; + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 static size_type __align_it(size_type __new_size) _NOEXCEPT {return (__new_size + (__bits_per_word-1)) & ~((size_type)__bits_per_word-1);} - _LIBCPP_INLINE_VISIBILITY size_type __recommend(size_type __new_size) const; - _LIBCPP_INLINE_VISIBILITY void __construct_at_end(size_type __n, bool __x); + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 size_type __recommend(size_type __new_size) const; + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 void __construct_at_end(size_type __n, bool __x); template typename enable_if < __is_cpp17_forward_iterator<_ForwardIterator>::value, void >::type - __construct_at_end(_ForwardIterator __first, _ForwardIterator __last); - void __append(size_type __n, const_reference __x); - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 __construct_at_end(_ForwardIterator __first, _ForwardIterator __last); + _LIBCPP_CONSTEXPR_AFTER_CXX17 void __append(size_type __n, const_reference __x); + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 reference __make_ref(size_type __pos) _NOEXCEPT {return reference(__begin_ + __pos / __bits_per_word, __storage_type(1) << __pos % __bits_per_word);} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 const_reference __make_ref(size_type __pos) const _NOEXCEPT { return __bit_const_reference(__begin_ + __pos / __bits_per_word, __storage_type(1) << __pos % __bits_per_word); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 iterator __make_iter(size_type __pos) _NOEXCEPT {return iterator(__begin_ + __pos / __bits_per_word, static_cast(__pos % __bits_per_word));} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 const_iterator __make_iter(size_type __pos) const _NOEXCEPT {return const_iterator(__begin_ + __pos / __bits_per_word, static_cast(__pos % __bits_per_word));} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 iterator __const_iterator_cast(const_iterator __p) _NOEXCEPT {return begin() + (__p - cbegin());} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 void __copy_assign_alloc(const vector& __v) {__copy_assign_alloc(__v, integral_constant());} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 void __copy_assign_alloc(const vector& __c, true_type) { if (__alloc() != __c.__alloc()) @@ -2307,33 +2383,33 @@ private: __alloc() = __c.__alloc(); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 void __copy_assign_alloc(const vector&, false_type) {} - void __move_assign(vector& __c, false_type); - void __move_assign(vector& __c, true_type) + _LIBCPP_CONSTEXPR_AFTER_CXX17 void __move_assign(vector& __c, false_type); + _LIBCPP_CONSTEXPR_AFTER_CXX17 void __move_assign(vector& __c, true_type) _NOEXCEPT_(is_nothrow_move_assignable::value); - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 void __move_assign_alloc(vector& __c) _NOEXCEPT_( !__storage_traits::propagate_on_container_move_assignment::value || is_nothrow_move_assignable::value) {__move_assign_alloc(__c, integral_constant());} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 void __move_assign_alloc(vector& __c, true_type) _NOEXCEPT_(is_nothrow_move_assignable::value) { __alloc() = _VSTD::move(__c.__alloc()); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 void __move_assign_alloc(vector&, false_type) _NOEXCEPT {} - size_t __hash_code() const _NOEXCEPT; + _LIBCPP_CONSTEXPR_AFTER_CXX17 size_t __hash_code() const _NOEXCEPT; friend class __bit_reference; friend class __bit_const_reference; @@ -2344,7 +2420,7 @@ private: }; template -void +_LIBCPP_CONSTEXPR_AFTER_CXX17 void vector::__vdeallocate() _NOEXCEPT { if (this->__begin_ != nullptr) @@ -2357,6 +2433,7 @@ vector::__vdeallocate() _NOEXCEPT } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 typename vector::size_type vector::max_size() const _NOEXCEPT { @@ -2369,7 +2446,7 @@ vector::max_size() const _NOEXCEPT // Precondition: __new_size > capacity() template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 typename vector::size_type vector::__recommend(size_type __new_size) const { @@ -2387,7 +2464,7 @@ vector::__recommend(size_type __new_size) const // Precondition: size() + __n <= capacity() // Postcondition: size() == size() + __n template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 void vector::__construct_at_end(size_type __n, bool __x) { @@ -2405,6 +2482,7 @@ vector::__construct_at_end(size_type __n, bool __x) template template +_LIBCPP_CONSTEXPR_AFTER_CXX17 typename enable_if < __is_cpp17_forward_iterator<_ForwardIterator>::value, @@ -2425,7 +2503,7 @@ vector::__construct_at_end(_ForwardIterator __first, _ForwardI } template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 vector::vector() _NOEXCEPT_(is_nothrow_default_constructible::value) : __begin_(nullptr), @@ -2435,7 +2513,7 @@ vector::vector() } template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 vector::vector(const allocator_type& __a) #if _LIBCPP_STD_VER <= 14 _NOEXCEPT_(is_nothrow_copy_constructible::value) @@ -2449,6 +2527,7 @@ vector::vector(const allocator_type& __a) } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 vector::vector(size_type __n) : __begin_(nullptr), __size_(0), @@ -2463,6 +2542,7 @@ vector::vector(size_type __n) #if _LIBCPP_STD_VER > 11 template +_LIBCPP_CONSTEXPR_AFTER_CXX17 vector::vector(size_type __n, const allocator_type& __a) : __begin_(nullptr), __size_(0), @@ -2477,6 +2557,7 @@ vector::vector(size_type __n, const allocator_type& __a) #endif template +_LIBCPP_CONSTEXPR_AFTER_CXX17 vector::vector(size_type __n, const value_type& __x) : __begin_(nullptr), __size_(0), @@ -2490,6 +2571,7 @@ vector::vector(size_type __n, const value_type& __x) } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 vector::vector(size_type __n, const value_type& __x, const allocator_type& __a) : __begin_(nullptr), __size_(0), @@ -2504,6 +2586,7 @@ vector::vector(size_type __n, const value_type& __x, const all template template +_LIBCPP_CONSTEXPR_AFTER_CXX17 vector::vector(_InputIterator __first, _InputIterator __last, typename enable_if<__is_exactly_cpp17_input_iterator<_InputIterator>::value>::type*) : __begin_(nullptr), @@ -2530,6 +2613,7 @@ vector::vector(_InputIterator __first, _InputIterator __last, template template +_LIBCPP_CONSTEXPR_AFTER_CXX17 vector::vector(_InputIterator __first, _InputIterator __last, const allocator_type& __a, typename enable_if<__is_exactly_cpp17_input_iterator<_InputIterator>::value>::type*) : __begin_(nullptr), @@ -2556,6 +2640,7 @@ vector::vector(_InputIterator __first, _InputIterator __last, template template +_LIBCPP_CONSTEXPR_AFTER_CXX17 vector::vector(_ForwardIterator __first, _ForwardIterator __last, typename enable_if<__is_cpp17_forward_iterator<_ForwardIterator>::value>::type*) : __begin_(nullptr), @@ -2572,6 +2657,7 @@ vector::vector(_ForwardIterator __first, _ForwardIterator __la template template +_LIBCPP_CONSTEXPR_AFTER_CXX17 vector::vector(_ForwardIterator __first, _ForwardIterator __last, const allocator_type& __a, typename enable_if<__is_cpp17_forward_iterator<_ForwardIterator>::value>::type*) : __begin_(nullptr), @@ -2589,6 +2675,7 @@ vector::vector(_ForwardIterator __first, _ForwardIterator __la #ifndef _LIBCPP_CXX03_LANG template +_LIBCPP_CONSTEXPR_AFTER_CXX17 vector::vector(initializer_list __il) : __begin_(nullptr), __size_(0), @@ -2603,6 +2690,7 @@ vector::vector(initializer_list __il) } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 vector::vector(initializer_list __il, const allocator_type& __a) : __begin_(nullptr), __size_(0), @@ -2619,6 +2707,7 @@ vector::vector(initializer_list __il, const alloca #endif // _LIBCPP_CXX03_LANG template +_LIBCPP_CONSTEXPR_AFTER_CXX17 vector::~vector() { if (__begin_ != nullptr) @@ -2627,6 +2716,7 @@ vector::~vector() } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 vector::vector(const vector& __v) : __begin_(nullptr), __size_(0), @@ -2640,6 +2730,7 @@ vector::vector(const vector& __v) } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 vector::vector(const vector& __v, const allocator_type& __a) : __begin_(nullptr), __size_(0), @@ -2653,6 +2744,7 @@ vector::vector(const vector& __v, const allocator_type& __a) } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 vector& vector::operator=(const vector& __v) { @@ -2674,7 +2766,7 @@ vector::operator=(const vector& __v) } template -inline _LIBCPP_INLINE_VISIBILITY vector::vector(vector&& __v) +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 vector::vector(vector&& __v) #if _LIBCPP_STD_VER > 14 _NOEXCEPT #else @@ -2689,6 +2781,7 @@ inline _LIBCPP_INLINE_VISIBILITY vector::vector(vector&& __v) } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 vector::vector(vector&& __v, const __type_identity_t& __a) : __begin_(nullptr), __size_(0), @@ -2710,7 +2803,7 @@ vector::vector(vector&& __v, const __type_identity_t -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 vector& vector::operator=(vector&& __v) _NOEXCEPT_((__noexcept_move_assign_container<_Allocator, __alloc_traits>::value)) @@ -2721,7 +2814,7 @@ vector::operator=(vector&& __v) } template -void +_LIBCPP_CONSTEXPR_AFTER_CXX17 void vector::__move_assign(vector& __c, false_type) { if (__alloc() != __c.__alloc()) @@ -2731,7 +2824,7 @@ vector::__move_assign(vector& __c, false_type) } template -void +_LIBCPP_CONSTEXPR_AFTER_CXX17 void vector::__move_assign(vector& __c, true_type) _NOEXCEPT_(is_nothrow_move_assignable::value) { @@ -2745,7 +2838,7 @@ vector::__move_assign(vector& __c, true_type) } template -void +_LIBCPP_CONSTEXPR_AFTER_CXX17 void vector::assign(size_type __n, const value_type& __x) { __size_ = 0; @@ -2768,7 +2861,7 @@ vector::assign(size_type __n, const value_type& __x) template template -typename enable_if <__is_exactly_cpp17_input_iterator<_InputIterator>::value, +_LIBCPP_CONSTEXPR_AFTER_CXX17 typename enable_if <__is_exactly_cpp17_input_iterator<_InputIterator>::value, void >::type vector::assign(_InputIterator __first, _InputIterator __last) @@ -2780,6 +2873,7 @@ vector::assign(_InputIterator __first, _InputIterator __last) template template +_LIBCPP_CONSTEXPR_AFTER_CXX17 typename enable_if < __is_cpp17_forward_iterator<_ForwardIterator>::value, @@ -2803,7 +2897,7 @@ vector::assign(_ForwardIterator __first, _ForwardIterator __la } template -void +_LIBCPP_CONSTEXPR_AFTER_CXX17 void vector::reserve(size_type __n) { if (__n > capacity()) @@ -2819,7 +2913,7 @@ vector::reserve(size_type __n) } template -void +_LIBCPP_CONSTEXPR_AFTER_CXX17 void vector::shrink_to_fit() _NOEXCEPT { if (__external_cap_to_internal(size()) > __cap()) @@ -2857,7 +2951,7 @@ vector::at(size_type __n) const } template -void +_LIBCPP_CONSTEXPR_AFTER_CXX17 void vector::push_back(const value_type& __x) { if (this->__size_ == this->capacity()) @@ -2867,7 +2961,7 @@ vector::push_back(const value_type& __x) } template -typename vector::iterator +_LIBCPP_CONSTEXPR_AFTER_CXX17 typename vector::iterator vector::insert(const_iterator __position, const value_type& __x) { iterator __r; @@ -2892,7 +2986,7 @@ vector::insert(const_iterator __position, const value_type& __ } template -typename vector::iterator +_LIBCPP_CONSTEXPR_AFTER_CXX17 typename vector::iterator vector::insert(const_iterator __position, size_type __n, const value_type& __x) { iterator __r; @@ -2919,7 +3013,7 @@ vector::insert(const_iterator __position, size_type __n, const template template -typename enable_if <__is_exactly_cpp17_input_iterator<_InputIterator>::value, +_LIBCPP_CONSTEXPR_AFTER_CXX17 typename enable_if <__is_exactly_cpp17_input_iterator<_InputIterator>::value, typename vector::iterator >::type vector::insert(const_iterator __position, _InputIterator __first, _InputIterator __last) @@ -2961,6 +3055,7 @@ vector::insert(const_iterator __position, _InputIterator __fir template template +_LIBCPP_CONSTEXPR_AFTER_CXX17 typename enable_if < __is_cpp17_forward_iterator<_ForwardIterator>::value, @@ -2994,7 +3089,7 @@ vector::insert(const_iterator __position, _ForwardIterator __f } template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 typename vector::iterator vector::erase(const_iterator __position) { @@ -3005,6 +3100,7 @@ vector::erase(const_iterator __position) } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 typename vector::iterator vector::erase(const_iterator __first, const_iterator __last) { @@ -3016,7 +3112,7 @@ vector::erase(const_iterator __first, const_iterator __last) } template -void +_LIBCPP_CONSTEXPR_AFTER_CXX17 void vector::swap(vector& __x) #if _LIBCPP_STD_VER >= 14 _NOEXCEPT @@ -3033,7 +3129,7 @@ vector::swap(vector& __x) } template -void +_LIBCPP_CONSTEXPR_AFTER_CXX17 void vector::resize(size_type __sz, value_type __x) { size_type __cs = size(); @@ -3062,7 +3158,7 @@ vector::resize(size_type __sz, value_type __x) } template -void +_LIBCPP_CONSTEXPR_AFTER_CXX17 void vector::flip() _NOEXCEPT { // do middle whole words @@ -3081,7 +3177,7 @@ vector::flip() _NOEXCEPT } template -bool +_LIBCPP_CONSTEXPR_AFTER_CXX17 bool vector::__invariants() const { if (this->__begin_ == nullptr) @@ -3100,7 +3196,7 @@ vector::__invariants() const } template -size_t +_LIBCPP_CONSTEXPR_AFTER_CXX17 size_t vector::__hash_code() const _NOEXCEPT { size_t __h = 0; @@ -3122,12 +3218,13 @@ template struct _LIBCPP_TEMPLATE_VIS hash > : public __unary_function, size_t> { - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 size_t operator()(const vector& __vec) const _NOEXCEPT {return __vec.__hash_code();} }; template +_LIBCPP_CONSTEXPR_AFTER_CXX17 inline _LIBCPP_INLINE_VISIBILITY bool operator==(const vector<_Tp, _Allocator>& __x, const vector<_Tp, _Allocator>& __y) @@ -3137,6 +3234,7 @@ operator==(const vector<_Tp, _Allocator>& __x, const vector<_Tp, _Allocator>& __ } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 inline _LIBCPP_INLINE_VISIBILITY bool operator!=(const vector<_Tp, _Allocator>& __x, const vector<_Tp, _Allocator>& __y) @@ -3145,6 +3243,7 @@ operator!=(const vector<_Tp, _Allocator>& __x, const vector<_Tp, _Allocator>& __ } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 inline _LIBCPP_INLINE_VISIBILITY bool operator< (const vector<_Tp, _Allocator>& __x, const vector<_Tp, _Allocator>& __y) @@ -3153,6 +3252,7 @@ operator< (const vector<_Tp, _Allocator>& __x, const vector<_Tp, _Allocator>& __ } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 inline _LIBCPP_INLINE_VISIBILITY bool operator> (const vector<_Tp, _Allocator>& __x, const vector<_Tp, _Allocator>& __y) @@ -3161,6 +3261,7 @@ operator> (const vector<_Tp, _Allocator>& __x, const vector<_Tp, _Allocator>& __ } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 inline _LIBCPP_INLINE_VISIBILITY bool operator>=(const vector<_Tp, _Allocator>& __x, const vector<_Tp, _Allocator>& __y) @@ -3169,6 +3270,7 @@ operator>=(const vector<_Tp, _Allocator>& __x, const vector<_Tp, _Allocator>& __ } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 inline _LIBCPP_INLINE_VISIBILITY bool operator<=(const vector<_Tp, _Allocator>& __x, const vector<_Tp, _Allocator>& __y) @@ -3177,6 +3279,7 @@ operator<=(const vector<_Tp, _Allocator>& __x, const vector<_Tp, _Allocator>& __ } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 inline _LIBCPP_INLINE_VISIBILITY void swap(vector<_Tp, _Allocator>& __x, vector<_Tp, _Allocator>& __y) @@ -3187,6 +3290,7 @@ swap(vector<_Tp, _Allocator>& __x, vector<_Tp, _Allocator>& __y) #if _LIBCPP_STD_VER > 17 template +_LIBCPP_CONSTEXPR_AFTER_CXX17 inline _LIBCPP_INLINE_VISIBILITY typename vector<_Tp, _Allocator>::size_type erase(vector<_Tp, _Allocator>& __c, const _Up& __v) { auto __old_size = __c.size(); @@ -3195,6 +3299,7 @@ erase(vector<_Tp, _Allocator>& __c, const _Up& __v) { } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 inline _LIBCPP_INLINE_VISIBILITY typename vector<_Tp, _Allocator>::size_type erase_if(vector<_Tp, _Allocator>& __c, _Predicate __pred) { auto __old_size = __c.size(); diff --git a/libcxx/src/include/sso_allocator.h b/libcxx/src/include/sso_allocator.h index 2baf599c5c242..6a682fc43f86f 100644 --- a/libcxx/src/include/sso_allocator.h +++ b/libcxx/src/include/sso_allocator.h @@ -41,6 +41,11 @@ class _LIBCPP_HIDDEN __sso_allocator typedef _Tp* pointer; typedef _Tp value_type; + template + struct rebind { + using other = __sso_allocator; + }; + _LIBCPP_INLINE_VISIBILITY __sso_allocator() throw() : __allocated_(false) {} _LIBCPP_INLINE_VISIBILITY __sso_allocator(const __sso_allocator&) throw() : __allocated_(false) {} template _LIBCPP_INLINE_VISIBILITY __sso_allocator(const __sso_allocator<_Up, _Np>&) throw() diff --git a/libcxx/test/std/containers/associative/map/map.cons/copy_assign.pass.cpp b/libcxx/test/std/containers/associative/map/map.cons/copy_assign.pass.cpp index 64ed36c70b767..3fd051f790619 100644 --- a/libcxx/test/std/containers/associative/map/map.cons/copy_assign.pass.cpp +++ b/libcxx/test/std/containers/associative/map/map.cons/copy_assign.pass.cpp @@ -12,6 +12,8 @@ // map& operator=(const map& m); +// XFAIL: libcpp-has-debug-mode + #include #include #include diff --git a/libcxx/test/std/containers/sequences/vector.bool/assign_copy.pass.cpp b/libcxx/test/std/containers/sequences/vector.bool/assign_copy.pass.cpp index c1233ea8f10c0..c4866ea4c9b45 100644 --- a/libcxx/test/std/containers/sequences/vector.bool/assign_copy.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector.bool/assign_copy.pass.cpp @@ -16,7 +16,7 @@ #include "test_allocator.h" #include "min_allocator.h" -int main(int, char**) +TEST_CONSTEXPR_CXX20 bool tests() { { std::vector > l(3, true, test_allocator(5)); @@ -42,5 +42,14 @@ int main(int, char**) } #endif - return 0; + return true; +} + +int main(int, char**) +{ + tests(); +#if TEST_STD_VER > 17 + static_assert(tests()); +#endif + return 0; } diff --git a/libcxx/test/std/containers/sequences/vector.bool/assign_initializer_list.pass.cpp b/libcxx/test/std/containers/sequences/vector.bool/assign_initializer_list.pass.cpp index eff0cdc99a167..0f5ec9061f52d 100644 --- a/libcxx/test/std/containers/sequences/vector.bool/assign_initializer_list.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector.bool/assign_initializer_list.pass.cpp @@ -18,7 +18,7 @@ #include "test_macros.h" #include "min_allocator.h" -int main(int, char**) +TEST_CONSTEXPR_CXX20 bool tests() { { std::vector d; @@ -39,5 +39,14 @@ int main(int, char**) assert(d[3] == true); } - return 0; + return true; +} + +int main(int, char**) +{ + tests(); +#if TEST_STD_VER > 17 + static_assert(tests()); +#endif + return 0; } diff --git a/libcxx/test/std/containers/sequences/vector.bool/assign_move.pass.cpp b/libcxx/test/std/containers/sequences/vector.bool/assign_move.pass.cpp index 19cc7898238a0..10271efc3f403 100644 --- a/libcxx/test/std/containers/sequences/vector.bool/assign_move.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector.bool/assign_move.pass.cpp @@ -18,7 +18,7 @@ #include "test_allocator.h" #include "min_allocator.h" -int main(int, char**) +TEST_CONSTEXPR_CXX20 bool tests() { { std::vector > l(test_allocator(5)); @@ -77,5 +77,14 @@ int main(int, char**) assert(l2.get_allocator() == lo.get_allocator()); } - return 0; + return true; +} + +int main(int, char**) +{ + tests(); +#if TEST_STD_VER > 17 + static_assert(tests()); +#endif + return 0; } diff --git a/libcxx/test/std/containers/sequences/vector.bool/capacity.pass.cpp b/libcxx/test/std/containers/sequences/vector.bool/capacity.pass.cpp index cb14329067e06..986453a189049 100644 --- a/libcxx/test/std/containers/sequences/vector.bool/capacity.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector.bool/capacity.pass.cpp @@ -17,7 +17,7 @@ #include "test_macros.h" #include "min_allocator.h" -int main(int, char**) +TEST_CONSTEXPR_CXX20 bool tests() { { std::vector v; @@ -42,5 +42,14 @@ int main(int, char**) } #endif - return 0; + return true; +} + +int main(int, char**) +{ + tests(); +#if TEST_STD_VER > 17 + static_assert(tests()); +#endif + return 0; } diff --git a/libcxx/test/std/containers/sequences/vector.bool/compare.pass.cpp b/libcxx/test/std/containers/sequences/vector.bool/compare.pass.cpp index 03b3b3d868d17..0f818029c1ff9 100644 --- a/libcxx/test/std/containers/sequences/vector.bool/compare.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector.bool/compare.pass.cpp @@ -20,7 +20,7 @@ #include "test_comparisons.h" -int main(int, char**) { +TEST_CONSTEXPR_CXX20 bool test() { typedef std::vector VB; { const VB v1, v2; @@ -76,5 +76,14 @@ int main(int, char**) { assert( (std::vector() >= std::vector())); } + return true; +} + +int main(int, char**) { + test(); +#if TEST_STD_VER > 17 + static_assert(test()); +#endif + return 0; } diff --git a/libcxx/test/std/containers/sequences/vector.bool/const_reference.pass.cpp b/libcxx/test/std/containers/sequences/vector.bool/const_reference.pass.cpp index 68b27479ba00b..c2cb7f0298ddb 100644 --- a/libcxx/test/std/containers/sequences/vector.bool/const_reference.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector.bool/const_reference.pass.cpp @@ -13,7 +13,7 @@ #include "test_macros.h" -bool test() { +TEST_CONSTEXPR_CXX20 bool test() { using CRefT = std::vector::const_reference; #if !defined(_LIBCPP_VERSION) || defined(_LIBCPP_ABI_BITSET_VECTOR_BOOL_CONST_SUBSCRIPT_RETURN_BOOL) ASSERT_SAME_TYPE(CRefT, bool); @@ -32,6 +32,9 @@ bool test() { int main(int, char**) { test(); +#if TEST_STD_VER > 17 + static_assert(test()); +#endif return 0; } diff --git a/libcxx/test/std/containers/sequences/vector.bool/construct_default.pass.cpp b/libcxx/test/std/containers/sequences/vector.bool/construct_default.pass.cpp index 3fd2bf8d195de..8f07524d070bb 100644 --- a/libcxx/test/std/containers/sequences/vector.bool/construct_default.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector.bool/construct_default.pass.cpp @@ -24,8 +24,7 @@ #include "min_allocator.h" template -void -test0() +TEST_CONSTEXPR_CXX20 void test0() { #if TEST_STD_VER > 14 LIBCPP_STATIC_ASSERT((noexcept(C{})), "" ); @@ -45,8 +44,7 @@ test0() } template -void -test1(const typename C::allocator_type& a) +TEST_CONSTEXPR_CXX20 void test1(const typename C::allocator_type& a) { #if TEST_STD_VER > 14 LIBCPP_STATIC_ASSERT((noexcept(C{typename C::allocator_type{}})), "" ); @@ -59,7 +57,7 @@ test1(const typename C::allocator_type& a) assert(c.get_allocator() == a); } -int main(int, char**) +TEST_CONSTEXPR_CXX20 bool tests() { { test0 >(); @@ -76,5 +74,14 @@ int main(int, char**) } #endif - return 0; + return true; +} + +int main(int, char**) +{ + tests(); +#if TEST_STD_VER > 17 + static_assert(tests()); +#endif + return 0; } diff --git a/libcxx/test/std/containers/sequences/vector.bool/construct_iter_iter.pass.cpp b/libcxx/test/std/containers/sequences/vector.bool/construct_iter_iter.pass.cpp index 9d236e0892d31..2f520d5abbf3e 100644 --- a/libcxx/test/std/containers/sequences/vector.bool/construct_iter_iter.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector.bool/construct_iter_iter.pass.cpp @@ -20,8 +20,7 @@ #include "min_allocator.h" template -void -test(Iterator first, Iterator last) +TEST_CONSTEXPR_CXX20 void test(Iterator first, Iterator last) { C c(first, last); LIBCPP_ASSERT(c.__invariants()); @@ -30,7 +29,7 @@ test(Iterator first, Iterator last) assert(*i == *first); } -int main(int, char**) +TEST_CONSTEXPR_CXX20 bool tests() { bool a[] = {0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0}; bool* an = a + sizeof(a)/sizeof(a[0]); @@ -47,5 +46,14 @@ int main(int, char**) test> >(a, an); #endif - return 0; + return true; +} + +int main(int, char**) +{ + tests(); +#if TEST_STD_VER > 17 + static_assert(tests()); +#endif + return 0; } diff --git a/libcxx/test/std/containers/sequences/vector.bool/construct_iter_iter_alloc.pass.cpp b/libcxx/test/std/containers/sequences/vector.bool/construct_iter_iter_alloc.pass.cpp index 3e4a37c3c5684..57e1cb2e0b502 100644 --- a/libcxx/test/std/containers/sequences/vector.bool/construct_iter_iter_alloc.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector.bool/construct_iter_iter_alloc.pass.cpp @@ -21,8 +21,7 @@ #include "min_allocator.h" template -void -test(Iterator first, Iterator last, const typename C::allocator_type& a) +TEST_CONSTEXPR_CXX20 void test(Iterator first, Iterator last, const typename C::allocator_type& a) { C c(first, last, a); LIBCPP_ASSERT(c.__invariants()); @@ -31,7 +30,7 @@ test(Iterator first, Iterator last, const typename C::allocator_type& a) assert(*i == *first); } -int main(int, char**) +TEST_CONSTEXPR_CXX20 bool tests() { bool a[] = {0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0}; bool* an = a + sizeof(a)/sizeof(a[0]); @@ -54,5 +53,14 @@ int main(int, char**) } #endif - return 0; + return true; +} + +int main(int, char**) +{ + tests(); +#if TEST_STD_VER > 17 + static_assert(tests()); +#endif + return 0; } diff --git a/libcxx/test/std/containers/sequences/vector.bool/construct_size.pass.cpp b/libcxx/test/std/containers/sequences/vector.bool/construct_size.pass.cpp index 2763df7e11d5c..bcc5a16859d36 100644 --- a/libcxx/test/std/containers/sequences/vector.bool/construct_size.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector.bool/construct_size.pass.cpp @@ -19,9 +19,8 @@ #include "test_allocator.h" template -void -test2(typename C::size_type n, - typename C::allocator_type const& a = typename C::allocator_type ()) +TEST_CONSTEXPR_CXX20 void test2(typename C::size_type n, + typename C::allocator_type const& a = typename C::allocator_type ()) { #if TEST_STD_VER >= 14 C c(n, a); @@ -37,8 +36,7 @@ test2(typename C::size_type n, } template -void -test1(typename C::size_type n) +TEST_CONSTEXPR_CXX20 void test1(typename C::size_type n) { C c(n); LIBCPP_ASSERT(c.__invariants()); @@ -49,14 +47,13 @@ test1(typename C::size_type n) } template -void -test(typename C::size_type n) +TEST_CONSTEXPR_CXX20 void test(typename C::size_type n) { test1 ( n ); test2 ( n ); } -int main(int, char**) +TEST_CONSTEXPR_CXX20 bool tests() { test >(50); #if TEST_STD_VER >= 11 @@ -64,5 +61,14 @@ int main(int, char**) test2> >( 100, test_allocator(23)); #endif - return 0; + return true; +} + +int main(int, char**) +{ + tests(); +#if TEST_STD_VER > 17 + static_assert(tests()); +#endif + return 0; } diff --git a/libcxx/test/std/containers/sequences/vector.bool/construct_size_value.pass.cpp b/libcxx/test/std/containers/sequences/vector.bool/construct_size_value.pass.cpp index 068989330a31f..629e8ba57ca85 100644 --- a/libcxx/test/std/containers/sequences/vector.bool/construct_size_value.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector.bool/construct_size_value.pass.cpp @@ -18,8 +18,7 @@ #include "min_allocator.h" template -void -test(typename C::size_type n, const typename C::value_type& x) +TEST_CONSTEXPR_CXX20 void test(typename C::size_type n, const typename C::value_type& x) { C c(n, x); LIBCPP_ASSERT(c.__invariants()); @@ -28,12 +27,21 @@ test(typename C::size_type n, const typename C::value_type& x) assert(*i == x); } -int main(int, char**) +TEST_CONSTEXPR_CXX20 bool tests() { test >(50, true); #if TEST_STD_VER >= 11 test> >(50, true); #endif - return 0; + return true; +} + +int main(int, char**) +{ + tests(); +#if TEST_STD_VER > 17 + static_assert(tests()); +#endif + return 0; } diff --git a/libcxx/test/std/containers/sequences/vector.bool/construct_size_value_alloc.pass.cpp b/libcxx/test/std/containers/sequences/vector.bool/construct_size_value_alloc.pass.cpp index e19f3c4a9d531..94a44ad282b71 100644 --- a/libcxx/test/std/containers/sequences/vector.bool/construct_size_value_alloc.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector.bool/construct_size_value_alloc.pass.cpp @@ -18,9 +18,9 @@ #include "min_allocator.h" template -void -test(typename C::size_type n, const typename C::value_type& x, - const typename C::allocator_type& a) +TEST_CONSTEXPR_CXX20 void test(typename C::size_type n, + const typename C::value_type& x, + const typename C::allocator_type& a) { C c(n, x, a); LIBCPP_ASSERT(c.__invariants()); @@ -30,12 +30,21 @@ test(typename C::size_type n, const typename C::value_type& x, assert(*i == x); } -int main(int, char**) +TEST_CONSTEXPR_CXX20 bool tests() { test >(50, true, std::allocator()); #if TEST_STD_VER >= 11 test> >(50, true, min_allocator()); #endif - return 0; + return true; +} + +int main(int, char**) +{ + tests(); +#if TEST_STD_VER > 17 + static_assert(tests()); +#endif + return 0; } diff --git a/libcxx/test/std/containers/sequences/vector.bool/copy.pass.cpp b/libcxx/test/std/containers/sequences/vector.bool/copy.pass.cpp index 618a37faf70af..bfd37e956dbdf 100644 --- a/libcxx/test/std/containers/sequences/vector.bool/copy.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector.bool/copy.pass.cpp @@ -19,8 +19,7 @@ #include "min_allocator.h" template -void -test(const C& x) +TEST_CONSTEXPR_CXX20 void test(const C& x) { typename C::size_type s = x.size(); C c(x); @@ -29,7 +28,7 @@ test(const C& x) assert(c == x); } -int main(int, char**) +TEST_CONSTEXPR_CXX20 bool tests() { { bool a[] = {0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0}; @@ -62,5 +61,14 @@ int main(int, char**) } #endif - return 0; + return true; +} + +int main(int, char**) +{ + tests(); +#if TEST_STD_VER > 17 + static_assert(tests()); +#endif + return 0; } diff --git a/libcxx/test/std/containers/sequences/vector.bool/copy_alloc.pass.cpp b/libcxx/test/std/containers/sequences/vector.bool/copy_alloc.pass.cpp index 7970b2c7ed962..468bf5d866004 100644 --- a/libcxx/test/std/containers/sequences/vector.bool/copy_alloc.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector.bool/copy_alloc.pass.cpp @@ -18,8 +18,7 @@ #include "min_allocator.h" template -void -test(const C& x, const typename C::allocator_type& a) +TEST_CONSTEXPR_CXX20 void test(const C& x, const typename C::allocator_type& a) { typename C::size_type s = x.size(); C c(x, a); @@ -28,7 +27,7 @@ test(const C& x, const typename C::allocator_type& a) assert(c == x); } -int main(int, char**) +TEST_CONSTEXPR_CXX20 bool tests() { { bool a[] = {0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0}; @@ -61,5 +60,14 @@ int main(int, char**) } #endif - return 0; + return true; +} + +int main(int, char**) +{ + tests(); +#if TEST_STD_VER > 17 + static_assert(tests()); +#endif + return 0; } diff --git a/libcxx/test/std/containers/sequences/vector.bool/emplace.pass.cpp b/libcxx/test/std/containers/sequences/vector.bool/emplace.pass.cpp index 121395bedff12..134af5a7979a1 100644 --- a/libcxx/test/std/containers/sequences/vector.bool/emplace.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector.bool/emplace.pass.cpp @@ -17,7 +17,7 @@ #include "test_macros.h" #include "min_allocator.h" -int main(int, char**) +TEST_CONSTEXPR_CXX20 bool tests() { { typedef std::vector C; @@ -65,5 +65,14 @@ int main(int, char**) assert(c.back() == true); } - return 0; + return true; +} + +int main(int, char**) +{ + tests(); +#if TEST_STD_VER > 17 + static_assert(tests()); +#endif + return 0; } diff --git a/libcxx/test/std/containers/sequences/vector.bool/emplace_back.pass.cpp b/libcxx/test/std/containers/sequences/vector.bool/emplace_back.pass.cpp index 52fe733df5d70..fccf6e5fb962c 100644 --- a/libcxx/test/std/containers/sequences/vector.bool/emplace_back.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector.bool/emplace_back.pass.cpp @@ -18,7 +18,7 @@ #include "test_macros.h" #include "min_allocator.h" -int main(int, char**) +TEST_CONSTEXPR_CXX20 bool tests() { { typedef std::vector C; @@ -88,5 +88,14 @@ int main(int, char**) assert(c.back() == true); } - return 0; + return true; +} + +int main(int, char**) +{ + tests(); +#if TEST_STD_VER > 17 + static_assert(tests()); +#endif + return 0; } diff --git a/libcxx/test/std/containers/sequences/vector.bool/empty.pass.cpp b/libcxx/test/std/containers/sequences/vector.bool/empty.pass.cpp index e0c0243e13902..ec4d2f97045dd 100644 --- a/libcxx/test/std/containers/sequences/vector.bool/empty.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector.bool/empty.pass.cpp @@ -18,7 +18,7 @@ #include "test_macros.h" #include "min_allocator.h" -int main(int, char**) +TEST_CONSTEXPR_CXX20 bool tests() { { typedef std::vector C; @@ -43,5 +43,14 @@ int main(int, char**) } #endif - return 0; + return true; +} + +int main(int, char**) +{ + tests(); +#if TEST_STD_VER > 17 + static_assert(tests()); +#endif + return 0; } diff --git a/libcxx/test/std/containers/sequences/vector.bool/enabled_hash.pass.cpp b/libcxx/test/std/containers/sequences/vector.bool/enabled_hash.pass.cpp index 1e456de3bee74..d89984a4a30ba 100644 --- a/libcxx/test/std/containers/sequences/vector.bool/enabled_hash.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector.bool/enabled_hash.pass.cpp @@ -19,12 +19,19 @@ #include "test_macros.h" #include "min_allocator.h" +TEST_CONSTEXPR_CXX20 bool test() { + test_hash_enabled_for_type >(); + test_hash_enabled_for_type>>(); + + return true; +} + int main(int, char**) { test_library_hash_specializations_available(); - { - test_hash_enabled_for_type >(); - test_hash_enabled_for_type>>(); - } + test(); +#if TEST_STD_VER > 17 + static_assert(test()); +#endif return 0; } diff --git a/libcxx/test/std/containers/sequences/vector.bool/erase_iter.pass.cpp b/libcxx/test/std/containers/sequences/vector.bool/erase_iter.pass.cpp index 53a3eac6550a9..42d1e76a9c770 100644 --- a/libcxx/test/std/containers/sequences/vector.bool/erase_iter.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector.bool/erase_iter.pass.cpp @@ -18,7 +18,7 @@ #include "test_macros.h" #include "min_allocator.h" -int main(int, char**) +TEST_CONSTEXPR_CXX20 bool tests() { bool a1[] = {1, 0, 1}; { @@ -64,5 +64,14 @@ int main(int, char**) } #endif - return 0; + return true; +} + +int main(int, char**) +{ + tests(); +#if TEST_STD_VER > 17 + static_assert(tests()); +#endif + return 0; } diff --git a/libcxx/test/std/containers/sequences/vector.bool/erase_iter_iter.pass.cpp b/libcxx/test/std/containers/sequences/vector.bool/erase_iter_iter.pass.cpp index c2c6e561e82b7..c19ce9987e1e1 100644 --- a/libcxx/test/std/containers/sequences/vector.bool/erase_iter_iter.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector.bool/erase_iter_iter.pass.cpp @@ -18,7 +18,7 @@ #include "test_macros.h" #include "min_allocator.h" -int main(int, char**) +TEST_CONSTEXPR_CXX20 bool tests() { bool a1[] = {1, 0, 1}; { @@ -84,5 +84,14 @@ int main(int, char**) } #endif - return 0; + return true; +} + +int main(int, char**) +{ + tests(); +#if TEST_STD_VER > 17 + static_assert(tests()); +#endif + return 0; } diff --git a/libcxx/test/std/containers/sequences/vector.bool/find.pass.cpp b/libcxx/test/std/containers/sequences/vector.bool/find.pass.cpp index 406aebae53991..73cca82e79f11 100644 --- a/libcxx/test/std/containers/sequences/vector.bool/find.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector.bool/find.pass.cpp @@ -20,7 +20,7 @@ #include "test_macros.h" -int main(int, char**) +TEST_CONSTEXPR_CXX20 bool tests() { { for (unsigned i = 1; i < 256; ++i) @@ -41,5 +41,14 @@ int main(int, char**) } } - return 0; + return true; +} + +int main(int, char**) +{ + tests(); +#if TEST_STD_VER > 17 + static_assert(tests()); +#endif + return 0; } diff --git a/libcxx/test/std/containers/sequences/vector.bool/get_allocator.pass.cpp b/libcxx/test/std/containers/sequences/vector.bool/get_allocator.pass.cpp index f518b4601eef3..a088cd8119abc 100644 --- a/libcxx/test/std/containers/sequences/vector.bool/get_allocator.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector.bool/get_allocator.pass.cpp @@ -18,7 +18,7 @@ #include "test_allocator.h" #include "test_macros.h" -int main(int, char**) { +TEST_CONSTEXPR_CXX20 bool test() { { std::allocator alloc; const std::vector vb(alloc); @@ -30,5 +30,14 @@ int main(int, char**) { assert(vb.get_allocator() == alloc); } + return true; +} + +int main(int, char**) { + test(); +#if TEST_STD_VER > 17 + static_assert(test()); +#endif + return 0; } diff --git a/libcxx/test/std/containers/sequences/vector.bool/initializer_list.pass.cpp b/libcxx/test/std/containers/sequences/vector.bool/initializer_list.pass.cpp index 216c0a53096ef..9b13922240d57 100644 --- a/libcxx/test/std/containers/sequences/vector.bool/initializer_list.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector.bool/initializer_list.pass.cpp @@ -18,7 +18,7 @@ #include "test_macros.h" #include "min_allocator.h" -int main(int, char**) +TEST_CONSTEXPR_CXX20 bool tests() { { std::vector d = {true, false, false, true}; @@ -37,5 +37,14 @@ int main(int, char**) assert(d[3] == true); } - return 0; + return true; +} + +int main(int, char**) +{ + tests(); +#if TEST_STD_VER > 17 + static_assert(tests()); +#endif + return 0; } diff --git a/libcxx/test/std/containers/sequences/vector.bool/initializer_list_alloc.pass.cpp b/libcxx/test/std/containers/sequences/vector.bool/initializer_list_alloc.pass.cpp index 7e1411281c475..0d5dd8a79fc53 100644 --- a/libcxx/test/std/containers/sequences/vector.bool/initializer_list_alloc.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector.bool/initializer_list_alloc.pass.cpp @@ -19,7 +19,7 @@ #include "test_allocator.h" #include "min_allocator.h" -int main(int, char**) +TEST_CONSTEXPR_CXX20 bool tests() { { std::vector> d({true, false, false, true}, test_allocator(3)); @@ -40,5 +40,14 @@ int main(int, char**) assert(d[3] == true); } - return 0; + return true; +} + +int main(int, char**) +{ + tests(); +#if TEST_STD_VER > 17 + static_assert(tests()); +#endif + return 0; } diff --git a/libcxx/test/std/containers/sequences/vector.bool/insert_iter_initializer_list.pass.cpp b/libcxx/test/std/containers/sequences/vector.bool/insert_iter_initializer_list.pass.cpp index 3cbcc25b2077e..2462e05f20360 100644 --- a/libcxx/test/std/containers/sequences/vector.bool/insert_iter_initializer_list.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector.bool/insert_iter_initializer_list.pass.cpp @@ -18,7 +18,7 @@ #include "test_macros.h" #include "min_allocator.h" -int main(int, char**) +TEST_CONSTEXPR_CXX20 bool tests() { { std::vector d(10, true); @@ -61,5 +61,14 @@ int main(int, char**) assert(d[13] == true); } - return 0; + return true; +} + +int main(int, char**) +{ + tests(); +#if TEST_STD_VER > 17 + static_assert(tests()); +#endif + return 0; } diff --git a/libcxx/test/std/containers/sequences/vector.bool/insert_iter_iter_iter.pass.cpp b/libcxx/test/std/containers/sequences/vector.bool/insert_iter_iter_iter.pass.cpp index 4ee9ea5d7f358..d4756cd0fee63 100644 --- a/libcxx/test/std/containers/sequences/vector.bool/insert_iter_iter_iter.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector.bool/insert_iter_iter_iter.pass.cpp @@ -20,7 +20,7 @@ #include "test_iterators.h" #include "min_allocator.h" -int main(int, char**) +TEST_CONSTEXPR_CXX20 bool tests() { { std::vector v(100); @@ -142,5 +142,14 @@ int main(int, char**) } #endif - return 0; + return true; +} + +int main(int, char**) +{ + tests(); +#if TEST_STD_VER > 17 + static_assert(tests()); +#endif + return 0; } diff --git a/libcxx/test/std/containers/sequences/vector.bool/insert_iter_size_value.pass.cpp b/libcxx/test/std/containers/sequences/vector.bool/insert_iter_size_value.pass.cpp index 84cafc90cc777..feea1888b70a3 100644 --- a/libcxx/test/std/containers/sequences/vector.bool/insert_iter_size_value.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector.bool/insert_iter_size_value.pass.cpp @@ -18,7 +18,7 @@ #include "test_macros.h" #include "min_allocator.h" -int main(int, char**) +TEST_CONSTEXPR_CXX20 bool tests() { { std::vector v(100); @@ -87,5 +87,14 @@ int main(int, char**) } #endif - return 0; + return true; +} + +int main(int, char**) +{ + tests(); +#if TEST_STD_VER > 17 + static_assert(tests()); +#endif + return 0; } diff --git a/libcxx/test/std/containers/sequences/vector.bool/insert_iter_value.pass.cpp b/libcxx/test/std/containers/sequences/vector.bool/insert_iter_value.pass.cpp index 4cc48988fce75..b9a926eef5ec7 100644 --- a/libcxx/test/std/containers/sequences/vector.bool/insert_iter_value.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector.bool/insert_iter_value.pass.cpp @@ -18,7 +18,7 @@ #include "test_macros.h" #include "min_allocator.h" -int main(int, char**) +TEST_CONSTEXPR_CXX20 bool tests() { { std::vector v(100); @@ -84,5 +84,14 @@ int main(int, char**) } #endif - return 0; + return true; +} + +int main(int, char**) +{ + tests(); +#if TEST_STD_VER > 17 + static_assert(tests()); +#endif + return 0; } diff --git a/libcxx/test/std/containers/sequences/vector.bool/iterators.pass.cpp b/libcxx/test/std/containers/sequences/vector.bool/iterators.pass.cpp index 1714c73742b62..9aaaac7a5557f 100644 --- a/libcxx/test/std/containers/sequences/vector.bool/iterators.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector.bool/iterators.pass.cpp @@ -22,7 +22,7 @@ #include "test_macros.h" #include "min_allocator.h" -int main(int, char**) +TEST_CONSTEXPR_CXX20 bool tests() { using IterRefT = std::iterator_traits::iterator>::reference; ASSERT_SAME_TYPE(IterRefT, std::vector::reference); @@ -66,6 +66,8 @@ int main(int, char**) typedef std::vector C; C::iterator i; C::const_iterator j; + (void) i; + (void) j; } #if TEST_STD_VER >= 11 { @@ -101,6 +103,8 @@ int main(int, char**) typedef std::vector> C; C::iterator i; C::const_iterator j; + (void) i; + (void) j; } #endif #if TEST_STD_VER > 11 @@ -130,5 +134,14 @@ int main(int, char**) } #endif - return 0; + return true; +} + +int main(int, char**) +{ + tests(); +#if TEST_STD_VER > 17 + static_assert(tests()); +#endif + return 0; } diff --git a/libcxx/test/std/containers/sequences/vector.bool/move.pass.cpp b/libcxx/test/std/containers/sequences/vector.bool/move.pass.cpp index a554ec8ab0162..0e65d9896f402 100644 --- a/libcxx/test/std/containers/sequences/vector.bool/move.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector.bool/move.pass.cpp @@ -18,7 +18,7 @@ #include "test_allocator.h" #include "min_allocator.h" -int main(int, char**) +TEST_CONSTEXPR_CXX20 bool tests() { test_allocator_statistics alloc_stats; { @@ -91,5 +91,14 @@ int main(int, char**) } } - return 0; + return true; +} + +int main(int, char**) +{ + tests(); +#if TEST_STD_VER > 17 + static_assert(tests()); +#endif + return 0; } diff --git a/libcxx/test/std/containers/sequences/vector.bool/move_alloc.pass.cpp b/libcxx/test/std/containers/sequences/vector.bool/move_alloc.pass.cpp index f7e2865089d7b..1f41657eb56ea 100644 --- a/libcxx/test/std/containers/sequences/vector.bool/move_alloc.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector.bool/move_alloc.pass.cpp @@ -18,7 +18,7 @@ #include "test_allocator.h" #include "min_allocator.h" -int main(int, char**) +TEST_CONSTEXPR_CXX20 bool tests() { { std::vector > l(test_allocator(5)); @@ -73,5 +73,14 @@ int main(int, char**) assert(l2.get_allocator() == min_allocator()); } - return 0; + return true; +} + +int main(int, char**) +{ + tests(); +#if TEST_STD_VER > 17 + static_assert(tests()); +#endif + return 0; } diff --git a/libcxx/test/std/containers/sequences/vector.bool/op_equal_initializer_list.pass.cpp b/libcxx/test/std/containers/sequences/vector.bool/op_equal_initializer_list.pass.cpp index efa6ca183adc2..618357120c6bd 100644 --- a/libcxx/test/std/containers/sequences/vector.bool/op_equal_initializer_list.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector.bool/op_equal_initializer_list.pass.cpp @@ -18,7 +18,7 @@ #include "test_macros.h" #include "min_allocator.h" -int main(int, char**) +TEST_CONSTEXPR_CXX20 bool tests() { { std::vector d; @@ -39,5 +39,14 @@ int main(int, char**) assert(d[3] == true); } - return 0; + return true; +} + +int main(int, char**) +{ + tests(); +#if TEST_STD_VER > 17 + static_assert(tests()); +#endif + return 0; } diff --git a/libcxx/test/std/containers/sequences/vector.bool/push_back.pass.cpp b/libcxx/test/std/containers/sequences/vector.bool/push_back.pass.cpp index b49dd1151b284..25f8fb6b29dfe 100644 --- a/libcxx/test/std/containers/sequences/vector.bool/push_back.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector.bool/push_back.pass.cpp @@ -18,7 +18,7 @@ #include "test_macros.h" #include "min_allocator.h" -int main(int, char**) +TEST_CONSTEXPR_CXX20 bool tests() { { bool a[] = {0, 1, 1, 0, 1, 0, 0}; @@ -47,5 +47,14 @@ int main(int, char**) } #endif - return 0; + return true; +} + +int main(int, char**) +{ + tests(); +#if TEST_STD_VER > 17 + static_assert(tests()); +#endif + return 0; } diff --git a/libcxx/test/std/containers/sequences/vector.bool/reference.swap.pass.cpp b/libcxx/test/std/containers/sequences/vector.bool/reference.swap.pass.cpp index c41bac188364c..8879d1f1d358c 100644 --- a/libcxx/test/std/containers/sequences/vector.bool/reference.swap.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector.bool/reference.swap.pass.cpp @@ -16,7 +16,7 @@ #include "test_macros.h" -int main(int, char**) +TEST_CONSTEXPR_CXX20 bool tests() { bool a[] = {false, true, false, true}; @@ -36,5 +36,14 @@ int main(int, char**) assert( r1); assert(!r2); - return 0; + return true; +} + +int main(int, char**) +{ + tests(); +#if TEST_STD_VER > 17 + static_assert(tests()); +#endif + return 0; } diff --git a/libcxx/test/std/containers/sequences/vector.bool/reference/assign_bool.pass.cpp b/libcxx/test/std/containers/sequences/vector.bool/reference/assign_bool.pass.cpp index ae2305a9195e8..64dcc3c608214 100644 --- a/libcxx/test/std/containers/sequences/vector.bool/reference/assign_bool.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector.bool/reference/assign_bool.pass.cpp @@ -15,7 +15,7 @@ #include "test_macros.h" -bool test() { +TEST_CONSTEXPR_CXX20 bool test() { std::vector vec; typedef std::vector::reference Ref; vec.push_back(true); @@ -47,6 +47,9 @@ bool test() { int main(int, char**) { test(); +#if TEST_STD_VER > 17 + static_assert(test()); +#endif return 0; } diff --git a/libcxx/test/std/containers/sequences/vector.bool/reference/assign_copy.pass.cpp b/libcxx/test/std/containers/sequences/vector.bool/reference/assign_copy.pass.cpp index d56342a9e9f56..bcccb20318ded 100644 --- a/libcxx/test/std/containers/sequences/vector.bool/reference/assign_copy.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector.bool/reference/assign_copy.pass.cpp @@ -13,7 +13,9 @@ #include #include -bool test() { +#include "test_macros.h" + +TEST_CONSTEXPR_CXX20 bool test() { std::vector vec; typedef std::vector::reference Ref; vec.push_back(true); @@ -71,6 +73,9 @@ bool test() { int main(int, char**) { test(); +#if TEST_STD_VER > 17 + static_assert(test()); +#endif return 0; } diff --git a/libcxx/test/std/containers/sequences/vector.bool/reference/ctor_copy.pass.cpp b/libcxx/test/std/containers/sequences/vector.bool/reference/ctor_copy.pass.cpp index 0348b47bc2603..46ac18ab493b7 100644 --- a/libcxx/test/std/containers/sequences/vector.bool/reference/ctor_copy.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector.bool/reference/ctor_copy.pass.cpp @@ -13,7 +13,9 @@ #include #include -bool test() { +#include "test_macros.h" + +TEST_CONSTEXPR_CXX20 bool test() { std::vector vec; typedef std::vector::reference Ref; vec.push_back(true); @@ -28,6 +30,9 @@ bool test() { int main(int, char**) { test(); +#if TEST_STD_VER > 17 + static_assert(test()); +#endif return 0; } diff --git a/libcxx/test/std/containers/sequences/vector.bool/reference/flip.pass.cpp b/libcxx/test/std/containers/sequences/vector.bool/reference/flip.pass.cpp index 8890fbfbb4df0..080975656ac9e 100644 --- a/libcxx/test/std/containers/sequences/vector.bool/reference/flip.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector.bool/reference/flip.pass.cpp @@ -13,7 +13,9 @@ #include #include -bool test() { +#include "test_macros.h" + +TEST_CONSTEXPR_CXX20 bool test() { std::vector vec; typedef std::vector::reference Ref; vec.push_back(true); @@ -33,6 +35,9 @@ bool test() { int main(int, char**) { test(); +#if TEST_STD_VER > 17 + static_assert(test()); +#endif return 0; } diff --git a/libcxx/test/std/containers/sequences/vector.bool/reference/operator_bool.pass.cpp b/libcxx/test/std/containers/sequences/vector.bool/reference/operator_bool.pass.cpp index 8d9d616199deb..02abd0e6be766 100644 --- a/libcxx/test/std/containers/sequences/vector.bool/reference/operator_bool.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector.bool/reference/operator_bool.pass.cpp @@ -14,7 +14,9 @@ #include #include -bool test() { +#include "test_macros.h" + +TEST_CONSTEXPR_CXX20 bool test() { std::vector vec; typedef std::vector::reference Ref; static_assert(std::is_convertible::value, ""); @@ -33,6 +35,9 @@ bool test() { int main(int, char**) { test(); +#if TEST_STD_VER > 17 + static_assert(test()); +#endif return 0; } diff --git a/libcxx/test/std/containers/sequences/vector.bool/reserve.pass.cpp b/libcxx/test/std/containers/sequences/vector.bool/reserve.pass.cpp index 6b9ceca2b1882..e179fb95aac22 100644 --- a/libcxx/test/std/containers/sequences/vector.bool/reserve.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector.bool/reserve.pass.cpp @@ -19,7 +19,7 @@ #include "min_allocator.h" #include "test_allocator.h" -int main(int, char**) +TEST_CONSTEXPR_CXX20 bool tests() { { std::vector v; @@ -59,7 +59,7 @@ int main(int, char**) } #endif #ifndef TEST_HAS_NO_EXCEPTIONS - { + if (!TEST_IS_CONSTANT_EVALUATED) { std::vector > v; v.reserve(5); try { @@ -76,5 +76,14 @@ int main(int, char**) } #endif - return 0; + return true; +} + +int main(int, char**) +{ + tests(); +#if TEST_STD_VER > 17 + static_assert(tests()); +#endif + return 0; } diff --git a/libcxx/test/std/containers/sequences/vector.bool/resize_size.pass.cpp b/libcxx/test/std/containers/sequences/vector.bool/resize_size.pass.cpp index d032247a97a87..ef83dbf0a9741 100644 --- a/libcxx/test/std/containers/sequences/vector.bool/resize_size.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector.bool/resize_size.pass.cpp @@ -17,7 +17,7 @@ #include "test_macros.h" #include "min_allocator.h" -int main(int, char**) +TEST_CONSTEXPR_CXX20 bool tests() { { std::vector v(100); @@ -54,5 +54,14 @@ int main(int, char**) } #endif - return 0; + return true; +} + +int main(int, char**) +{ + tests(); +#if TEST_STD_VER > 17 + static_assert(tests()); +#endif + return 0; } diff --git a/libcxx/test/std/containers/sequences/vector.bool/resize_size_value.pass.cpp b/libcxx/test/std/containers/sequences/vector.bool/resize_size_value.pass.cpp index 9cc7e2c98d70c..fa7ae3d3420a4 100644 --- a/libcxx/test/std/containers/sequences/vector.bool/resize_size_value.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector.bool/resize_size_value.pass.cpp @@ -17,7 +17,7 @@ #include "test_macros.h" #include "min_allocator.h" -int main(int, char**) +TEST_CONSTEXPR_CXX20 bool tests() { { std::vector v(100); @@ -50,5 +50,14 @@ int main(int, char**) } #endif - return 0; + return true; +} + +int main(int, char**) +{ + tests(); +#if TEST_STD_VER > 17 + static_assert(tests()); +#endif + return 0; } diff --git a/libcxx/test/std/containers/sequences/vector.bool/shrink_to_fit.pass.cpp b/libcxx/test/std/containers/sequences/vector.bool/shrink_to_fit.pass.cpp index 7ec8e66fbea45..b39245cab7bf4 100644 --- a/libcxx/test/std/containers/sequences/vector.bool/shrink_to_fit.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector.bool/shrink_to_fit.pass.cpp @@ -17,7 +17,7 @@ #include "test_macros.h" #include "min_allocator.h" -int main(int, char**) +TEST_CONSTEXPR_CXX20 bool tests() { { std::vector v(100); @@ -36,5 +36,14 @@ int main(int, char**) } #endif - return 0; + return true; +} + +int main(int, char**) +{ + tests(); +#if TEST_STD_VER > 17 + static_assert(tests()); +#endif + return 0; } diff --git a/libcxx/test/std/containers/sequences/vector.bool/size.pass.cpp b/libcxx/test/std/containers/sequences/vector.bool/size.pass.cpp index db737c930c359..33f8b72dd4722 100644 --- a/libcxx/test/std/containers/sequences/vector.bool/size.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector.bool/size.pass.cpp @@ -18,7 +18,7 @@ #include "test_macros.h" #include "min_allocator.h" -int main(int, char**) +TEST_CONSTEXPR_CXX20 bool tests() { { typedef std::vector C; @@ -59,5 +59,14 @@ int main(int, char**) } #endif - return 0; + return true; +} + +int main(int, char**) +{ + tests(); +#if TEST_STD_VER > 17 + static_assert(tests()); +#endif + return 0; } diff --git a/libcxx/test/std/containers/sequences/vector.bool/swap.pass.cpp b/libcxx/test/std/containers/sequences/vector.bool/swap.pass.cpp index 6dbd08cea9520..edd28ef308471 100644 --- a/libcxx/test/std/containers/sequences/vector.bool/swap.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector.bool/swap.pass.cpp @@ -17,7 +17,7 @@ #include "test_allocator.h" #include "min_allocator.h" -int main(int, char**) +TEST_CONSTEXPR_CXX20 bool tests() { { std::vector v1(100); @@ -96,5 +96,14 @@ int main(int, char**) } #endif - return 0; + return true; +} + +int main(int, char**) +{ + tests(); +#if TEST_STD_VER > 17 + static_assert(tests()); +#endif + return 0; } diff --git a/libcxx/test/std/containers/sequences/vector.bool/vector_bool.pass.cpp b/libcxx/test/std/containers/sequences/vector.bool/vector_bool.pass.cpp index 04380c9764e7d..b927f2a4dbdde 100644 --- a/libcxx/test/std/containers/sequences/vector.bool/vector_bool.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector.bool/vector_bool.pass.cpp @@ -24,7 +24,7 @@ #include "test_macros.h" #include "min_allocator.h" -int main(int, char**) +TEST_CONSTEXPR_CXX20 bool tests() { { typedef std::vector T; @@ -56,5 +56,14 @@ int main(int, char**) } #endif - return 0; + return true; +} + +int main(int, char**) +{ + tests(); +#if TEST_STD_VER > 17 + static_assert(tests()); +#endif + return 0; } diff --git a/libcxx/test/std/containers/sequences/vector/access.pass.cpp b/libcxx/test/std/containers/sequences/vector/access.pass.cpp index 27d6e319460fb..5989f1e037fd3 100644 --- a/libcxx/test/std/containers/sequences/vector/access.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector/access.pass.cpp @@ -29,9 +29,7 @@ #include "test_macros.h" template -C -make(int size, int start) -{ +TEST_CONSTEXPR_CXX20 C make(int size, int start) { C c; for (int i = 0; i < size; ++i) c.push_back(start + i); @@ -39,7 +37,7 @@ make(int size, int start) } template -void test_get_basic(Vector& c, int start_value) { +TEST_CONSTEXPR_CXX20 void test_get_basic(Vector& c, int start_value) { const int n = static_cast(c.size()); for (int i = 0; i < n; ++i) assert(c[i] == start_value + i); @@ -47,10 +45,12 @@ void test_get_basic(Vector& c, int start_value) { assert(c.at(i) == start_value + i); #ifndef TEST_HAS_NO_EXCEPTIONS - try { - TEST_IGNORE_NODISCARD c.at(n); - assert(false); - } catch (const std::out_of_range&) {} + if (!TEST_IS_CONSTANT_EVALUATED) { + try { + TEST_IGNORE_NODISCARD c.at(n); + assert(false); + } catch (const std::out_of_range&) {} + } #endif assert(c.front() == start_value); @@ -58,7 +58,7 @@ void test_get_basic(Vector& c, int start_value) { } template -void test_get() { +TEST_CONSTEXPR_CXX20 void test_get() { int start_value = 35; Vector c = make(10, start_value); const Vector& cc = c; @@ -67,7 +67,7 @@ void test_get() { } template -void test_set() { +TEST_CONSTEXPR_CXX20 void test_set() { int start_value = 35; const int n = 10; Vector c = make(n, start_value); @@ -93,7 +93,7 @@ void test_set() { } template -void test() { +TEST_CONSTEXPR_CXX20 void test() { test_get(); test_set(); @@ -112,12 +112,18 @@ void test() { ASSERT_SAME_TYPE(typename Vector::const_reference, decltype(cc.back())); } -int main(int, char**) -{ +TEST_CONSTEXPR_CXX20 bool tests() { test >(); #if TEST_STD_VER >= 11 test > >(); #endif + return true; +} - return 0; +int main(int, char**) { + tests(); +#if TEST_STD_VER > 17 + static_assert(tests()); +#endif + return 0; } diff --git a/libcxx/test/std/containers/sequences/vector/compare.pass.cpp b/libcxx/test/std/containers/sequences/vector/compare.pass.cpp index 21ffb9296fa52..917095e1f138d 100644 --- a/libcxx/test/std/containers/sequences/vector/compare.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector/compare.pass.cpp @@ -20,7 +20,7 @@ #include "test_comparisons.h" -int main(int, char**) { +TEST_CONSTEXPR_CXX20 bool test() { { const std::vector c1, c2; assert(testComparisons(c1, c2, true, false)); @@ -116,5 +116,14 @@ int main(int, char**) { assert((std::vector() >= std::vector())); } + return true; +} + +int main(int, char**) { + test(); +#if TEST_STD_VER > 17 + static_assert(test()); +#endif + return 0; } diff --git a/libcxx/test/std/containers/sequences/vector/constant_initialization.pass.cpp b/libcxx/test/std/containers/sequences/vector/constant_initialization.pass.cpp new file mode 100644 index 0000000000000..7a23a2d478a23 --- /dev/null +++ b/libcxx/test/std/containers/sequences/vector/constant_initialization.pass.cpp @@ -0,0 +1,23 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// XFAIL: libcpp-has-debug-mode + +#include +#include + +std::vector ca_allocs; + +int main(int, char**) { + ca_allocs.push_back(0); + for ([[maybe_unused]] const auto& a : ca_allocs) + ; + + return 0; +} diff --git a/libcxx/test/std/containers/sequences/vector/contiguous.pass.cpp b/libcxx/test/std/containers/sequences/vector/contiguous.pass.cpp index 21b90a698842e..d9f557e6c9770 100644 --- a/libcxx/test/std/containers/sequences/vector/contiguous.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector/contiguous.pass.cpp @@ -18,13 +18,13 @@ #include "min_allocator.h" template -void test_contiguous ( const C &c ) +TEST_CONSTEXPR_CXX20 void test_contiguous(const C &c) { for ( size_t i = 0; i < c.size(); ++i ) assert ( *(c.begin() + static_cast(i)) == *(std::addressof(*c.begin()) + i)); } -int main(int, char**) +TEST_CONSTEXPR_CXX20 bool tests() { { typedef int T; @@ -50,5 +50,14 @@ int main(int, char**) } #endif - return 0; + return true; +} + +int main(int, char**) +{ + tests(); +#if TEST_STD_VER > 17 + static_assert(tests()); +#endif + return 0; } diff --git a/libcxx/test/std/containers/sequences/vector/get_allocator.pass.cpp b/libcxx/test/std/containers/sequences/vector/get_allocator.pass.cpp index 3734893bfc570..c0003acae75ef 100644 --- a/libcxx/test/std/containers/sequences/vector/get_allocator.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector/get_allocator.pass.cpp @@ -18,7 +18,7 @@ #include "test_allocator.h" #include "test_macros.h" -int main(int, char**) { +TEST_CONSTEXPR_CXX20 bool test() { { std::allocator alloc; const std::vector v(alloc); @@ -30,5 +30,14 @@ int main(int, char**) { assert(v.get_allocator() == alloc); } + return true; +} + +int main(int, char**) { + test(); +#if TEST_STD_VER > 17 + static_assert(test()); +#endif + return 0; } diff --git a/libcxx/test/std/containers/sequences/vector/iterators.pass.cpp b/libcxx/test/std/containers/sequences/vector/iterators.pass.cpp index 296c551f76f67..70e0e35767e09 100644 --- a/libcxx/test/std/containers/sequences/vector/iterators.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector/iterators.pass.cpp @@ -28,7 +28,7 @@ struct A int second; }; -int main(int, char**) +TEST_CONSTEXPR_CXX20 bool tests() { { typedef int T; @@ -167,5 +167,14 @@ int main(int, char**) } #endif - return 0; + return true; +} + +int main(int, char**) +{ + tests(); +#if TEST_STD_VER > 17 + static_assert(tests()); +#endif + return 0; } diff --git a/libcxx/test/std/containers/sequences/vector/reverse_iterators.pass.cpp b/libcxx/test/std/containers/sequences/vector/reverse_iterators.pass.cpp index c2b5d4d481e54..1591f912f3372 100644 --- a/libcxx/test/std/containers/sequences/vector/reverse_iterators.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector/reverse_iterators.pass.cpp @@ -22,7 +22,7 @@ #include "min_allocator.h" template -void check_vector_reverse_iterators() { +TEST_CONSTEXPR_CXX20 void check_vector_reverse_iterators() { { Vector vec; assert(vec.rbegin() == vec.rend()); @@ -67,11 +67,20 @@ void check_vector_reverse_iterators() { } } -int main(int, char**) { +TEST_CONSTEXPR_CXX20 bool test() { check_vector_reverse_iterators >(); #if TEST_STD_VER >= 11 check_vector_reverse_iterators > >(); #endif + return true; +} + +int main(int, char**) { + test(); +#if TEST_STD_VER > 17 + static_assert(test()); +#endif + return 0; } diff --git a/libcxx/test/std/containers/sequences/vector/vector.capacity/capacity.pass.cpp b/libcxx/test/std/containers/sequences/vector/vector.capacity/capacity.pass.cpp index 41d885f250e03..b2eb33c6c5f53 100644 --- a/libcxx/test/std/containers/sequences/vector/vector.capacity/capacity.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector/vector.capacity/capacity.pass.cpp @@ -17,7 +17,7 @@ #include "min_allocator.h" #include "asan_testing.h" -int main(int, char**) +TEST_CONSTEXPR_CXX20 bool tests() { { std::vector v; @@ -46,5 +46,14 @@ int main(int, char**) } #endif - return 0; + return true; +} + +int main(int, char**) +{ + tests(); +#if TEST_STD_VER > 17 + static_assert(tests()); +#endif + return 0; } diff --git a/libcxx/test/std/containers/sequences/vector/vector.capacity/empty.pass.cpp b/libcxx/test/std/containers/sequences/vector/vector.capacity/empty.pass.cpp index cce2602bd360b..cc5f3bc90a670 100644 --- a/libcxx/test/std/containers/sequences/vector/vector.capacity/empty.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector/vector.capacity/empty.pass.cpp @@ -18,8 +18,7 @@ #include "test_macros.h" #include "min_allocator.h" -int main(int, char**) -{ +TEST_CONSTEXPR_CXX20 bool tests() { { typedef std::vector C; C c; @@ -43,5 +42,14 @@ int main(int, char**) } #endif - return 0; + return true; +} + +int main(int, char**) +{ + tests(); +#if TEST_STD_VER > 17 + static_assert(tests()); +#endif + return 0; } diff --git a/libcxx/test/std/containers/sequences/vector/vector.capacity/max_size.pass.cpp b/libcxx/test/std/containers/sequences/vector/vector.capacity/max_size.pass.cpp index c9cc6d5821c4f..3f8d62e2f2d6b 100644 --- a/libcxx/test/std/containers/sequences/vector/vector.capacity/max_size.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector/vector.capacity/max_size.pass.cpp @@ -19,7 +19,7 @@ #include "test_macros.h" -int main(int, char**) { +TEST_CONSTEXPR_CXX20 bool test() { { typedef limited_allocator A; typedef std::vector C; @@ -45,5 +45,15 @@ int main(int, char**) { assert(c.max_size() <= alloc_max_size(c.get_allocator())); } + return true; +} + +int main(int, char**) { + test(); + +#if TEST_STD_VER > 17 + static_assert(test()); +#endif + return 0; } diff --git a/libcxx/test/std/containers/sequences/vector/vector.capacity/reserve.pass.cpp b/libcxx/test/std/containers/sequences/vector/vector.capacity/reserve.pass.cpp index 3f4aadae3a2fa..99c489601b0f5 100644 --- a/libcxx/test/std/containers/sequences/vector/vector.capacity/reserve.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector/vector.capacity/reserve.pass.cpp @@ -18,8 +18,7 @@ #include "min_allocator.h" #include "asan_testing.h" -int main(int, char**) -{ +TEST_CONSTEXPR_CXX20 bool tests() { { std::vector v; v.reserve(10); @@ -50,7 +49,7 @@ int main(int, char**) assert(is_contiguous_container_asan_correct(v)); } #ifndef TEST_HAS_NO_EXCEPTIONS - { + if (!TEST_IS_CONSTANT_EVALUATED) { std::vector v; size_t sz = v.max_size() + 1; @@ -62,7 +61,7 @@ int main(int, char**) assert(v.capacity() == 0); } } - { + if (!TEST_IS_CONSTANT_EVALUATED) { std::vector v(10, 42); int* previous_data = v.data(); size_t previous_capacity = v.capacity(); @@ -102,7 +101,7 @@ int main(int, char**) } #endif #ifndef TEST_HAS_NO_EXCEPTIONS - { + if (!TEST_IS_CONSTANT_EVALUATED) { std::vector > v; v.reserve(50); assert(v.capacity() == 50); @@ -118,5 +117,16 @@ int main(int, char**) } #endif + return true; +} + +int main(int, char**) +{ + tests(); + +#if TEST_STD_VER > 17 + static_assert(tests()); +#endif + return 0; } diff --git a/libcxx/test/std/containers/sequences/vector/vector.capacity/resize_size.pass.cpp b/libcxx/test/std/containers/sequences/vector/vector.capacity/resize_size.pass.cpp index 41188acb7d893..0b9db8e691c08 100644 --- a/libcxx/test/std/containers/sequences/vector/vector.capacity/resize_size.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector/vector.capacity/resize_size.pass.cpp @@ -19,8 +19,7 @@ #include "min_allocator.h" #include "asan_testing.h" -int main(int, char**) -{ +TEST_CONSTEXPR_CXX20 bool tests() { { std::vector v(100); v.resize(50); @@ -81,5 +80,16 @@ int main(int, char**) } #endif + return true; +} + +int main(int, char**) +{ + tests(); + +#if TEST_STD_VER > 17 + static_assert(tests()); +#endif + return 0; } diff --git a/libcxx/test/std/containers/sequences/vector/vector.capacity/resize_size_value.pass.cpp b/libcxx/test/std/containers/sequences/vector/vector.capacity/resize_size_value.pass.cpp index 726ff8a7abef8..c0197982b4a45 100644 --- a/libcxx/test/std/containers/sequences/vector/vector.capacity/resize_size_value.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector/vector.capacity/resize_size_value.pass.cpp @@ -17,8 +17,7 @@ #include "min_allocator.h" #include "asan_testing.h" -int main(int, char**) -{ +TEST_CONSTEXPR_CXX20 bool tests() { { std::vector v(100); v.resize(50, 1); @@ -75,5 +74,14 @@ int main(int, char**) } #endif - return 0; + return true; +} + +int main(int, char**) +{ + tests(); +#if TEST_STD_VER > 17 + static_assert(tests()); +#endif + return 0; } diff --git a/libcxx/test/std/containers/sequences/vector/vector.capacity/shrink_to_fit.pass.cpp b/libcxx/test/std/containers/sequences/vector/vector.capacity/shrink_to_fit.pass.cpp index feb706653ca83..3f2487948430d 100644 --- a/libcxx/test/std/containers/sequences/vector/vector.capacity/shrink_to_fit.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector/vector.capacity/shrink_to_fit.pass.cpp @@ -17,8 +17,7 @@ #include "min_allocator.h" #include "asan_testing.h" -int main(int, char**) -{ +TEST_CONSTEXPR_CXX20 bool tests() { { std::vector v(100); v.push_back(1); @@ -38,7 +37,7 @@ int main(int, char**) assert(is_contiguous_container_asan_correct(v)); } #ifndef TEST_HAS_NO_EXCEPTIONS - { + if (!TEST_IS_CONSTANT_EVALUATED) { std::vector > v(100); v.push_back(1); assert(is_contiguous_container_asan_correct(v)); @@ -60,5 +59,14 @@ int main(int, char**) } #endif - return 0; + return true; +} + +int main(int, char**) +{ + tests(); +#if TEST_STD_VER > 17 + static_assert(tests()); +#endif + return 0; } diff --git a/libcxx/test/std/containers/sequences/vector/vector.capacity/size.pass.cpp b/libcxx/test/std/containers/sequences/vector/vector.capacity/size.pass.cpp index 373a7069f3a91..aa41da69b31ab 100644 --- a/libcxx/test/std/containers/sequences/vector/vector.capacity/size.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector/vector.capacity/size.pass.cpp @@ -18,7 +18,7 @@ #include "test_macros.h" #include "min_allocator.h" -int main(int, char**) +TEST_CONSTEXPR_CXX20 bool tests() { { typedef std::vector C; @@ -59,5 +59,14 @@ int main(int, char**) } #endif + return true; +} + +int main(int, char**) +{ + tests(); +#if TEST_STD_VER > 17 + static_assert(tests()); +#endif return 0; } diff --git a/libcxx/test/std/containers/sequences/vector/vector.capacity/swap.pass.cpp b/libcxx/test/std/containers/sequences/vector/vector.capacity/swap.pass.cpp index 33df254c11696..47a0435674136 100644 --- a/libcxx/test/std/containers/sequences/vector/vector.capacity/swap.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector/vector.capacity/swap.pass.cpp @@ -17,8 +17,7 @@ #include "min_allocator.h" #include "asan_testing.h" -int main(int, char**) -{ +TEST_CONSTEXPR_CXX20 bool tests() { { std::vector v1(100); std::vector v2(200); @@ -48,5 +47,14 @@ int main(int, char**) } #endif - return 0; + return true; +} + +int main(int, char**) +{ + tests(); +#if TEST_STD_VER > 17 + static_assert(tests()); +#endif + return 0; } diff --git a/libcxx/test/std/containers/sequences/vector/vector.cons/assign_copy.pass.cpp b/libcxx/test/std/containers/sequences/vector/vector.cons/assign_copy.pass.cpp index a14f90c0525da..f5b461b05a349 100644 --- a/libcxx/test/std/containers/sequences/vector/vector.cons/assign_copy.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector/vector.cons/assign_copy.pass.cpp @@ -17,8 +17,7 @@ #include "min_allocator.h" #include "allocators.h" -int main(int, char**) -{ +TEST_CONSTEXPR_CXX20 bool tests() { { std::vector > l(3, 2, test_allocator(5)); std::vector > l2(l, test_allocator(3)); @@ -81,5 +80,14 @@ int main(int, char**) } #endif - return 0; + return true; +} + +int main(int, char**) +{ + tests(); +#if TEST_STD_VER > 17 + static_assert(tests()); +#endif + return 0; } diff --git a/libcxx/test/std/containers/sequences/vector/vector.cons/assign_initializer_list.pass.cpp b/libcxx/test/std/containers/sequences/vector/vector.cons/assign_initializer_list.pass.cpp index ba5a102d5e053..19a1b77603552 100644 --- a/libcxx/test/std/containers/sequences/vector/vector.cons/assign_initializer_list.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector/vector.cons/assign_initializer_list.pass.cpp @@ -20,7 +20,7 @@ #include "asan_testing.h" template -void test ( Vec &v ) +TEST_CONSTEXPR_CXX20 void test(Vec &v) { v.assign({3, 4, 5, 6}); assert(v.size() == 4); @@ -31,8 +31,7 @@ void test ( Vec &v ) assert(v[3] == 6); } -int main(int, char**) -{ +TEST_CONSTEXPR_CXX20 bool tests() { { typedef std::vector V; V d1; @@ -50,5 +49,14 @@ int main(int, char**) test(d2); } - return 0; + return true; +} + +int main(int, char**) +{ + tests(); +#if TEST_STD_VER > 17 + static_assert(tests()); +#endif + return 0; } diff --git a/libcxx/test/std/containers/sequences/vector/vector.cons/assign_iter_iter.pass.cpp b/libcxx/test/std/containers/sequences/vector/vector.cons/assign_iter_iter.pass.cpp index 6a572fada2c01..4daa320673ba2 100644 --- a/libcxx/test/std/containers/sequences/vector/vector.cons/assign_iter_iter.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector/vector.cons/assign_iter_iter.pass.cpp @@ -23,7 +23,7 @@ #endif -void test() { +TEST_CONSTEXPR_CXX20 bool test() { #if TEST_STD_VER >= 11 int arr1[] = {42}; int arr2[] = {1, 101, 42}; @@ -77,9 +77,14 @@ void test() { dst.assign(It(src.data()), It(src.data() + src.size())); assert(dst == src); } + + return true; } int main(int, char**) { test(); +#if TEST_STD_VER > 17 + static_assert(test()); +#endif return 0; } diff --git a/libcxx/test/std/containers/sequences/vector/vector.cons/assign_move.pass.cpp b/libcxx/test/std/containers/sequences/vector/vector.cons/assign_move.pass.cpp index 3e25dc931f8fa..e6eba51a43bbb 100644 --- a/libcxx/test/std/containers/sequences/vector/vector.cons/assign_move.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector/vector.cons/assign_move.pass.cpp @@ -20,8 +20,7 @@ #include "min_allocator.h" #include "asan_testing.h" -int main(int, char**) -{ +TEST_CONSTEXPR_CXX20 bool tests() { { std::vector > l(test_allocator(5)); std::vector > lo(test_allocator(5)); @@ -97,5 +96,14 @@ int main(int, char**) assert(is_contiguous_container_asan_correct(l2)); } - return 0; + return true; +} + +int main(int, char**) +{ + tests(); +#if TEST_STD_VER > 17 + static_assert(tests()); +#endif + return 0; } diff --git a/libcxx/test/std/containers/sequences/vector/vector.cons/assign_size_value.pass.cpp b/libcxx/test/std/containers/sequences/vector/vector.cons/assign_size_value.pass.cpp index 37e85a1462066..896aa40c0db95 100644 --- a/libcxx/test/std/containers/sequences/vector/vector.cons/assign_size_value.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector/vector.cons/assign_size_value.pass.cpp @@ -18,10 +18,10 @@ #include "min_allocator.h" #include "asan_testing.h" -bool is6(int x) { return x == 6; } +TEST_CONSTEXPR bool is6(int x) { return x == 6; } template -void test ( Vec &v ) +TEST_CONSTEXPR_CXX20 void test(Vec &v) { v.assign(5, 6); assert(v.size() == 5); @@ -29,8 +29,7 @@ void test ( Vec &v ) assert(std::all_of(v.begin(), v.end(), is6)); } -int main(int, char**) -{ +TEST_CONSTEXPR_CXX20 bool tests() { { typedef std::vector V; V d1; @@ -56,5 +55,14 @@ int main(int, char**) } #endif - return 0; + return true; +} + +int main(int, char**) +{ + tests(); +#if TEST_STD_VER > 17 + static_assert(tests()); +#endif + return 0; } diff --git a/libcxx/test/std/containers/sequences/vector/vector.cons/construct_default.pass.cpp b/libcxx/test/std/containers/sequences/vector/vector.cons/construct_default.pass.cpp index 346c357d3f3ed..9a135b64a336c 100644 --- a/libcxx/test/std/containers/sequences/vector/vector.cons/construct_default.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector/vector.cons/construct_default.pass.cpp @@ -22,8 +22,7 @@ #include "asan_testing.h" template -void -test0() +TEST_CONSTEXPR_CXX20 void test0() { #if TEST_STD_VER > 14 static_assert((noexcept(C{})), "" ); @@ -45,8 +44,7 @@ test0() } template -void -test1(const typename C::allocator_type& a) +TEST_CONSTEXPR_CXX20 void test1(const typename C::allocator_type& a) { #if TEST_STD_VER > 14 static_assert((noexcept(C{typename C::allocator_type{}})), "" ); @@ -60,8 +58,7 @@ test1(const typename C::allocator_type& a) LIBCPP_ASSERT(is_contiguous_container_asan_correct(c)); } -int main(int, char**) -{ +TEST_CONSTEXPR_CXX20 bool tests() { { test0 >(); test0 >(); @@ -99,5 +96,14 @@ int main(int, char**) } #endif - return 0; + return true; +} + +int main(int, char**) +{ + tests(); +#if TEST_STD_VER > 17 + static_assert(tests()); +#endif + return 0; } diff --git a/libcxx/test/std/containers/sequences/vector/vector.cons/construct_iter_iter.pass.cpp b/libcxx/test/std/containers/sequences/vector/vector.cons/construct_iter_iter.pass.cpp index c7702d9f3d166..0f2fb36aaa67a 100644 --- a/libcxx/test/std/containers/sequences/vector/vector.cons/construct_iter_iter.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector/vector.cons/construct_iter_iter.pass.cpp @@ -25,7 +25,7 @@ #endif template -void test(Iterator first, Iterator last) { +TEST_CONSTEXPR_CXX20 void test(Iterator first, Iterator last) { { C c(first, last); LIBCPP_ASSERT(c.__invariants()); @@ -44,7 +44,7 @@ void test(Iterator first, Iterator last) { } } -static void basic_test_cases() { +TEST_CONSTEXPR_CXX20 void basic_test_cases() { int a[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 8, 7, 6, 5, 4, 3, 1, 0}; int* an = a + sizeof(a) / sizeof(a[0]); test >(cpp17_input_iterator(a), @@ -84,7 +84,7 @@ static void basic_test_cases() { #endif } -void emplaceable_concept_tests() { +TEST_CONSTEXPR_CXX20 void emplaceable_concept_tests() { #if TEST_STD_VER >= 11 int arr1[] = {42}; int arr2[] = {1, 101, 42}; @@ -160,7 +160,7 @@ struct B2 { int y; }; struct Der : B1, B2 { int z; }; // Initialize a vector with a different value type. -void test_ctor_with_different_value_type() { +TEST_CONSTEXPR_CXX20 void test_ctor_with_different_value_type() { { // Make sure initialization is performed with each element value, not with // a memory blob. @@ -189,12 +189,20 @@ void test_ctor_with_different_value_type() { } } - -int main(int, char**) { +TEST_CONSTEXPR_CXX20 bool tests() { basic_test_cases(); emplaceable_concept_tests(); // See PR34898 - test_ctor_under_alloc(); test_ctor_with_different_value_type(); - return 0; + return true; +} + +int main(int, char**) +{ + tests(); + test_ctor_under_alloc(); +#if TEST_STD_VER > 17 + static_assert(tests()); +#endif + return 0; } diff --git a/libcxx/test/std/containers/sequences/vector/vector.cons/construct_iter_iter_alloc.pass.cpp b/libcxx/test/std/containers/sequences/vector/vector.cons/construct_iter_iter_alloc.pass.cpp index ff68c56ac671e..5d38543963e5c 100644 --- a/libcxx/test/std/containers/sequences/vector/vector.cons/construct_iter_iter_alloc.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector/vector.cons/construct_iter_iter_alloc.pass.cpp @@ -26,7 +26,7 @@ #endif template -void test(Iterator first, Iterator last, const A& a) { +TEST_CONSTEXPR_CXX20 void test(Iterator first, Iterator last, const A& a) { C c(first, last, a); LIBCPP_ASSERT(c.__invariants()); assert(c.size() == static_cast(std::distance(first, last))); @@ -40,16 +40,16 @@ void test(Iterator first, Iterator last, const A& a) { template struct implicit_conv_allocator : min_allocator { - implicit_conv_allocator(void*) {} - implicit_conv_allocator(const implicit_conv_allocator&) = default; + TEST_CONSTEXPR implicit_conv_allocator(void*) {} + TEST_CONSTEXPR implicit_conv_allocator(const implicit_conv_allocator&) = default; template - implicit_conv_allocator(implicit_conv_allocator) {} + TEST_CONSTEXPR implicit_conv_allocator(implicit_conv_allocator) {} }; #endif -void basic_tests() { +TEST_CONSTEXPR_CXX20 void basic_tests() { { int a[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 8, 7, 6, 5, 4, 3, 1, 0}; int* an = a + sizeof(a) / sizeof(a[0]); @@ -86,7 +86,7 @@ void basic_tests() { #endif } -void emplaceable_concept_tests() { +TEST_CONSTEXPR_CXX20 void emplaceable_concept_tests() { #if TEST_STD_VER >= 11 int arr1[] = {42}; int arr2[] = {1, 101, 42}; @@ -162,9 +162,18 @@ void test_ctor_under_alloc() { #endif } -int main(int, char**) { +TEST_CONSTEXPR_CXX20 bool test() { basic_tests(); emplaceable_concept_tests(); // See PR34898 + + return true; +} + +int main(int, char**) { + test(); +#if TEST_STD_VER > 17 + static_assert(test()); +#endif test_ctor_under_alloc(); return 0; diff --git a/libcxx/test/std/containers/sequences/vector/vector.cons/construct_size.pass.cpp b/libcxx/test/std/containers/sequences/vector/vector.cons/construct_size.pass.cpp index a06031c564d8b..e4b1f431ae491 100644 --- a/libcxx/test/std/containers/sequences/vector/vector.cons/construct_size.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector/vector.cons/construct_size.pass.cpp @@ -21,6 +21,7 @@ #include "asan_testing.h" template +TEST_CONSTEXPR_CXX20 void test(typename C::size_type n, typename C::allocator_type const& a = typename C::allocator_type()) { @@ -52,24 +53,33 @@ void test(typename C::size_type n, #endif } -void tests() { +TEST_CONSTEXPR_CXX20 bool tests() { test >(0); test >(50); +#if TEST_STD_VER >= 11 + test>>(0); + test>>(50); +#endif + + return true; +} + +int main(int, char**) { + tests(); +#if TEST_STD_VER > 17 + static_assert(tests()); +#endif test >(0); test >(500); assert(DefaultOnly::count == 0); + #if TEST_STD_VER >= 11 - test>>(0); - test>>(50); test>>(0); test>>(500); test>>(0, test_allocator(23)); test>>(100, test_allocator(23)); assert(DefaultOnly::count == 0); #endif -} -int main(int, char**) { - tests(); return 0; } diff --git a/libcxx/test/std/containers/sequences/vector/vector.cons/construct_size_value.pass.cpp b/libcxx/test/std/containers/sequences/vector/vector.cons/construct_size_value.pass.cpp index 2f71c35ebc32f..7f7777c2c97dc 100644 --- a/libcxx/test/std/containers/sequences/vector/vector.cons/construct_size_value.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector/vector.cons/construct_size_value.pass.cpp @@ -19,7 +19,7 @@ #include "asan_testing.h" template -void +TEST_CONSTEXPR_CXX20 void test(typename C::size_type n, const typename C::value_type& x) { C c(n, x); @@ -30,8 +30,7 @@ test(typename C::size_type n, const typename C::value_type& x) assert(*i == x); } -int main(int, char**) -{ +TEST_CONSTEXPR_CXX20 bool tests() { test >(0, 3); test >(50, 3); // Add 1 for implementations that dynamically allocate a container proxy. @@ -43,5 +42,14 @@ int main(int, char**) test> >(50, 3); #endif - return 0; + return true; +} + +int main(int, char**) +{ + tests(); +#if TEST_STD_VER > 17 + static_assert(tests()); +#endif + return 0; } diff --git a/libcxx/test/std/containers/sequences/vector/vector.cons/construct_size_value_alloc.pass.cpp b/libcxx/test/std/containers/sequences/vector/vector.cons/construct_size_value_alloc.pass.cpp index 0db579fd22ce9..17d3a5876bc5b 100644 --- a/libcxx/test/std/containers/sequences/vector/vector.cons/construct_size_value_alloc.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector/vector.cons/construct_size_value_alloc.pass.cpp @@ -18,7 +18,7 @@ #include "asan_testing.h" template -void +TEST_CONSTEXPR_CXX20 void test(typename C::size_type n, const typename C::value_type& x, const typename C::allocator_type& a) { @@ -31,8 +31,7 @@ test(typename C::size_type n, const typename C::value_type& x, assert(*i == x); } -int main(int, char**) -{ +TEST_CONSTEXPR_CXX20 bool tests() { test >(0, 3, std::allocator()); test >(50, 3, std::allocator()); #if TEST_STD_VER >= 11 @@ -40,5 +39,14 @@ int main(int, char**) test> >(50, 3, min_allocator()); #endif - return 0; + return true; +} + +int main(int, char**) +{ + tests(); +#if TEST_STD_VER > 17 + static_assert(tests()); +#endif + return 0; } diff --git a/libcxx/test/std/containers/sequences/vector/vector.cons/copy.pass.cpp b/libcxx/test/std/containers/sequences/vector/vector.cons/copy.pass.cpp index b2553f9bdf922..88822e9c18357 100644 --- a/libcxx/test/std/containers/sequences/vector/vector.cons/copy.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector/vector.cons/copy.pass.cpp @@ -19,7 +19,7 @@ #include "asan_testing.h" template -void +TEST_CONSTEXPR_CXX20 void test(const C& x) { typename C::size_type s = x.size(); @@ -30,8 +30,7 @@ test(const C& x) LIBCPP_ASSERT(is_contiguous_container_asan_correct(c)); } -int main(int, char**) -{ +TEST_CONSTEXPR_CXX20 bool tests() { { int a[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 8, 7, 6, 5, 4, 3, 1, 0}; int* an = a + sizeof(a)/sizeof(a[0]); @@ -87,5 +86,14 @@ int main(int, char**) } #endif - return 0; + return true; +} + +int main(int, char**) +{ + tests(); +#if TEST_STD_VER > 17 + static_assert(tests()); +#endif + return 0; } diff --git a/libcxx/test/std/containers/sequences/vector/vector.cons/copy_alloc.pass.cpp b/libcxx/test/std/containers/sequences/vector/vector.cons/copy_alloc.pass.cpp index 1f07855165155..70434bcfc578c 100644 --- a/libcxx/test/std/containers/sequences/vector/vector.cons/copy_alloc.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector/vector.cons/copy_alloc.pass.cpp @@ -19,7 +19,7 @@ #include "asan_testing.h" template -void +TEST_CONSTEXPR_CXX20 void test(const C& x, const typename C::allocator_type& a) { typename C::size_type s = x.size(); @@ -30,8 +30,7 @@ test(const C& x, const typename C::allocator_type& a) LIBCPP_ASSERT(is_contiguous_container_asan_correct(c)); } -int main(int, char**) -{ +TEST_CONSTEXPR_CXX20 bool tests() { { int a[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 8, 7, 6, 5, 4, 3, 1, 0}; int* an = a + sizeof(a)/sizeof(a[0]); @@ -71,5 +70,14 @@ int main(int, char**) } #endif - return 0; + return true; +} + +int main(int, char**) +{ + tests(); +#if TEST_STD_VER > 17 + static_assert(tests()); +#endif + return 0; } diff --git a/libcxx/test/std/containers/sequences/vector/vector.cons/deduct.pass.cpp b/libcxx/test/std/containers/sequences/vector/vector.cons/deduct.pass.cpp index c876662bbbb2b..3aab782e38af5 100644 --- a/libcxx/test/std/containers/sequences/vector/vector.cons/deduct.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector/vector.cons/deduct.pass.cpp @@ -28,8 +28,7 @@ struct A {}; -int main(int, char**) -{ +TEST_CONSTEXPR_CXX20 bool tests() { // Test the explicit deduction guides { @@ -143,5 +142,13 @@ int main(int, char**) SequenceContainerDeductionGuidesSfinaeAway>(); + return true; +} + +int main(int, char**) { + tests(); +#if TEST_STD_VER > 17 + static_assert(tests()); +#endif return 0; } diff --git a/libcxx/test/std/containers/sequences/vector/vector.cons/default.recursive.pass.cpp b/libcxx/test/std/containers/sequences/vector/vector.cons/default.recursive.pass.cpp index 449751af11156..310f9ccfc9c6c 100644 --- a/libcxx/test/std/containers/sequences/vector/vector.cons/default.recursive.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector/vector.cons/default.recursive.pass.cpp @@ -22,5 +22,5 @@ struct X int main(int, char**) { - return 0; + return 0; } diff --git a/libcxx/test/std/containers/sequences/vector/vector.cons/default_noexcept.pass.cpp b/libcxx/test/std/containers/sequences/vector/vector.cons/default_noexcept.pass.cpp index 2fbb6c178d29d..3bd4a169d5f92 100644 --- a/libcxx/test/std/containers/sequences/vector/vector.cons/default_noexcept.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector/vector.cons/default_noexcept.pass.cpp @@ -30,8 +30,7 @@ struct some_alloc void allocate(size_t); }; -int main(int, char**) -{ +TEST_CONSTEXPR_CXX20 bool tests() { { typedef std::vector C; static_assert(std::is_nothrow_default_constructible::value, ""); @@ -49,5 +48,14 @@ int main(int, char**) static_assert(!std::is_nothrow_default_constructible::value, ""); } - return 0; + return true; +} + +int main(int, char**) +{ + tests(); +#if TEST_STD_VER > 17 + static_assert(tests()); +#endif + return 0; } diff --git a/libcxx/test/std/containers/sequences/vector/vector.cons/dtor_noexcept.pass.cpp b/libcxx/test/std/containers/sequences/vector/vector.cons/dtor_noexcept.pass.cpp index a0901858989ee..793475955506d 100644 --- a/libcxx/test/std/containers/sequences/vector/vector.cons/dtor_noexcept.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector/vector.cons/dtor_noexcept.pass.cpp @@ -28,7 +28,7 @@ struct some_alloc void allocate(size_t); }; -int main(int, char**) +TEST_CONSTEXPR_CXX20 bool tests() { { typedef std::vector C; @@ -49,5 +49,14 @@ int main(int, char**) } #endif // _LIBCPP_VERSION - return 0; + return true; +} + +int main(int, char**) +{ + tests(); +#if TEST_STD_VER > 17 + static_assert(tests()); +#endif + return 0; } diff --git a/libcxx/test/std/containers/sequences/vector/vector.cons/initializer_list.pass.cpp b/libcxx/test/std/containers/sequences/vector/vector.cons/initializer_list.pass.cpp index 5f06bb7b42206..6454f87f7e8ab 100644 --- a/libcxx/test/std/containers/sequences/vector/vector.cons/initializer_list.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector/vector.cons/initializer_list.pass.cpp @@ -18,7 +18,7 @@ #include "min_allocator.h" #include "asan_testing.h" -int main(int, char**) +TEST_CONSTEXPR_CXX20 bool tests() { { std::vector d = {3, 4, 5, 6}; @@ -39,5 +39,14 @@ int main(int, char**) assert(d[3] == 6); } - return 0; + return true; +} + +int main(int, char**) +{ + tests(); +#if TEST_STD_VER > 17 + static_assert(tests()); +#endif + return 0; } diff --git a/libcxx/test/std/containers/sequences/vector/vector.cons/initializer_list_alloc.pass.cpp b/libcxx/test/std/containers/sequences/vector/vector.cons/initializer_list_alloc.pass.cpp index c5cb997069692..157aefc5af823 100644 --- a/libcxx/test/std/containers/sequences/vector/vector.cons/initializer_list_alloc.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector/vector.cons/initializer_list_alloc.pass.cpp @@ -20,7 +20,7 @@ #include "min_allocator.h" #include "asan_testing.h" -int main(int, char**) +TEST_CONSTEXPR_CXX20 bool tests() { { std::vector> d({3, 4, 5, 6}, test_allocator(3)); @@ -49,5 +49,14 @@ int main(int, char**) assert(is_contiguous_container_asan_correct(d)); } - return 0; + return true; +} + +int main(int, char**) +{ + tests(); +#if TEST_STD_VER > 17 + static_assert(tests()); +#endif + return 0; } diff --git a/libcxx/test/std/containers/sequences/vector/vector.cons/move.pass.cpp b/libcxx/test/std/containers/sequences/vector/vector.cons/move.pass.cpp index 046f09fd4967d..0f3e737c1709b 100644 --- a/libcxx/test/std/containers/sequences/vector/vector.cons/move.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector/vector.cons/move.pass.cpp @@ -21,7 +21,7 @@ #include "min_allocator.h" #include "asan_testing.h" -int main(int, char**) +TEST_CONSTEXPR_CXX20 bool tests() { test_allocator_statistics alloc_stats; { @@ -131,5 +131,14 @@ int main(int, char**) } } - return 0; + return true; +} + +int main(int, char**) +{ + tests(); +#if TEST_STD_VER > 17 + static_assert(tests()); +#endif + return 0; } diff --git a/libcxx/test/std/containers/sequences/vector/vector.cons/move_alloc.pass.cpp b/libcxx/test/std/containers/sequences/vector/vector.cons/move_alloc.pass.cpp index 3f6b3fe425abd..2b6705a38e860 100644 --- a/libcxx/test/std/containers/sequences/vector/vector.cons/move_alloc.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector/vector.cons/move_alloc.pass.cpp @@ -20,7 +20,7 @@ #include "min_allocator.h" #include "asan_testing.h" -int main(int, char**) +TEST_CONSTEXPR_CXX20 bool tests() { { std::vector > l(test_allocator(5)); @@ -95,5 +95,14 @@ int main(int, char**) assert(is_contiguous_container_asan_correct(l2)); } - return 0; + return true; +} + +int main(int, char**) +{ + tests(); +#if TEST_STD_VER > 17 + static_assert(tests()); +#endif + return 0; } diff --git a/libcxx/test/std/containers/sequences/vector/vector.cons/move_assign_noexcept.pass.cpp b/libcxx/test/std/containers/sequences/vector/vector.cons/move_assign_noexcept.pass.cpp index 0f4538ae61c8e..fdd74a3f566b7 100644 --- a/libcxx/test/std/containers/sequences/vector/vector.cons/move_assign_noexcept.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector/vector.cons/move_assign_noexcept.pass.cpp @@ -96,5 +96,5 @@ int main(int, char**) } #endif - return 0; + return 0; } diff --git a/libcxx/test/std/containers/sequences/vector/vector.cons/op_equal_initializer_list.pass.cpp b/libcxx/test/std/containers/sequences/vector/vector.cons/op_equal_initializer_list.pass.cpp index ac924c0bc1189..f3d7b6a21b62e 100644 --- a/libcxx/test/std/containers/sequences/vector/vector.cons/op_equal_initializer_list.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector/vector.cons/op_equal_initializer_list.pass.cpp @@ -19,7 +19,7 @@ #include "min_allocator.h" #include "asan_testing.h" -int main(int, char**) +TEST_CONSTEXPR_CXX20 bool tests() { { std::vector d; @@ -42,5 +42,14 @@ int main(int, char**) assert(d[3] == 6); } - return 0; + return true; +} + +int main(int, char**) +{ + tests(); +#if TEST_STD_VER > 17 + static_assert(tests()); +#endif + return 0; } diff --git a/libcxx/test/std/containers/sequences/vector/vector.data/data.pass.cpp b/libcxx/test/std/containers/sequences/vector/vector.data/data.pass.cpp index 91eb2a2b324c5..4d2cadc00ceb1 100644 --- a/libcxx/test/std/containers/sequences/vector/vector.data/data.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector/vector.data/data.pass.cpp @@ -18,15 +18,15 @@ #include "asan_testing.h" struct Nasty { - Nasty() : i_(0) {} - Nasty(int i) : i_(i) {} - ~Nasty() {} + TEST_CONSTEXPR Nasty() : i_(0) {} + TEST_CONSTEXPR Nasty(int i) : i_(i) {} + TEST_CONSTEXPR_CXX20 ~Nasty() {} Nasty * operator&() const { assert(false); return nullptr; } int i_; - }; +}; -int main(int, char**) +TEST_CONSTEXPR_CXX20 bool tests() { { std::vector v; @@ -61,5 +61,14 @@ int main(int, char**) } #endif - return 0; + return true; +} + +int main(int, char**) +{ + tests(); +#if TEST_STD_VER > 17 + static_assert(tests()); +#endif + return 0; } diff --git a/libcxx/test/std/containers/sequences/vector/vector.data/data_const.pass.cpp b/libcxx/test/std/containers/sequences/vector/vector.data/data_const.pass.cpp index 2b76fe42d6e67..d314f90daf4b6 100644 --- a/libcxx/test/std/containers/sequences/vector/vector.data/data_const.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector/vector.data/data_const.pass.cpp @@ -18,15 +18,15 @@ #include "asan_testing.h" struct Nasty { - Nasty() : i_(0) {} - Nasty(int i) : i_(i) {} - ~Nasty() {} + TEST_CONSTEXPR Nasty() : i_(0) {} + TEST_CONSTEXPR Nasty(int i) : i_(i) {} + TEST_CONSTEXPR_CXX20 ~Nasty() {} Nasty * operator&() const { assert(false); return nullptr; } int i_; - }; +}; -int main(int, char**) +TEST_CONSTEXPR_CXX20 bool tests() { { const std::vector v; @@ -61,5 +61,14 @@ int main(int, char**) } #endif - return 0; + return true; +} + +int main(int, char**) +{ + tests(); +#if TEST_STD_VER > 17 + static_assert(tests()); +#endif + return 0; } diff --git a/libcxx/test/std/containers/sequences/vector/vector.erasure/erase.pass.cpp b/libcxx/test/std/containers/sequences/vector/vector.erasure/erase.pass.cpp index 141c55d2f113d..72441c12dac8e 100644 --- a/libcxx/test/std/containers/sequences/vector/vector.erasure/erase.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector/vector.erasure/erase.pass.cpp @@ -21,16 +21,15 @@ #include "min_allocator.h" template -void test0(S s, U val, S expected, size_t expected_erased_count) { +TEST_CONSTEXPR_CXX20 void test0(S s, U val, S expected, size_t expected_erased_count) { ASSERT_SAME_TYPE(typename S::size_type, decltype(std::erase(s, val))); assert(expected_erased_count == std::erase(s, val)); assert(s == expected); } template -void test() +TEST_CONSTEXPR_CXX20 void test() { - test0(S(), 1, S(), 0); test0(S({1}), 1, S(), 1); @@ -64,7 +63,7 @@ void test() test0(S({1, 2, 1}), opt(3), S({1, 2, 1}), 0); } -int main(int, char**) +TEST_CONSTEXPR_CXX20 bool tests() { test>(); test>> (); @@ -73,5 +72,14 @@ int main(int, char**) test>(); test>(); + return true; +} + +int main(int, char**) +{ + tests(); +#if TEST_STD_VER > 17 + static_assert(tests()); +#endif return 0; } diff --git a/libcxx/test/std/containers/sequences/vector/vector.erasure/erase_if.pass.cpp b/libcxx/test/std/containers/sequences/vector/vector.erasure/erase_if.pass.cpp index 5934f634369e5..1fcc1c9424868 100644 --- a/libcxx/test/std/containers/sequences/vector/vector.erasure/erase_if.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector/vector.erasure/erase_if.pass.cpp @@ -20,14 +20,14 @@ #include "min_allocator.h" template -void test0(S s, Pred p, S expected, size_t expected_erased_count) { +TEST_CONSTEXPR_CXX20 void test0(S s, Pred p, S expected, size_t expected_erased_count) { ASSERT_SAME_TYPE(typename S::size_type, decltype(std::erase_if(s, p))); assert(expected_erased_count == std::erase_if(s, p)); assert(s == expected); } template -void test() +TEST_CONSTEXPR_CXX20 void test() { auto is1 = [](auto v) { return v == 1;}; auto is2 = [](auto v) { return v == 2;}; @@ -65,7 +65,7 @@ void test() test0(S({1, 2, 3}), False, S({1, 2, 3}), 0); } -int main(int, char**) +TEST_CONSTEXPR_CXX20 bool tests() { test>(); test>> (); @@ -74,5 +74,14 @@ int main(int, char**) test>(); test>(); - return 0; + return true; +} + +int main(int, char**) +{ + tests(); +#if TEST_STD_VER > 17 + static_assert(tests()); +#endif + return 0; } diff --git a/libcxx/test/std/containers/sequences/vector/vector.modifiers/clear.pass.cpp b/libcxx/test/std/containers/sequences/vector/vector.modifiers/clear.pass.cpp index 334c67adcfc67..5a1e134f66fdf 100644 --- a/libcxx/test/std/containers/sequences/vector/vector.modifiers/clear.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector/vector.modifiers/clear.pass.cpp @@ -17,7 +17,7 @@ #include "min_allocator.h" #include "asan_testing.h" -int main(int, char**) +TEST_CONSTEXPR_CXX20 bool tests() { { int a[] = {1, 2, 3}; @@ -40,5 +40,14 @@ int main(int, char**) } #endif - return 0; + return true; +} + +int main(int, char**) +{ + tests(); +#if TEST_STD_VER > 17 + static_assert(tests()); +#endif + return 0; } diff --git a/libcxx/test/std/containers/sequences/vector/vector.modifiers/emplace.pass.cpp b/libcxx/test/std/containers/sequences/vector/vector.modifiers/emplace.pass.cpp index bc85f3e2969a7..f2c656cd27b2f 100644 --- a/libcxx/test/std/containers/sequences/vector/vector.modifiers/emplace.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector/vector.modifiers/emplace.pass.cpp @@ -28,10 +28,10 @@ class A A(const A&); A& operator=(const A&); public: - A(int i, double d) + TEST_CONSTEXPR_CXX14 A(int i, double d) : i_(i), d_(d) {} - A(A&& a) + TEST_CONSTEXPR_CXX14 A(A&& a) : i_(a.i_), d_(a.d_) { @@ -39,7 +39,7 @@ class A a.d_ = 0; } - A& operator=(A&& a) + TEST_CONSTEXPR_CXX14 A& operator=(A&& a) { i_ = a.i_; d_ = a.d_; @@ -48,11 +48,11 @@ class A return *this; } - int geti() const {return i_;} - double getd() const {return d_;} + TEST_CONSTEXPR_CXX14 int geti() const {return i_;} + TEST_CONSTEXPR_CXX14 double getd() const {return d_;} }; -int main(int, char**) +TEST_CONSTEXPR_CXX20 bool tests() { { std::vector c; @@ -133,5 +133,14 @@ int main(int, char**) assert(c.back().getd() == 4.5); } - return 0; + return true; +} + +int main(int, char**) +{ + tests(); +#if TEST_STD_VER > 17 + static_assert(tests()); +#endif + return 0; } diff --git a/libcxx/test/std/containers/sequences/vector/vector.modifiers/emplace_back.pass.cpp b/libcxx/test/std/containers/sequences/vector/vector.modifiers/emplace_back.pass.cpp index 5cf38f2f440f8..bb7fa745ac355 100644 --- a/libcxx/test/std/containers/sequences/vector/vector.modifiers/emplace_back.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector/vector.modifiers/emplace_back.pass.cpp @@ -30,10 +30,10 @@ class A A(const A&) = delete; A& operator=(const A&) = delete; - A(int i, double d) + TEST_CONSTEXPR_CXX14 A(int i, double d) : i_(i), d_(d) {} - A(A&& a) + TEST_CONSTEXPR_CXX14 A(A&& a) : i_(a.i_), d_(a.d_) { @@ -41,7 +41,7 @@ class A a.d_ = 0; } - A& operator=(A&& a) + TEST_CONSTEXPR_CXX14 A& operator=(A&& a) { i_ = a.i_; d_ = a.d_; @@ -50,11 +50,11 @@ class A return *this; } - int geti() const {return i_;} - double getd() const {return d_;} + TEST_CONSTEXPR_CXX14 int geti() const {return i_;} + TEST_CONSTEXPR_CXX14 double getd() const {return d_;} }; -int main(int, char**) +TEST_CONSTEXPR_CXX20 bool tests() { { std::vector c; @@ -157,5 +157,14 @@ int main(int, char**) for (int i = 0; i < sz; ++i) assert(c[i] == i); } - return 0; + return true; +} + +int main(int, char**) +{ + tests(); +#if TEST_STD_VER > 17 + static_assert(tests()); +#endif + return 0; } diff --git a/libcxx/test/std/containers/sequences/vector/vector.modifiers/emplace_extra.pass.cpp b/libcxx/test/std/containers/sequences/vector/vector.modifiers/emplace_extra.pass.cpp index 5bc35be643de6..3e1a1d82c2ebb 100644 --- a/libcxx/test/std/containers/sequences/vector/vector.modifiers/emplace_extra.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector/vector.modifiers/emplace_extra.pass.cpp @@ -19,8 +19,7 @@ #include "min_allocator.h" #include "asan_testing.h" -int main(int, char**) -{ +TEST_CONSTEXPR_CXX20 bool tests() { { std::vector v; v.reserve(3); @@ -71,5 +70,14 @@ int main(int, char**) assert(v.capacity() == old_capacity); assert(v[4] == 42); } - return 0; + + return true; +} + +int main(int, char**) { + tests(); +#if TEST_STD_VER > 17 + static_assert(tests()); +#endif + return 0; } diff --git a/libcxx/test/std/containers/sequences/vector/vector.modifiers/erase_iter.pass.cpp b/libcxx/test/std/containers/sequences/vector/vector.modifiers/erase_iter.pass.cpp index 423deff4a878f..43d843e24a11b 100644 --- a/libcxx/test/std/containers/sequences/vector/vector.modifiers/erase_iter.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector/vector.modifiers/erase_iter.pass.cpp @@ -33,7 +33,7 @@ struct Throws { bool Throws::sThrows = false; #endif -int main(int, char**) +TEST_CONSTEXPR_CXX20 bool tests() { { int a1[] = {1, 2, 3, 4, 5}; @@ -102,19 +102,30 @@ int main(int, char**) assert(is_contiguous_container_asan_correct(l1)); } #endif + + return true; +} + +int main(int, char**) +{ + tests(); +#if TEST_STD_VER > 17 + static_assert(tests()); +#endif + #ifndef TEST_HAS_NO_EXCEPTIONS // Test for LWG2853: // Throws: Nothing unless an exception is thrown by the assignment operator or move assignment operator of T. { - Throws arr[] = {1, 2, 3}; - std::vector v(arr, arr+3); - Throws::sThrows = true; - v.erase(v.begin()); - v.erase(--v.end()); - v.erase(v.begin()); - assert(v.size() == 0); + Throws arr[] = {1, 2, 3}; + std::vector v(arr, arr+3); + Throws::sThrows = true; + v.erase(v.begin()); + v.erase(--v.end()); + v.erase(v.begin()); + assert(v.size() == 0); } #endif - return 0; + return 0; } diff --git a/libcxx/test/std/containers/sequences/vector/vector.modifiers/erase_iter_iter.pass.cpp b/libcxx/test/std/containers/sequences/vector/vector.modifiers/erase_iter_iter.pass.cpp index 0025e7610368b..7857b8868a4c0 100644 --- a/libcxx/test/std/containers/sequences/vector/vector.modifiers/erase_iter_iter.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector/vector.modifiers/erase_iter_iter.pass.cpp @@ -33,7 +33,7 @@ struct Throws { bool Throws::sThrows = false; #endif -int main(int, char**) +TEST_CONSTEXPR_CXX20 bool tests() { int a1[] = {1, 2, 3}; { @@ -140,19 +140,30 @@ int main(int, char**) assert(is_contiguous_container_asan_correct(outer[1])); } #endif + + return true; +} + +int main(int, char**) +{ + tests(); +#if TEST_STD_VER > 17 + static_assert(tests()); +#endif + #ifndef TEST_HAS_NO_EXCEPTIONS // Test for LWG2853: // Throws: Nothing unless an exception is thrown by the assignment operator or move assignment operator of T. { - Throws arr[] = {1, 2, 3}; - std::vector v(arr, arr+3); - Throws::sThrows = true; - v.erase(v.begin(), --v.end()); - assert(v.size() == 1); - v.erase(v.begin(), v.end()); - assert(v.size() == 0); + Throws arr[] = {1, 2, 3}; + std::vector v(arr, arr+3); + Throws::sThrows = true; + v.erase(v.begin(), --v.end()); + assert(v.size() == 1); + v.erase(v.begin(), v.end()); + assert(v.size() == 0); } #endif - return 0; + return 0; } diff --git a/libcxx/test/std/containers/sequences/vector/vector.modifiers/insert_iter_initializer_list.pass.cpp b/libcxx/test/std/containers/sequences/vector/vector.modifiers/insert_iter_initializer_list.pass.cpp index 4a81fbfed65e7..92584892001a6 100644 --- a/libcxx/test/std/containers/sequences/vector/vector.modifiers/insert_iter_initializer_list.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector/vector.modifiers/insert_iter_initializer_list.pass.cpp @@ -54,10 +54,8 @@ void test_throwing() { } #endif // TEST_HAS_NO_EXCEPTIONS -int main(int, char**) { -#ifndef TEST_HAS_NO_EXCEPTIONS - test_throwing(); -#endif +TEST_CONSTEXPR_CXX20 bool tests() +{ { std::vector d(10, 1); std::vector::iterator i = d.insert(d.cbegin() + 2, {3, 4, 5, 6}); @@ -101,5 +99,16 @@ int main(int, char**) { assert(d[13] == 1); } + return true; +} + +int main(int, char**) { +#ifndef TEST_HAS_NO_EXCEPTIONS + test_throwing(); +#endif + tests(); +#if TEST_STD_VER > 17 + static_assert(tests()); +#endif return 0; } diff --git a/libcxx/test/std/containers/sequences/vector/vector.modifiers/insert_iter_iter_iter.pass.cpp b/libcxx/test/std/containers/sequences/vector/vector.modifiers/insert_iter_iter_iter.pass.cpp index ca8dcb8474c69..fe18d2da3b9e5 100644 --- a/libcxx/test/std/containers/sequences/vector/vector.modifiers/insert_iter_iter_iter.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector/vector.modifiers/insert_iter_iter_iter.pass.cpp @@ -26,7 +26,7 @@ struct S {}; void make_move_iterator(S*) {} } -int main(int, char**) +TEST_CONSTEXPR_CXX20 bool tests() { { typedef std::vector V; @@ -182,5 +182,14 @@ int main(int, char**) s.insert(s.end(), cpp17_input_iterator(nullptr), cpp17_input_iterator(nullptr)); } - return 0; + return true; +} + +int main(int, char**) +{ + tests(); +#if TEST_STD_VER > 17 + static_assert(tests()); +#endif + return 0; } diff --git a/libcxx/test/std/containers/sequences/vector/vector.modifiers/insert_iter_lvalue.pass.cpp b/libcxx/test/std/containers/sequences/vector/vector.modifiers/insert_iter_lvalue.pass.cpp index 63c1c64e272a8..c8bb994258894 100644 --- a/libcxx/test/std/containers/sequences/vector/vector.modifiers/insert_iter_lvalue.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector/vector.modifiers/insert_iter_lvalue.pass.cpp @@ -19,8 +19,8 @@ #include "min_allocator.h" #include "asan_testing.h" -int main(int, char**) -{ +TEST_CONSTEXPR_CXX20 bool test() { + { std::vector v(100); const int lvalue = 1; @@ -116,5 +116,15 @@ int main(int, char**) } #endif + return true; +} + +int main(int, char**) +{ + test(); +#if TEST_STD_VER > 17 + static_assert(test()); +#endif + return 0; } diff --git a/libcxx/test/std/containers/sequences/vector/vector.modifiers/insert_iter_rvalue.pass.cpp b/libcxx/test/std/containers/sequences/vector/vector.modifiers/insert_iter_rvalue.pass.cpp index fe03f2acfab28..11a7175c61967 100644 --- a/libcxx/test/std/containers/sequences/vector/vector.modifiers/insert_iter_rvalue.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector/vector.modifiers/insert_iter_rvalue.pass.cpp @@ -21,7 +21,7 @@ #include "min_allocator.h" #include "asan_testing.h" -int main(int, char**) +TEST_CONSTEXPR_CXX20 bool tests() { { std::vector v(100); @@ -63,5 +63,14 @@ int main(int, char**) assert(v[j] == MoveOnly()); } - return 0; + return true; +} + +int main(int, char**) +{ + tests(); +#if TEST_STD_VER > 17 + static_assert(tests()); +#endif + return 0; } diff --git a/libcxx/test/std/containers/sequences/vector/vector.modifiers/insert_iter_size_value.pass.cpp b/libcxx/test/std/containers/sequences/vector/vector.modifiers/insert_iter_size_value.pass.cpp index 5b182f44d6adc..c629428828081 100644 --- a/libcxx/test/std/containers/sequences/vector/vector.modifiers/insert_iter_size_value.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector/vector.modifiers/insert_iter_size_value.pass.cpp @@ -19,7 +19,7 @@ #include "min_allocator.h" #include "asan_testing.h" -int main(int, char**) +TEST_CONSTEXPR_CXX20 bool tests() { { std::vector v(100); @@ -112,5 +112,14 @@ int main(int, char**) } #endif - return 0; + return true; +} + +int main(int, char**) +{ + tests(); +#if TEST_STD_VER > 17 + static_assert(tests()); +#endif + return 0; } diff --git a/libcxx/test/std/containers/sequences/vector/vector.modifiers/pop_back.pass.cpp b/libcxx/test/std/containers/sequences/vector/vector.modifiers/pop_back.pass.cpp index 386328405d01a..9482920f0fe60 100644 --- a/libcxx/test/std/containers/sequences/vector/vector.modifiers/pop_back.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector/vector.modifiers/pop_back.pass.cpp @@ -18,7 +18,7 @@ #include "min_allocator.h" -int main(int, char**) +TEST_CONSTEXPR_CXX20 bool tests() { { std::vector c; @@ -50,5 +50,14 @@ int main(int, char**) assert(c[i] == i); } - return 0; + return true; +} + +int main(int, char**) +{ + tests(); +#if TEST_STD_VER > 17 + static_assert(tests()); +#endif + return 0; } diff --git a/libcxx/test/std/containers/sequences/vector/vector.modifiers/push_back.pass.cpp b/libcxx/test/std/containers/sequences/vector/vector.modifiers/push_back.pass.cpp index dcb6d4448ed50..2490fded523d6 100644 --- a/libcxx/test/std/containers/sequences/vector/vector.modifiers/push_back.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector/vector.modifiers/push_back.pass.cpp @@ -18,7 +18,7 @@ #include "min_allocator.h" #include "asan_testing.h" -int main(int, char**) +TEST_CONSTEXPR_CXX20 bool tests() { { std::vector c; @@ -110,5 +110,14 @@ int main(int, char**) } #endif - return 0; + return true; +} + +int main(int, char**) +{ + tests(); +#if TEST_STD_VER > 17 + static_assert(tests()); +#endif + return 0; } diff --git a/libcxx/test/std/containers/sequences/vector/vector.modifiers/push_back_rvalue.pass.cpp b/libcxx/test/std/containers/sequences/vector/vector.modifiers/push_back_rvalue.pass.cpp index e7527d44ca47f..92b629b3cdb4f 100644 --- a/libcxx/test/std/containers/sequences/vector/vector.modifiers/push_back_rvalue.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector/vector.modifiers/push_back_rvalue.pass.cpp @@ -21,7 +21,7 @@ #include "min_allocator.h" #include "asan_testing.h" -int main(int, char**) +TEST_CONSTEXPR_CXX20 bool tests() { { std::vector c; @@ -111,5 +111,14 @@ int main(int, char**) assert(c[j] == MoveOnly(j)); } - return 0; + return true; +} + +int main(int, char**) +{ + tests(); +#if TEST_STD_VER > 17 + static_assert(tests()); +#endif + return 0; } diff --git a/libcxx/test/std/containers/sequences/vector/vector.special/swap.pass.cpp b/libcxx/test/std/containers/sequences/vector/vector.special/swap.pass.cpp index 5866d2c130c61..e1f45208539ac 100644 --- a/libcxx/test/std/containers/sequences/vector/vector.special/swap.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector/vector.special/swap.pass.cpp @@ -19,7 +19,7 @@ #include "min_allocator.h" #include "asan_testing.h" -int main(int, char**) +TEST_CONSTEXPR_CXX20 bool tests() { { int a1[] = {1, 3, 7, 9, 10}; @@ -180,5 +180,14 @@ int main(int, char**) } #endif - return 0; + return true; +} + +int main(int, char**) +{ + tests(); +#if TEST_STD_VER > 17 + static_assert(tests()); +#endif + return 0; } diff --git a/libcxx/test/std/experimental/language.support/support.coroutines/end.to.end/oneshot_func.pass.cpp b/libcxx/test/std/experimental/language.support/support.coroutines/end.to.end/oneshot_func.pass.cpp index 4942372246811..105ca8a510336 100644 --- a/libcxx/test/std/experimental/language.support/support.coroutines/end.to.end/oneshot_func.pass.cpp +++ b/libcxx/test/std/experimental/language.support/support.coroutines/end.to.end/oneshot_func.pass.cpp @@ -8,6 +8,8 @@ // UNSUPPORTED: c++03, c++11 +// XFAIL: libcpp-has-debug-mode + #include #include #include diff --git a/libcxx/test/support/allocators.h b/libcxx/test/support/allocators.h index fce43acf129be..f4578da74ffca 100644 --- a/libcxx/test/support/allocators.h +++ b/libcxx/test/support/allocators.h @@ -9,6 +9,7 @@ #ifndef ALLOCATORS_H #define ALLOCATORS_H +#include #include #include @@ -201,8 +202,8 @@ class MaybePOCCAAllocator { typedef MaybePOCCAAllocator other; }; - MaybePOCCAAllocator() = default; - MaybePOCCAAllocator(int id, bool* copy_assigned_into) + TEST_CONSTEXPR MaybePOCCAAllocator() = default; + TEST_CONSTEXPR MaybePOCCAAllocator(int id, bool* copy_assigned_into) : id_(id), copy_assigned_into_(copy_assigned_into) {} template @@ -210,7 +211,7 @@ class MaybePOCCAAllocator { : id_(that.id_), copy_assigned_into_(that.copy_assigned_into_) {} MaybePOCCAAllocator(const MaybePOCCAAllocator&) = default; - MaybePOCCAAllocator& operator=(const MaybePOCCAAllocator& a) + TEST_CONSTEXPR_CXX14 MaybePOCCAAllocator& operator=(const MaybePOCCAAllocator& a) { id_ = a.id(); if (copy_assigned_into_) @@ -218,26 +219,26 @@ class MaybePOCCAAllocator { return *this; } - T* allocate(std::size_t n) + TEST_CONSTEXPR_CXX20 T* allocate(std::size_t n) { - return static_cast(::operator new(n * sizeof(T))); + return std::allocator().allocate(n); } - void deallocate(T* ptr, std::size_t) + TEST_CONSTEXPR_CXX20 void deallocate(T* ptr, std::size_t n) { - ::operator delete(ptr); + std::allocator().deallocate(ptr, n); } - int id() const { return id_; } + TEST_CONSTEXPR int id() const { return id_; } template - friend bool operator==(const MaybePOCCAAllocator& lhs, const MaybePOCCAAllocator& rhs) + TEST_CONSTEXPR friend bool operator==(const MaybePOCCAAllocator& lhs, const MaybePOCCAAllocator& rhs) { return lhs.id() == rhs.id(); } template - friend bool operator!=(const MaybePOCCAAllocator& lhs, const MaybePOCCAAllocator& rhs) + TEST_CONSTEXPR friend bool operator!=(const MaybePOCCAAllocator& lhs, const MaybePOCCAAllocator& rhs) { return !(lhs == rhs); } diff --git a/libcxx/test/support/asan_testing.h b/libcxx/test/support/asan_testing.h index 7f3312d9f8223..aae93019fe1c6 100644 --- a/libcxx/test/support/asan_testing.h +++ b/libcxx/test/support/asan_testing.h @@ -16,17 +16,19 @@ extern "C" int __sanitizer_verify_contiguous_container ( const void *beg, const void *mid, const void *end ); template -bool is_contiguous_container_asan_correct ( const std::vector &c ) +TEST_CONSTEXPR bool is_contiguous_container_asan_correct ( const std::vector &c ) { - if ( std::is_same >::value && c.data() != NULL) - return __sanitizer_verify_contiguous_container ( + if (std::__libcpp_is_constant_evaluated()) + return true; + if (std::is_same >::value && c.data() != NULL) + return __sanitizer_verify_contiguous_container( c.data(), c.data() + c.size(), c.data() + c.capacity()) != 0; return true; } #else template -bool is_contiguous_container_asan_correct ( const std::vector &) +TEST_CONSTEXPR bool is_contiguous_container_asan_correct ( const std::vector &) { return true; } diff --git a/libcxx/test/support/poisoned_hash_helper.h b/libcxx/test/support/poisoned_hash_helper.h index c39be5f0428b3..cbf36e03964c4 100644 --- a/libcxx/test/support/poisoned_hash_helper.h +++ b/libcxx/test/support/poisoned_hash_helper.h @@ -24,10 +24,10 @@ template struct TypeList; // Test that the specified Hash meets the requirements of an enabled hash template -void test_hash_enabled(InputKey const& key = InputKey{}); +TEST_CONSTEXPR_CXX20 void test_hash_enabled(InputKey const& key = InputKey{}); template -void test_hash_enabled_for_type(InputKey const& key = InputKey{}) { +TEST_CONSTEXPR_CXX20 void test_hash_enabled_for_type(InputKey const& key = InputKey{}) { return test_hash_enabled, T, InputKey>(key); } @@ -129,7 +129,7 @@ constexpr bool can_hash() { } // namespace PoisonedHashDetail template -void test_hash_enabled(InputKey const& key) { +TEST_CONSTEXPR_CXX20 void test_hash_enabled(InputKey const& key) { using namespace PoisonedHashDetail; static_assert(std::is_destructible::value, ""); diff --git a/libcxx/test/support/test_allocator.h b/libcxx/test/support/test_allocator.h index 741f6fc2f5324..3b9676ee17526 100644 --- a/libcxx/test/support/test_allocator.h +++ b/libcxx/test/support/test_allocator.h @@ -21,7 +21,7 @@ #include "test_macros.h" template -inline typename std::allocator_traits::size_type alloc_max_size(Alloc const& a) { +TEST_CONSTEXPR_CXX20 inline typename std::allocator_traits::size_type alloc_max_size(Alloc const& a) { typedef std::allocator_traits AT; return AT::max_size(a); } @@ -165,8 +165,12 @@ class test_allocator { TEST_CONSTEXPR size_type max_size() const TEST_NOEXCEPT { return UINT_MAX / sizeof(T); } template - TEST_CONSTEXPR_CXX14 void construct(pointer p, U&& val) { + TEST_CONSTEXPR_CXX20 void construct(pointer p, U&& val) { +#if TEST_STD_VER > 17 + std::construct_at(std::to_address(p), std::forward(val)); +#else ::new (static_cast(p)) T(std::forward(val)); +#endif } TEST_CONSTEXPR_CXX14 void destroy(pointer p) { p->~T(); } @@ -399,12 +403,16 @@ class TaggingAllocator { TEST_CONSTEXPR TaggingAllocator(const TaggingAllocator&) {} template - void construct(Tag_X* p, Args&&... args) { - ::new ((void*)p) Tag_X(Ctor_Tag(), std::forward(args)...); + TEST_CONSTEXPR_CXX20 void construct(Tag_X* p, Args&&... args) { +#if TEST_STD_VER > 17 + std::construct_at(p, Ctor_Tag{}, std::forward(args)...); +#else + ::new (static_cast(p)) Tag_X(Ctor_Tag(), std::forward(args)...); +#endif } template - void destroy(U* p) { + TEST_CONSTEXPR_CXX20 void destroy(U* p) { p->~U(); } @@ -421,9 +429,10 @@ struct limited_alloc_handle { TEST_CONSTEXPR_CXX20 T* allocate(std::size_t N) { if (N + outstanding_ > MaxAllocs) TEST_THROW(std::bad_alloc()); - last_alloc_ = std::allocator().allocate(N); + auto alloc = std::allocator().allocate(N); + last_alloc_ = alloc; outstanding_ += N; - return static_cast(last_alloc_); + return alloc; } template From fc03fad3dde95d9c0b073de28d43770bf3b68969 Mon Sep 17 00:00:00 2001 From: Amara Emerson Date: Wed, 27 Jul 2022 00:02:59 -0700 Subject: [PATCH 006/323] [AArch64][GlobalISel] Lower vector G_CTTZ. Fixes issue 56398 (cherry picked from commit 9cc1dd209d20eda51710f302800899730b419381) --- .../AArch64/GISel/AArch64LegalizerInfo.cpp | 2 +- .../AArch64/GlobalISel/legalize-cttz.mir | 26 +++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp b/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp index d3617b87a851d..380d3621e7452 100644 --- a/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp +++ b/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp @@ -662,8 +662,8 @@ AArch64LegalizerInfo::AArch64LegalizerInfo(const AArch64Subtarget &ST) getActionDefinitionsBuilder(G_CTTZ_ZERO_UNDEF).lower(); - // TODO: Handle vector types. getActionDefinitionsBuilder(G_CTTZ) + .lowerIf(isVector(0)) .clampScalar(0, s32, s64) .scalarSameSizeAs(1, 0) .customFor({s32, s64}); diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/legalize-cttz.mir b/llvm/test/CodeGen/AArch64/GlobalISel/legalize-cttz.mir index 418b31d061518..0486efc665d9c 100644 --- a/llvm/test/CodeGen/AArch64/GlobalISel/legalize-cttz.mir +++ b/llvm/test/CodeGen/AArch64/GlobalISel/legalize-cttz.mir @@ -88,3 +88,29 @@ body: | %1:_(s64) = G_CTTZ %val(s64) $x0 = COPY %1(s64) RET_ReallyLR implicit $x0 +... +--- +name: v4s32 +alignment: 4 +tracksRegLiveness: true +body: | + bb.0: + liveins: $q0 + + ; CHECK-LABEL: name: v4s32 + ; CHECK: liveins: $q0 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: %val:_(<4 x s32>) = COPY $q0 + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 -1 + ; CHECK-NEXT: [[BUILD_VECTOR:%[0-9]+]]:_(<4 x s32>) = G_BUILD_VECTOR [[C]](s32), [[C]](s32), [[C]](s32), [[C]](s32) + ; CHECK-NEXT: [[XOR:%[0-9]+]]:_(<4 x s32>) = G_XOR %val, [[BUILD_VECTOR]] + ; CHECK-NEXT: [[ADD:%[0-9]+]]:_(<4 x s32>) = G_ADD %val, [[BUILD_VECTOR]] + ; CHECK-NEXT: [[AND:%[0-9]+]]:_(<4 x s32>) = G_AND [[XOR]], [[ADD]] + ; CHECK-NEXT: [[CTPOP:%[0-9]+]]:_(<4 x s32>) = G_CTPOP [[AND]](<4 x s32>) + ; CHECK-NEXT: $q0 = COPY [[CTPOP]](<4 x s32>) + ; CHECK-NEXT: RET_ReallyLR implicit $q0 + %val:_(<4 x s32>) = COPY $q0 + %1:_(<4 x s32>) = G_CTTZ %val(<4 x s32>) + $q0 = COPY %1(<4 x s32>) + RET_ReallyLR implicit $q0 +... From e077f4a6bfde096a1e2a16e7e17d7ac39718b68a Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Wed, 27 Jul 2022 11:18:19 -0700 Subject: [PATCH 007/323] [ELF][test] Fix compressed-debug-level.test with zlib-ng The test is brittle but it seems unnecessary to remove size check now. Close #56222 (cherry picked from commit 876af563e73a3c1d6b49e13b4c1791a4208c8546) --- lld/test/ELF/compressed-debug-level.test | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lld/test/ELF/compressed-debug-level.test b/lld/test/ELF/compressed-debug-level.test index d755e9fedf13b..ee95f12679972 100644 --- a/lld/test/ELF/compressed-debug-level.test +++ b/lld/test/ELF/compressed-debug-level.test @@ -20,7 +20,7 @@ ## Here we check how -O flag affects the size of compressed sections produced. # HEADER: [Nr] Name Type Address Off Size -# LEVEL1: [ 1] .debug_info PROGBITS 00000000 000094 00001c +# LEVEL1: [ 1] .debug_info PROGBITS 00000000 000094 00001{{[bc]}} # LEVEL6: [ 1] .debug_info PROGBITS 00000000 000094 00001a ## A little arbitrary debug section which has a different size after From 57bdd9892d0eba5bdd25fc44799235be7b9f5153 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Mon, 25 Jul 2022 15:12:10 +0200 Subject: [PATCH 008/323] [ARM] Add target feature to force 32-bit atomics This adds a +atomic-32 target feature, which instructs LLVM to assume that lock-free 32-bit atomics are available for this target, even if they usually wouldn't be. If only atomic loads/stores are used, then this won't emit libcalls. If atomic CAS is used, then the user is responsible for providing any necessary __sync implementations (e.g. by masking interrupts for single-core privileged use cases). See https://reviews.llvm.org/D120026#3674333 for context on this change. The tl;dr is that the thumbv6m target in Rust has historically made atomic load/store only available, which is incompatible with the change from D120026, which switched these to use libatomic. Differential Revision: https://reviews.llvm.org/D130480 (cherry picked from commit b1b1086973d5be26f127540852ace59c5119e90a) --- llvm/lib/Target/ARM/ARM.td | 9 + llvm/lib/Target/ARM/ARMISelLowering.cpp | 3 +- llvm/test/CodeGen/ARM/thumbv6m-atomic32.ll | 203 +++++++++++++++++++++ 3 files changed, 214 insertions(+), 1 deletion(-) create mode 100644 llvm/test/CodeGen/ARM/thumbv6m-atomic32.ll diff --git a/llvm/lib/Target/ARM/ARM.td b/llvm/lib/Target/ARM/ARM.td index 73970b9c74c56..71388bc4efa4c 100644 --- a/llvm/lib/Target/ARM/ARM.td +++ b/llvm/lib/Target/ARM/ARM.td @@ -556,6 +556,15 @@ def FeatureAAPCSFrameChainLeaf : SubtargetFeature<"aapcs-frame-chain-leaf", "for leaf functions", [FeatureAAPCSFrameChain]>; +// Assume that lock-free 32-bit atomics are available, even if the target +// and operating system combination would not usually provide them. The user +// is responsible for providing any necessary __sync implementations. Code +// built with this feature is not ABI-compatible with code built without this +// feature, if atomic variables are exposed across the ABI boundary. +def FeatureAtomics32 : SubtargetFeature< + "atomics-32", "HasForced32BitAtomics", "true", + "Assume that lock-free 32-bit atomics are available">; + //===----------------------------------------------------------------------===// // ARM architecture class // diff --git a/llvm/lib/Target/ARM/ARMISelLowering.cpp b/llvm/lib/Target/ARM/ARMISelLowering.cpp index 743cca9ff71f2..4c24d70209325 100644 --- a/llvm/lib/Target/ARM/ARMISelLowering.cpp +++ b/llvm/lib/Target/ARM/ARMISelLowering.cpp @@ -1370,7 +1370,8 @@ ARMTargetLowering::ARMTargetLowering(const TargetMachine &TM, // instructions. (ARMv6 doesn't have dmb, but it has an equivalent // encoding; see ARMISD::MEMBARRIER_MCR.) setMaxAtomicSizeInBitsSupported(64); - } else if (Subtarget->isMClass() && Subtarget->hasV8MBaselineOps()) { + } else if ((Subtarget->isMClass() && Subtarget->hasV8MBaselineOps()) || + Subtarget->hasForced32BitAtomics()) { // Cortex-M (besides Cortex-M0) have 32-bit atomics. setMaxAtomicSizeInBitsSupported(32); } else { diff --git a/llvm/test/CodeGen/ARM/thumbv6m-atomic32.ll b/llvm/test/CodeGen/ARM/thumbv6m-atomic32.ll new file mode 100644 index 0000000000000..36ed03a8c384b --- /dev/null +++ b/llvm/test/CodeGen/ARM/thumbv6m-atomic32.ll @@ -0,0 +1,203 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=thumbv6m-none-eabi < %s | FileCheck %s --check-prefixes=CHECK,NO-ATOMIC32 +; RUN: llc -mtriple=thumbv6m-none-eabi -mattr=+atomics-32 < %s | FileCheck %s --check-prefixes=CHECK,ATOMIC32 + +define i32 @load32(ptr %p) { +; NO-ATOMIC32-LABEL: load32: +; NO-ATOMIC32: @ %bb.0: +; NO-ATOMIC32-NEXT: .save {r7, lr} +; NO-ATOMIC32-NEXT: push {r7, lr} +; NO-ATOMIC32-NEXT: movs r1, #5 +; NO-ATOMIC32-NEXT: bl __atomic_load_4 +; NO-ATOMIC32-NEXT: pop {r7, pc} +; +; ATOMIC32-LABEL: load32: +; ATOMIC32: @ %bb.0: +; ATOMIC32-NEXT: ldr r0, [r0] +; ATOMIC32-NEXT: dmb sy +; ATOMIC32-NEXT: bx lr + %v = load atomic i32, ptr %p seq_cst, align 4 + ret i32 %v +} + +define void @store32(ptr %p) { +; NO-ATOMIC32-LABEL: store32: +; NO-ATOMIC32: @ %bb.0: +; NO-ATOMIC32-NEXT: .save {r7, lr} +; NO-ATOMIC32-NEXT: push {r7, lr} +; NO-ATOMIC32-NEXT: movs r1, #0 +; NO-ATOMIC32-NEXT: movs r2, #5 +; NO-ATOMIC32-NEXT: bl __atomic_store_4 +; NO-ATOMIC32-NEXT: pop {r7, pc} +; +; ATOMIC32-LABEL: store32: +; ATOMIC32: @ %bb.0: +; ATOMIC32-NEXT: dmb sy +; ATOMIC32-NEXT: movs r1, #0 +; ATOMIC32-NEXT: str r1, [r0] +; ATOMIC32-NEXT: dmb sy +; ATOMIC32-NEXT: bx lr + store atomic i32 0, ptr %p seq_cst, align 4 + ret void +} + +define i32 @rmw32(ptr %p) { +; NO-ATOMIC32-LABEL: rmw32: +; NO-ATOMIC32: @ %bb.0: +; NO-ATOMIC32-NEXT: .save {r7, lr} +; NO-ATOMIC32-NEXT: push {r7, lr} +; NO-ATOMIC32-NEXT: movs r1, #1 +; NO-ATOMIC32-NEXT: movs r2, #5 +; NO-ATOMIC32-NEXT: bl __atomic_fetch_add_4 +; NO-ATOMIC32-NEXT: pop {r7, pc} +; +; ATOMIC32-LABEL: rmw32: +; ATOMIC32: @ %bb.0: +; ATOMIC32-NEXT: .save {r7, lr} +; ATOMIC32-NEXT: push {r7, lr} +; ATOMIC32-NEXT: dmb sy +; ATOMIC32-NEXT: movs r1, #1 +; ATOMIC32-NEXT: bl __sync_fetch_and_add_4 +; ATOMIC32-NEXT: dmb sy +; ATOMIC32-NEXT: pop {r7, pc} + %v = atomicrmw add ptr %p, i32 1 seq_cst, align 4 + ret i32 %v +} + +define i32 @cmpxchg32(ptr %p) { +; NO-ATOMIC32-LABEL: cmpxchg32: +; NO-ATOMIC32: @ %bb.0: +; NO-ATOMIC32-NEXT: .save {r7, lr} +; NO-ATOMIC32-NEXT: push {r7, lr} +; NO-ATOMIC32-NEXT: .pad #8 +; NO-ATOMIC32-NEXT: sub sp, #8 +; NO-ATOMIC32-NEXT: movs r1, #0 +; NO-ATOMIC32-NEXT: str r1, [sp, #4] +; NO-ATOMIC32-NEXT: movs r3, #5 +; NO-ATOMIC32-NEXT: str r3, [sp] +; NO-ATOMIC32-NEXT: add r1, sp, #4 +; NO-ATOMIC32-NEXT: movs r2, #1 +; NO-ATOMIC32-NEXT: bl __atomic_compare_exchange_4 +; NO-ATOMIC32-NEXT: ldr r0, [sp, #4] +; NO-ATOMIC32-NEXT: add sp, #8 +; NO-ATOMIC32-NEXT: pop {r7, pc} +; +; ATOMIC32-LABEL: cmpxchg32: +; ATOMIC32: @ %bb.0: +; ATOMIC32-NEXT: .save {r7, lr} +; ATOMIC32-NEXT: push {r7, lr} +; ATOMIC32-NEXT: dmb sy +; ATOMIC32-NEXT: movs r1, #0 +; ATOMIC32-NEXT: movs r2, #1 +; ATOMIC32-NEXT: bl __sync_val_compare_and_swap_4 +; ATOMIC32-NEXT: dmb sy +; ATOMIC32-NEXT: pop {r7, pc} + %res = cmpxchg ptr %p, i32 0, i32 1 seq_cst seq_cst + %res.0 = extractvalue { i32, i1 } %res, 0 + ret i32 %res.0 +} + +define i64 @load64(ptr %p) { +; CHECK-LABEL: load64: +; CHECK: @ %bb.0: +; CHECK-NEXT: .save {r7, lr} +; CHECK-NEXT: push {r7, lr} +; CHECK-NEXT: .pad #8 +; CHECK-NEXT: sub sp, #8 +; CHECK-NEXT: mov r1, r0 +; CHECK-NEXT: movs r0, #8 +; CHECK-NEXT: mov r2, sp +; CHECK-NEXT: movs r3, #5 +; CHECK-NEXT: bl __atomic_load +; CHECK-NEXT: ldr r1, [sp, #4] +; CHECK-NEXT: ldr r0, [sp] +; CHECK-NEXT: add sp, #8 +; CHECK-NEXT: pop {r7, pc} + %v = load atomic i64, ptr %p seq_cst, align 4 + ret i64 %v +} + +define void @store64(ptr %p) { +; CHECK-LABEL: store64: +; CHECK: @ %bb.0: +; CHECK-NEXT: .save {r7, lr} +; CHECK-NEXT: push {r7, lr} +; CHECK-NEXT: .pad #8 +; CHECK-NEXT: sub sp, #8 +; CHECK-NEXT: mov r1, r0 +; CHECK-NEXT: movs r0, #0 +; CHECK-NEXT: str r0, [sp, #4] +; CHECK-NEXT: str r0, [sp] +; CHECK-NEXT: movs r0, #8 +; CHECK-NEXT: mov r2, sp +; CHECK-NEXT: movs r3, #5 +; CHECK-NEXT: bl __atomic_store +; CHECK-NEXT: add sp, #8 +; CHECK-NEXT: pop {r7, pc} + store atomic i64 0, ptr %p seq_cst, align 4 + ret void +} + +define i64 @rmw64(ptr %p) { +; CHECK-LABEL: rmw64: +; CHECK: @ %bb.0: +; CHECK-NEXT: .save {r4, lr} +; CHECK-NEXT: push {r4, lr} +; CHECK-NEXT: .pad #24 +; CHECK-NEXT: sub sp, #24 +; CHECK-NEXT: mov r4, r0 +; CHECK-NEXT: ldr r0, [r0] +; CHECK-NEXT: ldr r1, [r4, #4] +; CHECK-NEXT: .LBB6_1: @ %atomicrmw.start +; CHECK-NEXT: @ =>This Inner Loop Header: Depth=1 +; CHECK-NEXT: str r0, [sp, #16] +; CHECK-NEXT: str r1, [sp, #20] +; CHECK-NEXT: movs r2, #0 +; CHECK-NEXT: adds r0, r0, #1 +; CHECK-NEXT: adcs r2, r1 +; CHECK-NEXT: str r2, [sp, #12] +; CHECK-NEXT: str r0, [sp, #8] +; CHECK-NEXT: movs r0, #5 +; CHECK-NEXT: str r0, [sp] +; CHECK-NEXT: str r0, [sp, #4] +; CHECK-NEXT: movs r0, #8 +; CHECK-NEXT: add r2, sp, #16 +; CHECK-NEXT: add r3, sp, #8 +; CHECK-NEXT: mov r1, r4 +; CHECK-NEXT: bl __atomic_compare_exchange +; CHECK-NEXT: mov r2, r0 +; CHECK-NEXT: ldr r1, [sp, #20] +; CHECK-NEXT: ldr r0, [sp, #16] +; CHECK-NEXT: cmp r2, #0 +; CHECK-NEXT: beq .LBB6_1 +; CHECK-NEXT: @ %bb.2: @ %atomicrmw.end +; CHECK-NEXT: add sp, #24 +; CHECK-NEXT: pop {r4, pc} + %v = atomicrmw add ptr %p, i64 1 seq_cst, align 4 + ret i64 %v +} + +define i64 @cmpxchg64(ptr %p) { +; CHECK-LABEL: cmpxchg64: +; CHECK: @ %bb.0: +; CHECK-NEXT: .save {r7, lr} +; CHECK-NEXT: push {r7, lr} +; CHECK-NEXT: .pad #16 +; CHECK-NEXT: sub sp, #16 +; CHECK-NEXT: movs r3, #0 +; CHECK-NEXT: str r3, [sp, #12] +; CHECK-NEXT: str r3, [sp, #8] +; CHECK-NEXT: movs r1, #5 +; CHECK-NEXT: str r1, [sp] +; CHECK-NEXT: str r1, [sp, #4] +; CHECK-NEXT: add r1, sp, #8 +; CHECK-NEXT: movs r2, #1 +; CHECK-NEXT: bl __atomic_compare_exchange_8 +; CHECK-NEXT: ldr r1, [sp, #12] +; CHECK-NEXT: ldr r0, [sp, #8] +; CHECK-NEXT: add sp, #16 +; CHECK-NEXT: pop {r7, pc} + %res = cmpxchg ptr %p, i64 0, i64 1 seq_cst seq_cst + %res.0 = extractvalue { i64, i1 } %res, 0 + ret i64 %res.0 +} From e8c390dfdb6a878b04e9bc4f45f05f6d678cccfc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Thu, 14 Jul 2022 22:39:55 +0300 Subject: [PATCH 009/323] [clang-tidy] Rename the make-confusable-table executable Rename it to clang-tidy-confusable-chars-gen, to make its role clearer in a wider context. In cross builds, the caller might want to provide this tool externally (to avoid needing to rebuild it in the cross build). In such a case, having the tool properly namespaced makes its role clearer. This matches how the clang-pseudo-gen tool was renamed in a43fef05d4fae32f02365c7b8fef2aa631d23628 / D126725. Differential Revision: https://reviews.llvm.org/D129798 (cherry picked from commit 18b4a8bcf3553174f770f09528c9bd01c8cebfe7) --- clang-tools-extra/clang-tidy/misc/CMakeLists.txt | 6 +++--- .../clang-tidy/misc/ConfusableTable/CMakeLists.txt | 2 +- .../clang-tidy/misc/ConfusableTable/BUILD.gn | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/clang-tools-extra/clang-tidy/misc/CMakeLists.txt b/clang-tools-extra/clang-tidy/misc/CMakeLists.txt index 04172db29ea5e..ee8fe0b37fce9 100644 --- a/clang-tools-extra/clang-tidy/misc/CMakeLists.txt +++ b/clang-tools-extra/clang-tidy/misc/CMakeLists.txt @@ -4,11 +4,11 @@ set(LLVM_LINK_COMPONENTS ) if(LLVM_USE_HOST_TOOLS) - build_native_tool(make-confusable-table make_confusable_table) + build_native_tool(clang-tidy-confusable-chars-gen make_confusable_table) set(make_confusable_table_target "${make_confusable_table}") else() - set(make_confusable_table $) - set(make_confusable_table_target make-confusable-table) + set(make_confusable_table $) + set(make_confusable_table_target clang-tidy-confusable-chars-gen) endif() add_subdirectory(ConfusableTable) diff --git a/clang-tools-extra/clang-tidy/misc/ConfusableTable/CMakeLists.txt b/clang-tools-extra/clang-tidy/misc/ConfusableTable/CMakeLists.txt index a35f206fbf783..f0ad2dbc0c578 100644 --- a/clang-tools-extra/clang-tidy/misc/ConfusableTable/CMakeLists.txt +++ b/clang-tools-extra/clang-tidy/misc/ConfusableTable/CMakeLists.txt @@ -1,6 +1,6 @@ set(LLVM_LINK_COMPONENTS Support) list(REMOVE_ITEM LLVM_COMMON_DEPENDS clang-tablegen-targets) -add_llvm_executable(make-confusable-table +add_llvm_executable(clang-tidy-confusable-chars-gen BuildConfusableTable.cpp ) diff --git a/llvm/utils/gn/secondary/clang-tools-extra/clang-tidy/misc/ConfusableTable/BUILD.gn b/llvm/utils/gn/secondary/clang-tools-extra/clang-tidy/misc/ConfusableTable/BUILD.gn index 10521474ce57e..25025c499f04a 100644 --- a/llvm/utils/gn/secondary/clang-tools-extra/clang-tidy/misc/ConfusableTable/BUILD.gn +++ b/llvm/utils/gn/secondary/clang-tools-extra/clang-tidy/misc/ConfusableTable/BUILD.gn @@ -1,4 +1,4 @@ -executable("make-confusable-table") { +executable("clang-tidy-confusable-chars-gen") { deps = [ "//llvm/lib/Support" ] sources = [ "BuildConfusableTable.cpp" ] } From 5e4e8822c4c4fe568607b4168ed2cf4cf559b4e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Thu, 14 Jul 2022 22:46:04 +0300 Subject: [PATCH 010/323] [clang-tidy] Add CLANG_TIDY_CONFUSABLE_CHARS_GEN cmake cache variable to avoid building when cross compiling This is similar to the LLVM_TABLEGEN, CLANG_TABLEGEN and CLANG_PSEUDO_GEN cmake cache variables. Differential Revision: https://reviews.llvm.org/D129799 (cherry picked from commit dc95d0c525636aed53a3b38258efa2dff4c83edf) --- clang-tools-extra/clang-tidy/misc/CMakeLists.txt | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/clang-tools-extra/clang-tidy/misc/CMakeLists.txt b/clang-tools-extra/clang-tidy/misc/CMakeLists.txt index ee8fe0b37fce9..de76b4b00c360 100644 --- a/clang-tools-extra/clang-tidy/misc/CMakeLists.txt +++ b/clang-tools-extra/clang-tidy/misc/CMakeLists.txt @@ -3,7 +3,13 @@ set(LLVM_LINK_COMPONENTS Support ) -if(LLVM_USE_HOST_TOOLS) +set(CLANG_TIDY_CONFUSABLE_CHARS_GEN "clang-tidy-confusable-chars-gen" CACHE + STRING "Host clang-tidy-confusable-chars-gen executable. Saves building if cross-compiling.") + +if(NOT CLANG_TIDY_CONFUSABLE_CHARS_GEN STREQUAL "clang-tidy-confusable-chars-gen") + set(make_confusable_table ${CLANG_TIDY_CONFUSABLE_CHARS_GEN}) + set(make_confusable_table_target ${CLANG_TIDY_CONFUSABLE_CHARS_GEN}) +elseif(LLVM_USE_HOST_TOOLS) build_native_tool(clang-tidy-confusable-chars-gen make_confusable_table) set(make_confusable_table_target "${make_confusable_table}") else() From fd8fd9e51cbeb76d290ceda941fd8b7d5a4151bc Mon Sep 17 00:00:00 2001 From: Joseph Huber Date: Wed, 27 Jul 2022 11:04:25 -0400 Subject: [PATCH 011/323] Revert "[OpenMP] Remove noinline attributes in the device runtime" The behaviour of this patch is not great, but it has some side-effects that are required for OpenMPOpt to work. The problem is that when we use `-mlink-builtin-bitcode` we only import used symbols from the runtime. Then OpenMPOpt will insert calls to symbols that were not previously included. This patch removed this implicit behaviour as these functions were kept alive by the `noinline` simply because it kept calls to them in the module. This caused regression in some tests that relied on some OpenMPOpt passes without using LTO. Reverting for the LLVM15 release but will try to fix it more correctly on main. This reverts commit d61d72dae604c3258e25c00622b1a85861450303. Fixes #56752 (cherry picked from commit b08369f7f288b6efb0897953da42ed54e60cfc0b) --- llvm/lib/Transforms/IPO/OpenMPOpt.cpp | 12 +++ .../OpenMP/remove_noinline_attributes.ll | 99 +++++++++++++++++++ .../DeviceRTL/include/Synchronization.h | 6 +- openmp/libomptarget/DeviceRTL/src/Mapping.cpp | 6 +- .../DeviceRTL/src/Parallelism.cpp | 5 +- openmp/libomptarget/DeviceRTL/src/State.cpp | 4 +- .../DeviceRTL/src/Synchronization.cpp | 6 +- 7 files changed, 127 insertions(+), 11 deletions(-) create mode 100644 llvm/test/Transforms/OpenMP/remove_noinline_attributes.ll diff --git a/llvm/lib/Transforms/IPO/OpenMPOpt.cpp b/llvm/lib/Transforms/IPO/OpenMPOpt.cpp index ef2384faa2730..0b42fc1519918 100644 --- a/llvm/lib/Transforms/IPO/OpenMPOpt.cpp +++ b/llvm/lib/Transforms/IPO/OpenMPOpt.cpp @@ -499,6 +499,18 @@ struct OMPInformationCache : public InformationCache { } #include "llvm/Frontend/OpenMP/OMPKinds.def" + // Remove the `noinline` attribute from `__kmpc`, `_OMP::` and `omp_` + // functions, except if `optnone` is present. + if (isOpenMPDevice(M)) { + for (Function &F : M) { + for (StringRef Prefix : {"__kmpc", "_ZN4_OMP", "omp_"}) + if (F.hasFnAttribute(Attribute::NoInline) && + F.getName().startswith(Prefix) && + !F.hasFnAttribute(Attribute::OptimizeNone)) + F.removeFnAttr(Attribute::NoInline); + } + } + // TODO: We should attach the attributes defined in OMPKinds.def. } diff --git a/llvm/test/Transforms/OpenMP/remove_noinline_attributes.ll b/llvm/test/Transforms/OpenMP/remove_noinline_attributes.ll new file mode 100644 index 0000000000000..349e2799de27a --- /dev/null +++ b/llvm/test/Transforms/OpenMP/remove_noinline_attributes.ll @@ -0,0 +1,99 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-attributes +; RUN: opt < %s -S -openmp-opt-cgscc | FileCheck %s +; RUN: opt < %s -S -passes=openmp-opt-cgscc | FileCheck %s + +declare void @unknown() + +; __kmpc functions +define void @__kmpc_noinline() noinline nounwind { +; CHECK: Function Attrs: nounwind +; CHECK-LABEL: @__kmpc_noinline( +; CHECK-NEXT: call void @unknown() +; CHECK-NEXT: ret void +; + call void @unknown() + ret void +} +; omp_X functions +define void @omp_noinline() noinline nounwind { +; CHECK: Function Attrs: nounwind +; CHECK-LABEL: @omp_noinline( +; CHECK-NEXT: call void @unknown() +; CHECK-NEXT: ret void +; + call void @unknown() + ret void +} +; _OMP namespace +define void @_ZN4_OMP_noinline() noinline nounwind { +; CHECK: Function Attrs: nounwind +; CHECK-LABEL: @_ZN4_OMP_noinline( +; CHECK-NEXT: call void @unknown() +; CHECK-NEXT: ret void +; + call void @unknown() + ret void +} + +; Negative tests: + +define void @__kmpc_noinline_optnone() noinline optnone nounwind { +; CHECK: Function Attrs: noinline nounwind optnone +; CHECK-LABEL: @__kmpc_noinline_optnone( +; CHECK-NEXT: call void @unknown() +; CHECK-NEXT: ret void +; + call void @unknown() + ret void +} +define void @omp_noinline_optnone() noinline optnone nounwind { +; CHECK: Function Attrs: noinline nounwind optnone +; CHECK-LABEL: @omp_noinline_optnone( +; CHECK-NEXT: call void @unknown() +; CHECK-NEXT: ret void +; + call void @unknown() + ret void +} +; _OMP namespace +define void @_ZN4_OMP_noinline_optnone() noinline optnone nounwind { +; CHECK: Function Attrs: noinline nounwind optnone +; CHECK-LABEL: @_ZN4_OMP_noinline_optnone( +; CHECK-NEXT: call void @unknown() +; CHECK-NEXT: ret void +; + call void @unknown() + ret void +} +define void @a___kmpc_noinline() noinline nounwind { +; CHECK: Function Attrs: noinline nounwind +; CHECK-LABEL: @a___kmpc_noinline( +; CHECK-NEXT: call void @unknown() +; CHECK-NEXT: ret void +; + call void @unknown() + ret void +} +define void @a_omp_noinline() noinline nounwind { +; CHECK: Function Attrs: noinline nounwind +; CHECK-LABEL: @a_omp_noinline( +; CHECK-NEXT: call void @unknown() +; CHECK-NEXT: ret void +; + call void @unknown() + ret void +} +define void @a__ZN4_OMP_noinline() noinline nounwind { +; CHECK: Function Attrs: noinline nounwind +; CHECK-LABEL: @a__ZN4_OMP_noinline( +; CHECK-NEXT: call void @unknown() +; CHECK-NEXT: ret void +; + call void @unknown() + ret void +} + +!llvm.module.flags = !{!0, !1} + +!0 = !{i32 7, !"openmp", i32 50} +!1 = !{i32 7, !"openmp-device", i32 50} diff --git a/openmp/libomptarget/DeviceRTL/include/Synchronization.h b/openmp/libomptarget/DeviceRTL/include/Synchronization.h index 4b8898f2ffb76..e33f37a659af2 100644 --- a/openmp/libomptarget/DeviceRTL/include/Synchronization.h +++ b/openmp/libomptarget/DeviceRTL/include/Synchronization.h @@ -29,13 +29,15 @@ void threads(); /// Synchronizing threads is allowed even if they all hit different instances of /// `synchronize::threads()`. However, `synchronize::threadsAligned()` is more -/// restrictive in that it requires all threads to hit the same instance. +/// restrictive in that it requires all threads to hit the same instance. The +/// noinline is removed by the openmp-opt pass and helps to preserve the +/// information till then. ///{ #pragma omp begin assumes ext_aligned_barrier /// Synchronize all threads in a block, they are are reaching the same /// instruction (hence all threads in the block are "aligned"). -void threadsAligned(); +__attribute__((noinline)) void threadsAligned(); #pragma omp end assumes ///} diff --git a/openmp/libomptarget/DeviceRTL/src/Mapping.cpp b/openmp/libomptarget/DeviceRTL/src/Mapping.cpp index b161c55382236..172bbbff68f8e 100644 --- a/openmp/libomptarget/DeviceRTL/src/Mapping.cpp +++ b/openmp/libomptarget/DeviceRTL/src/Mapping.cpp @@ -289,17 +289,17 @@ bool mapping::isGenericMode() { return !isSPMDMode(); } ///} extern "C" { -uint32_t __kmpc_get_hardware_thread_id_in_block() { +__attribute__((noinline)) uint32_t __kmpc_get_hardware_thread_id_in_block() { FunctionTracingRAII(); return mapping::getThreadIdInBlock(); } -uint32_t __kmpc_get_hardware_num_threads_in_block() { +__attribute__((noinline)) uint32_t __kmpc_get_hardware_num_threads_in_block() { FunctionTracingRAII(); return impl::getNumHardwareThreadsInBlock(); } -uint32_t __kmpc_get_warp_size() { +__attribute__((noinline)) uint32_t __kmpc_get_warp_size() { FunctionTracingRAII(); return impl::getWarpSize(); } diff --git a/openmp/libomptarget/DeviceRTL/src/Parallelism.cpp b/openmp/libomptarget/DeviceRTL/src/Parallelism.cpp index 5b133b009a7f7..27d1ff2e5a55c 100644 --- a/openmp/libomptarget/DeviceRTL/src/Parallelism.cpp +++ b/openmp/libomptarget/DeviceRTL/src/Parallelism.cpp @@ -243,7 +243,8 @@ void __kmpc_parallel_51(IdentTy *ident, int32_t, int32_t if_expr, __kmpc_end_sharing_variables(); } -bool __kmpc_kernel_parallel(ParallelRegionFnTy *WorkFn) { +__attribute__((noinline)) bool +__kmpc_kernel_parallel(ParallelRegionFnTy *WorkFn) { FunctionTracingRAII(); // Work function and arguments for L1 parallel region. *WorkFn = state::ParallelRegionFn; @@ -258,7 +259,7 @@ bool __kmpc_kernel_parallel(ParallelRegionFnTy *WorkFn) { return ThreadIsActive; } -void __kmpc_kernel_end_parallel() { +__attribute__((noinline)) void __kmpc_kernel_end_parallel() { FunctionTracingRAII(); // In case we have modified an ICV for this thread before a ThreadState was // created. We drop it now to not contaminate the next parallel region. diff --git a/openmp/libomptarget/DeviceRTL/src/State.cpp b/openmp/libomptarget/DeviceRTL/src/State.cpp index 92847f79829de..7a73330aa4cc0 100644 --- a/openmp/libomptarget/DeviceRTL/src/State.cpp +++ b/openmp/libomptarget/DeviceRTL/src/State.cpp @@ -393,12 +393,12 @@ int omp_get_initial_device(void) { return -1; } } extern "C" { -void *__kmpc_alloc_shared(uint64_t Bytes) { +__attribute__((noinline)) void *__kmpc_alloc_shared(uint64_t Bytes) { FunctionTracingRAII(); return memory::allocShared(Bytes, "Frontend alloc shared"); } -void __kmpc_free_shared(void *Ptr, uint64_t Bytes) { +__attribute__((noinline)) void __kmpc_free_shared(void *Ptr, uint64_t Bytes) { FunctionTracingRAII(); memory::freeShared(Ptr, Bytes, "Frontend free shared"); } diff --git a/openmp/libomptarget/DeviceRTL/src/Synchronization.cpp b/openmp/libomptarget/DeviceRTL/src/Synchronization.cpp index 350da0b460f15..43278715be8d1 100644 --- a/openmp/libomptarget/DeviceRTL/src/Synchronization.cpp +++ b/openmp/libomptarget/DeviceRTL/src/Synchronization.cpp @@ -358,12 +358,14 @@ void __kmpc_barrier(IdentTy *Loc, int32_t TId) { impl::namedBarrier(); } -void __kmpc_barrier_simple_spmd(IdentTy *Loc, int32_t TId) { +__attribute__((noinline)) void __kmpc_barrier_simple_spmd(IdentTy *Loc, + int32_t TId) { FunctionTracingRAII(); synchronize::threadsAligned(); } -void __kmpc_barrier_simple_generic(IdentTy *Loc, int32_t TId) { +__attribute__((noinline)) void __kmpc_barrier_simple_generic(IdentTy *Loc, + int32_t TId) { FunctionTracingRAII(); synchronize::threads(); } From b128f6feaa467e9f1f53c995848b7b750d00dd23 Mon Sep 17 00:00:00 2001 From: Jez Ng Date: Sun, 31 Jul 2022 13:24:58 -0400 Subject: [PATCH 012/323] [lld-macho] Release notes for 15.x From inspection of git log origin/release/14.x..origin/release/15.x -- lld/MachO Reviewed By: #lld-macho, thakis Differential Revision: https://reviews.llvm.org/D130850 --- lld/docs/ReleaseNotes.rst | 111 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) diff --git a/lld/docs/ReleaseNotes.rst b/lld/docs/ReleaseNotes.rst index 936d800cabc37..6cc4cb465ad71 100644 --- a/lld/docs/ReleaseNotes.rst +++ b/lld/docs/ReleaseNotes.rst @@ -71,6 +71,117 @@ MachO Improvements (`D129540 `_, `D122258 `_) +New flags +######### + +* ``-load_hidden`` and ``-hidden-l`` are now supported. + (`D130473 `_, + `D130529 `_) +* ``-alias`` is now supported. (`D129938 `_) +* ``-no_exported_symbols`` and ``-exported_symbols_list `` are now + supported. (`D127562 `_) +* ``-w`` -- to suppress warnings -- is now supported. + (`D127564 `_) +* ``-non_global_symbols_strip_list``, ``-non_global_symbols_no_strip_list``, and + ``-x`` are now supported. (`D126046 `_) +* ``--icf=safe`` is now supported. + (`D128938 `_, + `D123752 `_) +* ``-why_live`` is now supported. + (`D120377 `_) +* ``-pagezero_size`` is now supported. + (`D118724 `_) + +Improvements +############ + +* Linker optimization hints are now supported. + (`D129427 `_, + `D129059 `_, + `D128942 `_, + `D128093 `_) +* Rebase opcodes are now encoded more compactly. + (`D130180 `_, + `D128798 `_) +* C-strings are now aligned more compactly. + (`D121342 `_) +* ``--deduplicate-literals`` (and ``--icf={safe,all}``) now fold the + ``__cfstring`` section. + (`D130134 `_, + `D120137 `_) +* ICF now folds the ``__objc_classrefs`` section. + (`D121053 `_) +* ICF now folds functions with identical LSDAs. + (`D129830 `_) +* STABS entries for folded functions are now omitted. + (`D123252 `_) +* ``__objc_imageinfo`` sections are now folded. + (`D130125 `_) +* Dylibs with ``LC_DYLD_EXPORTS_TRIE`` can now be read. + (`D129430 `_) +* Writing zippered dylibs is now supported. + (`D124887 `_) +* C-string literals are now included in the mapfile. + (`D118077 `_) +* Symbol names in several more diagnostics are now demangled. + (`D130490 `_, + `D127110 `_, + `D125732 `_) +* Source information is now included in symbol error messages. + (`D128425 `_, + `D128184 `_) +* Numerous other improvements were made to diagnostic messages. + (`D127753 `_, + `D127696 `_, + `D127670 `_, + `D118903 `_, + `D118798 `_) +* Many performance and memory improvements were made. + (`D130000 `_, + `D128298 `_, + `D128290 `_, + `D126800 `_, + `D126785 `_, + `D121052 `_) +* Order files and call graph sorting can now be used together. + (`D117354 `_) +* Give LTO more precise symbol resolutions, which allows optimizations to be + more effective. + (`D119506 `_, + `D119372 `_, + `D119767 `_) +* Added partial support for linking object files built with DTrace probes. + (`D129062 `_) + +Fixes +##### + +* Programs using Swift linked with the 14.0 SDK but an older deployment target + no longer crash at startup when running on older iOS versions. This is because + we now correctly support ``$ld$previous`` symbols that contain an explicit + symbol name. (`D130725 `_) +* Match ld64's behavior when an archive is specified both via + ``LC_LINKER_OPTION`` and via the command line. + (`D129556 `_) +* ``-ObjC`` now correctly loads archives with Swift sections. + (`D125250 `_) +* ``-lto_object_path`` now accepts a filename (instead of just a directory + name.) (`D129705 `_) +* The ``LC_UUID`` hash now includes the output file's name. + (`D122843 `_) +* ``-flat_namespace`` now correctly makes all extern symbols in a dylib + interposable. (`D119294 `_) +* Fixed compact unwind output when linking on 32-bit hosts. + (`D129363 `_) +* Exporting private symbols no longer triggers an assertion. + (`D124143 `_) +* MacOS-only ``.tbd`` files are now supported when targeting Catalyst. + (`D124336 `_) +* Thunk symbols now have local visibility, avoiding false duplicate symbol + errors. (`D122624 `_) +* Fixed handling of relocatable object files within frameworks. + (`D114841 `_) + WebAssembly Improvements ------------------------ From 3928c126568de5f45d46c68cff12dbc88a40a250 Mon Sep 17 00:00:00 2001 From: Sunho Kim Date: Tue, 2 Aug 2022 08:44:18 +0900 Subject: [PATCH 013/323] [IntelJITEvents] Add missing include. Fixes compilation error. Differential Revision: https://reviews.llvm.org/D130898 (cherry picked from commit 5680ef870f9058c4b52a09a6aec2ddf384c5a558) --- .../lib/ExecutionEngine/IntelJITEvents/IntelJITEventListener.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/llvm/lib/ExecutionEngine/IntelJITEvents/IntelJITEventListener.cpp b/llvm/lib/ExecutionEngine/IntelJITEvents/IntelJITEventListener.cpp index 3f75012f5cf96..4afcf95e9e8e8 100644 --- a/llvm/lib/ExecutionEngine/IntelJITEvents/IntelJITEventListener.cpp +++ b/llvm/lib/ExecutionEngine/IntelJITEvents/IntelJITEventListener.cpp @@ -24,6 +24,7 @@ #include "llvm/IR/Function.h" #include "llvm/IR/Metadata.h" #include "llvm/IR/ValueHandle.h" +#include "llvm/Object/ELFObjectFile.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Object/SymbolSize.h" #include "llvm/Support/Debug.h" From 73d45fea656b1c15c20dd96b386d6004638ae7f3 Mon Sep 17 00:00:00 2001 From: Rainer Orth Date: Wed, 27 Jul 2022 12:30:18 +0200 Subject: [PATCH 014/323] [compiler-rt][Sanitizer] Link sanitizer libs with -latomic on SPARC When building on Linux/sparc64, the 32-bit `libclang_rt.asan.so`, `libclang_rt.ubsan_minimal.so`, and `libclang_rt.ubsan_standalone.so` failed to link with undefined references to 64-bit atomics, which `clang` cannot inline. Even D130569 didn't help because those libraries are linked with `-nodefaultlibs`, so dependent libraries need to be added explicitly. That's what this patch does. Tested on `sparc64-unknown-linux-gnu` and `sparcv9-sun-solaris2.11`. Differential Revision: https://reviews.llvm.org/D130571 (cherry picked from commit 0b2d5fd48bc281af89e5e7bfa33a3054b826ed52) --- compiler-rt/CMakeLists.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/compiler-rt/CMakeLists.txt b/compiler-rt/CMakeLists.txt index 4a572bc005fe8..62737735695f2 100644 --- a/compiler-rt/CMakeLists.txt +++ b/compiler-rt/CMakeLists.txt @@ -479,6 +479,12 @@ append_list_if(MINGW -fms-extensions SANITIZER_COMMON_CFLAGS) append_list_if(C_SUPPORTS_NODEFAULTLIBS_FLAG -nodefaultlibs SANITIZER_COMMON_LINK_FLAGS) append_list_if(COMPILER_RT_HAS_Z_TEXT -Wl,-z,text SANITIZER_COMMON_LINK_FLAGS) +# Only necessary for 32-bit SPARC. Solaris 11.2+ ld uses -z ignore/-z record +# natively, but supports --as-needed/--no-as-needed for GNU ld compatibility. +if("${COMPILER_RT_DEFAULT_TARGET_ARCH}" MATCHES "sparc") + list(APPEND SANITIZER_COMMON_LINK_LIBS -Wl,--as-needed atomic -Wl,--no-as-needed) +endif() + if (COMPILER_RT_USE_BUILTINS_LIBRARY) string(REPLACE "-Wl,-z,defs" "" CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS}") else() From 12e4e9777975858ea7f5f2a80157b0543c1f0c72 Mon Sep 17 00:00:00 2001 From: Rainer Orth Date: Wed, 27 Jul 2022 12:21:03 +0200 Subject: [PATCH 015/323] [Support] Handle SPARC in sys::getHostCPUName While working on D118450 , I noticed that `sys::getHostCPUName` lacks SPARC support. This patch implements it. The code is taken from/inspired by GCC's `gcc/config/sparc/driver-sparc.cc`. There's one caveat: since LLVM, unlike GCC, doesn't support the SPARC-M7, -S7, and -M8 CPUs, I map all those to the latest supported one (UltraSparc T4/`niagara4`). Tested on `sparcv9-sun-solaris2.11` and `sparc64-unknown-linux-gnu` by running `savcov --version` on - Netra SPARC S7-2 (SPARC-S7, Solaris 11.4) - SPARC T5-2 (SPARC T5, Solaris 11.4) - SPARC Enterprise T5220 (UltraSPARC T2, Solaris 11.3) - SPARC T5 (UltraSPARC T5, Debian sid) - SPARC T3 (UltraSPARC T3, Debian sid) - SPARC Enterprise T5220 (Debian sid) Differential Revision: https://reviews.llvm.org/D130272 (cherry picked from commit 979ddfff37d7e3bf258c2e5cbdc272fcb44c15f0) --- llvm/include/llvm/Support/Host.h | 1 + llvm/lib/Support/CMakeLists.txt | 3 + llvm/lib/Support/Host.cpp | 108 +++++++++++++++++++++++++++++++ 3 files changed, 112 insertions(+) diff --git a/llvm/include/llvm/Support/Host.h b/llvm/include/llvm/Support/Host.h index f683371ad1d36..369d6745db5ae 100644 --- a/llvm/include/llvm/Support/Host.h +++ b/llvm/include/llvm/Support/Host.h @@ -65,6 +65,7 @@ namespace sys { StringRef getHostCPUNameForARM(StringRef ProcCpuinfoContent); StringRef getHostCPUNameForS390x(StringRef ProcCpuinfoContent); StringRef getHostCPUNameForRISCV(StringRef ProcCpuinfoContent); + StringRef getHostCPUNameForSPARC(StringRef ProcCpuinfoContent); StringRef getHostCPUNameForBPF(); /// Helper functions to extract CPU details from CPUID on x86. diff --git a/llvm/lib/Support/CMakeLists.txt b/llvm/lib/Support/CMakeLists.txt index b2447cd168652..5044b2639a0f7 100644 --- a/llvm/lib/Support/CMakeLists.txt +++ b/llvm/lib/Support/CMakeLists.txt @@ -58,6 +58,9 @@ elseif( CMAKE_HOST_UNIX ) if( UNIX AND NOT (BEOS OR HAIKU) ) set(system_libs ${system_libs} m) endif() + if( UNIX AND ${CMAKE_SYSTEM_NAME} MATCHES "SunOS" ) + set(system_libs ${system_libs} kstat) + endif() if( FUCHSIA ) set(system_libs ${system_libs} zircon) endif() diff --git a/llvm/lib/Support/Host.cpp b/llvm/lib/Support/Host.cpp index 08e3a27e0173a..c97f273b07398 100644 --- a/llvm/lib/Support/Host.cpp +++ b/llvm/lib/Support/Host.cpp @@ -47,6 +47,9 @@ #ifdef _AIX #include #endif +#if defined(__sun__) && defined(__svr4__) +#include +#endif #define DEBUG_TYPE "host-detection" @@ -1413,6 +1416,111 @@ StringRef sys::getHostCPUName() { #endif #endif } +#elif defined(__sparc__) +#if defined(__linux__) +StringRef sys::detail::getHostCPUNameForSPARC(StringRef ProcCpuinfoContent) { + SmallVector Lines; + ProcCpuinfoContent.split(Lines, "\n"); + + // Look for cpu line to determine cpu name + StringRef Cpu; + for (unsigned I = 0, E = Lines.size(); I != E; ++I) { + if (Lines[I].startswith("cpu")) { + Cpu = Lines[I].substr(5).ltrim("\t :"); + break; + } + } + + return StringSwitch(Cpu) + .StartsWith("SuperSparc", "supersparc") + .StartsWith("HyperSparc", "hypersparc") + .StartsWith("SpitFire", "ultrasparc") + .StartsWith("BlackBird", "ultrasparc") + .StartsWith("Sabre", " ultrasparc") + .StartsWith("Hummingbird", "ultrasparc") + .StartsWith("Cheetah", "ultrasparc3") + .StartsWith("Jalapeno", "ultrasparc3") + .StartsWith("Jaguar", "ultrasparc3") + .StartsWith("Panther", "ultrasparc3") + .StartsWith("Serrano", "ultrasparc3") + .StartsWith("UltraSparc T1", "niagara") + .StartsWith("UltraSparc T2", "niagara2") + .StartsWith("UltraSparc T3", "niagara3") + .StartsWith("UltraSparc T4", "niagara4") + .StartsWith("UltraSparc T5", "niagara4") + .StartsWith("LEON", "leon3") + // niagara7/m8 not supported by LLVM yet. + .StartsWith("SPARC-M7", "niagara4" /* "niagara7" */) + .StartsWith("SPARC-S7", "niagara4" /* "niagara7" */) + .StartsWith("SPARC-M8", "niagara4" /* "m8" */) + .Default("generic"); +} +#endif + +StringRef sys::getHostCPUName() { +#if defined(__linux__) + std::unique_ptr P = getProcCpuinfoContent(); + StringRef Content = P ? P->getBuffer() : ""; + return detail::getHostCPUNameForSPARC(Content); +#elif defined(__sun__) && defined(__svr4__) + char *buf = NULL; + kstat_ctl_t *kc; + kstat_t *ksp; + kstat_named_t *brand = NULL; + + kc = kstat_open(); + if (kc != NULL) { + ksp = kstat_lookup(kc, const_cast("cpu_info"), -1, NULL); + if (ksp != NULL && kstat_read(kc, ksp, NULL) != -1 && + ksp->ks_type == KSTAT_TYPE_NAMED) + brand = + (kstat_named_t *)kstat_data_lookup(ksp, const_cast("brand")); + if (brand != NULL && brand->data_type == KSTAT_DATA_STRING) + buf = KSTAT_NAMED_STR_PTR(brand); + } + kstat_close(kc); + + return StringSwitch(buf) + .Case("TMS390S10", "supersparc") // Texas Instruments microSPARC I + .Case("TMS390Z50", "supersparc") // Texas Instruments SuperSPARC I + .Case("TMS390Z55", + "supersparc") // Texas Instruments SuperSPARC I with SuperCache + .Case("MB86904", "supersparc") // Fujitsu microSPARC II + .Case("MB86907", "supersparc") // Fujitsu TurboSPARC + .Case("RT623", "hypersparc") // Ross hyperSPARC + .Case("RT625", "hypersparc") + .Case("RT626", "hypersparc") + .Case("UltraSPARC-I", "ultrasparc") + .Case("UltraSPARC-II", "ultrasparc") + .Case("UltraSPARC-IIe", "ultrasparc") + .Case("UltraSPARC-IIi", "ultrasparc") + .Case("SPARC64-III", "ultrasparc") + .Case("SPARC64-IV", "ultrasparc") + .Case("UltraSPARC-III", "ultrasparc3") + .Case("UltraSPARC-III+", "ultrasparc3") + .Case("UltraSPARC-IIIi", "ultrasparc3") + .Case("UltraSPARC-IIIi+", "ultrasparc3") + .Case("UltraSPARC-IV", "ultrasparc3") + .Case("UltraSPARC-IV+", "ultrasparc3") + .Case("SPARC64-V", "ultrasparc3") + .Case("SPARC64-VI", "ultrasparc3") + .Case("SPARC64-VII", "ultrasparc3") + .Case("UltraSPARC-T1", "niagara") + .Case("UltraSPARC-T2", "niagara2") + .Case("UltraSPARC-T2", "niagara2") + .Case("UltraSPARC-T2+", "niagara2") + .Case("SPARC-T3", "niagara3") + .Case("SPARC-T4", "niagara4") + .Case("SPARC-T5", "niagara4") + // niagara7/m8 not supported by LLVM yet. + .Case("SPARC-M7", "niagara4" /* "niagara7" */) + .Case("SPARC-S7", "niagara4" /* "niagara7" */) + .Case("SPARC-M8", "niagara4" /* "m8" */) + .Default("generic"); +#else + return "generic"; +#endif +} #else StringRef sys::getHostCPUName() { return "generic"; } namespace llvm { From 0b96bce063b1cb0c118c94704b7ca778b687b239 Mon Sep 17 00:00:00 2001 From: Rainer Orth Date: Fri, 29 Jul 2022 09:19:38 +0200 Subject: [PATCH 016/323] [Driver] Use libatomic for 32-bit SPARC atomics support on Linux This is the Linux/sparc64 equivalent to D118021 , necessary to provide an external implementation of atomics on 32-bit SPARC which LLVM cannot inline even with `-mcpu=v9` or an equivalent default. Tested on `sparc64-unknown-linux-gnu`. Differential Revision: https://reviews.llvm.org/D130569 (cherry picked from commit 9b1897bbd0e3a6e9ef099e74c3d3ed35428c0460) --- clang/lib/Driver/ToolChains/Gnu.cpp | 10 ++++++++++ clang/test/Driver/linux-ld.c | 2 ++ 2 files changed, 12 insertions(+) diff --git a/clang/lib/Driver/ToolChains/Gnu.cpp b/clang/lib/Driver/ToolChains/Gnu.cpp index 34396b0b59c2b..f203cae1d329f 100644 --- a/clang/lib/Driver/ToolChains/Gnu.cpp +++ b/clang/lib/Driver/ToolChains/Gnu.cpp @@ -631,6 +631,16 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA, AddRunTimeLibs(ToolChain, D, CmdArgs, Args); + // LLVM support for atomics on 32-bit SPARC V8+ is incomplete, so + // forcibly link with libatomic as a workaround. + // TODO: Issue #41880 and D118021. + if (getToolChain().getTriple().getArch() == llvm::Triple::sparc) { + CmdArgs.push_back("--push-state"); + CmdArgs.push_back("--as-needed"); + CmdArgs.push_back("-latomic"); + CmdArgs.push_back("--pop-state"); + } + if (WantPthread && !isAndroid) CmdArgs.push_back("-lpthread"); diff --git a/clang/test/Driver/linux-ld.c b/clang/test/Driver/linux-ld.c index d7c58431fa76f..e76b35d6137c7 100644 --- a/clang/test/Driver/linux-ld.c +++ b/clang/test/Driver/linux-ld.c @@ -1007,6 +1007,7 @@ // CHECK-SPARCV8: "{{.*}}ld{{(.exe)?}}" // CHECK-SPARCV8: "-m" "elf32_sparc" // CHECK-SPARCV8: "-dynamic-linker" "{{(/usr/sparc-unknown-linux-gnu)?}}/lib/ld-linux.so.2" +// CHECK-SPARCV8: "--push-state" "--as-needed" "-latomic" "--pop-state" // // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=sparcel-unknown-linux-gnu \ @@ -1021,6 +1022,7 @@ // CHECK-SPARCV9: "{{.*}}ld{{(.exe)?}}" // CHECK-SPARCV9: "-m" "elf64_sparc" // CHECK-SPARCV9: "-dynamic-linker" "{{(/usr/sparcv9-unknown-linux-gnu)?}}/lib{{(64)?}}/ld-linux.so.2" +// CHECK-SPARCV9-NOT: "-latomic" // Test linker invocation on Android. // RUN: %clang -### %s -no-pie 2>&1 \ From b00211d9dc994139520bc83b4cbeb621ed9b9fec Mon Sep 17 00:00:00 2001 From: Rainer Orth Date: Fri, 29 Jul 2022 09:27:09 +0200 Subject: [PATCH 017/323] [clang][Driver] Handle SPARC -mcpu=native etc. To make use of SPARC support in `getHostCPUName` as implemented by D130272 , this patch uses it to handle `-mcpu=native` and `-mtune=native`. To match GCC, this patch rejects `-march` instead of silently treating it as a no-op. Tested on `sparcv9-sun-solaris2.11` and checking that those options are passed on as `-target-cpu` resp. `-tune-cpu` as expected. Differential Revision: https://reviews.llvm.org/D130273 (cherry picked from commit bf3714884ae4b4a0301bc6af78e8b4deff12558b) --- clang/lib/Driver/ToolChains/Arch/Sparc.cpp | 25 ++++++++++++++++++++++ clang/lib/Driver/ToolChains/Arch/Sparc.h | 3 +++ clang/lib/Driver/ToolChains/Clang.cpp | 12 +++++++++++ clang/lib/Driver/ToolChains/CommonArgs.cpp | 11 +++++----- clang/test/Driver/sparc-march.c | 4 ++++ clang/test/Driver/sparc-mcpu.c | 21 ++++++++++++++++++ clang/test/Driver/sparc-mtune.c | 21 ++++++++++++++++++ 7 files changed, 92 insertions(+), 5 deletions(-) create mode 100644 clang/test/Driver/sparc-march.c create mode 100644 clang/test/Driver/sparc-mcpu.c create mode 100644 clang/test/Driver/sparc-mtune.c diff --git a/clang/lib/Driver/ToolChains/Arch/Sparc.cpp b/clang/lib/Driver/ToolChains/Arch/Sparc.cpp index 70ba8eb2a7d0d..2c9d65e7714a2 100644 --- a/clang/lib/Driver/ToolChains/Arch/Sparc.cpp +++ b/clang/lib/Driver/ToolChains/Arch/Sparc.cpp @@ -12,6 +12,7 @@ #include "clang/Driver/Options.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/Option/ArgList.h" +#include "llvm/Support/Host.h" using namespace clang::driver; using namespace clang::driver::tools; @@ -113,6 +114,30 @@ sparc::FloatABI sparc::getSparcFloatABI(const Driver &D, return ABI; } +std::string sparc::getSparcTargetCPU(const Driver &D, const ArgList &Args, + const llvm::Triple &Triple) { + if (const Arg *A = Args.getLastArg(clang::driver::options::OPT_march_EQ)) { + D.Diag(diag::err_drv_unsupported_opt_for_target) + << A->getSpelling() << Triple.getTriple(); + return ""; + } + + if (const Arg *A = Args.getLastArg(clang::driver::options::OPT_mcpu_EQ)) { + StringRef CPUName = A->getValue(); + if (CPUName == "native") { + std::string CPU = std::string(llvm::sys::getHostCPUName()); + if (!CPU.empty() && CPU != "generic") + return CPU; + return ""; + } + return std::string(CPUName); + } + + if (Triple.getArch() == llvm::Triple::sparc && Triple.isOSSolaris()) + return "v9"; + return ""; +} + void sparc::getSparcTargetFeatures(const Driver &D, const ArgList &Args, std::vector &Features) { sparc::FloatABI FloatABI = sparc::getSparcFloatABI(D, Args); diff --git a/clang/lib/Driver/ToolChains/Arch/Sparc.h b/clang/lib/Driver/ToolChains/Arch/Sparc.h index d12a9a70e264c..44658c4259c69 100644 --- a/clang/lib/Driver/ToolChains/Arch/Sparc.h +++ b/clang/lib/Driver/ToolChains/Arch/Sparc.h @@ -28,6 +28,9 @@ enum class FloatABI { FloatABI getSparcFloatABI(const Driver &D, const llvm::opt::ArgList &Args); +std::string getSparcTargetCPU(const Driver &D, const llvm::opt::ArgList &Args, + const llvm::Triple &Triple); + void getSparcTargetFeatures(const Driver &D, const llvm::opt::ArgList &Args, std::vector &Features); const char *getSparcAsmModeForCPU(llvm::StringRef Name, diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index b62a025c50729..a97db90518ac7 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -2205,6 +2205,18 @@ void Clang::AddSparcTargetArgs(const ArgList &Args, CmdArgs.push_back("-mfloat-abi"); CmdArgs.push_back("hard"); } + + if (const Arg *A = Args.getLastArg(clang::driver::options::OPT_mtune_EQ)) { + StringRef Name = A->getValue(); + std::string TuneCPU; + if (Name == "native") + TuneCPU = std::string(llvm::sys::getHostCPUName()); + else + TuneCPU = std::string(Name); + + CmdArgs.push_back("-tune-cpu"); + CmdArgs.push_back(Args.MakeArgString(TuneCPU)); + } } void Clang::AddSystemZTargetArgs(const ArgList &Args, diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp index 1d2c085d683e1..443725f7d8a8d 100644 --- a/clang/lib/Driver/ToolChains/CommonArgs.cpp +++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp @@ -12,6 +12,7 @@ #include "Arch/M68k.h" #include "Arch/Mips.h" #include "Arch/PPC.h" +#include "Arch/Sparc.h" #include "Arch/SystemZ.h" #include "Arch/VE.h" #include "Arch/X86.h" @@ -431,15 +432,15 @@ std::string tools::getCPUName(const Driver &D, const ArgList &Args, case llvm::Triple::bpfel: case llvm::Triple::bpfeb: - case llvm::Triple::sparc: - case llvm::Triple::sparcel: - case llvm::Triple::sparcv9: if (const Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) return A->getValue(); - if (T.getArch() == llvm::Triple::sparc && T.isOSSolaris()) - return "v9"; return ""; + case llvm::Triple::sparc: + case llvm::Triple::sparcel: + case llvm::Triple::sparcv9: + return sparc::getSparcTargetCPU(D, Args, T); + case llvm::Triple::x86: case llvm::Triple::x86_64: return x86::getX86TargetCPU(D, Args, T); diff --git a/clang/test/Driver/sparc-march.c b/clang/test/Driver/sparc-march.c new file mode 100644 index 0000000000000..9adde8bfd6c56 --- /dev/null +++ b/clang/test/Driver/sparc-march.c @@ -0,0 +1,4 @@ +// RUN: %clang -target sparcv9 -march=v9 -### -c %s 2>&1 | FileCheck %s +// RUN: %clang -target sparc64 -march=v9 -### -c %s 2>&1 | FileCheck %s +// RUN: %clang -target sparc -march=v9 -### -c %s 2>&1 | FileCheck %s +// CHECK: error: unsupported option '-march=' for target diff --git a/clang/test/Driver/sparc-mcpu.c b/clang/test/Driver/sparc-mcpu.c new file mode 100644 index 0000000000000..92421f16e997d --- /dev/null +++ b/clang/test/Driver/sparc-mcpu.c @@ -0,0 +1,21 @@ +// RUN: %clang -target sparcv9 -### -c %s 2>&1 | FileCheck -check-prefix=SPARCV9 %s +// SPARCV9: "-cc1"{{.*}} "-triple" "sparcv9" + +// RUN: %clang -target sparc64 -### -c %s 2>&1 | FileCheck -check-prefix=SPARC64 %s +// SPARC64: "-cc1"{{.*}} "-triple" "sparc64" + +// RUN: %clang -target sparcv9 -mcpu=v9 -### -c %s 2>&1 | FileCheck -check-prefix=SPARCV9_V9 %s +// SPARCV9_V9: "-cc1"{{.*}} "-triple" "sparcv9"{{.*}} "-target-cpu" "v9" + +// RUN: %clang -target sparcv9 -mcpu=ultrasparc -### -c %s 2>&1 | FileCheck -check-prefix=SPARCV9_US %s +// SPARCV9_US: "-cc1"{{.*}} "-triple" "sparcv9"{{.*}} "-target-cpu" "ultrasparc" + +// RUN: %clang -target sparc -### -c %s 2>&1 | FileCheck -check-prefix=SPARC %s +// SPARC: "-cc1"{{.*}} "-triple" "sparc" + +// RUN: %clang -target sparc -mcpu=v9 -### -c %s 2>&1 | FileCheck -check-prefix=SPARC_V9 %s +// SPARC_V9: "-cc1"{{.*}} "-triple" "sparc"{{.*}} "-target-cpu" "v9" + +// RUN: %clang -target sparc -mcpu=ultrasparc -### -c %s 2>&1 | FileCheck -check-prefix=SPARC_US %s +// SPARC_US: "-cc1"{{.*}} "-triple" "sparc"{{.*}} "-target-cpu" "ultrasparc" + diff --git a/clang/test/Driver/sparc-mtune.c b/clang/test/Driver/sparc-mtune.c new file mode 100644 index 0000000000000..94eb05b54f4f9 --- /dev/null +++ b/clang/test/Driver/sparc-mtune.c @@ -0,0 +1,21 @@ +// RUN: %clang -target sparcv9 -### -c %s 2>&1 | FileCheck -check-prefix=SPARCV9 %s +// SPARCV9: "-cc1"{{.*}} "-triple" "sparcv9" + +// RUN: %clang -target sparc64 -### -c %s 2>&1 | FileCheck -check-prefix=SPARC64 %s +// SPARC64: "-cc1"{{.*}} "-triple" "sparc64" + +// RUN: %clang -target sparcv9 -mtune=v9 -### -c %s 2>&1 | FileCheck -check-prefix=SPARCV9_V9 %s +// SPARCV9_V9: "-cc1"{{.*}} "-triple" "sparcv9"{{.*}} "-tune-cpu" "v9" + +// RUN: %clang -target sparcv9 -mtune=ultrasparc -### -c %s 2>&1 | FileCheck -check-prefix=SPARCV9_US %s +// SPARCV9_US: "-cc1"{{.*}} "-triple" "sparcv9"{{.*}} "-tune-cpu" "ultrasparc" + +// RUN: %clang -target sparc -### -c %s 2>&1 | FileCheck -check-prefix=SPARC %s +// SPARC: "-cc1"{{.*}} "-triple" "sparc" + +// RUN: %clang -target sparc -mtune=v9 -### -c %s 2>&1 | FileCheck -check-prefix=SPARC_V9 %s +// SPARC_V9: "-cc1"{{.*}} "-triple" "sparc"{{.*}} "-tune-cpu" "v9" + +// RUN: %clang -target sparc -mtune=ultrasparc -### -c %s 2>&1 | FileCheck -check-prefix=SPARC_US %s +// SPARC_US: "-cc1"{{.*}} "-triple" "sparc"{{.*}} "-tune-cpu" "ultrasparc" + From 08c239e29fb4ebc4970fbb041a027f8fffcc1a21 Mon Sep 17 00:00:00 2001 From: Nico Weber Date: Thu, 9 Jun 2022 12:13:31 -0400 Subject: [PATCH 018/323] [lld/mac] Add support for $ld$previous symbols with explicit symbol name A symbol `$ld$previous$/Another$1.2.3$1$3.0$14.0$_xxx$` means "pretend symbol `_xxx` is in dylib `/Another` with version `1.2.3` if the deployment target is between `3.0` and `14.0` and we're targeting platform `1` (ie macOS)". This means dylibs can now inject synthetic dylibs into the link, so DylibFile needs to grow a 3rd constructor. The only other interesting thing is that such an injected dylib counts as a use of the original dylib. This patch gets this mostly right (if _only_ `$ld$previous` symbols are used from a dylib, we don't add a dep on the dylib itself, matching ld64), but one case where we don't match ld64 yet is that ld64 even omits the original dylib when linking it with `-needed-l`. Lld currently still adds a load command for the original dylib in that case. (That's for a future patch.) Fixes #56074. Differential Revision: https://reviews.llvm.org/D130725 (cherry picked from commit 241f0e8b76d544a4a07a7f775b8421632539be19) --- lld/MachO/DriverUtils.cpp | 2 +- lld/MachO/InputFiles.cpp | 74 ++++++++++-- lld/MachO/InputFiles.h | 17 ++- lld/MachO/Writer.cpp | 122 +++++++++++--------- lld/test/MachO/special-symbol-ld-previous.s | 80 +++++++++++-- 5 files changed, 219 insertions(+), 76 deletions(-) diff --git a/lld/MachO/DriverUtils.cpp b/lld/MachO/DriverUtils.cpp index d8e474d15cfd3..b91a435524430 100644 --- a/lld/MachO/DriverUtils.cpp +++ b/lld/MachO/DriverUtils.cpp @@ -211,7 +211,7 @@ DylibFile *macho::loadDylib(MemoryBufferRef mbref, DylibFile *umbrella, DylibFile *&file = loadedDylibs[path]; if (file) { if (explicitlyLinked) - file->explicitlyLinked = explicitlyLinked; + file->setExplicitlyLinked(); return file; } diff --git a/lld/MachO/InputFiles.cpp b/lld/MachO/InputFiles.cpp index b463d78175944..cbb04a3bf04fa 100644 --- a/lld/MachO/InputFiles.cpp +++ b/lld/MachO/InputFiles.cpp @@ -1944,6 +1944,14 @@ DylibFile::DylibFile(const InterfaceFile &interface, DylibFile *umbrella, } } +DylibFile::DylibFile(DylibFile *umbrella) + : InputFile(DylibKind, MemoryBufferRef{}), refState(RefState::Unreferenced), + explicitlyLinked(false), isBundleLoader(false) { + if (umbrella == nullptr) + umbrella = this; + this->umbrella = umbrella; +} + void DylibFile::parseReexports(const InterfaceFile &interface) { const InterfaceFile *topLevel = interface.getParent() == nullptr ? &interface : interface.getParent(); @@ -1955,6 +1963,39 @@ void DylibFile::parseReexports(const InterfaceFile &interface) { } } +bool DylibFile::isExplicitlyLinked() const { + if (!explicitlyLinked) + return false; + + // If this dylib was explicitly linked, but at least one of the symbols + // of the synthetic dylibs it created via $ld$previous symbols is + // referenced, then that synthetic dylib fulfils the explicit linkedness + // and we can deadstrip this dylib if it's unreferenced. + for (const auto *dylib : extraDylibs) + if (dylib->isReferenced()) + return false; + + return true; +} + +DylibFile *DylibFile::getSyntheticDylib(StringRef installName, + uint32_t currentVersion, + uint32_t compatVersion) { + for (DylibFile *dylib : extraDylibs) + if (dylib->installName == installName) { + // FIXME: Check what to do if different $ld$previous symbols + // request the same dylib, but with different versions. + return dylib; + } + + auto *dylib = make(umbrella == this ? nullptr : umbrella); + dylib->installName = saver().save(installName); + dylib->currentVersion = currentVersion; + dylib->compatibilityVersion = compatVersion; + extraDylibs.push_back(dylib); + return dylib; +} + // $ld$ symbols modify the properties/behavior of the library (e.g. its install // name, compatibility version or hide/add symbols) for specific target // versions. @@ -1990,10 +2031,9 @@ void DylibFile::handleLDPreviousSymbol(StringRef name, StringRef originalName) { std::tie(platformStr, name) = name.split('$'); std::tie(startVersion, name) = name.split('$'); std::tie(endVersion, name) = name.split('$'); - std::tie(symbolName, rest) = name.split('$'); - // TODO: ld64 contains some logic for non-empty symbolName as well. - if (!symbolName.empty()) - return; + std::tie(symbolName, rest) = name.rsplit('$'); + + // FIXME: Does this do the right thing for zippered files? unsigned platform; if (platformStr.getAsInteger(10, platform) || platform != static_cast(config->platform())) @@ -2014,8 +2054,9 @@ void DylibFile::handleLDPreviousSymbol(StringRef name, StringRef originalName) { config->platformInfo.minimum >= end) return; - this->installName = saver().save(installName); - + // Initialized to compatibilityVersion for the symbolName branch below. + uint32_t newCompatibilityVersion = compatibilityVersion; + uint32_t newCurrentVersionForSymbol = currentVersion; if (!compatVersion.empty()) { VersionTuple cVersion; if (cVersion.tryParse(compatVersion)) { @@ -2023,8 +2064,27 @@ void DylibFile::handleLDPreviousSymbol(StringRef name, StringRef originalName) { "' ignored"); return; } - compatibilityVersion = encodeVersion(cVersion); + newCompatibilityVersion = encodeVersion(cVersion); + newCurrentVersionForSymbol = newCompatibilityVersion; + } + + if (!symbolName.empty()) { + // A $ld$previous$ symbol with symbol name adds a symbol with that name to + // a dylib with given name and version. + auto *dylib = getSyntheticDylib(installName, newCurrentVersionForSymbol, + newCompatibilityVersion); + + // Just adding the symbol to the symtab works because dylibs contain their + // symbols in alphabetical order, guaranteeing $ld$ symbols to precede + // normal symbols. + dylib->symbols.push_back(symtab->addDylib( + saver().save(symbolName), dylib, /*isWeakDef=*/false, /*isTlv=*/false)); + return; } + + // A $ld$previous$ symbol without symbol name modifies the dylib it's in. + this->installName = saver().save(installName); + this->compatibilityVersion = newCompatibilityVersion; } void DylibFile::handleLDInstallNameSymbol(StringRef name, diff --git a/lld/MachO/InputFiles.h b/lld/MachO/InputFiles.h index ea6802814e4c4..89172922a0a75 100644 --- a/lld/MachO/InputFiles.h +++ b/lld/MachO/InputFiles.h @@ -219,10 +219,13 @@ class DylibFile final : public InputFile { explicit DylibFile(const llvm::MachO::InterfaceFile &interface, DylibFile *umbrella, bool isBundleLoader, bool explicitlyLinked); + explicit DylibFile(DylibFile *umbrella); void parseLoadCommands(MemoryBufferRef mb); void parseReexports(const llvm::MachO::InterfaceFile &interface); bool isReferenced() const { return numReferencedSymbols > 0; } + bool isExplicitlyLinked() const; + void setExplicitlyLinked() { explicitlyLinked = true; } static bool classof(const InputFile *f) { return f->kind() == DylibKind; } @@ -239,14 +242,26 @@ class DylibFile final : public InputFile { bool forceNeeded = false; bool forceWeakImport = false; bool deadStrippable = false; - bool explicitlyLinked = false; + +private: + bool explicitlyLinked = false; // Access via isExplicitlyLinked(). + +public: // An executable can be used as a bundle loader that will load the output // file being linked, and that contains symbols referenced, but not // implemented in the bundle. When used like this, it is very similar // to a dylib, so we've used the same class to represent it. bool isBundleLoader; + // Synthetic Dylib objects created by $ld$previous symbols in this dylib. + // Usually empty. These synthetic dylibs won't have synthetic dylibs + // themselves. + SmallVector extraDylibs; + private: + DylibFile *getSyntheticDylib(StringRef installName, uint32_t currentVersion, + uint32_t compatVersion); + bool handleLDSymbol(StringRef originalName); void handleLDPreviousSymbol(StringRef name, StringRef originalName); void handleLDInstallNameSymbol(StringRef name, StringRef originalName); diff --git a/lld/MachO/Writer.cpp b/lld/MachO/Writer.cpp index 7fad9f5564ce4..3c44a60f4be26 100644 --- a/lld/MachO/Writer.cpp +++ b/lld/MachO/Writer.cpp @@ -780,70 +780,80 @@ template void Writer::createLoadCommands() { if (config->outputType == MH_EXECUTE) in.header->addLoadCommand(make()); + // See ld64's OutputFile::buildDylibOrdinalMapping for the corresponding + // library ordinal computation code in ld64. int64_t dylibOrdinal = 1; DenseMap ordinalForInstallName; + + std::vector dylibFiles; for (InputFile *file : inputFiles) { - if (auto *dylibFile = dyn_cast(file)) { - if (dylibFile->isBundleLoader) { - dylibFile->ordinal = BIND_SPECIAL_DYLIB_MAIN_EXECUTABLE; - // Shortcut since bundle-loader does not re-export the symbols. + if (auto *dylibFile = dyn_cast(file)) + dylibFiles.push_back(dylibFile); + } + for (size_t i = 0; i < dylibFiles.size(); ++i) + dylibFiles.insert(dylibFiles.end(), dylibFiles[i]->extraDylibs.begin(), + dylibFiles[i]->extraDylibs.end()); - dylibFile->reexport = false; - continue; - } + for (DylibFile *dylibFile : dylibFiles) { + if (dylibFile->isBundleLoader) { + dylibFile->ordinal = BIND_SPECIAL_DYLIB_MAIN_EXECUTABLE; + // Shortcut since bundle-loader does not re-export the symbols. - // Don't emit load commands for a dylib that is not referenced if: - // - it was added implicitly (via a reexport, an LC_LOAD_DYLINKER -- - // if it's on the linker command line, it's explicit) - // - or it's marked MH_DEAD_STRIPPABLE_DYLIB - // - or the flag -dead_strip_dylibs is used - // FIXME: `isReferenced()` is currently computed before dead code - // stripping, so references from dead code keep a dylib alive. This - // matches ld64, but it's something we should do better. - if (!dylibFile->isReferenced() && !dylibFile->forceNeeded && - (!dylibFile->explicitlyLinked || dylibFile->deadStrippable || - config->deadStripDylibs)) - continue; + dylibFile->reexport = false; + continue; + } - // Several DylibFiles can have the same installName. Only emit a single - // load command for that installName and give all these DylibFiles the - // same ordinal. - // This can happen in several cases: - // - a new framework could change its installName to an older - // framework name via an $ld$ symbol depending on platform_version - // - symlinks (for example, libpthread.tbd is a symlink to libSystem.tbd; - // Foo.framework/Foo.tbd is usually a symlink to - // Foo.framework/Versions/Current/Foo.tbd, where - // Foo.framework/Versions/Current is usually a symlink to - // Foo.framework/Versions/A) - // - a framework can be linked both explicitly on the linker - // command line and implicitly as a reexport from a different - // framework. The re-export will usually point to the tbd file - // in Foo.framework/Versions/A/Foo.tbd, while the explicit link will - // usually find Foo.framework/Foo.tbd. These are usually symlinks, - // but in a --reproduce archive they will be identical but distinct - // files. - // In the first case, *semantically distinct* DylibFiles will have the - // same installName. - int64_t &ordinal = ordinalForInstallName[dylibFile->installName]; - if (ordinal) { - dylibFile->ordinal = ordinal; - continue; - } + // Don't emit load commands for a dylib that is not referenced if: + // - it was added implicitly (via a reexport, an LC_LOAD_DYLINKER -- + // if it's on the linker command line, it's explicit) + // - or it's marked MH_DEAD_STRIPPABLE_DYLIB + // - or the flag -dead_strip_dylibs is used + // FIXME: `isReferenced()` is currently computed before dead code + // stripping, so references from dead code keep a dylib alive. This + // matches ld64, but it's something we should do better. + if (!dylibFile->isReferenced() && !dylibFile->forceNeeded && + (!dylibFile->isExplicitlyLinked() || dylibFile->deadStrippable || + config->deadStripDylibs)) + continue; - ordinal = dylibFile->ordinal = dylibOrdinal++; - LoadCommandType lcType = - dylibFile->forceWeakImport || dylibFile->refState == RefState::Weak - ? LC_LOAD_WEAK_DYLIB - : LC_LOAD_DYLIB; - in.header->addLoadCommand(make(lcType, dylibFile->installName, - dylibFile->compatibilityVersion, - dylibFile->currentVersion)); - - if (dylibFile->reexport) - in.header->addLoadCommand( - make(LC_REEXPORT_DYLIB, dylibFile->installName)); + // Several DylibFiles can have the same installName. Only emit a single + // load command for that installName and give all these DylibFiles the + // same ordinal. + // This can happen in several cases: + // - a new framework could change its installName to an older + // framework name via an $ld$ symbol depending on platform_version + // - symlinks (for example, libpthread.tbd is a symlink to libSystem.tbd; + // Foo.framework/Foo.tbd is usually a symlink to + // Foo.framework/Versions/Current/Foo.tbd, where + // Foo.framework/Versions/Current is usually a symlink to + // Foo.framework/Versions/A) + // - a framework can be linked both explicitly on the linker + // command line and implicitly as a reexport from a different + // framework. The re-export will usually point to the tbd file + // in Foo.framework/Versions/A/Foo.tbd, while the explicit link will + // usually find Foo.framework/Foo.tbd. These are usually symlinks, + // but in a --reproduce archive they will be identical but distinct + // files. + // In the first case, *semantically distinct* DylibFiles will have the + // same installName. + int64_t &ordinal = ordinalForInstallName[dylibFile->installName]; + if (ordinal) { + dylibFile->ordinal = ordinal; + continue; } + + ordinal = dylibFile->ordinal = dylibOrdinal++; + LoadCommandType lcType = + dylibFile->forceWeakImport || dylibFile->refState == RefState::Weak + ? LC_LOAD_WEAK_DYLIB + : LC_LOAD_DYLIB; + in.header->addLoadCommand(make(lcType, dylibFile->installName, + dylibFile->compatibilityVersion, + dylibFile->currentVersion)); + + if (dylibFile->reexport) + in.header->addLoadCommand( + make(LC_REEXPORT_DYLIB, dylibFile->installName)); } if (functionStartsSection) diff --git a/lld/test/MachO/special-symbol-ld-previous.s b/lld/test/MachO/special-symbol-ld-previous.s index db397353287fa..8cdfb976dd045 100644 --- a/lld/test/MachO/special-symbol-ld-previous.s +++ b/lld/test/MachO/special-symbol-ld-previous.s @@ -2,52 +2,110 @@ # RUN: rm -rf %t; split-file --no-leading-lines %s %t -# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %t/foo.s -o %t/foo.o +# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %t/ref_xxx.s -o %t/ref_xxx.o +# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %t/ref_ySyy.s -o %t/ref_ySyy.o +# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %t/ref_zzz.s -o %t/ref_zzz.o ## Case 1: special symbol $ld$previous affects the install name / compatibility version ## since the specified version 11.0.0 is within the affected range [3.0, 14.0). -# RUN: %lld -o %t/libfoo1.dylib %t/libLDPreviousInstallName.tbd %t/foo.o -dylib -platform_version macos 11.0.0 11.0.0 +# RUN: %lld -o %t/libfoo1.dylib %t/libLDPreviousInstallName.tbd %t/ref_xxx.o -dylib -platform_version macos 11.0.0 11.0.0 # RUN: llvm-objdump --macho --dylibs-used %t/libfoo1.dylib | FileCheck --check-prefix=CASE1 %s -# CASE1: /New (compatibility version 1.2.3, current version 5.0.0) +# CASE1: /Old (compatibility version 1.2.3, current version 5.0.0) ## Case 2: special symbol $ld$previous does not affect the install name / compatibility version ## since the specified version 2.0.0 is lower than the affected range [3.0, 14.0). -# RUN: %lld -o %t/libfoo2.dylib %t/libLDPreviousInstallName.tbd %t/foo.o -dylib -platform_version macos 2.0.0 2.0.0 +# RUN: %lld -o %t/libfoo2.dylib %t/libLDPreviousInstallName.tbd %t/ref_xxx.o -dylib -platform_version macos 2.0.0 2.0.0 # RUN: llvm-objdump --macho --dylibs-used %t/libfoo2.dylib | FileCheck --check-prefix=CASE2 %s -# CASE2: /Old (compatibility version 1.1.1, current version 5.0.0) +# CASE2: /New (compatibility version 1.1.1, current version 5.0.0) ## Case 3: special symbol $ld$previous does not affect the install name / compatibility version ## since the specified version 14.0.0 is higher than the affected range [3.0, 14.0). -# RUN: %lld -o %t/libfoo3.dylib %t/libLDPreviousInstallName.tbd %t/foo.o -dylib -platform_version macos 2.0.0 2.0.0 +# RUN: %lld -o %t/libfoo3.dylib %t/libLDPreviousInstallName.tbd %t/ref_xxx.o -dylib -platform_version macos 2.0.0 2.0.0 # RUN: llvm-objdump --macho --dylibs-used %t/libfoo3.dylib | FileCheck --check-prefix=CASE3 %s -# CASE3: /Old (compatibility version 1.1.1, current version 5.0.0) +# CASE3: /New (compatibility version 1.1.1, current version 5.0.0) + +## The remaining cases test handling when a symbol name is part of $ld$previous. + +## Case 4: special symbol $ld$previous affects the install name / compatibility version +## when the specified version 11.0.0 is within the affected range [3.0, 14.0) when a symbol +## is part of $previous$ if and only if that named symbol is referenced. +## That is, for $ld$previous$/NewName$$3.0$14.0$_symNam$, if _symNam is +## referenced, it refers to dylib /NewName if the deployment target is +## in [3.0, 14.0). + +# RUN: %lld -o %t/libfoo4_yes.dylib %t/libLDPreviousInstallName-Symbol.tbd %t/ref_ySyy.o -dylib -platform_version macos 11.0.0 11.0.0 +# RUN: llvm-otool -L %t/libfoo4_yes.dylib | FileCheck --check-prefix=CASE4-YES --implicit-check-not=/New %s +# CASE4-YES: /Old (compatibility version 1.2.3, current version 1.2.3) + +## $previous has no effect because deployment target is too new. +# RUN: %lld -o %t/libfoo4_no.dylib %t/libLDPreviousInstallName-Symbol.tbd %t/ref_ySyy.o -dylib -platform_version macos 14.0.0 14.0.0 +# RUN: llvm-otool -L %t/libfoo4_no.dylib | FileCheck --check-prefix=CASE4-NO --implicit-check-not=/Old %s +# CASE4-NO: /New (compatibility version 1.1.1, current version 5.0.0) + +## $previous has no effect because named symbol isn't referenced. +# RUN: %lld -o %t/libfoo4_no.dylib %t/libLDPreviousInstallName-Symbol.tbd %t/ref_zzz.o -dylib -platform_version macos 11.0.0 11.0.0 +# RUN: llvm-otool -L %t/libfoo4_no.dylib | FileCheck --check-prefix=CASE4-NO %s + +## Case 5: Reference two symbols that add different $previous names each, +## and one that references the "normal" dylib. +## This should produce three different load commands. +# RUN: %lld -o %t/libfoo5.dylib %t/libLDPreviousInstallName-Symbol.tbd %t/ref_xxx.o %t/ref_ySyy.o %t/ref_zzz.o -dylib -platform_version macos 11.0.0 11.0.0 +# RUN: llvm-otool -L %t/libfoo5.dylib | FileCheck --check-prefix=CASE5 %s +# CASE5: /New (compatibility version 1.1.1, current version 5.0.0) +# CASE5-DAG: /Another (compatibility version 1.1.1, current version 5.0.0) +# CASE5-DAG: /Old (compatibility version 1.2.3, current version 1.2.3) ## Check that we emit a warning for an invalid start, end and compatibility versions. -# RUN: %no-fatal-warnings-lld -o %t/libfoo1.dylib %t/libLDPreviousInvalid.tbd %t/foo.o -dylib \ +# RUN: %no-fatal-warnings-lld -o %t/libfoo1.dylib %t/libLDPreviousInvalid.tbd %t/ref_xxx.o -dylib \ # RUN: -platform_version macos 11.0.0 11.0.0 2>&1 | FileCheck --check-prefix=INVALID-VERSION %s # INVALID-VERSION-DAG: failed to parse start version, symbol '$ld$previous$/New$1.2.3$1$3.a$14.0$$' ignored # INVALID-VERSION-DAG: failed to parse end version, symbol '$ld$previous$/New$1.2.3$1$3.0$14.b$$' ignored # INVALID-VERSION-DAG: failed to parse compatibility version, symbol '$ld$previous$/New$1.2.c$1$3.0$14.0$$' ignored -#--- foo.s +#--- ref_xxx.s .long _xxx@GOTPCREL +#--- ref_ySyy.s +.long _y$yy@GOTPCREL + +#--- ref_zzz.s +.long _zzz@GOTPCREL + #--- libLDPreviousInstallName.tbd --- !tapi-tbd-v3 archs: [ x86_64 ] uuids: [ 'x86_64: 19311019-01AB-342E-812B-73A74271A715' ] platform: macosx -install-name: '/Old' +install-name: '/New' +current-version: 5 +compatibility-version: 1.1.1 +exports: + - archs: [ x86_64 ] + symbols: [ '$ld$previous$/Old$1.2.3$1$3.0$14.0$$', _xxx ] +... + +#--- libLDPreviousInstallName-Symbol.tbd +--- !tapi-tbd-v3 +archs: [ x86_64 ] +uuids: [ 'x86_64: 19311019-01AB-342E-812B-73A74271A715' ] +platform: macosx +install-name: '/New' current-version: 5 compatibility-version: 1.1.1 exports: - archs: [ x86_64 ] - symbols: [ '$ld$previous$/New$1.2.3$1$3.0$14.0$$', _xxx ] + symbols: [ + '$ld$previous$/Another$$1$3.0$14.0$_xxx$', + '$ld$previous$/Old$1.2.3$1$3.0$14.0$_y$yy$', + _xxx, + '_y$yy', + _zzz, + ] ... #--- libLDPreviousInvalid.tbd From 0214d986fb64f89cc75289199100475af2e73870 Mon Sep 17 00:00:00 2001 From: Tom Stellard Date: Tue, 2 Aug 2022 02:02:15 -0700 Subject: [PATCH 019/323] workflows: Remove symbol versions from libclang.so in the libclang ABI test Now that the symbol version for libclang.so changes for each release again, we need to remove the symbol versions from the shared library in order for the ABI checker to be able to compare with an older version of the shared library. --- .github/workflows/libclang-abi-tests.yml | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/.github/workflows/libclang-abi-tests.yml b/.github/workflows/libclang-abi-tests.yml index 90e816b0eaedd..1b063f6430a14 100644 --- a/.github/workflows/libclang-abi-tests.yml +++ b/.github/workflows/libclang-abi-tests.yml @@ -124,12 +124,10 @@ jobs: - name: Dump ABI run: | parallel abi-dumper -lver ${{ matrix.ref }} -skip-cxx -public-headers ./install/include/${{ needs.abi-dump-setup.outputs.ABI_HEADERS }} -o {}-${{ matrix.ref }}.abi ./build/lib/{} ::: ${{ needs.abi-dump-setup.outputs.ABI_LIBS }} - # Remove symbol versioning from dumps, so we can compare across major - # versions. We don't need to do this for libclang.so since its ABI - # is stable across major releases and the symbol versions don't change. - if [ -e libclang-cpp.so-${{ matrix.ref }}.abi ]; then - sed -i 's/LLVM_[0-9]\+/LLVM_NOVERSION/' libclang-cpp.so-${{ matrix.ref }}.abi - fi + for lib in ${{ needs.abi-dump-setup.outputs.ABI_LIBS }}; do + # Remove symbol versioning from dumps, so we can compare across major versions. + sed -i 's/LLVM_${{ matrix.llvm_version_major }}/LLVM_NOVERSION/' $lib-${{ matrix.ref }}.abi + done - name: Upload ABI file uses: actions/upload-artifact@v2 with: From 79b1ca8ebdeb2bc8c20fceb53b95959526a0b716 Mon Sep 17 00:00:00 2001 From: Simon Pilgrim Date: Tue, 2 Aug 2022 11:38:47 +0100 Subject: [PATCH 020/323] [DAG] matchRotateSub - ensure the (pre-extended) shift amount is wide enough for the amount mask (PR56859) matchRotateSub is given shift amounts that will already have stripped any/zero-extend nodes from - so make sure those values are wide enough to take a mask. (cherry picked from commit b651fdff79027064071db7c1d0250553e3e6a232) --- llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 26 +++++++------ llvm/test/CodeGen/X86/rotate5.ll | 39 +++++++++++++++++++ 2 files changed, 54 insertions(+), 11 deletions(-) create mode 100644 llvm/test/CodeGen/X86/rotate5.ll diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index 654879115ff95..a367ea51be303 100644 --- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -7301,12 +7301,14 @@ static bool matchRotateSub(SDValue Pos, SDValue Neg, unsigned EltSize, unsigned MaskLoBits = 0; if (IsRotate && isPowerOf2_64(EltSize)) { unsigned Bits = Log2_64(EltSize); - APInt DemandedBits = - APInt::getLowBitsSet(Neg.getScalarValueSizeInBits(), Bits); - if (SDValue Inner = - TLI.SimplifyMultipleUseDemandedBits(Neg, DemandedBits, DAG)) { - Neg = Inner; - MaskLoBits = Bits; + unsigned NegBits = Neg.getScalarValueSizeInBits(); + if (NegBits >= Bits) { + APInt DemandedBits = APInt::getLowBitsSet(NegBits, Bits); + if (SDValue Inner = + TLI.SimplifyMultipleUseDemandedBits(Neg, DemandedBits, DAG)) { + Neg = Inner; + MaskLoBits = Bits; + } } } @@ -7322,11 +7324,13 @@ static bool matchRotateSub(SDValue Pos, SDValue Neg, unsigned EltSize, // affect Mask's demanded bits, just replace Pos with Pos'. These operations // are redundant for the purpose of the equality. if (MaskLoBits) { - APInt DemandedBits = - APInt::getLowBitsSet(Pos.getScalarValueSizeInBits(), MaskLoBits); - if (SDValue Inner = - TLI.SimplifyMultipleUseDemandedBits(Pos, DemandedBits, DAG)) { - Pos = Inner; + unsigned PosBits = Pos.getScalarValueSizeInBits(); + if (PosBits >= MaskLoBits) { + APInt DemandedBits = APInt::getLowBitsSet(PosBits, MaskLoBits); + if (SDValue Inner = + TLI.SimplifyMultipleUseDemandedBits(Pos, DemandedBits, DAG)) { + Pos = Inner; + } } } diff --git a/llvm/test/CodeGen/X86/rotate5.ll b/llvm/test/CodeGen/X86/rotate5.ll new file mode 100644 index 0000000000000..b1f38f87ec895 --- /dev/null +++ b/llvm/test/CodeGen/X86/rotate5.ll @@ -0,0 +1,39 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc < %s -mtriple=i686-unknown-unknown | FileCheck %s --check-prefixes=X86 +; RUN: llc < %s -mtriple=x86_64-unknown-unknown | FileCheck %s --check-prefixes=X64 + +; Ensure that the (pre-extended) shift amount type is wide enough to take any mask. +define void @PR56859() { +; X86-LABEL: PR56859: +; X86: # %bb.0: # %entry +; X86-NEXT: movl (%eax), %ecx +; X86-NEXT: testl %ecx, %ecx +; X86-NEXT: setne %al +; X86-NEXT: movl $1, %edx +; X86-NEXT: # kill: def $cl killed $cl killed $ecx +; X86-NEXT: shrl %cl, %edx +; X86-NEXT: btsl %eax, %edx +; X86-NEXT: movl %edx, (%eax) +; X86-NEXT: retl +; +; X64-LABEL: PR56859: +; X64: # %bb.0: # %entry +; X64-NEXT: movl (%rax), %ecx +; X64-NEXT: testl %ecx, %ecx +; X64-NEXT: setne %al +; X64-NEXT: movl $1, %edx +; X64-NEXT: # kill: def $cl killed $cl killed $ecx +; X64-NEXT: shrl %cl, %edx +; X64-NEXT: btsl %eax, %edx +; X64-NEXT: movl %edx, (%rax) +; X64-NEXT: retq +entry: + %0 = load i32, ptr undef, align 4 + %tobool = icmp ne i32 %0, 0 + %lor.ext = zext i1 %tobool to i32 + %shr = lshr i32 1, %0 + %shl = shl i32 1, %lor.ext + %or = or i32 %shl, %shr + store i32 %or, ptr undef, align 4 + ret void +} From 626fadf59918b09cdbdb578b0fc7490c4fce9093 Mon Sep 17 00:00:00 2001 From: Tom Stellard Date: Tue, 2 Aug 2022 02:02:15 -0700 Subject: [PATCH 021/323] workflows: Fix typo from 2d3d0f50ceb938c155a7283e684f28190d24d6ba (cherry picked from commit be3587ae9ab2289179eea0bf6b241d796524062a) --- .github/workflows/libclang-abi-tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/libclang-abi-tests.yml b/.github/workflows/libclang-abi-tests.yml index 1b063f6430a14..8cc2f3a0fa3fa 100644 --- a/.github/workflows/libclang-abi-tests.yml +++ b/.github/workflows/libclang-abi-tests.yml @@ -126,7 +126,7 @@ jobs: parallel abi-dumper -lver ${{ matrix.ref }} -skip-cxx -public-headers ./install/include/${{ needs.abi-dump-setup.outputs.ABI_HEADERS }} -o {}-${{ matrix.ref }}.abi ./build/lib/{} ::: ${{ needs.abi-dump-setup.outputs.ABI_LIBS }} for lib in ${{ needs.abi-dump-setup.outputs.ABI_LIBS }}; do # Remove symbol versioning from dumps, so we can compare across major versions. - sed -i 's/LLVM_${{ matrix.llvm_version_major }}/LLVM_NOVERSION/' $lib-${{ matrix.ref }}.abi + sed -i 's/LLVM_[0-9]\+/LLVM_NOVERSION/' $lib-${{ matrix.ref }}.abi done - name: Upload ABI file uses: actions/upload-artifact@v2 From 0601c8a6d616176ce1ec1048d404d5c241b1b393 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20G=C3=B3rny?= Date: Sun, 31 Jul 2022 13:02:57 +0200 Subject: [PATCH 022/323] [libcxx] [test] Cover i386 & sparc64 in string.capacity test Differential Revision: https://reviews.llvm.org/D130837 (cherry picked from commit 09cf95bd3ec24c77a854a0e0d9431a6d4ba460bc) --- .../strings/basic.string/string.capacity/max_size.pass.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libcxx/test/libcxx/strings/basic.string/string.capacity/max_size.pass.cpp b/libcxx/test/libcxx/strings/basic.string/string.capacity/max_size.pass.cpp index 4d6248b9af1d1..0f7e17cb4ab7f 100644 --- a/libcxx/test/libcxx/strings/basic.string/string.capacity/max_size.pass.cpp +++ b/libcxx/test/libcxx/strings/basic.string/string.capacity/max_size.pass.cpp @@ -64,7 +64,7 @@ bool test() { #if _LIBCPP_ABI_VERSION == 1 -# if defined(__x86_64__) +# if defined(__x86_64__) || defined(__i386__) full_size(); # elif defined(__APPLE__) && defined(__aarch64__) half_size(); @@ -74,7 +74,7 @@ bool test() { # else full_size(); # endif -# elif defined(__powerpc__) || defined(__powerpc64__) +# elif defined(__powerpc__) || defined(__powerpc64__) || defined(__sparc64__) half_size(); # elif defined(_WIN32) full_size(); From 96a26d96c7d468af4dde717827365e5eeb5e289d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20G=C3=B3rny?= Date: Sat, 30 Jul 2022 20:53:02 +0200 Subject: [PATCH 023/323] [openmp] [test] Fix prepending config.library_dir to LD_LIBRARY_PATH Fix the LD_LIBRARY_PATH prepending order to make sure that config.library_path ends up before any potentially-system directories (e.g. config.hwloc_library_dir). This makes sure that we are testing against the just-built openmp libraries rather than the version that is already installed. Also rename the function to `prepend_*` to make it clearer what it actually does. https://github.com/llvm/llvm-project/issues/56821 Differential Revision: https://reviews.llvm.org/D130825 (cherry picked from commit eb4612ca239bffbf1612e0bce442043e716bb9f5) --- openmp/runtime/test/lit.cfg | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/openmp/runtime/test/lit.cfg b/openmp/runtime/test/lit.cfg index 76727f3ed5287..b000787409ef6 100644 --- a/openmp/runtime/test/lit.cfg +++ b/openmp/runtime/test/lit.cfg @@ -11,7 +11,7 @@ if 'PYLINT_IMPORT' in os.environ: config = object() lit_config = object() -def append_dynamic_library_path(path): +def prepend_dynamic_library_path(path): if config.operating_system == 'Windows': name = 'PATH' sep = ';' @@ -65,10 +65,13 @@ for feature in config.test_compiler_features: config.available_features.add(feature) # Setup environment to find dynamic library at runtime -append_dynamic_library_path(config.library_dir) if config.using_hwloc: - append_dynamic_library_path(config.hwloc_library_dir) + prepend_dynamic_library_path(config.hwloc_library_dir) config.available_features.add('hwloc') +# Note: please keep config.library_dir *after* any potentially system +# directories, as otherwise preinstalled openmp libraries will be used +# over just-built +prepend_dynamic_library_path(config.library_dir) # Rpath modifications for Darwin if config.operating_system == 'Darwin': From e38b9de601b36b26754854fda60b11817fd54b17 Mon Sep 17 00:00:00 2001 From: Hui Xie Date: Wed, 27 Jul 2022 13:20:16 +0100 Subject: [PATCH 024/323] [libc++][ranges] implement `std::ranges::inplace_merge` Differential Revision: https://reviews.llvm.org/D130627 (cherry picked from commit 8a61749f767e9af773051fc4f6dc99276fe189e3) --- libcxx/docs/Status/RangesAlgorithms.csv | 2 +- libcxx/include/CMakeLists.txt | 1 + libcxx/include/__algorithm/algorithm_family.h | 52 +++ libcxx/include/__algorithm/inplace_merge.h | 89 ++--- .../__algorithm/ranges_inplace_merge.h | 52 +-- libcxx/include/__algorithm/stable_sort.h | 2 +- libcxx/include/algorithm | 20 +- libcxx/include/module.modulemap.in | 1 + ...obust_against_copying_comparators.pass.cpp | 4 +- ...obust_against_copying_projections.pass.cpp | 4 +- libcxx/test/libcxx/private_headers.verify.cpp | 1 + .../alg.merge/ranges_inplace_merge.pass.cpp | 304 +++++++++++++++++- .../ranges_robust_against_dangling.pass.cpp | 4 +- ...robust_against_nonbool_predicates.pass.cpp | 25 +- ...es_robust_against_omitting_invoke.pass.cpp | 23 +- ...es_robust_against_proxy_iterators.pass.cpp | 1 + .../niebloid.compile.pass.cpp | 2 +- 17 files changed, 485 insertions(+), 102 deletions(-) create mode 100644 libcxx/include/__algorithm/algorithm_family.h diff --git a/libcxx/docs/Status/RangesAlgorithms.csv b/libcxx/docs/Status/RangesAlgorithms.csv index ecbfb3329c536..3ae87225c3eb9 100644 --- a/libcxx/docs/Status/RangesAlgorithms.csv +++ b/libcxx/docs/Status/RangesAlgorithms.csv @@ -77,7 +77,7 @@ Permutation,sort,Konstantin Varlamov,`D127557 `_,✅ Permutation,stable_sort,Konstantin Varlamov,`D127834 `_,✅ Permutation,nth_element,Konstantin Varlamov,`D128149 `_,✅ Permutation,partial_sort,Konstantin Varlamov,`D128744 `_,✅ -Permutation,inplace_merge,Not assigned,n/a,Not started +Permutation,inplace_merge,Hui Xie,`D130627 `_,✅ Permutation,make_heap,Konstantin Varlamov,`D128115 `_,✅ Permutation,push_heap,Konstantin Varlamov,`D128115 `_,✅ Permutation,pop_heap,Konstantin Varlamov,`D128115 `_,✅ diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt index 970b4683d37b6..371f0c0cf223b 100644 --- a/libcxx/include/CMakeLists.txt +++ b/libcxx/include/CMakeLists.txt @@ -1,5 +1,6 @@ set(files __algorithm/adjacent_find.h + __algorithm/algorithm_family.h __algorithm/all_of.h __algorithm/any_of.h __algorithm/binary_search.h diff --git a/libcxx/include/__algorithm/algorithm_family.h b/libcxx/include/__algorithm/algorithm_family.h new file mode 100644 index 0000000000000..30ffff832ebc3 --- /dev/null +++ b/libcxx/include/__algorithm/algorithm_family.h @@ -0,0 +1,52 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_ALGORITHM_FAMILY_H +#define _LIBCPP___ALGORITHM_ALGORITHM_FAMILY_H + +#include <__algorithm/iterator_operations.h> +#include <__algorithm/move.h> +#include <__algorithm/ranges_move.h> +#include <__config> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +struct _AlgFamily; + +#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) + +template <> +struct _AlgFamily<_RangeAlgPolicy> { + static constexpr auto __move = ranges::move; +}; + +#endif + +template <> +struct _AlgFamily<_ClassicAlgPolicy> { + + // move + template + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 static _OutputIterator + __move(_InputIterator __first, _InputIterator __last, _OutputIterator __result) { + return std::move( + std::move(__first), + std::move(__last), + std::move(__result)); + } +}; + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_ALGORITHM_FAMILY_H diff --git a/libcxx/include/__algorithm/inplace_merge.h b/libcxx/include/__algorithm/inplace_merge.h index cb662e791872b..e33894eada3f2 100644 --- a/libcxx/include/__algorithm/inplace_merge.h +++ b/libcxx/include/__algorithm/inplace_merge.h @@ -9,6 +9,7 @@ #ifndef _LIBCPP___ALGORITHM_INPLACE_MERGE_H #define _LIBCPP___ALGORITHM_INPLACE_MERGE_H +#include <__algorithm/algorithm_family.h> #include <__algorithm/comp.h> #include <__algorithm/comp_ref_type.h> #include <__algorithm/iterator_operations.h> @@ -54,18 +55,17 @@ class __invert // invert the sense of a comparison bool operator()(const _T1& __x, const _T2& __y) {return __p_(__y, __x);} }; -template -void __half_inplace_merge(_InputIterator1 __first1, _InputIterator1 __last1, - _InputIterator2 __first2, _InputIterator2 __last2, - _OutputIterator __result, _Compare __comp) +template +void __half_inplace_merge(_InputIterator1 __first1, _Sent1 __last1, + _InputIterator2 __first2, _Sent2 __last2, + _OutputIterator __result, _Compare&& __comp) { for (; __first1 != __last1; ++__result) { if (__first2 == __last2) { - // TODO(alg-policy): pass `_AlgPolicy` once it's supported by `move`. - _VSTD::move(__first1, __last1, __result); + _AlgFamily<_AlgPolicy>::__move(__first1, __last1, __result); return; } @@ -84,13 +84,15 @@ void __half_inplace_merge(_InputIterator1 __first1, _InputIterator1 __last1, } template -void -__buffered_inplace_merge(_BidirectionalIterator __first, _BidirectionalIterator __middle, _BidirectionalIterator __last, - _Compare __comp, typename iterator_traits<_BidirectionalIterator>::difference_type __len1, - typename iterator_traits<_BidirectionalIterator>::difference_type __len2, - typename iterator_traits<_BidirectionalIterator>::value_type* __buff) -{ - typedef typename iterator_traits<_BidirectionalIterator>::value_type value_type; +void __buffered_inplace_merge( + _BidirectionalIterator __first, + _BidirectionalIterator __middle, + _BidirectionalIterator __last, + _Compare&& __comp, + typename iterator_traits<_BidirectionalIterator>::difference_type __len1, + typename iterator_traits<_BidirectionalIterator>::difference_type __len2, + typename iterator_traits<_BidirectionalIterator>::value_type* __buff) { + typedef typename iterator_traits<_BidirectionalIterator>::value_type value_type; __destruct_n __d(0); unique_ptr __h2(__buff, __d); if (__len1 <= __len2) @@ -98,7 +100,7 @@ __buffered_inplace_merge(_BidirectionalIterator __first, _BidirectionalIterator value_type* __p = __buff; for (_BidirectionalIterator __i = __first; __i != __middle; __d.template __incr(), (void) ++__i, (void) ++__p) ::new ((void*)__p) value_type(_IterOps<_AlgPolicy>::__iter_move(__i)); - std::__half_inplace_merge<_AlgPolicy, _Compare>(__buff, __p, __middle, __last, __first, __comp); + std::__half_inplace_merge<_AlgPolicy>(__buff, __p, __middle, __last, __first, __comp); } else { @@ -108,19 +110,22 @@ __buffered_inplace_merge(_BidirectionalIterator __first, _BidirectionalIterator typedef __unconstrained_reverse_iterator<_BidirectionalIterator> _RBi; typedef __unconstrained_reverse_iterator _Rv; typedef __invert<_Compare> _Inverted; - std::__half_inplace_merge<_AlgPolicy, _Inverted>(_Rv(__p), _Rv(__buff), + std::__half_inplace_merge<_AlgPolicy>(_Rv(__p), _Rv(__buff), _RBi(__middle), _RBi(__first), _RBi(__last), _Inverted(__comp)); } } template -void -__inplace_merge(_BidirectionalIterator __first, _BidirectionalIterator __middle, _BidirectionalIterator __last, - _Compare __comp, typename iterator_traits<_BidirectionalIterator>::difference_type __len1, - typename iterator_traits<_BidirectionalIterator>::difference_type __len2, - typename iterator_traits<_BidirectionalIterator>::value_type* __buff, ptrdiff_t __buff_size) -{ +void __inplace_merge( + _BidirectionalIterator __first, + _BidirectionalIterator __middle, + _BidirectionalIterator __last, + _Compare&& __comp, + typename iterator_traits<_BidirectionalIterator>::difference_type __len1, + typename iterator_traits<_BidirectionalIterator>::difference_type __len2, + typename iterator_traits<_BidirectionalIterator>::value_type* __buff, + ptrdiff_t __buff_size) { using _Ops = _IterOps<_AlgPolicy>; typedef typename iterator_traits<_BidirectionalIterator>::difference_type difference_type; @@ -130,7 +135,7 @@ __inplace_merge(_BidirectionalIterator __first, _BidirectionalIterator __middle, if (__len2 == 0) return; if (__len1 <= __buff_size || __len2 <= __buff_size) - return std::__buffered_inplace_merge<_AlgPolicy, _Compare> + return std::__buffered_inplace_merge<_AlgPolicy> (__first, __middle, __last, __comp, __len1, __len2, __buff); // shrink [__first, __middle) as much as possible (with no moves), returning if it shrinks to 0 for (; true; ++__first, (void) --__len1) @@ -158,8 +163,7 @@ __inplace_merge(_BidirectionalIterator __first, _BidirectionalIterator __middle, __len21 = __len2 / 2; __m2 = __middle; _Ops::advance(__m2, __len21); - // TODO: replace _ClassicAlgPolicy and __identity with _AlgPolicy and projection - __m1 = std::__upper_bound<_ClassicAlgPolicy>(__first, __middle, *__m2, __comp, std::__identity()); + __m1 = std::__upper_bound<_AlgPolicy>(__first, __middle, *__m2, __comp, std::__identity()); __len11 = _Ops::distance(__first, __m1); } else @@ -187,9 +191,8 @@ __inplace_merge(_BidirectionalIterator __first, _BidirectionalIterator __middle, // merge smaller range with recursive call and larger with tail recursion elimination if (__len11 + __len21 < __len12 + __len22) { - std::__inplace_merge<_AlgPolicy, _Compare>( + std::__inplace_merge<_AlgPolicy>( __first, __m1, __middle, __comp, __len11, __len21, __buff, __buff_size); -// _VSTD::__inplace_merge<_Compare>(__middle, __m2, __last, __comp, __len12, __len22, __buff, __buff_size); __first = __middle; __middle = __m2; __len1 = __len12; @@ -197,9 +200,8 @@ __inplace_merge(_BidirectionalIterator __first, _BidirectionalIterator __middle, } else { - std::__inplace_merge<_AlgPolicy, _Compare>( + std::__inplace_merge<_AlgPolicy>( __middle, __m2, __last, __comp, __len12, __len22, __buff, __buff_size); -// _VSTD::__inplace_merge<_Compare>(__first, __m1, __middle, __comp, __len11, __len21, __buff, __buff_size); __last = __middle; __middle = __m1; __len1 = __len11; @@ -208,33 +210,40 @@ __inplace_merge(_BidirectionalIterator __first, _BidirectionalIterator __middle, } } -template -inline _LIBCPP_INLINE_VISIBILITY +template +_LIBCPP_HIDE_FROM_ABI void -inplace_merge(_BidirectionalIterator __first, _BidirectionalIterator __middle, _BidirectionalIterator __last, - _Compare __comp) +__inplace_merge(_BidirectionalIterator __first, _BidirectionalIterator __middle, _BidirectionalIterator __last, + _Compare&& __comp) { typedef typename iterator_traits<_BidirectionalIterator>::value_type value_type; typedef typename iterator_traits<_BidirectionalIterator>::difference_type difference_type; - difference_type __len1 = _VSTD::distance(__first, __middle); - difference_type __len2 = _VSTD::distance(__middle, __last); + difference_type __len1 = _IterOps<_AlgPolicy>::distance(__first, __middle); + difference_type __len2 = _IterOps<_AlgPolicy>::distance(__middle, __last); difference_type __buf_size = _VSTD::min(__len1, __len2); // TODO: Remove the use of std::get_temporary_buffer _LIBCPP_SUPPRESS_DEPRECATED_PUSH pair __buf = _VSTD::get_temporary_buffer(__buf_size); _LIBCPP_SUPPRESS_DEPRECATED_POP unique_ptr __h(__buf.first); - typedef typename __comp_ref_type<_Compare>::type _Comp_ref; - return _VSTD::__inplace_merge<_ClassicAlgPolicy, _Comp_ref>(__first, __middle, __last, __comp, __len1, __len2, - __buf.first, __buf.second); + return std::__inplace_merge<_AlgPolicy>( + std::move(__first), std::move(__middle), std::move(__last), __comp, __len1, __len2, __buf.first, __buf.second); +} + +template +inline _LIBCPP_HIDE_FROM_ABI void inplace_merge( + _BidirectionalIterator __first, _BidirectionalIterator __middle, _BidirectionalIterator __last, _Compare __comp) { + typedef typename __comp_ref_type<_Compare>::type _Comp_ref; + std::__inplace_merge<_ClassicAlgPolicy>( + std::move(__first), std::move(__middle), std::move(__last), static_cast<_Comp_ref>(__comp)); } template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_HIDE_FROM_ABI void inplace_merge(_BidirectionalIterator __first, _BidirectionalIterator __middle, _BidirectionalIterator __last) { - _VSTD::inplace_merge(__first, __middle, __last, + std::inplace_merge(std::move(__first), std::move(__middle), std::move(__last), __less::value_type>()); } diff --git a/libcxx/include/__algorithm/ranges_inplace_merge.h b/libcxx/include/__algorithm/ranges_inplace_merge.h index a0867e486c3a0..2152e6648c350 100644 --- a/libcxx/include/__algorithm/ranges_inplace_merge.h +++ b/libcxx/include/__algorithm/ranges_inplace_merge.h @@ -10,6 +10,7 @@ #define _LIBCPP___ALGORITHM_RANGES_INPLACE_MERGE_H #include <__algorithm/inplace_merge.h> +#include <__algorithm/iterator_operations.h> #include <__algorithm/make_projected.h> #include <__config> #include <__functional/identity.h> @@ -17,6 +18,7 @@ #include <__functional/ranges_operations.h> #include <__iterator/concepts.h> #include <__iterator/iterator_traits.h> +#include <__iterator/next.h> #include <__iterator/projected.h> #include <__iterator/sortable.h> #include <__ranges/access.h> @@ -36,28 +38,38 @@ _LIBCPP_BEGIN_NAMESPACE_STD namespace ranges { namespace __inplace_merge { -struct __fn { + struct __fn { + template + _LIBCPP_HIDE_FROM_ABI static constexpr auto + __inplace_merge_impl(_Iter __first, _Iter __middle, _Sent __last, _Comp&& __comp, _Proj&& __proj) { + auto __last_iter = ranges::next(__middle, __last); + std::__inplace_merge<_RangeAlgPolicy>( + std::move(__first), std::move(__middle), __last_iter, ranges::__make_projected_comp(__comp, __proj)); + return __last_iter; + } - template _Sent, class _Comp = ranges::less, class _Proj = identity> - requires sortable<_Iter, _Comp, _Proj> - _LIBCPP_HIDE_FROM_ABI - _Iter operator()(_Iter __first, _Iter __middle, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { - // TODO: implement - (void)__first; (void)__middle; (void)__last; (void)__comp; (void)__proj; - return {}; - } + template < + bidirectional_iterator _Iter, + sentinel_for<_Iter> _Sent, + class _Comp = ranges::less, + class _Proj = identity> + requires sortable<_Iter, _Comp, _Proj> + _LIBCPP_HIDE_FROM_ABI _Iter + operator()(_Iter __first, _Iter __middle, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { + return __inplace_merge_impl( + std::move(__first), std::move(__middle), std::move(__last), std::move(__comp), std::move(__proj)); + } - template - requires sortable, _Comp, _Proj> - _LIBCPP_HIDE_FROM_ABI - borrowed_iterator_t<_Range> operator()(_Range&& __range, iterator_t<_Range> __middle, - _Comp __comp = {}, _Proj __proj = {}) const { - // TODO: implement - (void)__range; (void)__middle; (void)__comp; (void)__proj; - return {}; - } - -}; + template + requires sortable< + iterator_t<_Range>, + _Comp, + _Proj> _LIBCPP_HIDE_FROM_ABI borrowed_iterator_t<_Range> + operator()(_Range&& __range, iterator_t<_Range> __middle, _Comp __comp = {}, _Proj __proj = {}) const { + return __inplace_merge_impl( + ranges::begin(__range), std::move(__middle), ranges::end(__range), std::move(__comp), std::move(__proj)); + } + }; } // namespace __inplace_merge diff --git a/libcxx/include/__algorithm/stable_sort.h b/libcxx/include/__algorithm/stable_sort.h index 6122758bdefe8..fb149eeb65dc0 100644 --- a/libcxx/include/__algorithm/stable_sort.h +++ b/libcxx/include/__algorithm/stable_sort.h @@ -203,7 +203,7 @@ __stable_sort(_RandomAccessIterator __first, _RandomAccessIterator __last, _Comp } std::__stable_sort<_AlgPolicy, _Compare>(__first, __m, __comp, __l2, __buff, __buff_size); std::__stable_sort<_AlgPolicy, _Compare>(__m, __last, __comp, __len - __l2, __buff, __buff_size); - std::__inplace_merge<_AlgPolicy, _Compare>(__first, __m, __last, __comp, __l2, __len - __l2, __buff, __buff_size); + std::__inplace_merge<_AlgPolicy>(__first, __m, __last, __comp, __l2, __len - __l2, __buff, __buff_size); } template diff --git a/libcxx/include/algorithm b/libcxx/include/algorithm index 197b3b1043bbe..4fc353a8ce5dd 100644 --- a/libcxx/include/algorithm +++ b/libcxx/include/algorithm @@ -803,7 +803,7 @@ namespace ranges { set_symmetric_difference(I1 first1, S1 last1, I2 first2, S2 last2, O result, Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); // since C++20 - + template requires mergeable, iterator_t, O, Comp, Proj1, Proj2> @@ -816,13 +816,13 @@ namespace ranges { indirect_strict_weak_order> Comp = ranges::less> constexpr subrange equal_range(I first, S last, const T& value, Comp comp = {}, Proj proj = {}); // since C++20 - + template, Proj>> Comp = ranges::less> constexpr borrowed_subrange_t equal_range(R&& r, const T& value, Comp comp = {}, Proj proj = {}); // since C++20 - + template using set_union_result = in_in_out_result; // since C++20 @@ -847,13 +847,24 @@ namespace ranges { ranges::less> constexpr bool includes(I1 first1, S1 last1, I2 first2, S2 last2, Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); // Since C++20 - + template, Proj1>, projected, Proj2>> Comp = ranges::less> constexpr bool includes(R1&& r1, R2&& r2, Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); // Since C++20 + + template S, class Comp = ranges::less, + class Proj = identity> + requires sortable + I inplace_merge(I first, I middle, S last, Comp comp = {}, Proj proj = {}); // Since C++20 + + template + requires sortable, Comp, Proj> + borrowed_iterator_t + inplace_merge(R&& r, iterator_t middle, Comp comp = {}, + Proj proj = {}); // Since C++20 } constexpr bool // constexpr in C++20 @@ -1607,6 +1618,7 @@ template #include <__algorithm/ranges_generate.h> #include <__algorithm/ranges_generate_n.h> #include <__algorithm/ranges_includes.h> +#include <__algorithm/ranges_inplace_merge.h> #include <__algorithm/ranges_is_heap.h> #include <__algorithm/ranges_is_heap_until.h> #include <__algorithm/ranges_is_partitioned.h> diff --git a/libcxx/include/module.modulemap.in b/libcxx/include/module.modulemap.in index 98485bcd93ab3..1cfd4ae3bfef4 100644 --- a/libcxx/include/module.modulemap.in +++ b/libcxx/include/module.modulemap.in @@ -239,6 +239,7 @@ module std [system] { module __algorithm { module adjacent_find { private header "__algorithm/adjacent_find.h" } + module algorithm_family { private header "__algorithm/algorithm_family.h" } module all_of { private header "__algorithm/all_of.h" } module any_of { private header "__algorithm/any_of.h" } module binary_search { private header "__algorithm/binary_search.h" } diff --git a/libcxx/test/libcxx/algorithms/ranges_robust_against_copying_comparators.pass.cpp b/libcxx/test/libcxx/algorithms/ranges_robust_against_copying_comparators.pass.cpp index 48eeb01b57587..669fa9c1842ef 100644 --- a/libcxx/test/libcxx/algorithms/ranges_robust_against_copying_comparators.pass.cpp +++ b/libcxx/test/libcxx/algorithms/ranges_robust_against_copying_comparators.pass.cpp @@ -138,8 +138,8 @@ constexpr bool all_the_algorithms() (void)std::ranges::is_sorted(a, Less(&copies)); assert(copies == 0); (void)std::ranges::is_sorted_until(first, last, Less(&copies)); assert(copies == 0); (void)std::ranges::is_sorted_until(a, Less(&copies)); assert(copies == 0); - //if (!std::is_constant_evaluated()) { (void)std::ranges::inplace_merge(first, mid, last, Less(&copies)); assert(copies == 0); } - //if (!std::is_constant_evaluated()) { (void)std::ranges::inplace_merge(a, mid, Less(&copies)); assert(copies == 0); } + if (!std::is_constant_evaluated()) { (void)std::ranges::inplace_merge(first, mid, last, Less(&copies)); assert(copies == 0); } + if (!std::is_constant_evaluated()) { (void)std::ranges::inplace_merge(a, mid, Less(&copies)); assert(copies == 0); } (void)std::ranges::lexicographical_compare(first, last, first2, last2, Less(&copies)); assert(copies == 0); (void)std::ranges::lexicographical_compare(a, b, Less(&copies)); assert(copies == 0); (void)std::ranges::lower_bound(first, last, value, Less(&copies)); assert(copies == 0); diff --git a/libcxx/test/libcxx/algorithms/ranges_robust_against_copying_projections.pass.cpp b/libcxx/test/libcxx/algorithms/ranges_robust_against_copying_projections.pass.cpp index 80b8a5ec4d836..22fdf09888af7 100644 --- a/libcxx/test/libcxx/algorithms/ranges_robust_against_copying_projections.pass.cpp +++ b/libcxx/test/libcxx/algorithms/ranges_robust_against_copying_projections.pass.cpp @@ -121,8 +121,8 @@ constexpr bool all_the_algorithms() (void)std::ranges::is_sorted(a, Less(), Proj(&copies)); assert(copies == 0); (void)std::ranges::is_sorted_until(first, last, Less(), Proj(&copies)); assert(copies == 0); (void)std::ranges::is_sorted_until(a, Less(), Proj(&copies)); assert(copies == 0); - //if (!std::is_constant_evaluated()) { (void)std::ranges::inplace_merge(first, mid, last, Less(), Proj(&copies)); assert(copies == 0); } - //if (!std::is_constant_evaluated()) { (void)std::ranges::inplace_merge(a, mid, Less(), Proj(&copies)); assert(copies == 0); } + if (!std::is_constant_evaluated()) { (void)std::ranges::inplace_merge(first, mid, last, Less(), Proj(&copies)); assert(copies == 0); } + if (!std::is_constant_evaluated()) { (void)std::ranges::inplace_merge(a, mid, Less(), Proj(&copies)); assert(copies == 0); } (void)std::ranges::lexicographical_compare(first, last, first2, last2, Less(), Proj(&copies), Proj(&copies)); assert(copies == 0); (void)std::ranges::lexicographical_compare(a, b, Less(), Proj(&copies), Proj(&copies)); assert(copies == 0); (void)std::ranges::lower_bound(first, last, value, Less(), Proj(&copies)); assert(copies == 0); diff --git a/libcxx/test/libcxx/private_headers.verify.cpp b/libcxx/test/libcxx/private_headers.verify.cpp index f9cb581c16b83..5b3e65be251d9 100644 --- a/libcxx/test/libcxx/private_headers.verify.cpp +++ b/libcxx/test/libcxx/private_headers.verify.cpp @@ -37,6 +37,7 @@ END-SCRIPT // DO NOT MANUALLY EDIT ANYTHING BETWEEN THE MARKERS BELOW // GENERATED-MARKER #include <__algorithm/adjacent_find.h> // expected-error@*:* {{use of private header from outside its module: '__algorithm/adjacent_find.h'}} +#include <__algorithm/algorithm_family.h> // expected-error@*:* {{use of private header from outside its module: '__algorithm/algorithm_family.h'}} #include <__algorithm/all_of.h> // expected-error@*:* {{use of private header from outside its module: '__algorithm/all_of.h'}} #include <__algorithm/any_of.h> // expected-error@*:* {{use of private header from outside its module: '__algorithm/any_of.h'}} #include <__algorithm/binary_search.h> // expected-error@*:* {{use of private header from outside its module: '__algorithm/binary_search.h'}} diff --git a/libcxx/test/std/algorithms/alg.sorting/alg.merge/ranges_inplace_merge.pass.cpp b/libcxx/test/std/algorithms/alg.sorting/alg.merge/ranges_inplace_merge.pass.cpp index fff2a67004557..12863b8b9e01f 100644 --- a/libcxx/test/std/algorithms/alg.sorting/alg.merge/ranges_inplace_merge.pass.cpp +++ b/libcxx/test/std/algorithms/alg.sorting/alg.merge/ranges_inplace_merge.pass.cpp @@ -27,23 +27,315 @@ #include #include #include +#include #include "almost_satisfies_types.h" +#include "counting_predicates.h" +#include "counting_projection.h" #include "test_iterators.h" -// TODO: SFINAE tests. +template < class Iter, + class Middle = Iter, + class Sent = sentinel_wrapper>, + class Comp = std::ranges::less, + class Proj = std::identity> +concept HasInplaceMergeIter = + requires(Iter&& iter, Middle&& mid, Sent&& sent, Comp&& comp, Proj&& proj) { + std::ranges::inplace_merge( + std::forward(iter), + std::forward(mid), + std::forward(sent), + std::forward(comp), + std::forward(proj)); + }; -constexpr bool test() { - // TODO: main tests. - // TODO: A custom comparator works. - // TODO: A custom projection works. +static_assert(HasInplaceMergeIter); +// !bidirectional_­iterator +static_assert(!HasInplaceMergeIter); +static_assert(!HasInplaceMergeIter>); + +// !sentinel_for +static_assert(!HasInplaceMergeIter); +static_assert(!HasInplaceMergeIter); + +// !sortable +static_assert(!HasInplaceMergeIter>); +static_assert(!HasInplaceMergeIter); + +template < class Range, + class Middle = std::ranges::iterator_t, + class Comp = std::ranges::less, + class Proj = std::identity> +concept HasInplaceMergeRange = + requires(Range&& r, Middle&& mid, Comp&& comp, Proj&& proj) { + std::ranges::inplace_merge( + std::forward(r), std::forward(mid), std::forward(comp), std::forward(proj)); + }; + +template +using R = UncheckedRange; + +static_assert(HasInplaceMergeRange, int*>); + +// !bidirectional_range +static_assert(!HasInplaceMergeRange>>); +static_assert(!HasInplaceMergeRange>); + +// !sortable, Comp, Proj> +static_assert(!HasInplaceMergeRange, int*, ComparatorNotCopyable>); +static_assert(!HasInplaceMergeIter, const int*>); + +template class SentWrapper, std::size_t N1, std::size_t N2> +void testInplaceMergeImpl(std::array input, int midIdx, std::array expected) { + std::is_sorted(input.begin(), input.begin() + midIdx); + std::is_sorted(input.begin() + midIdx, input.end()); + std::is_sorted(expected.begin(), expected.end()); + + using Sent = SentWrapper; + + // iterator overload + { + auto in = input; + std::same_as decltype(auto) result = + std::ranges::inplace_merge(In{in.data()}, In{in.data() + midIdx}, Sent{In{in.data() + in.size()}}); + assert(std::ranges::equal(in, expected)); + assert(base(result) == in.data() + in.size()); + } + + // range overload + { + auto in = input; + std::ranges::subrange r{In{in.data()}, Sent{In{in.data() + in.size()}}}; + std::same_as decltype(auto) result = std::ranges::inplace_merge(r, In{in.data() + midIdx}); + assert(std::ranges::equal(in, expected)); + assert(base(result) == in.data() + in.size()); + } +} + +template class SentWrapper> +void testImpl() { + // sorted range + { + std::array in{0, 1, 5, 6, 9, 10}; + std::array expected = in; + testInplaceMergeImpl(in, 3, expected); + } + + // [first, mid) is longer + { + std::array in{0, 5, 9, 15, 18, 22, 2, 4, 6, 10}; + std::array expected = {0, 2, 4, 5, 6, 9, 10, 15, 18, 22}; + testInplaceMergeImpl(in, 6, expected); + } + + // [first, mid) is shorter + { + std::array in{0, 5, 9, 2, 4, 6, 10}; + std::array expected = {0, 2, 4, 5, 6, 9, 10}; + testInplaceMergeImpl(in, 3, expected); + } + + // [first, mid) == [mid, last) + { + std::array in{0, 5, 9, 0, 5, 9}; + std::array expected = {0, 0, 5, 5, 9, 9}; + testInplaceMergeImpl(in, 3, expected); + } + + // duplicates within each range + { + std::array in{1, 5, 5, 2, 9, 9, 9}; + std::array expected = {1, 2, 5, 5, 9, 9, 9}; + testInplaceMergeImpl(in, 3, expected); + } + + // all the same + { + std::array in{5, 5, 5, 5, 5, 5, 5, 5}; + std::array expected = in; + testInplaceMergeImpl(in, 5, expected); + } + + // [first, mid) is empty (mid == begin) + { + std::array in{0, 1, 5, 6, 9, 10}; + std::array expected = in; + testInplaceMergeImpl(in, 0, expected); + } + + // [mid, last] is empty (mid == end) + { + std::array in{0, 1, 5, 6, 9, 10}; + std::array expected = in; + testInplaceMergeImpl(in, 6, expected); + } + + // both empty + { + std::array in{}; + std::array expected = in; + testInplaceMergeImpl(in, 0, expected); + } + + // mid == first + 1 + { + std::array in{9, 2, 5, 7, 10}; + std::array expected{2, 5, 7, 9, 10}; + testInplaceMergeImpl(in, 1, expected); + } + + // mid == last - 1 + { + std::array in{2, 5, 7, 10, 9}; + std::array expected{2, 5, 7, 9, 10}; + testInplaceMergeImpl(in, 4, expected); + } +} + +template < template class SentWrapper> +void withAllPermutationsOfIter() { + testImpl, SentWrapper>(); + testImpl, SentWrapper>(); + testImpl, SentWrapper>(); + testImpl(); +} + +bool test() { + withAllPermutationsOfIter(); + withAllPermutationsOfIter(); + + struct Data { + int data; + }; + + const auto equal = [](const Data& x, const Data& y) { return x.data == y.data; }; + // Test custom comparator + { + std::array input{{{4}, {8}, {2}, {5}}}; + std::array expected{{{2}, {4}, {5}, {8}}}; + const auto comp = [](const Data& x, const Data& y) { return x.data < y.data; }; + + // iterator overload + { + auto in = input; + auto result = std::ranges::inplace_merge(in.begin(), in.begin() + 2, in.end(), comp); + assert(std::ranges::equal(in, expected, equal)); + assert(result == in.end()); + } + + // range overload + { + auto in = input; + auto result = std::ranges::inplace_merge(in, in.begin() + 2, comp); + assert(std::ranges::equal(in, expected, equal)); + assert(result == in.end()); + } + } + + // Test custom projection + { + std::array input{{{4}, {8}, {2}, {5}}}; + std::array expected{{{2}, {4}, {5}, {8}}}; + + const auto proj = &Data::data; + + // iterator overload + { + auto in = input; + auto result = std::ranges::inplace_merge(in.begin(), in.begin() + 2, in.end(), {}, proj); + assert(std::ranges::equal(in, expected, equal)); + assert(result == in.end()); + } + + // range overload + { + auto in = input; + auto result = std::ranges::inplace_merge(in, in.begin() + 2, {}, proj); + assert(std::ranges::equal(in, expected, equal)); + assert(result == in.end()); + } + } + + // Remarks: Stable. + { + struct IntAndID { + int data; + int id; + constexpr auto operator<=>(const IntAndID& rhs) const { return data <=> rhs.data; } + constexpr auto operator==(const IntAndID& rhs) const { return data == rhs.data; } + }; + std::array input{{{0, 0}, {1, 0}, {2, 0}, {0, 1}, {1, 1}, {2, 1}}}; + + // iterator overload + { + auto in = input; + auto result = std::ranges::inplace_merge(in.begin(), in.begin() + 3, in.end()); + assert(std::ranges::equal(in, std::array{0, 0, 1, 1, 2, 2}, {}, &IntAndID::data)); + assert(std::ranges::equal(in, std::array{0, 1, 0, 1, 0, 1}, {}, &IntAndID::id)); + assert(result == in.end()); + } + + // range overload + { + auto in = input; + auto result = std::ranges::inplace_merge(in, in.begin() + 3); + assert(std::ranges::equal(in, std::array{0, 0, 1, 1, 2, 2}, {}, &IntAndID::data)); + assert(std::ranges::equal(in, std::array{0, 1, 0, 1, 0, 1}, {}, &IntAndID::id)); + assert(result == in.end()); + } + } + + // Complexity: Let N = last - first : + // - For the overloads with no ExecutionPolicy, and if enough + // additional memory is available, exactly N − 1 comparisons. + // - Otherwise, O(NlogN) comparisons. + // In either case, twice as many projections as comparisons. + { + std::array input{1, 2, 3, 3, 3, 7, 7, 2, 2, 5, 5, 6, 6}; + std::array expected{1, 2, 2, 2, 3, 3, 3, 5, 5, 6, 6, 7, 7}; + auto mid = 7; + // iterator overload + { + auto in = input; + int numberOfComp = 0; + int numberOfProj = 0; + auto result = std::ranges::inplace_merge( + in.begin(), + in.begin() + mid, + in.end(), + counting_predicate{std::ranges::less{}, numberOfComp}, + counting_projection{numberOfProj}); + assert(std::ranges::equal(in, expected)); + assert(result == in.end()); + + // the spec specifies exactly N-1 comparison but we actually + // do not invoke as many times as specified + assert(numberOfComp <= static_cast(in.size() - 1)); + assert(numberOfProj <= 2 * numberOfComp); + } + // range overload + { + auto in = input; + int numberOfComp = 0; + int numberOfProj = 0; + auto result = std::ranges::inplace_merge( + in, + in.begin() + mid, + counting_predicate{std::ranges::less{}, numberOfComp}, + counting_projection{numberOfProj}); + assert(std::ranges::equal(in, expected)); + assert(result == in.end()); + assert(numberOfComp <= static_cast(in.size() - 1)); + assert(numberOfProj <= 2 * numberOfComp); + } + } return true; } int main(int, char**) { test(); - static_assert(test()); + // inplace_merge is not constexpr in the latest finished Standard (C++20) return 0; } diff --git a/libcxx/test/std/algorithms/ranges_robust_against_dangling.pass.cpp b/libcxx/test/std/algorithms/ranges_robust_against_dangling.pass.cpp index 40d1043d4b1b4..e147c875902c2 100644 --- a/libcxx/test/std/algorithms/ranges_robust_against_dangling.pass.cpp +++ b/libcxx/test/std/algorithms/ranges_robust_against_dangling.pass.cpp @@ -193,8 +193,8 @@ constexpr bool test_all() { dangling_1st(std::ranges::stable_sort, in); dangling_1st(std::ranges::partial_sort, in, mid); dangling_1st(std::ranges::nth_element, in, mid); - //if (!std::is_constant_evaluated()) - // dangling_1st(std::ranges::inplace_merge, in, mid); + if (!std::is_constant_evaluated()) + dangling_1st(std::ranges::inplace_merge, in, mid); dangling_1st(std::ranges::make_heap, in); dangling_1st(std::ranges::push_heap, in); dangling_1st(std::ranges::pop_heap, in); diff --git a/libcxx/test/std/algorithms/ranges_robust_against_nonbool_predicates.pass.cpp b/libcxx/test/std/algorithms/ranges_robust_against_nonbool_predicates.pass.cpp index f5f7160869368..eeeec9c1f57f3 100644 --- a/libcxx/test/std/algorithms/ranges_robust_against_nonbool_predicates.pass.cpp +++ b/libcxx/test/std/algorithms/ranges_robust_against_nonbool_predicates.pass.cpp @@ -35,36 +35,36 @@ static_assert(std::convertible_to); // Invokes both the (iterator, sentinel, ...) and the (range, ...) overloads of the given niebloid. // (in, ...) -template -constexpr void test(Func&& func, Input& in, Args&& ...args) { +template +constexpr void test(Func&& func, Input& in, Args&&... args) { func(in.begin(), in.end(), std::forward(args)...); func(in, std::forward(args)...); } // (in1, in2, ...) -template -constexpr void test(Func&& func, Input& in1, Input& in2, Args&& ...args) { +template +constexpr void test(Func&& func, Input& in1, Input& in2, Args&&... args) { func(in1.begin(), in1.end(), in2.begin(), in2.end(), std::forward(args)...); func(in1, in2, std::forward(args)...); } // (in, mid, ...) -template -constexpr void test_mid(Func&& func, Input& in, std::ranges::iterator_t mid, Args&& ...args) { +template +constexpr void test_mid(Func&& func, Input& in, std::ranges::iterator_t mid, Args&&... args) { func(in.begin(), mid, in.end(), std::forward(args)...); func(in, mid, std::forward(args)...); } constexpr bool test_all() { - std::array in = {1, 2, 3}; + std::array in = {1, 2, 3}; std::array in2 = {4, 5, 6}; - auto mid = in.begin() + 1; + auto mid = in.begin() + 1; std::array output = {7, 8, 9, 10, 11, 12}; - auto out = output.begin(); - auto out2 = output.begin() + 1; + auto out = output.begin(); + auto out2 = output.begin() + 1; - int x = 2; + int x = 2; int count = 1; test(std::ranges::any_of, in, unary_pred); @@ -133,7 +133,8 @@ constexpr bool test_all() { test(std::ranges::stable_sort, in, binary_pred); test_mid(std::ranges::partial_sort, in, mid, binary_pred); test_mid(std::ranges::nth_element, in, mid, binary_pred); - //test_mid(std::ranges::inplace_merge, in, mid, binary_pred); + if (!std::is_constant_evaluated()) + test_mid(std::ranges::inplace_merge, in, mid, binary_pred); test(std::ranges::make_heap, in, binary_pred); test(std::ranges::push_heap, in, binary_pred); test(std::ranges::pop_heap, in, binary_pred); diff --git a/libcxx/test/std/algorithms/ranges_robust_against_omitting_invoke.pass.cpp b/libcxx/test/std/algorithms/ranges_robust_against_omitting_invoke.pass.cpp index 2da3db405c324..aa0b15db6dee6 100644 --- a/libcxx/test/std/algorithms/ranges_robust_against_omitting_invoke.pass.cpp +++ b/libcxx/test/std/algorithms/ranges_robust_against_omitting_invoke.pass.cpp @@ -36,34 +36,34 @@ struct Bar { // Invokes both the (iterator, sentinel, ...) and the (range, ...) overloads of the given niebloid. // (in, ...) -template -constexpr void test(Func&& func, Input& in, Args&& ...args) { +template +constexpr void test(Func&& func, Input& in, Args&&... args) { func(in.begin(), in.end(), std::forward(args)...); func(in, std::forward(args)...); } // (in1, in2, ...) -template -constexpr void test(Func&& func, Input& in1, Input& in2, Args&& ...args) { +template +constexpr void test(Func&& func, Input& in1, Input& in2, Args&&... args) { func(in1.begin(), in1.end(), in2.begin(), in2.end(), std::forward(args)...); func(in1, in2, std::forward(args)...); } // (in, mid, ...) -template -constexpr void test_mid(Func&& func, Input& in, std::ranges::iterator_t mid, Args&& ...args) { +template +constexpr void test_mid(Func&& func, Input& in, std::ranges::iterator_t mid, Args&&... args) { func(in.begin(), mid, in.end(), std::forward(args)...); func(in, mid, std::forward(args)...); } constexpr bool test_all() { - std::array in = {Bar{Foo{1}}, Bar{Foo{2}}, Bar{Foo{3}}}; + std::array in = {Bar{Foo{1}}, Bar{Foo{2}}, Bar{Foo{3}}}; std::array in2 = {Bar{Foo{4}}, Bar{Foo{5}}, Bar{Foo{6}}}; - auto mid = in.begin() + 1; + auto mid = in.begin() + 1; std::array output = {Bar{Foo{7}}, Bar{Foo{8}}, Bar{Foo{9}}, Bar{Foo{10}}, Bar{Foo{11}}, Bar{Foo{12}}}; - auto out = output.begin(); - auto out2 = output.begin() + 1; + auto out = output.begin(); + auto out2 = output.begin() + 1; Bar a{Foo{1}}; Bar b{Foo{2}}; @@ -162,7 +162,8 @@ constexpr bool test_all() { test(std::ranges::stable_sort, in, &Foo::binary_pred, &Bar::val); test_mid(std::ranges::partial_sort, in, mid, &Foo::binary_pred, &Bar::val); test_mid(std::ranges::nth_element, in, mid, &Foo::binary_pred, &Bar::val); - //test_mid(std::ranges::inplace_merge, in, mid, binary_pred); + if (!std::is_constant_evaluated()) + test_mid(std::ranges::inplace_merge, in, mid, &Foo::binary_pred, &Bar::val); test(std::ranges::make_heap, in, &Foo::binary_pred, &Bar::val); test(std::ranges::push_heap, in, &Foo::binary_pred, &Bar::val); test(std::ranges::pop_heap, in, &Foo::binary_pred, &Bar::val); diff --git a/libcxx/test/std/algorithms/ranges_robust_against_proxy_iterators.pass.cpp b/libcxx/test/std/algorithms/ranges_robust_against_proxy_iterators.pass.cpp index aba570160899a..4013065eb42a4 100644 --- a/libcxx/test/std/algorithms/ranges_robust_against_proxy_iterators.pass.cpp +++ b/libcxx/test/std/algorithms/ranges_robust_against_proxy_iterators.pass.cpp @@ -164,6 +164,7 @@ constexpr void run_tests() { // test(std::ranges::stable_sort, in); test_mid(std::ranges::partial_sort, in, mid); test_mid(std::ranges::nth_element, in, mid); + // TODO(ranges): `inplace_merge` requires `ranges::rotate` to be implemented. //if (!std::is_constant_evaluated()) // test_mid(std::ranges::inplace_merge, in, mid); test(std::ranges::make_heap, in); diff --git a/libcxx/test/std/library/description/conventions/customization.point.object/niebloid.compile.pass.cpp b/libcxx/test/std/library/description/conventions/customization.point.object/niebloid.compile.pass.cpp index ebe78c1742216..1fc6dfb89c4b9 100644 --- a/libcxx/test/std/library/description/conventions/customization.point.object/niebloid.compile.pass.cpp +++ b/libcxx/test/std/library/description/conventions/customization.point.object/niebloid.compile.pass.cpp @@ -87,7 +87,7 @@ static_assert(test(std::ranges::for_each_n, a, 10, odd)); static_assert(test(std::ranges::generate, a, gen)); static_assert(test(std::ranges::generate_n, a, 10, gen)); static_assert(test(std::ranges::includes, a, a)); -//static_assert(test(std::ranges::inplace_merge, a, a+5)); +static_assert(test(std::ranges::inplace_merge, a, a+5)); static_assert(test(std::ranges::is_heap, a)); static_assert(test(std::ranges::is_heap_until, a)); static_assert(test(std::ranges::is_partitioned, a, odd)); From 9e126d6fd2628b187ee356e66694df686817e125 Mon Sep 17 00:00:00 2001 From: Nikolas Klauser Date: Wed, 27 Jul 2022 23:52:45 +0200 Subject: [PATCH 025/323] [libc++] Fix unwrapping ranges with different iterators and sentinels Reviewed By: ldionne, huixie90, #libc Spies: arichardson, sstefan1, libcxx-commits, mgorny Differential Revision: https://reviews.llvm.org/D129040 (cherry picked from commit e01b4fe956dd038fed71cf3c552d3383905d022a) --- libcxx/include/CMakeLists.txt | 1 + libcxx/include/__algorithm/copy.h | 10 +- libcxx/include/__algorithm/unwrap_range.h | 97 +++++++++++++++++++ libcxx/include/module.modulemap.in | 1 + libcxx/test/libcxx/private_headers.verify.cpp | 1 + .../alg.copy/ranges.copy.pass.cpp | 15 ++- 6 files changed, 117 insertions(+), 8 deletions(-) create mode 100644 libcxx/include/__algorithm/unwrap_range.h diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt index 371f0c0cf223b..36eb70d39d769 100644 --- a/libcxx/include/CMakeLists.txt +++ b/libcxx/include/CMakeLists.txt @@ -181,6 +181,7 @@ set(files __algorithm/unique.h __algorithm/unique_copy.h __algorithm/unwrap_iter.h + __algorithm/unwrap_range.h __algorithm/upper_bound.h __assert __availability diff --git a/libcxx/include/__algorithm/copy.h b/libcxx/include/__algorithm/copy.h index 5428baa688592..f7535a81547a8 100644 --- a/libcxx/include/__algorithm/copy.h +++ b/libcxx/include/__algorithm/copy.h @@ -10,6 +10,7 @@ #define _LIBCPP___ALGORITHM_COPY_H #include <__algorithm/unwrap_iter.h> +#include <__algorithm/unwrap_range.h> #include <__config> #include <__iterator/iterator_traits.h> #include <__iterator/reverse_iterator.h> @@ -88,10 +89,11 @@ template ::value && is_copy_constructible<_OutIter>::value, int> = 0> inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 -pair<_InIter, _OutIter> -__copy(_InIter __first, _Sent __last, _OutIter __result) { - auto __ret = std::__copy_impl(std::__unwrap_iter(__first), std::__unwrap_iter(__last), std::__unwrap_iter(__result)); - return std::make_pair(std::__rewrap_iter(__first, __ret.first), std::__rewrap_iter(__result, __ret.second)); +pair<_InIter, _OutIter> __copy(_InIter __first, _Sent __last, _OutIter __result) { + auto __range = std::__unwrap_range(__first, __last); + auto __ret = std::__copy_impl(std::move(__range.first), std::move(__range.second), std::__unwrap_iter(__result)); + return std::make_pair( + std::__rewrap_range<_Sent>(__first, __ret.first), std::__rewrap_iter(__result, __ret.second)); } template diff --git a/libcxx/include/__algorithm/unwrap_range.h b/libcxx/include/__algorithm/unwrap_range.h new file mode 100644 index 0000000000000..745906a96e15b --- /dev/null +++ b/libcxx/include/__algorithm/unwrap_range.h @@ -0,0 +1,97 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_UNWRAP_RANGE_H +#define _LIBCPP___ALGORITHM_UNWRAP_RANGE_H + +#include <__algorithm/unwrap_iter.h> +#include <__concepts/constructible.h> +#include <__config> +#include <__iterator/concepts.h> +#include <__iterator/next.h> +#include <__utility/declval.h> +#include <__utility/move.h> +#include <__utility/pair.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +// __unwrap_range and __rewrap_range are used to unwrap ranges which may have different iterator and sentinel types. +// __unwrap_iter and __rewrap_iter don't work for this, because they assume that the iterator and sentinel have +// the same type. __unwrap_range tries to get two iterators and then forward to __unwrap_iter. + +#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) +template +struct __unwrap_range_impl { + _LIBCPP_HIDE_FROM_ABI static constexpr auto __unwrap(_Iter __first, _Sent __sent) + requires random_access_iterator<_Iter> && sized_sentinel_for<_Sent, _Iter> + { + auto __last = ranges::next(__first, __sent); + return pair{std::__unwrap_iter(std::move(__first)), std::__unwrap_iter(std::move(__last))}; + } + + _LIBCPP_HIDE_FROM_ABI static constexpr auto __unwrap(_Iter __first, _Sent __last) { + return pair{std::move(__first), std::move(__last)}; + } + + _LIBCPP_HIDE_FROM_ABI static constexpr auto + __rewrap(_Iter __orig_iter, decltype(std::__unwrap_iter(__orig_iter)) __iter) + requires random_access_iterator<_Iter> && sized_sentinel_for<_Sent, _Iter> + { + return std::__rewrap_iter(std::move(__orig_iter), std::move(__iter)); + } + + _LIBCPP_HIDE_FROM_ABI static constexpr auto __rewrap(const _Iter&, _Iter __iter) + requires (!(random_access_iterator<_Iter> && sized_sentinel_for<_Sent, _Iter>)) + { + return __iter; + } +}; + +template +struct __unwrap_range_impl<_Iter, _Iter> { + _LIBCPP_HIDE_FROM_ABI static constexpr auto __unwrap(_Iter __first, _Iter __last) { + return pair{std::__unwrap_iter(std::move(__first)), std::__unwrap_iter(std::move(__last))}; + } + + _LIBCPP_HIDE_FROM_ABI static constexpr auto + __rewrap(_Iter __orig_iter, decltype(std::__unwrap_iter(__orig_iter)) __iter) { + return std::__rewrap_iter(std::move(__orig_iter), std::move(__iter)); + } +}; + +template +_LIBCPP_HIDE_FROM_ABI constexpr auto __unwrap_range(_Iter __first, _Sent __last) { + return __unwrap_range_impl<_Iter, _Sent>::__unwrap(std::move(__first), std::move(__last)); +} + +template < + class _Sent, + class _Iter, + class _Unwrapped = decltype(std::__unwrap_range(std::declval<_Iter>(), std::declval<_Sent>()))> +_LIBCPP_HIDE_FROM_ABI constexpr _Iter __rewrap_range(_Iter __orig_iter, _Unwrapped __iter) { + return __unwrap_range_impl<_Iter, _Sent>::__rewrap(std::move(__orig_iter), std::move(__iter)); +} +#else // _LIBCPP_STD_VER > 17 +template ()))> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR pair<_Unwrapped, _Unwrapped> __unwrap_range(_Iter __first, _Iter __last) { + return std::make_pair(std::__unwrap_iter(std::move(__first)), std::__unwrap_iter(std::move(__last))); +} + +template ()))> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Iter __rewrap_range(_Iter __orig_iter, _Unwrapped __iter) { + return std::__rewrap_iter(std::move(__orig_iter), std::move(__iter)); +} +#endif // _LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_UNWRAP_RANGE_H diff --git a/libcxx/include/module.modulemap.in b/libcxx/include/module.modulemap.in index 1cfd4ae3bfef4..88f4d152063b6 100644 --- a/libcxx/include/module.modulemap.in +++ b/libcxx/include/module.modulemap.in @@ -420,6 +420,7 @@ module std [system] { module unique { private header "__algorithm/unique.h" } module unique_copy { private header "__algorithm/unique_copy.h" } module unwrap_iter { private header "__algorithm/unwrap_iter.h" } + module unwrap_range { private header "__algorithm/unwrap_range.h" } module upper_bound { private header "__algorithm/upper_bound.h" } } } diff --git a/libcxx/test/libcxx/private_headers.verify.cpp b/libcxx/test/libcxx/private_headers.verify.cpp index 5b3e65be251d9..516991b2ac262 100644 --- a/libcxx/test/libcxx/private_headers.verify.cpp +++ b/libcxx/test/libcxx/private_headers.verify.cpp @@ -218,6 +218,7 @@ END-SCRIPT #include <__algorithm/unique.h> // expected-error@*:* {{use of private header from outside its module: '__algorithm/unique.h'}} #include <__algorithm/unique_copy.h> // expected-error@*:* {{use of private header from outside its module: '__algorithm/unique_copy.h'}} #include <__algorithm/unwrap_iter.h> // expected-error@*:* {{use of private header from outside its module: '__algorithm/unwrap_iter.h'}} +#include <__algorithm/unwrap_range.h> // expected-error@*:* {{use of private header from outside its module: '__algorithm/unwrap_range.h'}} #include <__algorithm/upper_bound.h> // expected-error@*:* {{use of private header from outside its module: '__algorithm/upper_bound.h'}} #include <__availability> // expected-error@*:* {{use of private header from outside its module: '__availability'}} #include <__bit/bit_cast.h> // expected-error@*:* {{use of private header from outside its module: '__bit/bit_cast.h'}} diff --git a/libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/ranges.copy.pass.cpp b/libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/ranges.copy.pass.cpp index 390bafed7aa54..cc58dd2732c49 100644 --- a/libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/ranges.copy.pass.cpp +++ b/libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/ranges.copy.pass.cpp @@ -95,13 +95,20 @@ constexpr void test_iterators() { } } +template +constexpr void test_sentinels() { + test_iterators(); + test_iterators>(); + test_iterators>(); +} + template constexpr void test_in_iterators() { test_iterators, Out, sentinel_wrapper>>(); - test_iterators, Out>(); - test_iterators, Out>(); - test_iterators, Out>(); - test_iterators, Out>(); + test_sentinels, Out>(); + test_sentinels, Out>(); + test_sentinels, Out>(); + test_sentinels, Out>(); } template From b55abcf777c97ab0fb056191ca6a6efdc9e329ce Mon Sep 17 00:00:00 2001 From: Nikolas Klauser Date: Thu, 28 Jul 2022 10:32:02 +0200 Subject: [PATCH 026/323] [libc++] Fix merge-conflict in .clang-format (cherry picked from commit d5a3cc1d88d888e38633eb55e2afadb4cf788000) --- libcxx/.clang-format | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libcxx/.clang-format b/libcxx/.clang-format index 8d8eff5905afb..acc6773c16ded 100644 --- a/libcxx/.clang-format +++ b/libcxx/.clang-format @@ -68,7 +68,7 @@ MaxEmptyLinesToKeep: 1 NamespaceIndentation: Inner PackConstructorInitializers: NextLine -PenaltyIndentedWhitespace: 61 +PenaltyIndentedWhitespace: 2 Language: Cpp Standard: c++20 From c9905b8cb0139f410ce63081989a328559e11374 Mon Sep 17 00:00:00 2001 From: Konstantin Varlamov Date: Thu, 28 Jul 2022 02:06:44 -0700 Subject: [PATCH 027/323] [libc++] Make `_IterOps::__iter_move` more similar to `std::ranges::iter_move`. Avoid relying on `iterator_traits` and instead deduce the return type of dereferencing the iterator. Additionally, add a static check to reject iterators with incorrect `iterator_traits` at compile time. Differential Revision: https://reviews.llvm.org/D130538 (cherry picked from commit b3afea1ce0bd3c9293edae67c1839318eecdd7bf) --- .../include/__algorithm/iterator_operations.h | 49 +++++++++++---- .../algorithms/bad_iterator_traits.verify.cpp | 61 +++++++++++++++++++ 2 files changed, 97 insertions(+), 13 deletions(-) create mode 100644 libcxx/test/libcxx/algorithms/bad_iterator_traits.verify.cpp diff --git a/libcxx/include/__algorithm/iterator_operations.h b/libcxx/include/__algorithm/iterator_operations.h index 8307d71214e58..6ac5170b4a0ee 100644 --- a/libcxx/include/__algorithm/iterator_operations.h +++ b/libcxx/include/__algorithm/iterator_operations.h @@ -17,6 +17,7 @@ #include <__iterator/iter_swap.h> #include <__iterator/iterator_traits.h> #include <__iterator/next.h> +#include <__utility/declval.h> #include <__utility/forward.h> #include <__utility/move.h> #include @@ -63,24 +64,46 @@ struct _IterOps<_ClassicAlgPolicy> { return std::distance(__first, __last); } - // iter_move + template + using __deref_t = decltype(*std::declval<_Iter&>()); + + template + using __move_t = decltype(std::move(*std::declval<_Iter&>())); + template _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 - // Declaring the return type is necessary for C++03, so we basically mirror what `decltype(auto)` would deduce. - static __enable_if_t< - is_reference >::reference>::value, - typename remove_reference< typename iterator_traits<__uncvref_t<_Iter> >::reference >::type&&> - __iter_move(_Iter&& __i) { + static void __validate_iter_reference() { + static_assert(is_same<__deref_t<_Iter>, typename iterator_traits<__uncvref_t<_Iter> >::reference>::value, + "It looks like your iterator's `iterator_traits::reference` does not match the return type of " + "dereferencing the iterator, i.e., calling `*it`. This is undefined behavior according to [input.iterators] " + "and can lead to dangling reference issues at runtime, so we are flagging this."); + } + + // iter_move + template + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 static + // If the result of dereferencing `_Iter` is a reference type, deduce the result of calling `std::move` on it. Note + // that the C++03 mode doesn't support `decltype(auto)` as the return type. + __enable_if_t< + is_reference<__deref_t<_Iter> >::value, + __move_t<_Iter> > + __iter_move(_Iter&& __i) { + __validate_iter_reference<_Iter>(); + return std::move(*std::forward<_Iter>(__i)); } template - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 - // Declaring the return type is necessary for C++03, so we basically mirror what `decltype(auto)` would deduce. - static __enable_if_t< - !is_reference >::reference>::value, - typename iterator_traits<__uncvref_t<_Iter> >::reference> - __iter_move(_Iter&& __i) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 static + // If the result of dereferencing `_Iter` is a value type, deduce the return value of this function to also be a + // value -- otherwise, after `operator*` returns a temporary, this function would return a dangling reference to that + // temporary. Note that the C++03 mode doesn't support `auto` as the return type. + __enable_if_t< + !is_reference<__deref_t<_Iter> >::value, + __deref_t<_Iter> > + __iter_move(_Iter&& __i) { + __validate_iter_reference<_Iter>(); + return *std::forward<_Iter>(__i); } @@ -100,7 +123,7 @@ struct _IterOps<_ClassicAlgPolicy> { template _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_AFTER_CXX11 - __uncvref_t<_Iter> next(_Iter&& __it, + __uncvref_t<_Iter> next(_Iter&& __it, typename iterator_traits<__uncvref_t<_Iter> >::difference_type __n = 1){ return std::next(std::forward<_Iter>(__it), __n); } diff --git a/libcxx/test/libcxx/algorithms/bad_iterator_traits.verify.cpp b/libcxx/test/libcxx/algorithms/bad_iterator_traits.verify.cpp new file mode 100644 index 0000000000000..61e1712987e7c --- /dev/null +++ b/libcxx/test/libcxx/algorithms/bad_iterator_traits.verify.cpp @@ -0,0 +1,61 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// std::sort + +#include +#include +#include +#include + +struct BadIter { + struct Value { + friend bool operator==(const Value& x, const Value& y); + friend bool operator!=(const Value& x, const Value& y); + friend bool operator< (const Value& x, const Value& y); + friend bool operator<=(const Value& x, const Value& y); + friend bool operator> (const Value& x, const Value& y); + friend bool operator>=(const Value& x, const Value& y); + friend void swap(Value, Value); + }; + + using iterator_category = std::random_access_iterator_tag; + using value_type = Value; + using reference = Value&; + using difference_type = long; + using pointer = Value*; + + Value operator*() const; // Not `Value&`. + reference operator[](difference_type n) const; + + BadIter& operator++(); + BadIter& operator--(); + BadIter operator++(int); + BadIter operator--(int); + + BadIter& operator+=(difference_type n); + BadIter& operator-=(difference_type n); + friend BadIter operator+(BadIter x, difference_type n); + friend BadIter operator+(difference_type n, BadIter x); + friend BadIter operator-(BadIter x, difference_type n); + friend difference_type operator-(BadIter x, BadIter y); + + friend bool operator==(const BadIter& x, const BadIter& y); + friend bool operator!=(const BadIter& x, const BadIter& y); + friend bool operator< (const BadIter& x, const BadIter& y); + friend bool operator<=(const BadIter& x, const BadIter& y); + friend bool operator> (const BadIter& x, const BadIter& y); + friend bool operator>=(const BadIter& x, const BadIter& y); +}; + +// Verify that iterators with incorrect `iterator_traits` are rejected. This protects against potential undefined +// behavior when these iterators are passed to standard algorithms. +void test() { + std::sort(BadIter(), BadIter()); + //expected-error-re@*:* {{{{(static_assert|static assertion)}} failed {{.*}}It looks like your iterator's `iterator_traits::reference` does not match the return type of dereferencing the iterator}} +} From 6ba660d17410d02f5fa71d878ac49e2fdee4169f Mon Sep 17 00:00:00 2001 From: Louis Dionne Date: Thu, 28 Jul 2022 10:25:30 -0400 Subject: [PATCH 028/323] [libc++] Properly log crashes with the assertion handler on older Androids This reintroduces the same workaround we have in libc++abi for older Androids based on https://reviews.llvm.org/D130507#inline-1255914. Differential Revision: https://reviews.llvm.org/D130708 (cherry picked from commit 1422a9689d7907a4561da7b906ec392840d9e635) --- libcxx/src/assert.cpp | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/libcxx/src/assert.cpp b/libcxx/src/assert.cpp index c218645f17712..d6e96f255e353 100644 --- a/libcxx/src/assert.cpp +++ b/libcxx/src/assert.cpp @@ -14,9 +14,13 @@ #ifdef __BIONIC__ # include -# include +# if __ANDROID_API__ >= 21 +# include extern "C" void android_set_abort_message(const char* msg); -#endif +# else +# include +# endif // __ANDROID_API__ >= 21 +#endif // __BIONIC__ #if defined(__APPLE__) && __has_include() # include @@ -48,14 +52,22 @@ void __libcpp_assertion_handler(char const* format, ...) { vasprintf(&buffer, format, list); CRSetCrashLogMessage(buffer); #elif defined(__BIONIC__) - // Show error in tombstone. vasprintf(&buffer, format, list); + +# if __ANDROID_API__ >= 21 + // Show error in tombstone. android_set_abort_message(buffer); // Show error in logcat. openlog("libc++", 0, 0); syslog(LOG_CRIT, "%s", buffer); closelog(); +# else + // The good error reporting wasn't available in Android until L. Since we're + // about to abort anyway, just call __assert2, which will log _somewhere_ + // (tombstone and/or logcat) in older releases. + __assert2(__FILE__, __LINE__, __func__, buffer); +# endif // __ANDROID_API__ >= 21 #endif va_end(list); From 62f1e6638158d8848777a29d9d142bb5481c7b67 Mon Sep 17 00:00:00 2001 From: Hui Xie Date: Sat, 23 Jul 2022 01:44:25 +0100 Subject: [PATCH 029/323] [libc++][ranges] implement `std::ranges::unique{_copy}` implement `std::ranges::unique` and `std::ranges::unique_copy` Differential Revision: https://reviews.llvm.org/D130404 (cherry picked from commit 72f57e3a30d597346feec74cf626796b0055680f) --- libcxx/docs/Status/RangesAlgorithms.csv | 4 +- libcxx/include/__algorithm/adjacent_find.h | 32 +- .../include/__algorithm/iterator_operations.h | 8 + libcxx/include/__algorithm/ranges_unique.h | 46 +- .../include/__algorithm/ranges_unique_copy.h | 73 +++- libcxx/include/__algorithm/unique.h | 48 ++- libcxx/include/__algorithm/unique_copy.h | 147 ++++--- libcxx/include/algorithm | 30 ++ ...obust_against_copying_comparators.pass.cpp | 8 +- ...obust_against_copying_projections.pass.cpp | 8 +- .../alg.unique/ranges_unique.pass.cpp | 208 ++++++++- .../alg.unique/ranges_unique_copy.pass.cpp | 402 +++++++++++++++++- .../alg.unique/unique_copy.pass.cpp | 23 + ...result_alias_declarations.compile.pass.cpp | 2 +- .../ranges_robust_against_dangling.pass.cpp | 8 +- ...robust_against_nonbool_predicates.pass.cpp | 4 +- ...es_robust_against_omitting_invoke.pass.cpp | 4 +- ...es_robust_against_proxy_iterators.pass.cpp | 4 +- .../niebloid.compile.pass.cpp | 4 +- 19 files changed, 889 insertions(+), 174 deletions(-) diff --git a/libcxx/docs/Status/RangesAlgorithms.csv b/libcxx/docs/Status/RangesAlgorithms.csv index 3ae87225c3eb9..176ece9ae0473 100644 --- a/libcxx/docs/Status/RangesAlgorithms.csv +++ b/libcxx/docs/Status/RangesAlgorithms.csv @@ -57,7 +57,7 @@ Write,swap_ranges,Nikolas Klauser,`D116303 `_,✅ Write,reverse_copy,Nikolas Klauser,`D127211 `_,✅ Write,rotate_copy,Nikolas Klauser,`D127211 `_,✅ Write,sample,Not assigned,n/a,Not started -Write,unique_copy,Not assigned,n/a,Not started +Write,unique_copy,Hui Xie,`D130404 `,✅ Write,partition_copy,Konstantin Varlamov,`D130070 `_,✅ Write,partial_sort_copy,Konstantin Varlamov,n/a,In progress Merge,merge,Hui Xie,`D128611 `_,✅ @@ -70,7 +70,7 @@ Permutation,remove_if,Nikolas Klauser,`D128618 `_,✅ Permutation,reverse,Nikolas Klauser,`D125752 `_,✅ Permutation,rotate,Nikolas Klauser,`D124122 `_,Under review Permutation,shuffle,Konstantin Varlamov,`D130321 `_,✅ -Permutation,unique,Not assigned,n/a,Not started +Permutation,unique,Hui Xie,`D130404 `,✅ Permutation,partition,Konstantin Varlamov,`D129624 `_,✅ Permutation,stable_partition,Konstantin Varlamov,`D129624 `_,✅ Permutation,sort,Konstantin Varlamov,`D127557 `_,✅ diff --git a/libcxx/include/__algorithm/adjacent_find.h b/libcxx/include/__algorithm/adjacent_find.h index 83d8c260f27a2..1089bb20d5b2d 100644 --- a/libcxx/include/__algorithm/adjacent_find.h +++ b/libcxx/include/__algorithm/adjacent_find.h @@ -11,8 +11,10 @@ #define _LIBCPP___ALGORITHM_ADJACENT_FIND_H #include <__algorithm/comp.h> +#include <__algorithm/iterator_operations.h> #include <__config> #include <__iterator/iterator_traits.h> +#include <__utility/move.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -20,25 +22,31 @@ _LIBCPP_BEGIN_NAMESPACE_STD +template +_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 _Iter +__adjacent_find(_Iter __first, _Sent __last, _BinaryPredicate&& __pred) { + if (__first == __last) + return __first; + _Iter __i = __first; + while (++__i != __last) { + if (__pred(*__first, *__i)) + return __first; + __first = __i; + } + return __i; +} + template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator adjacent_find(_ForwardIterator __first, _ForwardIterator __last, _BinaryPredicate __pred) { - if (__first != __last) { - _ForwardIterator __i = __first; - while (++__i != __last) { - if (__pred(*__first, *__i)) - return __first; - __first = __i; - } - } - return __last; + return std::__adjacent_find(std::move(__first), std::move(__last), __pred); } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator adjacent_find(_ForwardIterator __first, _ForwardIterator __last) { typedef typename iterator_traits<_ForwardIterator>::value_type __v; - return _VSTD::adjacent_find(__first, __last, __equal_to<__v>()); + return std::adjacent_find(std::move(__first), std::move(__last), __equal_to<__v>()); } _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__algorithm/iterator_operations.h b/libcxx/include/__algorithm/iterator_operations.h index 6ac5170b4a0ee..e060574652d4e 100644 --- a/libcxx/include/__algorithm/iterator_operations.h +++ b/libcxx/include/__algorithm/iterator_operations.h @@ -17,6 +17,7 @@ #include <__iterator/iter_swap.h> #include <__iterator/iterator_traits.h> #include <__iterator/next.h> +#include <__iterator/readable_traits.h> #include <__utility/declval.h> #include <__utility/forward.h> #include <__utility/move.h> @@ -35,6 +36,10 @@ struct _RangeAlgPolicy {}; template <> struct _IterOps<_RangeAlgPolicy> { + + template + using __value_type = iter_value_t<_Iter>; + static constexpr auto advance = ranges::advance; static constexpr auto distance = ranges::distance; static constexpr auto __iter_move = ranges::iter_move; @@ -50,6 +55,9 @@ struct _ClassicAlgPolicy {}; template <> struct _IterOps<_ClassicAlgPolicy> { + template + using __value_type = typename iterator_traits<_Iter>::value_type; + // advance template _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 diff --git a/libcxx/include/__algorithm/ranges_unique.h b/libcxx/include/__algorithm/ranges_unique.h index bdf755e9406e2..85185280724b6 100644 --- a/libcxx/include/__algorithm/ranges_unique.h +++ b/libcxx/include/__algorithm/ranges_unique.h @@ -9,6 +9,7 @@ #ifndef _LIBCPP___ALGORITHM_RANGES_UNIQUE_H #define _LIBCPP___ALGORITHM_RANGES_UNIQUE_H +#include <__algorithm/iterator_operations.h> #include <__algorithm/make_projected.h> #include <__algorithm/unique.h> #include <__config> @@ -37,28 +38,31 @@ _LIBCPP_BEGIN_NAMESPACE_STD namespace ranges { namespace __unique { -struct __fn { + struct __fn { + template < + permutable _Iter, + sentinel_for<_Iter> _Sent, + class _Proj = identity, + indirect_equivalence_relation> _Comp = ranges::equal_to> + _LIBCPP_HIDE_FROM_ABI constexpr subrange<_Iter> + operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { + auto __ret = std::__unique<_RangeAlgPolicy>( + std::move(__first), std::move(__last), ranges::__make_projected_comp(__comp, __proj)); + return {std::move(__ret.first), std::move(__ret.second)}; + } - template _Sent, class _Proj = identity, - indirect_equivalence_relation> _Comp = ranges::equal_to> - _LIBCPP_HIDE_FROM_ABI constexpr - subrange<_Iter> operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { - // TODO: implement - (void)__first; (void)__last; (void)__comp; (void)__proj; - return {}; - } - - template , _Proj>> _Comp = ranges::equal_to> - requires permutable> - _LIBCPP_HIDE_FROM_ABI constexpr - borrowed_subrange_t<_Range> operator()(_Range&& __range, _Comp __comp = {}, _Proj __proj = {}) const { - // TODO: implement - (void)__range; (void)__comp; (void)__proj; - return {}; - } - -}; + template < + forward_range _Range, + class _Proj = identity, + indirect_equivalence_relation, _Proj>> _Comp = ranges::equal_to> + requires permutable> + _LIBCPP_HIDE_FROM_ABI constexpr borrowed_subrange_t<_Range> + operator()(_Range&& __range, _Comp __comp = {}, _Proj __proj = {}) const { + auto __ret = std::__unique<_RangeAlgPolicy>( + ranges::begin(__range), ranges::end(__range), ranges::__make_projected_comp(__comp, __proj)); + return {std::move(__ret.first), std::move(__ret.second)}; + } + }; } // namespace __unique diff --git a/libcxx/include/__algorithm/ranges_unique_copy.h b/libcxx/include/__algorithm/ranges_unique_copy.h index 56361aa8ae2f3..d047b444aa5e7 100644 --- a/libcxx/include/__algorithm/ranges_unique_copy.h +++ b/libcxx/include/__algorithm/ranges_unique_copy.h @@ -10,6 +10,7 @@ #define _LIBCPP___ALGORITHM_RANGES_UNIQUE_COPY_H #include <__algorithm/in_out_result.h> +#include <__algorithm/iterator_operations.h> #include <__algorithm/make_projected.h> #include <__algorithm/unique_copy.h> #include <__concepts/same_as.h> @@ -19,8 +20,8 @@ #include <__functional/ranges_operations.h> #include <__iterator/concepts.h> #include <__iterator/iterator_traits.h> -#include <__iterator/readable_traits.h> #include <__iterator/projected.h> +#include <__iterator/readable_traits.h> #include <__ranges/access.h> #include <__ranges/concepts.h> #include <__ranges/dangling.h> @@ -42,42 +43,68 @@ using unique_copy_result = in_out_result<_InIter, _OutIter>; namespace __unique_copy { +template +concept __can_reread_from_output = (input_iterator<_OutIter> && same_as, iter_value_t<_OutIter>>); + struct __fn { + template + static consteval auto __get_algo_tag() { + if constexpr (forward_iterator<_InIter>) { + return __unique_copy_tags::__reread_from_input_tag{}; + } else if constexpr (__can_reread_from_output<_InIter, _OutIter>) { + return __unique_copy_tags::__reread_from_output_tag{}; + } else if constexpr (indirectly_copyable_storable<_InIter, _OutIter>) { + return __unique_copy_tags::__read_from_tmp_value_tag{}; + } + } + + template + using __algo_tag_t = decltype(__get_algo_tag<_InIter, _OutIter>()); - template _Sent, weakly_incrementable _OutIter, class _Proj = identity, + template _Sent, + weakly_incrementable _OutIter, + class _Proj = identity, indirect_equivalence_relation> _Comp = ranges::equal_to> - requires indirectly_copyable<_InIter, _OutIter> && - (forward_iterator<_InIter> || - (input_iterator<_OutIter> && same_as, iter_value_t<_OutIter>>) || - indirectly_copyable_storable<_InIter, _OutIter>) - _LIBCPP_HIDE_FROM_ABI constexpr - unique_copy_result<_InIter, _OutIter> + requires indirectly_copyable<_InIter, _OutIter> && + (forward_iterator<_InIter> || + (input_iterator<_OutIter> && same_as, iter_value_t<_OutIter>>) || + indirectly_copyable_storable<_InIter, _OutIter>) + _LIBCPP_HIDE_FROM_ABI constexpr unique_copy_result<_InIter, _OutIter> operator()(_InIter __first, _Sent __last, _OutIter __result, _Comp __comp = {}, _Proj __proj = {}) const { - // TODO: implement - (void)__first; (void)__last; (void)__result; (void)__comp; (void)__proj; - return {}; + auto __ret = std::__unique_copy<_RangeAlgPolicy>( + std::move(__first), + std::move(__last), + std::move(__result), + __make_projected_comp(__comp, __proj), + __algo_tag_t<_InIter, _OutIter>()); + return {std::move(__ret.first), std::move(__ret.second)}; } - template , _Proj>> _Comp = ranges::equal_to> - requires indirectly_copyable, _OutIter> && - (forward_iterator> || - (input_iterator<_OutIter> && same_as, iter_value_t<_OutIter>>) || - indirectly_copyable_storable, _OutIter>) - _LIBCPP_HIDE_FROM_ABI constexpr - unique_copy_result, _OutIter> + requires indirectly_copyable, _OutIter> && + (forward_iterator> || + (input_iterator<_OutIter> && same_as, iter_value_t<_OutIter>>) || + indirectly_copyable_storable, _OutIter>) + _LIBCPP_HIDE_FROM_ABI constexpr unique_copy_result, _OutIter> operator()(_Range&& __range, _OutIter __result, _Comp __comp = {}, _Proj __proj = {}) const { - // TODO: implement - (void)__range; (void)__result; (void)__comp; (void)__proj; - return {}; + auto __ret = std::__unique_copy<_RangeAlgPolicy>( + ranges::begin(__range), + ranges::end(__range), + std::move(__result), + __make_projected_comp(__comp, __proj), + __algo_tag_t, _OutIter>()); + return {std::move(__ret.first), std::move(__ret.second)}; } - }; } // namespace __unique_copy inline namespace __cpo { - inline constexpr auto unique_copy = __unique_copy::__fn{}; +inline constexpr auto unique_copy = __unique_copy::__fn{}; } // namespace __cpo } // namespace ranges diff --git a/libcxx/include/__algorithm/unique.h b/libcxx/include/__algorithm/unique.h index 264d727d93c88..1727225a91cdb 100644 --- a/libcxx/include/__algorithm/unique.h +++ b/libcxx/include/__algorithm/unique.h @@ -11,9 +11,11 @@ #include <__algorithm/adjacent_find.h> #include <__algorithm/comp.h> +#include <__algorithm/iterator_operations.h> #include <__config> #include <__iterator/iterator_traits.h> #include <__utility/move.h> +#include <__utility/pair.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -23,32 +25,34 @@ _LIBCPP_BEGIN_NAMESPACE_STD // unique +template +_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 std::pair<_Iter, _Iter> +__unique(_Iter __first, _Sent __last, _BinaryPredicate&& __pred) { + __first = std::__adjacent_find(__first, __last, __pred); + if (__first != __last) { + // ... a a ? ... + // f i + _Iter __i = __first; + for (++__i; ++__i != __last;) + if (!__pred(*__first, *__i)) + *++__first = _IterOps<_AlgPolicy>::__iter_move(__i); + ++__first; + return std::pair<_Iter, _Iter>(std::move(__first), std::move(__i)); + } + return std::pair<_Iter, _Iter>(__first, __first); +} + template -_LIBCPP_NODISCARD_EXT _LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator -unique(_ForwardIterator __first, _ForwardIterator __last, _BinaryPredicate __pred) -{ - __first = _VSTD::adjacent_find<_ForwardIterator, _BinaryPredicate&>(__first, __last, __pred); - if (__first != __last) - { - // ... a a ? ... - // f i - _ForwardIterator __i = __first; - for (++__i; ++__i != __last;) - if (!__pred(*__first, *__i)) - *++__first = _VSTD::move(*__i); - ++__first; - } - return __first; +_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator +unique(_ForwardIterator __first, _ForwardIterator __last, _BinaryPredicate __pred) { + return std::__unique<_ClassicAlgPolicy>(std::move(__first), std::move(__last), __pred).first; } template -_LIBCPP_NODISCARD_EXT inline -_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 -_ForwardIterator -unique(_ForwardIterator __first, _ForwardIterator __last) -{ - typedef typename iterator_traits<_ForwardIterator>::value_type __v; - return _VSTD::unique(__first, __last, __equal_to<__v>()); +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator +unique(_ForwardIterator __first, _ForwardIterator __last) { + typedef typename iterator_traits<_ForwardIterator>::value_type __v; + return std::unique(__first, __last, __equal_to<__v>()); } _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__algorithm/unique_copy.h b/libcxx/include/__algorithm/unique_copy.h index f58517749f514..c7c8d8e9d8fde 100644 --- a/libcxx/include/__algorithm/unique_copy.h +++ b/libcxx/include/__algorithm/unique_copy.h @@ -10,8 +10,14 @@ #define _LIBCPP___ALGORITHM_UNIQUE_COPY_H #include <__algorithm/comp.h> +#include <__algorithm/iterator_operations.h> #include <__config> #include <__iterator/iterator_traits.h> +#include <__type_traits/conditional.h> +#include <__type_traits/is_base_of.h> +#include <__type_traits/is_same.h> +#include <__utility/move.h> +#include <__utility/pair.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -19,88 +25,99 @@ _LIBCPP_BEGIN_NAMESPACE_STD -template -_LIBCPP_CONSTEXPR_AFTER_CXX17 _OutputIterator -__unique_copy(_InputIterator __first, _InputIterator __last, _OutputIterator __result, _BinaryPredicate __pred, - input_iterator_tag, output_iterator_tag) -{ - if (__first != __last) - { - typename iterator_traits<_InputIterator>::value_type __t(*__first); +namespace __unique_copy_tags { + +struct __reread_from_input_tag {}; +struct __reread_from_output_tag {}; +struct __read_from_tmp_value_tag {}; + +} // namespace __unique_copy_tags + +template +_LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI pair<_InputIterator, _OutputIterator> +__unique_copy(_InputIterator __first, + _Sent __last, + _OutputIterator __result, + _BinaryPredicate&& __pred, + __unique_copy_tags::__read_from_tmp_value_tag) { + if (__first != __last) { + typename _IterOps<_AlgPolicy>::template __value_type<_InputIterator> __t(*__first); + *__result = __t; + ++__result; + while (++__first != __last) { + if (!__pred(__t, *__first)) { + __t = *__first; *__result = __t; ++__result; - while (++__first != __last) - { - if (!__pred(__t, *__first)) - { - __t = *__first; - *__result = __t; - ++__result; - } - } + } } - return __result; + } + return pair<_InputIterator, _OutputIterator>(std::move(__first), std::move(__result)); } -template -_LIBCPP_CONSTEXPR_AFTER_CXX17 _OutputIterator -__unique_copy(_ForwardIterator __first, _ForwardIterator __last, _OutputIterator __result, _BinaryPredicate __pred, - forward_iterator_tag, output_iterator_tag) -{ - if (__first != __last) - { - _ForwardIterator __i = __first; - *__result = *__i; +template +_LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI pair<_ForwardIterator, _OutputIterator> +__unique_copy(_ForwardIterator __first, + _Sent __last, + _OutputIterator __result, + _BinaryPredicate&& __pred, + __unique_copy_tags::__reread_from_input_tag) { + if (__first != __last) { + _ForwardIterator __i = __first; + *__result = *__i; + ++__result; + while (++__first != __last) { + if (!__pred(*__i, *__first)) { + *__result = *__first; ++__result; - while (++__first != __last) - { - if (!__pred(*__i, *__first)) - { - *__result = *__first; - ++__result; - __i = __first; - } - } + __i = __first; + } } - return __result; + } + return pair<_ForwardIterator, _OutputIterator>(std::move(__first), std::move(__result)); } -template -_LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator -__unique_copy(_InputIterator __first, _InputIterator __last, _ForwardIterator __result, _BinaryPredicate __pred, - input_iterator_tag, forward_iterator_tag) -{ - if (__first != __last) - { - *__result = *__first; - while (++__first != __last) - if (!__pred(*__result, *__first)) - *++__result = *__first; - ++__result; - } - return __result; +template +_LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI pair<_InputIterator, _InputAndOutputIterator> +__unique_copy(_InputIterator __first, + _Sent __last, + _InputAndOutputIterator __result, + _BinaryPredicate&& __pred, + __unique_copy_tags::__reread_from_output_tag) { + if (__first != __last) { + *__result = *__first; + while (++__first != __last) + if (!__pred(*__result, *__first)) + *++__result = *__first; + ++__result; + } + return pair<_InputIterator, _InputAndOutputIterator>(std::move(__first), std::move(__result)); } template -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 -_OutputIterator -unique_copy(_InputIterator __first, _InputIterator __last, _OutputIterator __result, _BinaryPredicate __pred) -{ - return _VSTD::__unique_copy<_BinaryPredicate&>(__first, __last, __result, __pred, - typename iterator_traits<_InputIterator>::iterator_category(), - typename iterator_traits<_OutputIterator>::iterator_category()); +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 _OutputIterator +unique_copy(_InputIterator __first, _InputIterator __last, _OutputIterator __result, _BinaryPredicate __pred) { + using __algo_tag = typename conditional< + is_base_of::iterator_category>::value, + __unique_copy_tags::__reread_from_input_tag, + typename conditional< + is_base_of::iterator_category>::value && + is_same< typename iterator_traits<_InputIterator>::value_type, + typename iterator_traits<_OutputIterator>::value_type>::value, + __unique_copy_tags::__reread_from_output_tag, + __unique_copy_tags::__read_from_tmp_value_tag>::type >::type; + return std::__unique_copy<_ClassicAlgPolicy>( + std::move(__first), std::move(__last), std::move(__result), __pred, __algo_tag()) + .second; } template -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 -_OutputIterator -unique_copy(_InputIterator __first, _InputIterator __last, _OutputIterator __result) -{ - typedef typename iterator_traits<_InputIterator>::value_type __v; - return _VSTD::unique_copy(__first, __last, __result, __equal_to<__v>()); +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 _OutputIterator +unique_copy(_InputIterator __first, _InputIterator __last, _OutputIterator __result) { + typedef typename iterator_traits<_InputIterator>::value_type __v; + return std::unique_copy(std::move(__first), std::move(__last), std::move(__result), __equal_to<__v>()); } - _LIBCPP_END_NAMESPACE_STD #endif // _LIBCPP___ALGORITHM_UNIQUE_COPY_H diff --git a/libcxx/include/algorithm b/libcxx/include/algorithm index 4fc353a8ce5dd..7b510b5096afd 100644 --- a/libcxx/include/algorithm +++ b/libcxx/include/algorithm @@ -865,6 +865,34 @@ namespace ranges { borrowed_iterator_t inplace_merge(R&& r, iterator_t middle, Comp comp = {}, Proj proj = {}); // Since C++20 + + template S, class Proj = identity, + indirect_equivalence_relation> C = ranges::equal_to> + constexpr subrange unique(I first, S last, C comp = {}, Proj proj = {}); // Since C++20 + + template, Proj>> C = ranges::equal_to> + requires permutable> + constexpr borrowed_subrange_t + unique(R&& r, C comp = {}, Proj proj = {}); // Since C++20 + + template S, weakly_incrementable O, class Proj = identity, + indirect_equivalence_relation> C = ranges::equal_to> + requires indirectly_copyable && + (forward_iterator || + (input_iterator && same_as, iter_value_t>) || + indirectly_copyable_storable) + constexpr unique_copy_result + unique_copy(I first, S last, O result, C comp = {}, Proj proj = {}); // Since C++20 + + template, Proj>> C = ranges::equal_to> + requires indirectly_copyable, O> && + (forward_iterator> || + (input_iterator && same_as, iter_value_t>) || + indirectly_copyable_storable, O>) + constexpr unique_copy_result, O> + unique_copy(R&& r, O result, C comp = {}, Proj proj = {}); // Since C++20 } constexpr bool // constexpr in C++20 @@ -1665,6 +1693,8 @@ template #include <__algorithm/ranges_stable_sort.h> #include <__algorithm/ranges_swap_ranges.h> #include <__algorithm/ranges_transform.h> +#include <__algorithm/ranges_unique.h> +#include <__algorithm/ranges_unique_copy.h> #include <__algorithm/ranges_upper_bound.h> #include <__algorithm/remove.h> #include <__algorithm/remove_copy.h> diff --git a/libcxx/test/libcxx/algorithms/ranges_robust_against_copying_comparators.pass.cpp b/libcxx/test/libcxx/algorithms/ranges_robust_against_copying_comparators.pass.cpp index 669fa9c1842ef..b4328006539f7 100644 --- a/libcxx/test/libcxx/algorithms/ranges_robust_against_copying_comparators.pass.cpp +++ b/libcxx/test/libcxx/algorithms/ranges_robust_against_copying_comparators.pass.cpp @@ -222,10 +222,10 @@ constexpr bool all_the_algorithms() (void)std::ranges::transform(a, first2, UnaryTransform(&copies)); assert(copies == 0); (void)std::ranges::transform(first, mid, mid, last, first2, BinaryTransform(&copies)); assert(copies == 0); (void)std::ranges::transform(a, b, first2, BinaryTransform(&copies)); assert(copies == 0); - //(void)std::ranges::unique(first, last, Equal(&copies)); assert(copies == 0); - //(void)std::ranges::unique(a, Equal(&copies)); assert(copies == 0); - //(void)std::ranges::unique_copy(first, last, first2, Equal(&copies)); assert(copies == 0); - //(void)std::ranges::unique_copy(a, first2, Equal(&copies)); assert(copies == 0); + (void)std::ranges::unique(first, last, Equal(&copies)); assert(copies == 0); + (void)std::ranges::unique(a, Equal(&copies)); assert(copies == 0); + (void)std::ranges::unique_copy(first, last, first2, Equal(&copies)); assert(copies == 0); + (void)std::ranges::unique_copy(a, first2, Equal(&copies)); assert(copies == 0); (void)std::ranges::upper_bound(first, last, value, Less(&copies)); assert(copies == 0); (void)std::ranges::upper_bound(a, value, Less(&copies)); assert(copies == 0); diff --git a/libcxx/test/libcxx/algorithms/ranges_robust_against_copying_projections.pass.cpp b/libcxx/test/libcxx/algorithms/ranges_robust_against_copying_projections.pass.cpp index 22fdf09888af7..4eadbcc97a65c 100644 --- a/libcxx/test/libcxx/algorithms/ranges_robust_against_copying_projections.pass.cpp +++ b/libcxx/test/libcxx/algorithms/ranges_robust_against_copying_projections.pass.cpp @@ -213,10 +213,10 @@ constexpr bool all_the_algorithms() (void)std::ranges::transform(a, first2, UnaryTransform(), Proj(&copies)); assert(copies == 0); (void)std::ranges::transform(first, mid, mid, last, first2, BinaryTransform(), Proj(&copies), Proj(&copies)); assert(copies == 0); (void)std::ranges::transform(a, b, first2, BinaryTransform(), Proj(&copies), Proj(&copies)); assert(copies == 0); - //(void)std::ranges::unique(first, last, Equal(), Proj(&copies)); assert(copies == 0); - //(void)std::ranges::unique(a, Equal(), Proj(&copies)); assert(copies == 0); - //(void)std::ranges::unique_copy(first, last, first2, Equal(), Proj(&copies)); assert(copies == 0); - //(void)std::ranges::unique_copy(a, first2, Equal(), Proj(&copies)); assert(copies == 0); + (void)std::ranges::unique(first, last, Equal(), Proj(&copies)); assert(copies == 0); + (void)std::ranges::unique(a, Equal(), Proj(&copies)); assert(copies == 0); + (void)std::ranges::unique_copy(first, last, first2, Equal(), Proj(&copies)); assert(copies == 0); + (void)std::ranges::unique_copy(a, first2, Equal(), Proj(&copies)); assert(copies == 0); (void)std::ranges::upper_bound(first, last, value, Less(), Proj(&copies)); assert(copies == 0); (void)std::ranges::upper_bound(a, value, Less(), Proj(&copies)); assert(copies == 0); diff --git a/libcxx/test/std/algorithms/alg.modifying.operations/alg.unique/ranges_unique.pass.cpp b/libcxx/test/std/algorithms/alg.modifying.operations/alg.unique/ranges_unique.pass.cpp index 216ae6a1b98ef..bb60109e77351 100644 --- a/libcxx/test/std/algorithms/alg.modifying.operations/alg.unique/ranges_unique.pass.cpp +++ b/libcxx/test/std/algorithms/alg.modifying.operations/alg.unique/ranges_unique.pass.cpp @@ -28,14 +28,214 @@ #include #include "almost_satisfies_types.h" +#include "counting_predicates.h" +#include "counting_projection.h" #include "test_iterators.h" -// TODO: SFINAE tests. +template +concept HasUniqueIter = + requires(Iter&& iter, Sent&& sent, Comp&& comp, Proj&& proj) { + std::ranges::unique( + std::forward(iter), std::forward(sent), std::forward(comp), std::forward(proj)); + }; + +static_assert(HasUniqueIter); + +// !permutable +static_assert(!HasUniqueIter); +static_assert(!HasUniqueIter); + +// !sentinel_for +static_assert(!HasUniqueIter); + +// !indirect_equivalence_relation> +static_assert(!HasUniqueIter>); + +template +concept HasUniqueRange = + requires(Range&& range, Comp&& comp, Proj&& proj) { + std::ranges::unique(std::forward(range), std::forward(comp), std::forward(proj)); + }; + +template +using R = UncheckedRange; + +static_assert(HasUniqueRange>); + +// !forward_range +static_assert(!HasUniqueRange); +static_assert(!HasUniqueRange); + +// permutable> +static_assert(!HasUniqueRange>); +static_assert(!HasUniqueRange>); + +// !indirect_equivalence_relation, Proj>> +static_assert(!HasUniqueRange, ComparatorNotCopyable>); + +template class SentWrapper, std::size_t N1, std::size_t N2> +constexpr void testUniqueImpl(std::array input, std::array expected) { + using Sent = SentWrapper; + + // iterator overload + { + auto in = input; + std::same_as> decltype(auto) result = + std::ranges::unique(Iter{in.data()}, Sent{Iter{in.data() + in.size()}}); + assert(std::ranges::equal(std::ranges::subrange{Iter{in.data()}, result.begin()}, expected)); + assert(base(result.end()) == in.data() + in.size()); + } + + // range overload + { + auto in = input; + std::ranges::subrange r{Iter{in.data()}, Sent{Iter{in.data() + in.size()}}}; + std::same_as> decltype(auto) result = std::ranges::unique(r); + assert(std::ranges::equal(std::ranges::subrange{Iter{in.data()}, result.begin()}, expected)); + assert(base(result.end()) == in.data() + in.size()); + } +} + +template class SentWrapper> +constexpr void testImpl() { + // no consecutive elements + { + std::array in{1, 2, 3, 2, 1}; + std::array expected{1, 2, 3, 2, 1}; + testUniqueImpl(in, expected); + } + + // one group of consecutive elements + { + std::array in{2, 3, 3, 3, 4, 3}; + std::array expected{2, 3, 4, 3}; + testUniqueImpl(in, expected); + } + + // multiple groups of consecutive elements + { + std::array in{2, 3, 3, 3, 4, 3, 3, 5, 5, 5}; + std::array expected{2, 3, 4, 3, 5}; + testUniqueImpl(in, expected); + } + + // all the same + { + std::array in{1, 1, 1, 1, 1, 1}; + std::array expected{1}; + testUniqueImpl(in, expected); + } + + // empty range + { + std::array in{}; + std::array expected{}; + testUniqueImpl(in, expected); + } + + // single element range + std::array in{1}; + std::array expected{1}; + testUniqueImpl(in, expected); +} + +template