diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp --- a/clang/lib/AST/DeclCXX.cpp +++ b/clang/lib/AST/DeclCXX.cpp @@ -1378,7 +1378,11 @@ } void CXXRecordDecl::addedEligibleSpecialMemberFunction(const CXXMethodDecl *MD, - unsigned SMKind) { + unsigned SMKind) { + // FIXME: We shouldn't change DeclaredNonTrivialSpecialMembers if `MD` is + // a function template, but this needs CWG attention before we break ABI. + // See https://github.com/llvm/llvm-project/issues/59206 + if (const auto *DD = dyn_cast(MD)) { if (DD->isUserProvided()) data().HasIrrelevantDestructor = false; diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -18193,8 +18193,11 @@ CXXMethodDecl *M1, CXXMethodDecl *M2, Sema::CXXSpecialMember CSM) { + // We don't want to compare templates to non-templates: See + // https://github.com/llvm/llvm-project/issues/59206 if (CSM == Sema::CXXDefaultConstructor) - return true; + return bool(M1->getDescribedFunctionTemplate()) == + bool(M2->getDescribedFunctionTemplate()); if (!Context.hasSameType(M1->getParamDecl(0)->getType(), M2->getParamDecl(0)->getType())) return false; diff --git a/clang/test/SemaCXX/constrained-special-member-functions.cpp b/clang/test/SemaCXX/constrained-special-member-functions.cpp --- a/clang/test/SemaCXX/constrained-special-member-functions.cpp +++ b/clang/test/SemaCXX/constrained-special-member-functions.cpp @@ -225,3 +225,43 @@ S<2, 2> s2; } } + +namespace GH59206 { + +struct A { + A() = default; //eligible, second constructor unsatisfied + template + A(Args&&... args) requires (sizeof...(Args) > 0) {} +}; + +struct B { + B() = default; //ineligible, second constructor more constrained + template + B(Args&&... args) requires (sizeof...(Args) == 0) {} +}; + +struct C { + C() = default; //eligible, but + template //also eligible and non-trivial + C(Args&&... args) {} +}; + +struct D : B {}; + +static_assert(__is_trivially_copyable(A), ""); +static_assert(__is_trivially_copyable(B), ""); +static_assert(__is_trivially_copyable(C), ""); +static_assert(__is_trivially_copyable(D), ""); + +// FIXME: Update when https://github.com/llvm/llvm-project/issues/59206 is +// resolved. +static_assert(!__is_trivial(A), ""); +static_assert(!__is_trivial(B), ""); +static_assert(!__is_trivial(C), ""); +static_assert(__is_trivial(D), ""); +static_assert(__is_trivially_constructible(A), ""); +static_assert(__is_trivially_constructible(B), ""); +static_assert(__is_trivially_constructible(C), ""); +static_assert(__is_trivially_constructible(D), ""); + +}