[PATCH] D127593: [clang] Fix trivially copyable for copy constructor and copy assignment operator
Javier Alvarez via Phabricator via cfe-commits
cfe-commits at lists.llvm.org
Sun Jun 12 03:22:19 PDT 2022
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;
}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D127593.436204.patch
Type: text/x-patch
Size: 3537 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20220612/b5b57b09/attachment-0001.bin>
More information about the cfe-commits
mailing list