zoecarver created this revision.
Herald added a reviewer: aaron.ballman.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.
zoecarver requested review of this revision.

Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D92361

Files:
  clang/include/clang/Basic/AttrDocs.td
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/lib/Sema/SemaDeclCXX.cpp
  clang/test/CodeGenCXX/trivial_abi.cpp
  clang/test/SemaCXX/attr-trivial-abi.cpp
  clang/test/SemaObjCXX/attr-trivial-abi.mm

Index: clang/test/SemaObjCXX/attr-trivial-abi.mm
===================================================================
--- clang/test/SemaObjCXX/attr-trivial-abi.mm
+++ clang/test/SemaObjCXX/attr-trivial-abi.mm
@@ -101,34 +101,3 @@
 };
 
 S17<int> s17;
-
-namespace deletedCopyMoveConstructor {
-  struct __attribute__((trivial_abi)) CopyMoveDeleted { // expected-warning {{'trivial_abi' cannot be applied to 'CopyMoveDeleted'}} expected-note {{copy constructors and move constructors are all deleted}}
-    CopyMoveDeleted(const CopyMoveDeleted &) = delete;
-    CopyMoveDeleted(CopyMoveDeleted &&) = delete;
-  };
-
-  struct __attribute__((trivial_abi)) S18 { // expected-warning {{'trivial_abi' cannot be applied to 'S18'}} expected-note {{copy constructors and move constructors are all deleted}}
-    CopyMoveDeleted a;
-  };
-
-  struct __attribute__((trivial_abi)) CopyDeleted {
-    CopyDeleted(const CopyDeleted &) = delete;
-    CopyDeleted(CopyDeleted &&) = default;
-  };
-
-  struct __attribute__((trivial_abi)) MoveDeleted {
-    MoveDeleted(const MoveDeleted &) = default;
-    MoveDeleted(MoveDeleted &&) = delete;
-  };
-
-  struct __attribute__((trivial_abi)) S19 { // expected-warning {{'trivial_abi' cannot be applied to 'S19'}} expected-note {{copy constructors and move constructors are all deleted}}
-    CopyDeleted a;
-    MoveDeleted b;
-  };
-
-  // This is fine since the move constructor isn't deleted.
-  struct __attribute__((trivial_abi)) S20 {
-    int &&a; // a member of rvalue reference type deletes the copy constructor.
-  };
-}
Index: clang/test/SemaCXX/attr-trivial-abi.cpp
===================================================================
--- clang/test/SemaCXX/attr-trivial-abi.cpp
+++ clang/test/SemaCXX/attr-trivial-abi.cpp
@@ -79,34 +79,3 @@
 };
 
 S17<int> s17;
-
-namespace deletedCopyMoveConstructor {
-struct __attribute__((trivial_abi)) CopyMoveDeleted { // expected-warning {{'trivial_abi' cannot be applied to 'CopyMoveDeleted'}} expected-note {{copy constructors and move constructors are all deleted}}
-  CopyMoveDeleted(const CopyMoveDeleted &) = delete;
-  CopyMoveDeleted(CopyMoveDeleted &&) = delete;
-};
-
-struct __attribute__((trivial_abi)) S18 { // expected-warning {{'trivial_abi' cannot be applied to 'S18'}} expected-note {{copy constructors and move constructors are all deleted}}
-  CopyMoveDeleted a;
-};
-
-struct __attribute__((trivial_abi)) CopyDeleted {
-  CopyDeleted(const CopyDeleted &) = delete;
-  CopyDeleted(CopyDeleted &&) = default;
-};
-
-struct __attribute__((trivial_abi)) MoveDeleted {
-  MoveDeleted(const MoveDeleted &) = default;
-  MoveDeleted(MoveDeleted &&) = delete;
-};
-
-struct __attribute__((trivial_abi)) S19 { // expected-warning {{'trivial_abi' cannot be applied to 'S19'}} expected-note {{copy constructors and move constructors are all deleted}}
-  CopyDeleted a;
-  MoveDeleted b;
-};
-
-// This is fine since the move constructor isn't deleted.
-struct __attribute__((trivial_abi)) S20 {
-  int &&a; // a member of rvalue reference type deletes the copy constructor.
-};
-} // namespace deletedCopyMoveConstructor
Index: clang/test/CodeGenCXX/trivial_abi.cpp
===================================================================
--- clang/test/CodeGenCXX/trivial_abi.cpp
+++ clang/test/CodeGenCXX/trivial_abi.cpp
@@ -5,6 +5,9 @@
 // CHECK: %[[STRUCT_LARGE:.*]] = type { i32*, [128 x i32] }
 // CHECK: %[[STRUCT_TRIVIAL:.*]] = type { i32 }
 // CHECK: %[[STRUCT_NONTRIVIAL:.*]] = type { i32 }
+// CHECK: [[STRUCT_COPY_MOVE_DELETED:%.*]] = type { i8 }
+// CHECK: [[STRUCT_MOVE_LIKE_1:%.*]] = type { i8 }
+// CHECK: [[STRUCT_MOVE_LIKE_2:%.*]] = type { i8 }
 
 struct __attribute__((trivial_abi)) Small {
   int *p;
@@ -55,6 +58,26 @@
   Small m0() override;
 };
 
+struct __attribute__((trivial_abi)) CopyMoveDeleted {
+  CopyMoveDeleted(CopyMoveDeleted const&) = delete;
+  CopyMoveDeleted(CopyMoveDeleted &&) = delete;
+  CopyMoveDeleted(int) {}
+  ~CopyMoveDeleted() {}
+};
+
+struct __attribute__((trivial_abi)) TemplatedMoveLikeCtor {
+  TemplatedMoveLikeCtor(TemplatedMoveLikeCtor const&) = delete;
+  TemplatedMoveLikeCtor(TemplatedMoveLikeCtor &&) = delete;
+  template<class T> TemplatedMoveLikeCtor(T&&) { }
+  ~TemplatedMoveLikeCtor() {}
+};
+
+struct __attribute__((trivial_abi)) TemplatedMoveLikeCtor2 {
+  TemplatedMoveLikeCtor2(TemplatedMoveLikeCtor2 const&) = delete;
+  template<class = int> TemplatedMoveLikeCtor2(TemplatedMoveLikeCtor2&&) { }
+  ~TemplatedMoveLikeCtor2() {}
+};
+
 // CHECK-LABEL: define i64 @_ZThn8_N2D02m0Ev(
 // CHECK: %[[RETVAL:.*]] = alloca %[[STRUCT_SMALL]], align 8
 // CHECK: %[[CALL:.*]] = tail call i64 @_ZN2D02m0Ev(
@@ -262,3 +285,22 @@
 void testExceptionLarge() {
   calleeExceptionLarge(Large(), Large());
 }
+
+// CHECK-LABEL: define void @_Z19testCopyMoveDeleted15CopyMoveDeleted(i8 %{{.*}})
+// CHECK: call [[STRUCT_COPY_MOVE_DELETED]]* @_ZN15CopyMoveDeletedD1Ev([[STRUCT_COPY_MOVE_DELETED]]*
+// CHECK: ret void
+void testCopyMoveDeleted(CopyMoveDeleted ) { }
+
+// CHECK-LABEL: define void @_Z25testTemplatedMoveLikeCtor21TemplatedMoveLikeCtor(i8 %{{.*}})
+// CHECK: call [[STRUCT_MOVE_LIKE_1]]* @_ZN21TemplatedMoveLikeCtorD1Ev([[STRUCT_MOVE_LIKE_1]]*
+// CHECK: ret void
+TemplatedMoveLikeCtor testTemplatedMoveLikeCtor(TemplatedMoveLikeCtor a) {
+    return a;
+}
+
+// CHECK: define void @_Z26testTemplatedMoveLikeCtor222TemplatedMoveLikeCtor2(i8 %{{.*}})
+// CHECK: call [[STRUCT_MOVE_LIKE_2]]* @_ZN22TemplatedMoveLikeCtor2D1Ev([[STRUCT_MOVE_LIKE_2]]*
+// CHECK: ret void
+TemplatedMoveLikeCtor2 testTemplatedMoveLikeCtor2(TemplatedMoveLikeCtor2 a) {
+    return a;
+}
Index: clang/lib/Sema/SemaDeclCXX.cpp
===================================================================
--- clang/lib/Sema/SemaDeclCXX.cpp
+++ clang/lib/Sema/SemaDeclCXX.cpp
@@ -6412,6 +6412,9 @@
   if (D->isDependentType() || D->isInvalidDecl())
     return false;
 
+  if (D->hasAttr<TrivialABIAttr>())
+    return true;
+
   // Clang <= 4 used the pre-C++11 rule, which ignores move operations.
   // The PS4 platform ABI follows the behavior of Clang 3.2.
   if (CCK == TargetInfo::CCK_ClangABI4OrPS4)
@@ -9764,32 +9767,9 @@
     RD.dropAttr<TrivialABIAttr>();
   };
 
-  // Ill-formed if the copy and move constructors are deleted.
-  auto HasNonDeletedCopyOrMoveConstructor = [&]() {
-    // If the type is dependent, then assume it might have
-    // implicit copy or move ctor because we won't know yet at this point.
-    if (RD.isDependentType())
-      return true;
-    if (RD.needsImplicitCopyConstructor() &&
-        !RD.defaultedCopyConstructorIsDeleted())
-      return true;
-    if (RD.needsImplicitMoveConstructor() &&
-        !RD.defaultedMoveConstructorIsDeleted())
-      return true;
-    for (const CXXConstructorDecl *CD : RD.ctors())
-      if (CD->isCopyOrMoveConstructor() && !CD->isDeleted())
-        return true;
-    return false;
-  };
-
-  if (!HasNonDeletedCopyOrMoveConstructor()) {
-    PrintDiagAndRemoveAttr(0);
-    return;
-  }
-
   // Ill-formed if the struct has virtual functions.
   if (RD.isPolymorphic()) {
-    PrintDiagAndRemoveAttr(1);
+    PrintDiagAndRemoveAttr(0);
     return;
   }
 
@@ -9798,12 +9778,12 @@
     // virtual base.
     if (!B.getType()->isDependentType() &&
         !B.getType()->getAsCXXRecordDecl()->canPassInRegisters()) {
-      PrintDiagAndRemoveAttr(2);
+      PrintDiagAndRemoveAttr(1);
       return;
     }
 
     if (B.isVirtual()) {
-      PrintDiagAndRemoveAttr(3);
+      PrintDiagAndRemoveAttr(2);
       return;
     }
   }
@@ -9813,14 +9793,14 @@
     // non-trivial for the purpose of calls.
     QualType FT = FD->getType();
     if (FT.getObjCLifetime() == Qualifiers::OCL_Weak) {
-      PrintDiagAndRemoveAttr(4);
+      PrintDiagAndRemoveAttr(3);
       return;
     }
 
     if (const auto *RT = FT->getBaseElementTypeUnsafe()->getAs<RecordType>())
       if (!RT->isDependentType() &&
           !cast<CXXRecordDecl>(RT->getDecl())->canPassInRegisters()) {
-        PrintDiagAndRemoveAttr(5);
+        PrintDiagAndRemoveAttr(4);
         return;
       }
   }
Index: clang/include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -3361,7 +3361,6 @@
   "'trivial_abi' cannot be applied to %0">, InGroup<IgnoredAttributes>;
 def note_cannot_use_trivial_abi_reason : Note<
   "'trivial_abi' is disallowed on %0 because %select{"
-  "its copy constructors and move constructors are all deleted|"
   "it is polymorphic|"
   "it has a base of a non-trivial class type|it has a virtual base|"
   "it has a __weak field|it has a field of a non-trivial class type}1">;
Index: clang/include/clang/Basic/AttrDocs.td
===================================================================
--- clang/include/clang/Basic/AttrDocs.td
+++ clang/include/clang/Basic/AttrDocs.td
@@ -2983,9 +2983,9 @@
 It instructs the compiler to pass and return the type using the C ABI for the
 underlying type when the type would otherwise be considered non-trivial for the
 purpose of calls.
-A class annotated with ``trivial_abi`` can have non-trivial destructors or
-copy/move constructors without automatically becoming non-trivial for the
-purposes of calls. For example:
+A class annotated with trivial_abi can have non-trivial destructors or copy/move
+constructors or deleted move and copy constructors without automatically
+becoming non-trivial for the purposes of calls. For example:
 
   .. code-block:: c++
 
@@ -3011,7 +3011,6 @@
 Attribute ``trivial_abi`` has no effect in the following cases:
 
 - The class directly declares a virtual base or virtual methods.
-- Copy constructors and move constructors of the class are all deleted.
 - The class has a base class that is non-trivial for the purposes of calls.
 - The class has a non-static data member whose type is non-trivial for the
   purposes of calls, which includes:
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to