[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