diff --git a/stl/inc/algorithm b/stl/inc/algorithm index 0bfef44a07b..0f8e36e6f3d 100644 --- a/stl/inc/algorithm +++ b/stl/inc/algorithm @@ -374,8 +374,8 @@ namespace ranges { #if _HAS_CXX23 _EXPORT_STD template struct in_value_result { - /* [[no_unique_address]] */ _In in; - /* [[no_unique_address]] */ _Ty value; + _MSVC_NO_UNIQUE_ADDRESS _In in; + _MSVC_NO_UNIQUE_ADDRESS _Ty value; template requires convertible_to && convertible_to diff --git a/stl/inc/mdspan b/stl/inc/mdspan index bedc6046035..fa151c8a499 100644 --- a/stl/inc/mdspan +++ b/stl/inc/mdspan @@ -23,8 +23,8 @@ _STL_DISABLE_CLANG_WARNINGS #undef new // TRANSITION, non-_Ugly attribute tokens -#pragma push_macro("empty_bases") -#undef empty_bases +#pragma push_macro("msvc") +#undef msvc _STD_BEGIN template @@ -1073,37 +1073,37 @@ concept _Elidable_layout_mapping = || (same_as<_LayoutPolicy, layout_stride> && _Extents::rank() == 0); template -struct _Mdspan_mapping_base { +struct _Mdspan_mapping_holder { _STL_INTERNAL_STATIC_ASSERT(_Is_extents<_Extents>); using _Mapping = _LayoutPolicy::template mapping<_Extents>; - constexpr _Mdspan_mapping_base() noexcept = default; + constexpr _Mdspan_mapping_holder() noexcept = default; - constexpr explicit _Mdspan_mapping_base(const _Extents& _Exts) : _Map(_Exts) {} + constexpr explicit _Mdspan_mapping_holder(const _Extents& _Exts) : _Map(_Exts) {} - constexpr explicit _Mdspan_mapping_base(_Extents&& _Exts) : _Map(_STD move(_Exts)) {} + constexpr explicit _Mdspan_mapping_holder(_Extents&& _Exts) : _Map(_STD move(_Exts)) {} template - constexpr explicit _Mdspan_mapping_base(const _OtherMapping& _Map_) : _Map(_Map_) {} + constexpr explicit _Mdspan_mapping_holder(const _OtherMapping& _Map_) : _Map(_Map_) {} - _Mapping _Map = _Mapping(); + _MSVC_NO_UNIQUE_ADDRESS _Mapping _Map = _Mapping(); }; template _LayoutPolicy> -struct _Mdspan_mapping_base<_Extents, _LayoutPolicy> { +struct _Mdspan_mapping_holder<_Extents, _LayoutPolicy> { _STL_INTERNAL_STATIC_ASSERT(_Is_extents<_Extents>); using _Mapping = _LayoutPolicy::template mapping<_Extents>; - constexpr _Mdspan_mapping_base() noexcept = default; + constexpr _Mdspan_mapping_holder() noexcept = default; - constexpr explicit _Mdspan_mapping_base(const _Extents&) noexcept {} + constexpr explicit _Mdspan_mapping_holder(const _Extents&) noexcept {} - constexpr explicit _Mdspan_mapping_base(_Extents&&) noexcept {} + constexpr explicit _Mdspan_mapping_holder(_Extents&&) noexcept {} template - constexpr explicit _Mdspan_mapping_base(const _OtherMapping& _Map_) { + constexpr explicit _Mdspan_mapping_holder(const _OtherMapping& _Map_) { // NB: Constructing _Mapping from _OtherMapping may have side effects - we should create a temporary. if constexpr (!_Elidable_layout_mapping) { (void) _Mapping{_Map_}; @@ -1117,21 +1117,21 @@ template concept _Elidable_accessor_policy = _Is_specialization_v<_AccessorPolicy, default_accessor>; template -struct _Mdspan_accessor_base { - constexpr _Mdspan_accessor_base() noexcept = default; +struct _Mdspan_accessor_holder { + constexpr _Mdspan_accessor_holder() noexcept = default; template - constexpr explicit _Mdspan_accessor_base(const _OtherAccessorPolicy& _Acc_) : _Acc(_Acc_) {} + constexpr explicit _Mdspan_accessor_holder(const _OtherAccessorPolicy& _Acc_) : _Acc(_Acc_) {} - _AccessorPolicy _Acc = _AccessorPolicy(); + _MSVC_NO_UNIQUE_ADDRESS _AccessorPolicy _Acc = _AccessorPolicy(); }; template <_Elidable_accessor_policy _AccessorPolicy> -struct _Mdspan_accessor_base<_AccessorPolicy> { - constexpr _Mdspan_accessor_base() noexcept = default; +struct _Mdspan_accessor_holder<_AccessorPolicy> { + constexpr _Mdspan_accessor_holder() noexcept = default; template - constexpr explicit _Mdspan_accessor_base(const _OtherAccessorPolicy& _Acc_) { + constexpr explicit _Mdspan_accessor_holder(const _OtherAccessorPolicy& _Acc_) { // NB: Constructing _AccessorPolicy from _OtherAccessorPolicy may have side effects - we should create a // temporary. if constexpr (!_Elidable_accessor_policy<_OtherAccessorPolicy>) { @@ -1160,8 +1160,7 @@ _NODISCARD constexpr _IndexType _Mdspan_checked_index_cast(_OtherIndexType&& _Id _EXPORT_STD template > -class __declspec(empty_bases) mdspan : private _Mdspan_mapping_base<_Extents, _LayoutPolicy>, - private _Mdspan_accessor_base<_AccessorPolicy> { +class mdspan { public: using extents_type = _Extents; using layout_type = _LayoutPolicy; @@ -1176,9 +1175,6 @@ public: using reference = accessor_type::reference; private: - using _Mapping_base = _Mdspan_mapping_base; - using _Accessor_base = _Mdspan_accessor_base; - static_assert( sizeof(element_type) > 0, "ElementType must be a complete type (N4950 [mdspan.mdspan.overview]/2.1)."); static_assert( @@ -1208,7 +1204,7 @@ public: } _NODISCARD constexpr index_type extent(_In_range_(<, extents_type::_Rank) const rank_type _Idx) const noexcept { - return this->_Map.extents().extent(_Idx); + return _Mapping._Map.extents().extent(_Idx); } constexpr mdspan() noexcept(is_nothrow_default_constructible_v @@ -1229,8 +1225,7 @@ public: constexpr explicit mdspan(data_handle_type _Ptr_, _OtherIndexTypes... _Exts) noexcept(is_nothrow_constructible_v && is_nothrow_default_constructible_v) // strengthened - : _Mapping_base(extents_type{static_cast(_STD move(_Exts))...}), _Accessor_base(), - _Ptr(_STD move(_Ptr_)) {} + : _Mapping(extents_type{static_cast(_STD move(_Exts))...}), _Accessor(), _Ptr(_STD move(_Ptr_)) {} template requires is_convertible_v @@ -1240,7 +1235,7 @@ public: constexpr explicit(_Size != rank_dynamic()) mdspan(data_handle_type _Ptr_, span<_OtherIndexType, _Size> _Exts) noexcept(is_nothrow_constructible_v && is_nothrow_default_constructible_v) // strengthened - : _Mapping_base(extents_type{_Exts}), _Accessor_base(), _Ptr(_STD move(_Ptr_)) {} + : _Mapping(extents_type{_Exts}), _Accessor(), _Ptr(_STD move(_Ptr_)) {} template requires is_convertible_v @@ -1251,23 +1246,23 @@ public: mdspan(data_handle_type _Ptr_, const array<_OtherIndexType, _Size>& _Exts) noexcept(is_nothrow_constructible_v && is_nothrow_default_constructible_v) // strengthened - : _Mapping_base(extents_type{_Exts}), _Accessor_base(), _Ptr(_STD move(_Ptr_)) {} + : _Mapping(extents_type{_Exts}), _Accessor(), _Ptr(_STD move(_Ptr_)) {} constexpr mdspan(data_handle_type _Ptr_, const extents_type& _Exts) noexcept(is_nothrow_constructible_v && is_nothrow_default_constructible_v) // strengthened requires is_constructible_v && is_default_constructible_v - : _Mapping_base(_Exts), _Accessor_base(), _Ptr(_STD move(_Ptr_)) {} + : _Mapping(_Exts), _Accessor(), _Ptr(_STD move(_Ptr_)) {} constexpr mdspan(data_handle_type _Ptr_, const mapping_type& _Map_) noexcept(is_nothrow_copy_constructible_v && is_nothrow_default_constructible_v) // strengthened requires is_default_constructible_v - : _Mapping_base(_Map_), _Accessor_base(), _Ptr(_STD move(_Ptr_)) {} + : _Mapping(_Map_), _Accessor(), _Ptr(_STD move(_Ptr_)) {} constexpr mdspan(data_handle_type _Ptr_, const mapping_type& _Map_, const accessor_type& _Acc_) noexcept( is_nothrow_copy_constructible_v && is_nothrow_copy_constructible_v) // strengthened - : _Mapping_base(_Map_), _Accessor_base(_Acc_), _Ptr(_STD move(_Ptr_)) {} + : _Mapping(_Map_), _Accessor(_Acc_), _Ptr(_STD move(_Ptr_)) {} template requires is_constructible_v&> @@ -1280,7 +1275,7 @@ public: && is_nothrow_constructible_v&> && is_nothrow_constructible_v) // strengthened - : _Mapping_base(_Other.mapping()), _Accessor_base(_Other.accessor()), _Ptr(_Other.data_handle()) { + : _Mapping(_Other.mapping()), _Accessor(_Other.accessor()), _Ptr(_Other.data_handle()) { static_assert(is_constructible_v, "The data_handle_type must be constructible from const typename OtherAccessor::data_handle_type& (N4950 " "[mdspan.mdspan.cons]/20.1)."); @@ -1346,20 +1341,21 @@ public: _NODISCARD constexpr size_type size() const noexcept { #if _ITERATOR_DEBUG_LEVEL != 0 if constexpr (rank_dynamic() != 0) { - _STL_VERIFY(this->_Map.extents().template _Is_dynamic_multidim_index_space_size_representable(), + _STL_VERIFY( + _Mapping._Map.extents().template _Is_dynamic_multidim_index_space_size_representable(), "The size of the multidimensional index space extents() must be representable as a value of type " "size_type (N4950 [mdspan.mdspan.members]/7)."); } #endif // _ITERATOR_DEBUG_LEVEL != 0 return static_cast( - _Fwd_prod_of_extents::_Calculate(this->_Map.extents(), extents_type::_Rank)); + _Fwd_prod_of_extents::_Calculate(_Mapping._Map.extents(), extents_type::_Rank)); } _NODISCARD constexpr bool empty() const noexcept { if constexpr (extents_type::_Multidim_index_space_size_is_always_zero) { return true; } else { - const extents_type& _Exts = this->_Map.extents(); + const extents_type& _Exts = _Mapping._Map.extents(); for (rank_type _Idx = 0; _Idx < extents_type::_Rank; ++_Idx) { if (_Exts.extent(_Idx) == 0) { return true; @@ -1373,16 +1369,16 @@ public: swap(_Left._Ptr, _Right._Ptr); // intentional ADL if constexpr (!_Elidable_layout_mapping) { - swap(_Left._Map, _Right._Map); // intentional ADL + swap(_Left._Mapping._Map, _Right._Mapping._Map); // intentional ADL } if constexpr (!_Elidable_accessor_policy) { - swap(_Left._Acc, _Right._Acc); // intentional ADL + swap(_Left._Accessor._Acc, _Right._Accessor._Acc); // intentional ADL } } _NODISCARD constexpr const extents_type& extents() const noexcept { - return this->_Map.extents(); + return _Mapping._Map.extents(); } _NODISCARD constexpr const data_handle_type& data_handle() const noexcept { @@ -1390,11 +1386,11 @@ public: } _NODISCARD constexpr const mapping_type& mapping() const noexcept { - return this->_Map; + return _Mapping._Map; } _NODISCARD constexpr const accessor_type& accessor() const noexcept { - return this->_Acc; + return _Accessor._Acc; } _NODISCARD static constexpr bool is_always_unique() noexcept /* strengthened */ { @@ -1412,38 +1408,42 @@ public: return _Result; } - _NODISCARD constexpr bool is_unique() const noexcept(noexcept(this->_Map.is_unique())) /* strengthened */ { - return this->_Map.is_unique(); + _NODISCARD constexpr bool is_unique() const noexcept(noexcept(_Mapping._Map.is_unique())) /* strengthened */ { + return _Mapping._Map.is_unique(); } - _NODISCARD constexpr bool is_exhaustive() const noexcept(noexcept(this->_Map.is_exhaustive())) /* strengthened */ { - return this->_Map.is_exhaustive(); + _NODISCARD constexpr bool is_exhaustive() const + noexcept(noexcept(_Mapping._Map.is_exhaustive())) /* strengthened */ { + return _Mapping._Map.is_exhaustive(); } - _NODISCARD constexpr bool is_strided() const noexcept(noexcept(this->_Map.is_strided())) /* strengthened */ { - return this->_Map.is_strided(); + _NODISCARD constexpr bool is_strided() const noexcept(noexcept(_Mapping._Map.is_strided())) /* strengthened */ { + return _Mapping._Map.is_strided(); } _NODISCARD constexpr index_type stride(const rank_type _Idx) const - noexcept(noexcept(this->_Map.stride(_Idx))) /* strengthened */ { - return this->_Map.stride(_Idx); + noexcept(noexcept(_Mapping._Map.stride(_Idx))) /* strengthened */ { + return _Mapping._Map.stride(_Idx); } private: template _NODISCARD constexpr reference _Access_impl(_OtherIndexTypes... _Indices) const - noexcept(noexcept(this->_Acc.access(_Ptr, static_cast(this->_Map(_Indices...))))) { + noexcept(noexcept(_Accessor._Acc.access(_Ptr, static_cast(_Mapping._Map(_Indices...))))) { _STL_INTERNAL_STATIC_ASSERT(conjunction_v...>); #if _MSVC_STL_HARDENING_MDSPAN || _ITERATOR_DEBUG_LEVEL != 0 - _STL_VERIFY(this->_Map.extents()._Contains_multidimensional_index(make_index_sequence{}, _Indices...), - "mdspan subscript out of range; extents_type::index-cast(std::move(indices)) must be " - "a multidimensional index in extents() (N5001 [mdspan.mdspan.members]/3)."); + _STL_VERIFY( + _Mapping._Map.extents()._Contains_multidimensional_index(make_index_sequence{}, _Indices...), + "mdspan subscript out of range; extents_type::index-cast(std::move(indices)) must be a multidimensional " + "index in extents() (N5001 [mdspan.mdspan.members]/3)."); #endif - return this->_Acc.access(_Ptr, static_cast(this->_Map(_Indices...))); + return _Accessor._Acc.access(_Ptr, static_cast(_Mapping._Map(_Indices...))); } - /* [[no_unique_address]] */ data_handle_type _Ptr = data_handle_type(); + _MSVC_NO_UNIQUE_ADDRESS _Mdspan_mapping_holder _Mapping; + _MSVC_NO_UNIQUE_ADDRESS _Mdspan_accessor_holder _Accessor; + _MSVC_NO_UNIQUE_ADDRESS data_handle_type _Ptr = data_handle_type(); }; template @@ -1480,7 +1480,7 @@ mdspan(const typename _AccessorType::data_handle_type&, const _MappingType&, con _STD_END // TRANSITION, non-_Ugly attribute tokens -#pragma pop_macro("empty_bases") +#pragma pop_macro("msvc") #pragma pop_macro("new") _STL_RESTORE_CLANG_WARNINGS diff --git a/stl/inc/ranges b/stl/inc/ranges index 06520461db3..8768eede7ea 100644 --- a/stl/inc/ranges +++ b/stl/inc/ranges @@ -31,6 +31,10 @@ _STL_DISABLE_CLANG_WARNINGS #pragma push_macro("new") #undef new +// TRANSITION, non-_Ugly attribute tokens +#pragma push_macro("msvc") +#undef msvc + _STD_BEGIN namespace ranges { // MUCH machinery defined in , some in <__msvc_ranges_to.hpp> @@ -1087,7 +1091,7 @@ namespace ranges { using _Index_type = conditional_t, ptrdiff_t, _Bo>; const _Ty* _Value{}; - /* [[no_unique_address]] */ _Index_type _Current{}; + _Index_type _Current{}; constexpr explicit _Iterator(const _Ty* _Val, _Index_type _Bo_ = _Index_type{}) noexcept // strengthened : _Value(_Val), _Current(_Bo_) { @@ -3453,7 +3457,7 @@ namespace ranges { using _Parent_t = _Maybe_const<_Const, join_with_view>; using _Base = _Maybe_const<_Const, _Vw>; - /* [[no_unique_address]] */ sentinel_t<_Base> _Last{}; + _MSVC_NO_UNIQUE_ADDRESS sentinel_t<_Base> _Last{}; constexpr explicit _Sentinel(_Parent_t& _Parent) noexcept(noexcept(_RANGES end(_Parent._Range)) @@ -5129,7 +5133,7 @@ namespace ranges { using _Base_iterator = iterator_t<_Base_t>; using _Reference_type = tuple, range_reference_t<_Base_t>>; - /* [[no_unique_address]] */ _Base_iterator _Current{}; + _MSVC_NO_UNIQUE_ADDRESS _Base_iterator _Current{}; range_difference_t<_Base_t> _Pos = 0; constexpr explicit _Iterator(_Base_iterator _Current_, range_difference_t<_Base_t> _Pos_) @@ -5289,7 +5293,7 @@ namespace ranges { using _Base_t = _Maybe_const<_Const, _Vw>; using _Base_sentinel = sentinel_t<_Base_t>; - /* [[no_unique_address]] */ _Base_sentinel _End{}; + _MSVC_NO_UNIQUE_ADDRESS _Base_sentinel _End{}; constexpr explicit _Sentinel(_Base_sentinel _End_) noexcept(is_nothrow_move_constructible_v<_Base_sentinel>) // strengthened @@ -5725,8 +5729,8 @@ namespace ranges { using _Base_iterator = iterator_t<_Base>; using _Base_sentinel = sentinel_t<_Base>; - /* [[no_unique_address]] */ _Base_iterator _Current{}; - /* [[no_unique_address]] */ _Base_sentinel _End{}; + _MSVC_NO_UNIQUE_ADDRESS _Base_iterator _Current{}; + _MSVC_NO_UNIQUE_ADDRESS _Base_sentinel _End{}; range_difference_t<_Base> _Count = 0; range_difference_t<_Base> _Missing = 0; @@ -6284,7 +6288,7 @@ namespace ranges { class _Sentinel { private: friend slide_view; - /* [[no_unique_address]] */ sentinel_t<_Vw> _Last{}; + _MSVC_NO_UNIQUE_ADDRESS sentinel_t<_Vw> _Last{}; constexpr explicit _Sentinel(sentinel_t<_Vw> _Last_) noexcept(is_nothrow_move_constructible_v>) /* strengthened */ @@ -9243,6 +9247,9 @@ _EXPORT_STD namespace views = ranges::views; _STD_END +// TRANSITION, non-_Ugly attribute tokens +#pragma pop_macro("msvc") + #pragma pop_macro("new") _STL_RESTORE_CLANG_WARNINGS #pragma warning(pop) diff --git a/stl/inc/xmemory b/stl/inc/xmemory index acac82131e1..21cb148dc12 100644 --- a/stl/inc/xmemory +++ b/stl/inc/xmemory @@ -25,6 +25,10 @@ _STL_DISABLE_CLANG_WARNINGS #pragma push_macro("new") #undef new +// TRANSITION, non-_Ugly attribute tokens +#pragma push_macro("msvc") +#undef msvc + #if _USE_STD_VECTOR_ALGORITHMS extern "C" { void* __stdcall __std_remove_1(void* _First, void* _Last, uint8_t _Val) noexcept; @@ -2736,8 +2740,8 @@ namespace ranges { _EXPORT_STD template #endif // ^^^ !defined(__cpp_lib_byte) ^^^ struct elements_of { - /* [[no_unique_address]] */ _Rng range; - /* [[no_unique_address]] */ _Alloc allocator{}; + _MSVC_NO_UNIQUE_ADDRESS _Rng range; + _MSVC_NO_UNIQUE_ADDRESS _Alloc allocator{}; }; #if defined(__cpp_lib_byte) @@ -2801,6 +2805,9 @@ _STD_END #define _LIST_REMOVE_RETURN void #endif // ^^^ !_HAS_CXX20 ^^^ +// TRANSITION, non-_Ugly attribute tokens +#pragma pop_macro("msvc") + #pragma pop_macro("new") _STL_RESTORE_CLANG_WARNINGS #pragma warning(pop) diff --git a/stl/inc/xutility b/stl/inc/xutility index 966a1d66036..e1a0c2fd8e5 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -4949,8 +4949,8 @@ namespace ranges { #if _HAS_CXX23 _EXPORT_STD template struct out_value_result { - /* [[no_unique_address]] */ _Out out; - /* [[no_unique_address]] */ _Ty value; + _MSVC_NO_UNIQUE_ADDRESS _Out out; + _MSVC_NO_UNIQUE_ADDRESS _Ty value; template <_Convertible_from _OOut, _Convertible_from _TTy> constexpr operator out_value_result<_OOut, _TTy>() const& { diff --git a/stl/inc/yvals_core.h b/stl/inc/yvals_core.h index 3525693fa21..3240ccc5b8a 100644 --- a/stl/inc/yvals_core.h +++ b/stl/inc/yvals_core.h @@ -739,6 +739,18 @@ #define _MSVC_LIFETIMEBOUND #endif +#if _HAS_CXX23 // TRANSITION, ABI, should just use [[no_unique_address]] when _HAS_CXX20. +// Should we enable use of [[msvc::no_unique_address]] or [[no_unique_address]] to allow potentially-overlapping member +// subobjects? +#if _HAS_MSVC_ATTRIBUTE(no_unique_address) +#define _MSVC_NO_UNIQUE_ADDRESS [[msvc::no_unique_address]] +#elif __has_cpp_attribute(no_unique_address) // TRANSITION, DevCom-10747012, EDG recognizes [[no_unique_address]]. +#define _MSVC_NO_UNIQUE_ADDRESS [[no_unique_address]] +#else +#error Either [[msvc::no_unique_address]] or [[no_unique_address]] must be supported because this is ABI-critical. +#endif +#endif // _HAS_CXX23 + #undef _HAS_MSVC_ATTRIBUTE #pragma pop_macro("lifetimebound") #pragma pop_macro("intrinsic") diff --git a/tests/std/include/test_mdspan_support.hpp b/tests/std/include/test_mdspan_support.hpp index 500d22be37a..e9706697bed 100644 --- a/tests/std/include/test_mdspan_support.hpp +++ b/tests/std/include/test_mdspan_support.hpp @@ -175,6 +175,28 @@ constexpr bool check_accessor_policy_requirements() { return true; } +template +struct TrivialAccessor { + using offset_policy = TrivialAccessor; + using element_type = ElementType; + using reference = ElementType&; + using data_handle_type = ElementType*; + + constexpr reference access(data_handle_type handle, std::size_t off) const noexcept { + return handle[off]; + } + + constexpr data_handle_type offset(data_handle_type handle, std::size_t off) const noexcept { + return handle + off; + } + + int member; +}; + +static_assert(check_accessor_policy_requirements>()); +static_assert(std::is_trivially_copyable_v>); +static_assert(std::is_trivially_default_constructible_v>); + namespace detail { template constexpr void check_members_with_mixed_extents(Fn&& fn) { diff --git a/tests/std/test.lst b/tests/std/test.lst index e188823bfcf..c6238c7781f 100644 --- a/tests/std/test.lst +++ b/tests/std/test.lst @@ -189,6 +189,7 @@ tests\GH_001103_countl_zero_correctness tests\GH_001105_custom_streambuf_throws tests\GH_001123_random_cast_out_of_range tests\GH_001277_num_get_bad_grouping +tests\GH_001394_msvc_no_unique_address_23 tests\GH_001411_core_headers tests\GH_001530_binomial_accuracy tests\GH_001541_case_sensitive_boolalpha @@ -279,6 +280,7 @@ tests\P0009R18_mdspan_layout_stride tests\P0009R18_mdspan_layout_stride_death tests\P0009R18_mdspan_mdspan tests\P0009R18_mdspan_mdspan_death +tests\P0009R18_mdspan_msabi tests\P0019R8_atomic_ref tests\P0024R2_parallel_algorithms_adjacent_difference tests\P0024R2_parallel_algorithms_adjacent_find diff --git a/tests/std/tests/GH_001394_msvc_no_unique_address_23/env.lst b/tests/std/tests/GH_001394_msvc_no_unique_address_23/env.lst new file mode 100644 index 00000000000..642f530ffad --- /dev/null +++ b/tests/std/tests/GH_001394_msvc_no_unique_address_23/env.lst @@ -0,0 +1,4 @@ +# Copyright (c) Microsoft Corporation. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +RUNALL_INCLUDE ..\usual_latest_matrix.lst diff --git a/tests/std/tests/GH_001394_msvc_no_unique_address_23/test.compile.pass.cpp b/tests/std/tests/GH_001394_msvc_no_unique_address_23/test.compile.pass.cpp new file mode 100644 index 00000000000..a9bf3b07850 --- /dev/null +++ b/tests/std/tests/GH_001394_msvc_no_unique_address_23/test.compile.pass.cpp @@ -0,0 +1,102 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +// Tests MSVC STL specific behavior on ABI. + +#include +#include +#include +#include +#include +#include +#include + +using namespace std; + +static_assert(sizeof(ranges::in_value_result) == sizeof(int)); +static_assert(sizeof(ranges::in_value_result) == sizeof(int)); +#ifndef __EDG__ // TRANSITION, DevCom-10747012 +static_assert(is_empty_v>); +#endif // ^^^ no workaround ^^^ + +static_assert(sizeof(ranges::out_value_result) == sizeof(int)); +static_assert(sizeof(ranges::out_value_result) == sizeof(int)); +#ifndef __EDG__ // TRANSITION, DevCom-10747012 +static_assert(is_empty_v>); +#endif // ^^^ no workaround ^^^ + +struct stateless_input_it { + using value_type = int; + using difference_type = ptrdiff_t; + + int operator*() const noexcept { + return 42; + } + + stateless_input_it& operator++() noexcept { + return *this; + } + + stateless_input_it operator++(int) noexcept { + return {}; + } +}; + +struct stateless_forward_it { + using value_type = int; + using difference_type = ptrdiff_t; + + int operator*() const noexcept { + return 42; + } + + stateless_forward_it& operator++() noexcept { + return *this; + } + + stateless_forward_it operator++(int) noexcept { + return {}; + } + + friend bool operator==(stateless_forward_it, stateless_forward_it) = default; +}; + +static_assert(input_iterator); +static_assert(forward_iterator); + +using test_range = ranges::subrange; +using test_outer_range = ranges::subrange; +using stateless_input_range = ranges::subrange; +using stateless_fwd_range = ranges::subrange; +using stateless_fwd_common_range = ranges::subrange; + +#ifndef __EDG__ // TRANSITION, DevCom-10747012 +static_assert(is_empty_v); +#endif // ^^^ no workaround ^^^ + +static_assert(sizeof((stateless_input_range{} | views::enumerate).begin()) == sizeof(ptrdiff_t)); +#ifndef __EDG__ // TRANSITION, DevCom-10747012 +static_assert(is_empty_v); +#endif // ^^^ no workaround ^^^ + +static_assert(sizeof((stateless_fwd_range{} | views::chunk(42)).begin()) == sizeof(ptrdiff_t) * 2); +#ifndef __EDG__ // TRANSITION, DevCom-10747012 +static_assert(sizeof((stateless_fwd_common_range{} | views::chunk(42)).begin()) == sizeof(ptrdiff_t) * 2); +#endif // ^^^ no workaround ^^^ + +static_assert(sizeof((stateless_fwd_range{} | views::chunk_by(ranges::less{})).begin()) == sizeof(void*) * 2); +static_assert(sizeof((stateless_fwd_common_range{} | views::chunk_by(ranges::less{})).begin()) == sizeof(void*) * 2); + +#ifndef __EDG__ // TRANSITION, DevCom-10747012 +static_assert(is_empty_v); +#endif // ^^^ no workaround ^^^ + +static_assert(sizeof(ranges::elements_of>) == sizeof(int[1])); +static_assert(sizeof(ranges::elements_of>) == sizeof(int (*)[1])); +static_assert(sizeof(ranges::elements_of, pmr::polymorphic_allocator>) + == sizeof(pmr::polymorphic_allocator)); +static_assert(sizeof(ranges::elements_of, allocator>) == 1); + +#ifndef __EDG__ // TRANSITION, DevCom-10747012 +static_assert(is_empty_v, allocator>>); +#endif // ^^^ no workaround ^^^ diff --git a/tests/std/tests/P0009R18_mdspan_extents/test.cpp b/tests/std/tests/P0009R18_mdspan_extents/test.cpp index 2dedead9cc9..90163bfe391 100644 --- a/tests/std/tests/P0009R18_mdspan_extents/test.cpp +++ b/tests/std/tests/P0009R18_mdspan_extents/test.cpp @@ -545,12 +545,6 @@ static_assert(all_extents_dynamic, 7>); static_assert(all_extents_dynamic, 8>); static_assert(all_extents_dynamic, 9>); -// When 'E::rank_dynamic()' is equal to 0 then 'is_empty_v' should be true (MSVC STL specific behavior) -static_assert(!is_empty_v>); -static_assert(!is_empty_v>); -static_assert(is_empty_v>); -static_assert(is_empty_v>); - int main() { static_assert(test()); test(); diff --git a/tests/std/tests/P0009R18_mdspan_layout_left/test.cpp b/tests/std/tests/P0009R18_mdspan_layout_left/test.cpp index b26ca701f86..90d00be88b7 100644 --- a/tests/std/tests/P0009R18_mdspan_layout_left/test.cpp +++ b/tests/std/tests/P0009R18_mdspan_layout_left/test.cpp @@ -486,12 +486,6 @@ constexpr void check_correctness() { } } -// When 'M::extents_type::rank_dynamic()' is equal to 0 then 'is_empty_v' should be true (MSVC STL specific behavior) -static_assert(!is_empty_v>>); -static_assert(!is_empty_v>>); -static_assert(is_empty_v>>); -static_assert(is_empty_v>>); - constexpr bool test() { check_members_with_various_extents([](const E& e) { check_members(e, make_index_sequence{}); }); if (!is_constant_evaluated()) { // too heavy for compile time diff --git a/tests/std/tests/P0009R18_mdspan_layout_right/test.cpp b/tests/std/tests/P0009R18_mdspan_layout_right/test.cpp index 89899ab408c..fa3679ff03f 100644 --- a/tests/std/tests/P0009R18_mdspan_layout_right/test.cpp +++ b/tests/std/tests/P0009R18_mdspan_layout_right/test.cpp @@ -517,12 +517,6 @@ constexpr void check_correctness() { } } -// When 'M::extents_type::rank_dynamic()' is equal to 0 then 'is_empty_v' should be true (MSVC STL specific behavior) -static_assert(!is_empty_v>>); -static_assert(!is_empty_v>>); -static_assert(is_empty_v>>); -static_assert(is_empty_v>>); - constexpr bool test() { check_members_with_various_extents([](const E& e) { check_members(e, make_index_sequence{}); }); if (!is_constant_evaluated()) { // too heavy for compile time diff --git a/tests/std/tests/P0009R18_mdspan_layout_stride/test.cpp b/tests/std/tests/P0009R18_mdspan_layout_stride/test.cpp index f2dadd09de6..dc6daa67e0a 100644 --- a/tests/std/tests/P0009R18_mdspan_layout_stride/test.cpp +++ b/tests/std/tests/P0009R18_mdspan_layout_stride/test.cpp @@ -821,12 +821,6 @@ constexpr void check_correctness() { } } -// When 'M::extents_type::rank()' is equal to 0 then 'is_empty_v' should be true (MSVC STL specific behavior) -static_assert(!is_empty_v>>); -static_assert(!is_empty_v>>); -static_assert(!is_empty_v>>); -static_assert(is_empty_v>>); - constexpr bool test() { // Check signed integers check_members(extents{5}, array{1}); diff --git a/tests/std/tests/P0009R18_mdspan_mdspan/test.cpp b/tests/std/tests/P0009R18_mdspan_mdspan/test.cpp index 330d3cadc34..a36411d53e8 100644 --- a/tests/std/tests/P0009R18_mdspan_mdspan/test.cpp +++ b/tests/std/tests/P0009R18_mdspan_mdspan/test.cpp @@ -318,28 +318,6 @@ struct AccessorWithCustomOffsetPolicy { static_assert(check_accessor_policy_requirements>()); -template -struct TrivialAccessor { - using offset_policy = TrivialAccessor; - using element_type = ElementType; - using reference = ElementType&; - using data_handle_type = ElementType*; - - constexpr reference access(data_handle_type handle, size_t off) const noexcept { - return handle[off]; - } - - constexpr data_handle_type offset(data_handle_type handle, size_t off) const noexcept { - return handle + off; - } - - int member; -}; - -static_assert(check_accessor_policy_requirements>()); -static_assert(is_trivially_copyable_v>); -static_assert(is_trivially_default_constructible_v>); - template class AccessorTemplate> constexpr void check_modeled_concepts_and_member_types() { using Accessor = AccessorTemplate; @@ -1360,25 +1338,6 @@ constexpr void check_deduction_guides() { } } -// When -// * 'Mds::accessor_type' is a specialization of 'default_accessor', and -// * 'Mds::layout_type' is -// * 'layout_left' or 'layout_right' and 'Mds::extents_type::rank_dynamic() == 0', or -// * 'layout_stride' and 'Mds::extents_type::rank() == 0' -// then 'sizeof(Mds) == sizeof(void*)' (MSVC STL specific behavior). -static_assert(sizeof(mdspan, layout_left>) == sizeof(void*)); -static_assert(sizeof(mdspan, layout_left>) > sizeof(void*)); -static_assert(sizeof(mdspan, layout_left, TrivialAccessor>) > sizeof(void*)); - -static_assert(sizeof(mdspan, layout_right>) == sizeof(void*)); -static_assert(sizeof(mdspan, layout_right>) > sizeof(void*)); -static_assert(sizeof(mdspan, layout_right, TrivialAccessor>) > sizeof(void*)); - -static_assert(sizeof(mdspan, layout_stride>) == sizeof(void*)); -static_assert(sizeof(mdspan, layout_stride>) > sizeof(void*)); -static_assert(sizeof(mdspan, layout_stride>) > sizeof(void*)); -static_assert(sizeof(mdspan, layout_stride, TrivialAccessor>) > sizeof(void*)); - constexpr bool test() { check_modeled_concepts_and_member_types, layout_left, default_accessor>(); check_modeled_concepts_and_member_types, layout_right, default_accessor>(); diff --git a/tests/std/tests/P0009R18_mdspan_msabi/env.lst b/tests/std/tests/P0009R18_mdspan_msabi/env.lst new file mode 100644 index 00000000000..642f530ffad --- /dev/null +++ b/tests/std/tests/P0009R18_mdspan_msabi/env.lst @@ -0,0 +1,4 @@ +# Copyright (c) Microsoft Corporation. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +RUNALL_INCLUDE ..\usual_latest_matrix.lst diff --git a/tests/std/tests/P0009R18_mdspan_msabi/test.compile.pass.cpp b/tests/std/tests/P0009R18_mdspan_msabi/test.compile.pass.cpp new file mode 100644 index 00000000000..0d85c79d2be --- /dev/null +++ b/tests/std/tests/P0009R18_mdspan_msabi/test.compile.pass.cpp @@ -0,0 +1,54 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +// Tests MSVC STL specific behavior on ABI. + +#include +#include + +#include + +using namespace std; + +// When 'E::rank_dynamic()' is equal to 0 then 'is_empty_v' should be true +static_assert(!is_empty_v>); +static_assert(!is_empty_v>); +static_assert(is_empty_v>); +static_assert(is_empty_v>); + +// When 'M::extents_type::rank_dynamic()' is equal to 0 then 'is_empty_v' should be true +static_assert(!is_empty_v>>); +static_assert(!is_empty_v>>); +static_assert(is_empty_v>>); +static_assert(is_empty_v>>); + +// When 'M::extents_type::rank_dynamic()' is equal to 0 then 'is_empty_v' should be true +static_assert(!is_empty_v>>); +static_assert(!is_empty_v>>); +static_assert(is_empty_v>>); +static_assert(is_empty_v>>); + +// When 'M::extents_type::rank()' is equal to 0 then 'is_empty_v' should be true +static_assert(!is_empty_v>>); +static_assert(!is_empty_v>>); +static_assert(!is_empty_v>>); +static_assert(is_empty_v>>); + +// When +// * 'Mds::accessor_type' is a specialization of 'default_accessor', and +// * 'Mds::layout_type' is +// * 'layout_left' or 'layout_right' and 'Mds::extents_type::rank_dynamic() == 0', or +// * 'layout_stride' and 'Mds::extents_type::rank() == 0' +// then 'sizeof(Mds) == sizeof(void*)'. +static_assert(sizeof(mdspan, layout_left>) == sizeof(void*)); +static_assert(sizeof(mdspan, layout_left>) > sizeof(void*)); +static_assert(sizeof(mdspan, layout_left, TrivialAccessor>) > sizeof(void*)); + +static_assert(sizeof(mdspan, layout_right>) == sizeof(void*)); +static_assert(sizeof(mdspan, layout_right>) > sizeof(void*)); +static_assert(sizeof(mdspan, layout_right, TrivialAccessor>) > sizeof(void*)); + +static_assert(sizeof(mdspan, layout_stride>) == sizeof(void*)); +static_assert(sizeof(mdspan, layout_stride>) > sizeof(void*)); +static_assert(sizeof(mdspan, layout_stride>) > sizeof(void*)); +static_assert(sizeof(mdspan, layout_stride, TrivialAccessor>) > sizeof(void*));