diff --git a/libcxx/include/__config b/libcxx/include/__config --- a/libcxx/include/__config +++ b/libcxx/include/__config @@ -114,6 +114,8 @@ # define _LIBCPP_ABI_DO_NOT_EXPORT_BASIC_STRING_COMMON // Remove vector base class # define _LIBCPP_ABI_DO_NOT_EXPORT_VECTOR_BASE_COMMON +// According to the Standard, `bitset::operator[] const` returns bool +# define _LIBCPP_ABI_BITSET_VECTOR_BOOL_CONST_SUBSCRIPT_RETURN_BOOL #elif _LIBCPP_ABI_VERSION == 1 # if !defined(_LIBCPP_OBJECT_FORMAT_COFF) // Enable compiling copies of now inline methods into the dylib to support diff --git a/libcxx/include/bitset b/libcxx/include/bitset --- a/libcxx/include/bitset +++ b/libcxx/include/bitset @@ -714,9 +714,12 @@ bitset& flip(size_t __pos); // element access: - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR - const_reference operator[](size_t __p) const {return base::__make_ref(__p);} - _LIBCPP_INLINE_VISIBILITY reference operator[](size_t __p) {return base::__make_ref(__p);} +#ifdef _LIBCPP_ABI_BITSET_VECTOR_BOOL_CONST_SUBSCRIPT_RETURN_BOOL + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool operator[](size_t __p) const {return base::__make_ref(__p);} +#else + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR const_reference operator[](size_t __p) const {return base::__make_ref(__p);} +#endif + _LIBCPP_HIDE_FROM_ABI reference operator[](size_t __p) {return base::__make_ref(__p);} _LIBCPP_INLINE_VISIBILITY unsigned long to_ulong() const; _LIBCPP_INLINE_VISIBILITY diff --git a/libcxx/include/vector b/libcxx/include/vector --- a/libcxx/include/vector +++ b/libcxx/include/vector @@ -2077,7 +2077,11 @@ __compressed_pair __cap_alloc_; public: typedef __bit_reference reference; +#ifdef _LIBCPP_ABI_BITSET_VECTOR_BOOL_CONST_SUBSCRIPT_RETURN_BOOL + using const_reference = bool; +#else typedef __bit_const_reference const_reference; +#endif private: _LIBCPP_INLINE_VISIBILITY size_type& __cap() _NOEXCEPT 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 new file mode 100644 --- /dev/null +++ b/libcxx/test/std/containers/sequences/vector.bool/const_reference.pass.cpp @@ -0,0 +1,37 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// + +#include +#include + +#include "test_macros.h" + +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); +#else + ASSERT_SAME_TYPE(CRefT, std::__bit_const_reference>); + std::vector vec; + vec.push_back(true); + CRefT ref = vec[0]; + assert(ref); + vec[0] = false; + assert(!ref); +#endif + + return true; +} + +int main(int, char**) { + test(); + + return 0; +} diff --git a/libcxx/test/std/utilities/template.bitset/bitset.members/index.pass.cpp b/libcxx/test/std/utilities/template.bitset/bitset.members/index.pass.cpp --- a/libcxx/test/std/utilities/template.bitset/bitset.members/index.pass.cpp +++ b/libcxx/test/std/utilities/template.bitset/bitset.members/index.pass.cpp @@ -42,6 +42,7 @@ assert(r == false); assert(v1.test(N/2) == false); } + ASSERT_SAME_TYPE(decltype(v1[0]), typename std::bitset::reference); } } @@ -56,5 +57,11 @@ test_index<65>(); test_index<1000>(); + std::bitset<1> set; + set[0] = false; + auto b = set[0]; + set[0] = true; + assert(b); + return 0; } diff --git a/libcxx/test/std/utilities/template.bitset/bitset.members/index_const.pass.cpp b/libcxx/test/std/utilities/template.bitset/bitset.members/index_const.pass.cpp --- a/libcxx/test/std/utilities/template.bitset/bitset.members/index_const.pass.cpp +++ b/libcxx/test/std/utilities/template.bitset/bitset.members/index_const.pass.cpp @@ -25,6 +25,11 @@ assert(v[N/2] == v.test(N/2)); } } +#if !defined(_LIBCPP_VERSION) || defined(_LIBCPP_ABI_BITSET_VECTOR_BOOL_CONST_SUBSCRIPT_RETURN_BOOL) + ASSERT_SAME_TYPE(decltype(cases[0][0]), bool); +#else + ASSERT_SAME_TYPE(decltype(cases[0][0]), typename std::bitset::const_reference); +#endif } int main(int, char**) { @@ -38,5 +43,16 @@ test_index_const<65>(); test_index_const<1000>(); + std::bitset<1> set_; + set_[0] = false; + const auto& set = set_; + auto b = set[0]; + set_[0] = true; +#if !defined(_LIBCPP_VERSION) || defined(_LIBCPP_ABI_BITSET_VECTOR_BOOL_CONST_SUBSCRIPT_RETURN_BOOL) + assert(!b); +#else + assert(b); +#endif + return 0; }