[Clang] _default-movable_ should be based on the first declaration (#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 #143599
This commit is contained in:
@@ -105,7 +105,7 @@ static CXXMethodDecl *LookupSpecialMemberFromXValue(Sema &SemaRef,
|
||||
switch (OCS.BestViableFunction(SemaRef, LookupLoc, Best)) {
|
||||
case OR_Success:
|
||||
case OR_Deleted:
|
||||
return cast<CXXMethodDecl>(Best->Function);
|
||||
return cast<CXXMethodDecl>(Best->Function)->getCanonicalDecl();
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
@@ -164,6 +164,8 @@ static bool IsDefaultMovable(Sema &SemaRef, const CXXRecordDecl *D) {
|
||||
if (!Dtr)
|
||||
return true;
|
||||
|
||||
Dtr = Dtr->getCanonicalDecl();
|
||||
|
||||
if (Dtr->isUserProvided() && (!Dtr->isDefaulted() || Dtr->isDeleted()))
|
||||
return false;
|
||||
|
||||
@@ -2044,11 +2046,13 @@ static void DiagnoseNonDefaultMovable(Sema &SemaRef, SourceLocation Loc,
|
||||
<< diag::TraitNotSatisfiedReason::UserProvidedAssign
|
||||
<< Decl->isMoveAssignmentOperator() << Decl->getSourceRange();
|
||||
}
|
||||
CXXDestructorDecl *Dtr = D->getDestructor();
|
||||
if (Dtr && Dtr->isUserProvided() && !Dtr->isDefaulted())
|
||||
SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)
|
||||
<< diag::TraitNotSatisfiedReason::DeletedDtr << /*User Provided*/ 1
|
||||
<< Dtr->getSourceRange();
|
||||
if (CXXDestructorDecl *Dtr = D->getDestructor()) {
|
||||
Dtr = Dtr->getCanonicalDecl();
|
||||
if (Dtr->isUserProvided() && !Dtr->isDefaulted())
|
||||
SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)
|
||||
<< diag::TraitNotSatisfiedReason::DeletedDtr << /*User Provided*/ 1
|
||||
<< Dtr->getSourceRange();
|
||||
}
|
||||
}
|
||||
|
||||
static void DiagnoseNonTriviallyRelocatableReason(Sema &SemaRef,
|
||||
|
||||
@@ -388,3 +388,24 @@ void do_test__builtin_trivially_relocate() {
|
||||
// expected-note@-1 {{'test__builtin_trivially_relocate<S *, S *, int>' requested here}}
|
||||
// expected-error@#reloc1 {{first argument to '__builtin_trivially_relocate' must be relocatable}}
|
||||
}
|
||||
|
||||
|
||||
namespace GH143599 {
|
||||
struct A { ~A (); };
|
||||
A::~A () = default;
|
||||
|
||||
static_assert (!__builtin_is_cpp_trivially_relocatable(A));
|
||||
static_assert (!__builtin_is_replaceable(A));
|
||||
|
||||
struct B { B(const B&); };
|
||||
B::B (const B&) = default;
|
||||
|
||||
static_assert (!__builtin_is_cpp_trivially_relocatable(B));
|
||||
static_assert (!__builtin_is_replaceable(B));
|
||||
|
||||
struct C { C& operator=(const C&); };
|
||||
C& C::operator=(const C&) = default;
|
||||
|
||||
static_assert (!__builtin_is_cpp_trivially_relocatable(C));
|
||||
static_assert (!__builtin_is_replaceable(C));
|
||||
}
|
||||
|
||||
@@ -320,6 +320,29 @@ static_assert(__builtin_is_cpp_trivially_relocatable(UnionOfPolymorphic));
|
||||
|
||||
}
|
||||
|
||||
struct GH143599 { // expected-note 2 {{'GH143599' defined here}}
|
||||
~GH143599 ();
|
||||
GH143599(const GH143599&);
|
||||
GH143599& operator=(const GH143599&);
|
||||
};
|
||||
GH143599::~GH143599 () = default;
|
||||
GH143599::GH143599 (const GH143599&) = default;
|
||||
GH143599& GH143599::operator=(const GH143599&) = default;
|
||||
|
||||
static_assert (__builtin_is_cpp_trivially_relocatable(GH143599));
|
||||
// expected-error@-1 {{static assertion failed due to requirement '__builtin_is_cpp_trivially_relocatable(GH143599)'}} \
|
||||
// expected-note@-1 {{'GH143599' is not trivially relocatable}} \
|
||||
// expected-note@-1 {{because it has a user provided copy constructor}} \
|
||||
// expected-note@-1 {{because it has a user provided copy assignment operator}} \
|
||||
// expected-note@-1 {{because it has a user-provided destructor}}
|
||||
|
||||
static_assert (__builtin_is_replaceable(GH143599));
|
||||
// expected-error@-1 {{static assertion failed due to requirement '__builtin_is_replaceable(GH143599)'}} \
|
||||
// expected-note@-1 {{'GH143599' is not replaceable}} \
|
||||
// expected-note@-1 {{because it has a user provided copy constructor}} \
|
||||
// expected-note@-1 {{because it has a user provided copy assignment operator}} \
|
||||
// expected-note@-1 {{because it has a user-provided destructor}}
|
||||
|
||||
namespace trivially_copyable {
|
||||
struct B {
|
||||
virtual ~B();
|
||||
|
||||
Reference in New Issue
Block a user