Javier-varez created this revision. Herald added a project: All. Javier-varez requested review of this revision. Herald added a project: clang. Herald added a subscriber: cfe-commits.
>From [class.copy.ctor]: A non-template constructor for class X is a copy constructor if its first parameter is of type X&, const X&, volatile X& or const volatile X&, and either there are no other parameters or else all other parameters have default arguments (9.3.4.7). A copy/move constructor for class X is trivial if it is not user-provided and if: - class X has no virtual functions (11.7.3) and no virtual base classes (11.7.2), and - the constructor selected to copy/move each direct base class subobject is trivial, and - or each non-static data member of X that is of class type (or array thereof), the constructor selected to copy/move that member is trivial; otherwise the copy/move constructor is non-trivial. So `T(T&) = default`; should be trivial assuming that the previous provisions are met. This works in GCC, but not in Clang at the moment: https://godbolt.org/z/fTGe71b6P Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D127593 Files: clang/lib/Sema/SemaDeclCXX.cpp clang/test/CXX/special/class.copy/p12-0x.cpp clang/test/CXX/special/class.copy/p25-0x.cpp Index: clang/test/CXX/special/class.copy/p25-0x.cpp =================================================================== --- clang/test/CXX/special/class.copy/p25-0x.cpp +++ clang/test/CXX/special/class.copy/p25-0x.cpp @@ -31,7 +31,22 @@ struct NonConstCopy { NonConstCopy &operator=(NonConstCopy &) = default; }; -using _ = not_trivially_assignable<NonConstCopy>; +static_assert(__has_trivial_assign(NonConstCopy), ""); +static_assert(__is_trivially_assignable(NonConstCopy&, NonConstCopy&), ""); +static_assert(!__is_trivially_assignable(NonConstCopy&, const NonConstCopy &), ""); +static_assert(!__is_trivially_assignable(NonConstCopy&, NonConstCopy), ""); +static_assert(!__is_trivially_assignable(NonConstCopy&, NonConstCopy&&), ""); +static_assert(__is_trivially_assignable(NonConstCopy&&, NonConstCopy&), ""); +static_assert(!__is_trivially_assignable(NonConstCopy&&, const NonConstCopy &), ""); +static_assert(!__is_trivially_assignable(NonConstCopy&&, NonConstCopy), ""); +static_assert(!__is_trivially_assignable(NonConstCopy&&, NonConstCopy&&), ""); + +struct DefaultedSpecialMembers { + DefaultedSpecialMembers &operator=(const DefaultedSpecialMembers &) = default; + DefaultedSpecialMembers &operator=(DefaultedSpecialMembers &) = default; + DefaultedSpecialMembers &operator=(DefaultedSpecialMembers &&) = default; +}; +using _ = trivially_assignable<DefaultedSpecialMembers>; // class X has no virtual functions struct VFn { Index: clang/test/CXX/special/class.copy/p12-0x.cpp =================================================================== --- clang/test/CXX/special/class.copy/p12-0x.cpp +++ clang/test/CXX/special/class.copy/p12-0x.cpp @@ -28,7 +28,18 @@ struct NonConstCopy { NonConstCopy(NonConstCopy &) = default; }; -using _ = not_trivially_copyable<NonConstCopy>; +static_assert(__has_trivial_copy(NonConstCopy), ""); +static_assert(__is_trivially_constructible(NonConstCopy, NonConstCopy&), ""); +static_assert(!__is_trivially_constructible(NonConstCopy, NonConstCopy), ""); +static_assert(!__is_trivially_constructible(NonConstCopy, const NonConstCopy &), ""); +static_assert(!__is_trivially_constructible(NonConstCopy, NonConstCopy &&), ""); + +struct DefaultedSpecialMembers { + DefaultedSpecialMembers(const DefaultedSpecialMembers&) = default; + DefaultedSpecialMembers(DefaultedSpecialMembers &) = default; + DefaultedSpecialMembers(DefaultedSpecialMembers &&) = default; +}; +using _ = trivially_copyable<DefaultedSpecialMembers>; // class X has no virtual functions struct VFn { Index: clang/lib/Sema/SemaDeclCXX.cpp =================================================================== --- clang/lib/Sema/SemaDeclCXX.cpp +++ clang/lib/Sema/SemaDeclCXX.cpp @@ -9772,11 +9772,9 @@ case CXXCopyConstructor: case CXXCopyAssignment: { - // Trivial copy operations always have const, non-volatile parameter types. - ConstArg = true; const ParmVarDecl *Param0 = MD->getParamDecl(0); const ReferenceType *RT = Param0->getType()->getAs<ReferenceType>(); - if (!RT || RT->getPointeeType().getCVRQualifiers() != Qualifiers::Const) { + if (!RT) { if (Diagnose) Diag(Param0->getLocation(), diag::note_nontrivial_param_type) << Param0->getSourceRange() << Param0->getType() @@ -9784,6 +9782,10 @@ Context.getRecordType(RD).withConst()); return false; } + + if (RT && ((RT->getPointeeType().getCVRQualifiers() & Qualifiers::Const) == Qualifiers::Const)) { + ConstArg = true; + } break; }
Index: clang/test/CXX/special/class.copy/p25-0x.cpp =================================================================== --- clang/test/CXX/special/class.copy/p25-0x.cpp +++ clang/test/CXX/special/class.copy/p25-0x.cpp @@ -31,7 +31,22 @@ struct NonConstCopy { NonConstCopy &operator=(NonConstCopy &) = default; }; -using _ = not_trivially_assignable<NonConstCopy>; +static_assert(__has_trivial_assign(NonConstCopy), ""); +static_assert(__is_trivially_assignable(NonConstCopy&, NonConstCopy&), ""); +static_assert(!__is_trivially_assignable(NonConstCopy&, const NonConstCopy &), ""); +static_assert(!__is_trivially_assignable(NonConstCopy&, NonConstCopy), ""); +static_assert(!__is_trivially_assignable(NonConstCopy&, NonConstCopy&&), ""); +static_assert(__is_trivially_assignable(NonConstCopy&&, NonConstCopy&), ""); +static_assert(!__is_trivially_assignable(NonConstCopy&&, const NonConstCopy &), ""); +static_assert(!__is_trivially_assignable(NonConstCopy&&, NonConstCopy), ""); +static_assert(!__is_trivially_assignable(NonConstCopy&&, NonConstCopy&&), ""); + +struct DefaultedSpecialMembers { + DefaultedSpecialMembers &operator=(const DefaultedSpecialMembers &) = default; + DefaultedSpecialMembers &operator=(DefaultedSpecialMembers &) = default; + DefaultedSpecialMembers &operator=(DefaultedSpecialMembers &&) = default; +}; +using _ = trivially_assignable<DefaultedSpecialMembers>; // class X has no virtual functions struct VFn { Index: clang/test/CXX/special/class.copy/p12-0x.cpp =================================================================== --- clang/test/CXX/special/class.copy/p12-0x.cpp +++ clang/test/CXX/special/class.copy/p12-0x.cpp @@ -28,7 +28,18 @@ struct NonConstCopy { NonConstCopy(NonConstCopy &) = default; }; -using _ = not_trivially_copyable<NonConstCopy>; +static_assert(__has_trivial_copy(NonConstCopy), ""); +static_assert(__is_trivially_constructible(NonConstCopy, NonConstCopy&), ""); +static_assert(!__is_trivially_constructible(NonConstCopy, NonConstCopy), ""); +static_assert(!__is_trivially_constructible(NonConstCopy, const NonConstCopy &), ""); +static_assert(!__is_trivially_constructible(NonConstCopy, NonConstCopy &&), ""); + +struct DefaultedSpecialMembers { + DefaultedSpecialMembers(const DefaultedSpecialMembers&) = default; + DefaultedSpecialMembers(DefaultedSpecialMembers &) = default; + DefaultedSpecialMembers(DefaultedSpecialMembers &&) = default; +}; +using _ = trivially_copyable<DefaultedSpecialMembers>; // class X has no virtual functions struct VFn { Index: clang/lib/Sema/SemaDeclCXX.cpp =================================================================== --- clang/lib/Sema/SemaDeclCXX.cpp +++ clang/lib/Sema/SemaDeclCXX.cpp @@ -9772,11 +9772,9 @@ case CXXCopyConstructor: case CXXCopyAssignment: { - // Trivial copy operations always have const, non-volatile parameter types. - ConstArg = true; const ParmVarDecl *Param0 = MD->getParamDecl(0); const ReferenceType *RT = Param0->getType()->getAs<ReferenceType>(); - if (!RT || RT->getPointeeType().getCVRQualifiers() != Qualifiers::Const) { + if (!RT) { if (Diagnose) Diag(Param0->getLocation(), diag::note_nontrivial_param_type) << Param0->getSourceRange() << Param0->getType() @@ -9784,6 +9782,10 @@ Context.getRecordType(RD).withConst()); return false; } + + if (RT && ((RT->getPointeeType().getCVRQualifiers() & Qualifiers::Const) == Qualifiers::Const)) { + ConstArg = true; + } break; }
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits