Skip to content

Commit 7a18790

Browse files
EricWFzmodem
authored andcommitted
[libc++] Fix ABI break in __bit_reference.
The libc++ __bit_iterator type has weird ABI calling conventions as a quirk of the implementation. The const bit iterator is trivial, but the non-const bit iterator is not because it declares a user-defined copy constructor. Changing this now is an ABI break, so this test ensures that each type is trivial/non-trivial as expected. The definition of 'non-trivial for the purposes of calls': A type is considered non-trivial for the purposes of calls if: * it has a non-trivial copy constructor, move constructor, or destructor, or * all of its copy and move constructors are deleted. (cherry picked from commit a829443)
1 parent a572a8a commit 7a18790

File tree

2 files changed

+72
-0
lines changed

2 files changed

+72
-0
lines changed

libcxx/include/__bit_reference

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1122,6 +1122,21 @@ public:
11221122
__bit_iterator(const __type_for_copy_to_const& __it) _NOEXCEPT
11231123
: __seg_(__it.__seg_), __ctz_(__it.__ctz_) {}
11241124

1125+
// The non-const __bit_iterator has historically had a non-trivial
1126+
// copy constructor (as a quirk of its construction). We need to maintain
1127+
// this for ABI purposes.
1128+
using __type_for_abi_non_trivial_copy_ctor =
1129+
_If<!_IsConst, __bit_iterator, struct __private_nat>;
1130+
1131+
_LIBCPP_INLINE_VISIBILITY
1132+
__bit_iterator(__type_for_abi_non_trivial_copy_ctor const& __it) _NOEXCEPT
1133+
: __seg_(__it.__seg_), __ctz_(__it.__ctz_) {}
1134+
1135+
// Always declare the copy assignment operator since the implicit declaration
1136+
// is deprecated.
1137+
_LIBCPP_INLINE_VISIBILITY
1138+
__bit_iterator& operator=(__bit_iterator const&) = default;
1139+
11251140
_LIBCPP_INLINE_VISIBILITY reference operator*() const _NOEXCEPT
11261141
{return reference(__seg_, __storage_type(1) << __ctz_);}
11271142

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
// <vector>
10+
11+
// typedef ... iterator;
12+
// typedef ... const_iterator;
13+
14+
// The libc++ __bit_iterator type has weird ABI calling conventions as a quirk
15+
// of the implementation. The const bit iterator is trivial, but the non-const
16+
// bit iterator is not because it declares a user-defined copy constructor.
17+
//
18+
// Changing this now is an ABI break, so this test ensures that each type
19+
// is trivial/non-trivial as expected.
20+
21+
// The definition of 'non-trivial for the purposes of calls':
22+
// A type is considered non-trivial for the purposes of calls if:
23+
// * it has a non-trivial copy constructor, move constructor, or
24+
// destructor, or
25+
// * all of its copy and move constructors are deleted.
26+
27+
// UNSUPPORTED: c++98, c++03
28+
29+
#include <vector>
30+
#include <cassert>
31+
32+
#include "test_macros.h"
33+
34+
template <class T>
35+
using IsTrivialForCall = std::integral_constant<bool,
36+
std::is_trivially_copy_constructible<T>::value &&
37+
std::is_trivially_move_constructible<T>::value &&
38+
std::is_trivially_destructible<T>::value
39+
// Ignore the all-deleted case, it shouldn't occur here.
40+
>;
41+
42+
void test_const_iterator() {
43+
using It = std::vector<bool>::const_iterator;
44+
static_assert(IsTrivialForCall<It>::value, "");
45+
}
46+
47+
void test_non_const_iterator() {
48+
using It = std::vector<bool>::iterator;
49+
static_assert(!IsTrivialForCall<It>::value, "");
50+
}
51+
52+
int main(int, char**) {
53+
test_const_iterator();
54+
test_non_const_iterator();
55+
56+
return 0;
57+
}

0 commit comments

Comments
 (0)