Skip to content

Commit 57df9ee

Browse files
committed
Consider a class as trivially relocatable when the user-provided special member is ineligible
1 parent 873fce6 commit 57df9ee

File tree

2 files changed

+112
-15
lines changed

2 files changed

+112
-15
lines changed

clang/lib/AST/DeclCXX.cpp

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -884,14 +884,6 @@ void CXXRecordDecl::addedMember(Decl *D) {
884884
? !Constructor->isImplicit()
885885
: (Constructor->isUserProvided() || Constructor->isExplicit()))
886886
data().Aggregate = false;
887-
888-
// A trivially relocatable class is a class:
889-
// -- where no eligible copy constructor, move constructor, copy
890-
// assignment operator, move assignment operator, or destructor is
891-
// user-provided,
892-
if (Constructor->isUserProvided() && (Constructor->isCopyConstructor() ||
893-
Constructor->isMoveConstructor()))
894-
data().IsNaturallyTriviallyRelocatable = false;
895887
}
896888
}
897889

@@ -923,13 +915,8 @@ void CXXRecordDecl::addedMember(Decl *D) {
923915
data().HasDeclaredCopyAssignmentWithConstParam = true;
924916
}
925917

926-
if (Method->isMoveAssignmentOperator()) {
918+
if (Method->isMoveAssignmentOperator())
927919
SMKind |= SMF_MoveAssignment;
928-
}
929-
930-
if (Method->isUserProvided() && (Method->isCopyAssignmentOperator() ||
931-
Method->isMoveAssignmentOperator()))
932-
data().IsNaturallyTriviallyRelocatable = false;
933920

934921
// Keep the list of conversion functions up-to-date.
935922
if (auto *Conversion = dyn_cast<CXXConversionDecl>(D)) {
@@ -1526,7 +1513,6 @@ void CXXRecordDecl::addedEligibleSpecialMemberFunction(const CXXMethodDecl *MD,
15261513
if (const auto *DD = dyn_cast<CXXDestructorDecl>(MD)) {
15271514
if (DD->isUserProvided()) {
15281515
data().HasIrrelevantDestructor = false;
1529-
data().IsNaturallyTriviallyRelocatable = false;
15301516
}
15311517
// If the destructor is explicitly defaulted and not trivial or not public
15321518
// or if the destructor is deleted, we clear HasIrrelevantDestructor in
@@ -1543,6 +1529,17 @@ void CXXRecordDecl::addedEligibleSpecialMemberFunction(const CXXMethodDecl *MD,
15431529
data().IsAnyDestructorNoReturn = true;
15441530
}
15451531

1532+
// A trivially relocatable class is a class:
1533+
// -- where no eligible copy constructor, move constructor, copy
1534+
// assignment operator, move assignment operator, or destructor is
1535+
// user-provided,
1536+
if (MD->isUserProvided() &&
1537+
(SMKind & (SMF_CopyConstructor | SMF_MoveConstructor |
1538+
SMF_CopyAssignment | SMF_MoveAssignment | SMF_Destructor)) !=
1539+
0u) {
1540+
data().IsNaturallyTriviallyRelocatable = false;
1541+
}
1542+
15461543
if (!MD->isImplicit() && !MD->isUserProvided()) {
15471544
// This method is user-declared but not user-provided. We can't work
15481545
// out whether it's trivial yet (not until we get to the end of the

clang/test/SemaCXX/is-trivially-relocatable.cpp

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,3 +104,103 @@ static_assert(!__is_trivially_relocatable(Der<NonTrivialMoveAssign>));
104104
static_assert(!__is_trivially_relocatable(Mut<NonTrivialMoveAssign>));
105105
static_assert(!__is_trivially_relocatable(Non<NonTrivialMoveAssign>));
106106
#endif
107+
108+
#if __cplusplus >= 202002L
109+
template<bool B>
110+
struct EligibleNonTrivialDefaultCtor {
111+
EligibleNonTrivialDefaultCtor() requires B;
112+
EligibleNonTrivialDefaultCtor() = default;
113+
};
114+
// Only the Rule of 5 members (not default ctor) affect trivial relocatability.
115+
static_assert(__is_trivially_relocatable(EligibleNonTrivialDefaultCtor<true>));
116+
static_assert(__is_trivially_relocatable(EligibleNonTrivialDefaultCtor<false>));
117+
118+
template<bool B>
119+
struct IneligibleNonTrivialDefaultCtor {
120+
IneligibleNonTrivialDefaultCtor();
121+
IneligibleNonTrivialDefaultCtor() requires B = default;
122+
};
123+
// Only the Rule of 5 members (not default ctor) affect trivial relocatability.
124+
static_assert(__is_trivially_relocatable(IneligibleNonTrivialDefaultCtor<true>));
125+
static_assert(__is_trivially_relocatable(IneligibleNonTrivialDefaultCtor<false>));
126+
127+
template<bool B>
128+
struct EligibleNonTrivialCopyCtor {
129+
EligibleNonTrivialCopyCtor(const EligibleNonTrivialCopyCtor&) requires B;
130+
EligibleNonTrivialCopyCtor(const EligibleNonTrivialCopyCtor&) = default;
131+
};
132+
static_assert(!__is_trivially_relocatable(EligibleNonTrivialCopyCtor<true>));
133+
static_assert(__is_trivially_relocatable(EligibleNonTrivialCopyCtor<false>));
134+
135+
template<bool B>
136+
struct IneligibleNonTrivialCopyCtor {
137+
IneligibleNonTrivialCopyCtor(const IneligibleNonTrivialCopyCtor&);
138+
IneligibleNonTrivialCopyCtor(const IneligibleNonTrivialCopyCtor&) requires B = default;
139+
};
140+
static_assert(__is_trivially_relocatable(IneligibleNonTrivialCopyCtor<true>));
141+
static_assert(!__is_trivially_relocatable(IneligibleNonTrivialCopyCtor<false>));
142+
143+
template<bool B>
144+
struct EligibleNonTrivialMoveCtor {
145+
EligibleNonTrivialMoveCtor(EligibleNonTrivialMoveCtor&&) requires B;
146+
EligibleNonTrivialMoveCtor(EligibleNonTrivialMoveCtor&&) = default;
147+
};
148+
static_assert(!__is_trivially_relocatable(EligibleNonTrivialMoveCtor<true>));
149+
static_assert(__is_trivially_relocatable(EligibleNonTrivialMoveCtor<false>));
150+
151+
template<bool B>
152+
struct IneligibleNonTrivialMoveCtor {
153+
IneligibleNonTrivialMoveCtor(IneligibleNonTrivialMoveCtor&&);
154+
IneligibleNonTrivialMoveCtor(IneligibleNonTrivialMoveCtor&&) requires B = default;
155+
};
156+
static_assert(__is_trivially_relocatable(IneligibleNonTrivialMoveCtor<true>));
157+
static_assert(!__is_trivially_relocatable(IneligibleNonTrivialMoveCtor<false>));
158+
159+
template<bool B>
160+
struct EligibleNonTrivialCopyAssign {
161+
EligibleNonTrivialCopyAssign& operator=(const EligibleNonTrivialCopyAssign&) requires B;
162+
EligibleNonTrivialCopyAssign& operator=(const EligibleNonTrivialCopyAssign&) = default;
163+
};
164+
static_assert(!__is_trivially_relocatable(EligibleNonTrivialCopyAssign<true>));
165+
static_assert(__is_trivially_relocatable(EligibleNonTrivialCopyAssign<false>));
166+
167+
template<bool B>
168+
struct IneligibleNonTrivialCopyAssign {
169+
IneligibleNonTrivialCopyAssign& operator=(const IneligibleNonTrivialCopyAssign&);
170+
IneligibleNonTrivialCopyAssign& operator=(const IneligibleNonTrivialCopyAssign&) requires B = default;
171+
};
172+
static_assert(__is_trivially_relocatable(IneligibleNonTrivialCopyAssign<true>));
173+
static_assert(!__is_trivially_relocatable(IneligibleNonTrivialCopyAssign<false>));
174+
175+
template<bool B>
176+
struct EligibleNonTrivialMoveAssign {
177+
EligibleNonTrivialMoveAssign& operator=(EligibleNonTrivialMoveAssign&&) requires B;
178+
EligibleNonTrivialMoveAssign& operator=(EligibleNonTrivialMoveAssign&&) = default;
179+
};
180+
static_assert(!__is_trivially_relocatable(EligibleNonTrivialMoveAssign<true>));
181+
static_assert(__is_trivially_relocatable(EligibleNonTrivialMoveAssign<false>));
182+
183+
template<bool B>
184+
struct IneligibleNonTrivialMoveAssign {
185+
IneligibleNonTrivialMoveAssign& operator=(IneligibleNonTrivialMoveAssign&&);
186+
IneligibleNonTrivialMoveAssign& operator=(IneligibleNonTrivialMoveAssign&&) requires B = default;
187+
};
188+
static_assert(__is_trivially_relocatable(IneligibleNonTrivialMoveAssign<true>));
189+
static_assert(!__is_trivially_relocatable(IneligibleNonTrivialMoveAssign<false>));
190+
191+
template<bool B>
192+
struct EligibleNonTrivialDtor {
193+
~EligibleNonTrivialDtor() requires B;
194+
~EligibleNonTrivialDtor() = default;
195+
};
196+
static_assert(!__is_trivially_relocatable(EligibleNonTrivialDtor<true>));
197+
static_assert(__is_trivially_relocatable(EligibleNonTrivialDtor<false>));
198+
199+
template<bool B>
200+
struct IneligibleNonTrivialDtor {
201+
~IneligibleNonTrivialDtor();
202+
~IneligibleNonTrivialDtor() requires B = default;
203+
};
204+
static_assert(__is_trivially_relocatable(IneligibleNonTrivialDtor<true>));
205+
static_assert(!__is_trivially_relocatable(IneligibleNonTrivialDtor<false>));
206+
#endif

0 commit comments

Comments
 (0)