Skip to content

Commit 6b0cb76

Browse files
authored
[Clang] _default-movable_ should be based on the first declaration (llvm#143661)
When the definition of a special member function was defaulted we would not consider it user-provided, even when the first declaration was not defaulted. Fixes llvm#143599
1 parent b09206d commit 6b0cb76

File tree

3 files changed

+54
-6
lines changed

3 files changed

+54
-6
lines changed

clang/lib/Sema/SemaTypeTraits.cpp

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ static CXXMethodDecl *LookupSpecialMemberFromXValue(Sema &SemaRef,
105105
switch (OCS.BestViableFunction(SemaRef, LookupLoc, Best)) {
106106
case OR_Success:
107107
case OR_Deleted:
108-
return cast<CXXMethodDecl>(Best->Function);
108+
return cast<CXXMethodDecl>(Best->Function)->getCanonicalDecl();
109109
default:
110110
return nullptr;
111111
}
@@ -164,6 +164,8 @@ static bool IsDefaultMovable(Sema &SemaRef, const CXXRecordDecl *D) {
164164
if (!Dtr)
165165
return true;
166166

167+
Dtr = Dtr->getCanonicalDecl();
168+
167169
if (Dtr->isUserProvided() && (!Dtr->isDefaulted() || Dtr->isDeleted()))
168170
return false;
169171

@@ -2044,11 +2046,13 @@ static void DiagnoseNonDefaultMovable(Sema &SemaRef, SourceLocation Loc,
20442046
<< diag::TraitNotSatisfiedReason::UserProvidedAssign
20452047
<< Decl->isMoveAssignmentOperator() << Decl->getSourceRange();
20462048
}
2047-
CXXDestructorDecl *Dtr = D->getDestructor();
2048-
if (Dtr && Dtr->isUserProvided() && !Dtr->isDefaulted())
2049-
SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)
2050-
<< diag::TraitNotSatisfiedReason::DeletedDtr << /*User Provided*/ 1
2051-
<< Dtr->getSourceRange();
2049+
if (CXXDestructorDecl *Dtr = D->getDestructor()) {
2050+
Dtr = Dtr->getCanonicalDecl();
2051+
if (Dtr->isUserProvided() && !Dtr->isDefaulted())
2052+
SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)
2053+
<< diag::TraitNotSatisfiedReason::DeletedDtr << /*User Provided*/ 1
2054+
<< Dtr->getSourceRange();
2055+
}
20522056
}
20532057

20542058
static void DiagnoseNonTriviallyRelocatableReason(Sema &SemaRef,

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

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -388,3 +388,24 @@ void do_test__builtin_trivially_relocate() {
388388
// expected-note@-1 {{'test__builtin_trivially_relocate<S *, S *, int>' requested here}}
389389
// expected-error@#reloc1 {{first argument to '__builtin_trivially_relocate' must be relocatable}}
390390
}
391+
392+
393+
namespace GH143599 {
394+
struct A { ~A (); };
395+
A::~A () = default;
396+
397+
static_assert (!__builtin_is_cpp_trivially_relocatable(A));
398+
static_assert (!__builtin_is_replaceable(A));
399+
400+
struct B { B(const B&); };
401+
B::B (const B&) = default;
402+
403+
static_assert (!__builtin_is_cpp_trivially_relocatable(B));
404+
static_assert (!__builtin_is_replaceable(B));
405+
406+
struct C { C& operator=(const C&); };
407+
C& C::operator=(const C&) = default;
408+
409+
static_assert (!__builtin_is_cpp_trivially_relocatable(C));
410+
static_assert (!__builtin_is_replaceable(C));
411+
}

clang/test/SemaCXX/type-traits-unsatisfied-diags.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,29 @@ static_assert(__builtin_is_cpp_trivially_relocatable(UnionOfPolymorphic));
320320

321321
}
322322

323+
struct GH143599 { // expected-note 2 {{'GH143599' defined here}}
324+
~GH143599 ();
325+
GH143599(const GH143599&);
326+
GH143599& operator=(const GH143599&);
327+
};
328+
GH143599::~GH143599 () = default;
329+
GH143599::GH143599 (const GH143599&) = default;
330+
GH143599& GH143599::operator=(const GH143599&) = default;
331+
332+
static_assert (__builtin_is_cpp_trivially_relocatable(GH143599));
333+
// expected-error@-1 {{static assertion failed due to requirement '__builtin_is_cpp_trivially_relocatable(GH143599)'}} \
334+
// expected-note@-1 {{'GH143599' is not trivially relocatable}} \
335+
// expected-note@-1 {{because it has a user provided copy constructor}} \
336+
// expected-note@-1 {{because it has a user provided copy assignment operator}} \
337+
// expected-note@-1 {{because it has a user-provided destructor}}
338+
339+
static_assert (__builtin_is_replaceable(GH143599));
340+
// expected-error@-1 {{static assertion failed due to requirement '__builtin_is_replaceable(GH143599)'}} \
341+
// expected-note@-1 {{'GH143599' is not replaceable}} \
342+
// expected-note@-1 {{because it has a user provided copy constructor}} \
343+
// expected-note@-1 {{because it has a user provided copy assignment operator}} \
344+
// expected-note@-1 {{because it has a user-provided destructor}}
345+
323346
namespace trivially_copyable {
324347
struct B {
325348
virtual ~B();

0 commit comments

Comments
 (0)