royjacobson created this revision.
Herald added a project: All.
royjacobson requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

As noted in https://github.com/llvm/llvm-project/issues/59624, we sometimes 
mark implicitly
deleted special member functions as non-trivial. This is unnecessary work and 
leads to some
weird type traits errors.

This fixes the problem by making the implicitly deleted special member 
functions always
trivial.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D140664

Files:
  clang/docs/ReleaseNotes.rst
  clang/lib/Sema/SemaDeclCXX.cpp
  clang/test/AST/ast-dump-funcs.cpp
  clang/test/SemaCXX/GH59624.cpp

Index: clang/test/SemaCXX/GH59624.cpp
===================================================================
--- /dev/null
+++ clang/test/SemaCXX/GH59624.cpp
@@ -0,0 +1,22 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11
+// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++20
+// expected-no-diagnostics
+
+namespace GH59624 {
+
+struct Foo{
+    int x{0};
+};
+struct CFoo{
+    const int x{0};
+};
+struct Bar{
+    const Foo y;
+};
+
+// Deleted move assignment shouldn't make type non-trivially copyable:
+
+static_assert(__is_trivially_copyable(Bar), "");
+
+}
+
Index: clang/test/AST/ast-dump-funcs.cpp
===================================================================
--- clang/test/AST/ast-dump-funcs.cpp
+++ clang/test/AST/ast-dump-funcs.cpp
@@ -54,10 +54,10 @@
   virtual void g() = 0;
   // CHECK: CXXMethodDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:22> col:16 g 'void ()' virtual pure
 
-  // CHECK: CXXConstructorDecl 0x{{[^ ]*}} <line:[[@LINE-33]]:8> col:8 implicit S 'void (const S &)' inline default_delete noexcept-unevaluated
+  // CHECK: CXXConstructorDecl 0x{{[^ ]*}} <line:[[@LINE-33]]:8> col:8 implicit S 'void (const S &)' inline default_delete trivial noexcept-unevaluated
   // CHECK: CXXConstructorDecl 0x{{[^ ]*}} <col:8> col:8 implicit constexpr S 'void (S &&)' inline default noexcept-unevaluated
-  // CHECK: CXXMethodDecl 0x{{[^ ]*}} <col:8> col:8 implicit operator= 'S &(const S &)' inline default_delete noexcept-unevaluated
-  // CHECK: CXXMethodDecl 0x{{[^ ]*}} <col:8> col:8 implicit operator= 'S &(S &&)' inline default_delete noexcept-unevaluated
+  // CHECK: CXXMethodDecl 0x{{[^ ]*}} <col:8> col:8 implicit operator= 'S &(const S &)' inline default_delete trivial noexcept-unevaluated
+  // CHECK: CXXMethodDecl 0x{{[^ ]*}} <col:8> col:8 implicit operator= 'S &(S &&)' inline default_delete trivial noexcept-unevaluated
   // CHECK: CXXDestructorDecl 0x{{[^ ]*}} <col:8> col:8 implicit ~S 'void ()' inline default noexcept-unevaluated
 };
 
@@ -70,9 +70,9 @@
   // CHECK-NEXT: IntegerLiteral 0x{{[^ ]*}} <col:23> 'int' 100
   // CHECK-NEXT: OverrideAttr
 
-  // CHECK: CXXConstructorDecl 0x{{[^ ]*}} <line:[[@LINE-9]]:8> col:8 implicit T 'void (const T &)' inline default_delete noexcept-unevaluated
-  // CHECK: CXXMethodDecl 0x{{[^ ]*}} <col:8> col:8 implicit operator= 'T &(const T &)' inline default_delete noexcept-unevaluated
-  // CHECK: CXXMethodDecl 0x{{[^ ]*}} <col:8> col:8 implicit operator= 'T &(T &&)' inline default_delete noexcept-unevaluated
+  // CHECK: CXXConstructorDecl 0x{{[^ ]*}} <line:[[@LINE-9]]:8> col:8 implicit T 'void (const T &)' inline default_delete trivial noexcept-unevaluated
+  // CHECK: CXXMethodDecl 0x{{[^ ]*}} <col:8> col:8 implicit operator= 'T &(const T &)' inline default_delete trivial noexcept-unevaluated
+  // CHECK: CXXMethodDecl 0x{{[^ ]*}} <col:8> col:8 implicit operator= 'T &(T &&)' inline default_delete trivial noexcept-unevaluated
   // CHECK: CXXDestructorDecl 0x{{[^ ]*}} <col:8> col:8 implicit ~T 'void ()' inline default noexcept-unevaluated
 };
 
Index: clang/lib/Sema/SemaDeclCXX.cpp
===================================================================
--- clang/lib/Sema/SemaDeclCXX.cpp
+++ clang/lib/Sema/SemaDeclCXX.cpp
@@ -14475,11 +14475,6 @@
                                                nullptr);
   CopyAssignment->setParams(FromParam);
 
-  CopyAssignment->setTrivial(
-    ClassDecl->needsOverloadResolutionForCopyAssignment()
-      ? SpecialMemberIsTrivial(CopyAssignment, CXXCopyAssignment)
-      : ClassDecl->hasTrivialCopyAssignment());
-
   // Note that we have added this copy-assignment operator.
   ++getASTContext().NumImplicitCopyAssignmentOperatorsDeclared;
 
@@ -14489,6 +14484,11 @@
   if (ShouldDeleteSpecialMember(CopyAssignment, CXXCopyAssignment)) {
     ClassDecl->setImplicitCopyAssignmentIsDeleted();
     SetDeclDeleted(CopyAssignment, ClassLoc);
+  } else {
+    CopyAssignment->setTrivial(
+      ClassDecl->needsOverloadResolutionForCopyAssignment()
+        ? SpecialMemberIsTrivial(CopyAssignment, CXXCopyAssignment)
+        : ClassDecl->hasTrivialCopyAssignment());
   }
 
   if (S)
@@ -14813,10 +14813,6 @@
                                                nullptr);
   MoveAssignment->setParams(FromParam);
 
-  MoveAssignment->setTrivial(
-    ClassDecl->needsOverloadResolutionForMoveAssignment()
-      ? SpecialMemberIsTrivial(MoveAssignment, CXXMoveAssignment)
-      : ClassDecl->hasTrivialMoveAssignment());
 
   // Note that we have added this copy-assignment operator.
   ++getASTContext().NumImplicitMoveAssignmentOperatorsDeclared;
@@ -14827,6 +14823,11 @@
   if (ShouldDeleteSpecialMember(MoveAssignment, CXXMoveAssignment)) {
     ClassDecl->setImplicitMoveAssignmentIsDeleted();
     SetDeclDeleted(MoveAssignment, ClassLoc);
+  } else {
+    MoveAssignment->setTrivial(
+      ClassDecl->needsOverloadResolutionForMoveAssignment()
+        ? SpecialMemberIsTrivial(MoveAssignment, CXXMoveAssignment)
+        : ClassDecl->hasTrivialMoveAssignment());
   }
 
   if (S)
@@ -15197,18 +15198,6 @@
                           /*TInfo=*/TSI, SC_None, nullptr);
   CopyConstructor->setParams(FromParam);
 
-  CopyConstructor->setTrivial(
-      ClassDecl->needsOverloadResolutionForCopyConstructor()
-          ? SpecialMemberIsTrivial(CopyConstructor, CXXCopyConstructor)
-          : ClassDecl->hasTrivialCopyConstructor());
-
-  CopyConstructor->setTrivialForCall(
-      ClassDecl->hasAttr<TrivialABIAttr>() ||
-      (ClassDecl->needsOverloadResolutionForCopyConstructor()
-           ? SpecialMemberIsTrivial(CopyConstructor, CXXCopyConstructor,
-             TAH_ConsiderTrivialABI)
-           : ClassDecl->hasTrivialCopyConstructorForCall()));
-
   // Note that we have declared this constructor.
   ++getASTContext().NumImplicitCopyConstructorsDeclared;
 
@@ -15218,6 +15207,18 @@
   if (ShouldDeleteSpecialMember(CopyConstructor, CXXCopyConstructor)) {
     ClassDecl->setImplicitCopyConstructorIsDeleted();
     SetDeclDeleted(CopyConstructor, ClassLoc);
+  } else {
+    CopyConstructor->setTrivial(
+        ClassDecl->needsOverloadResolutionForCopyConstructor()
+            ? SpecialMemberIsTrivial(CopyConstructor, CXXCopyConstructor)
+            : ClassDecl->hasTrivialCopyConstructor());
+
+    CopyConstructor->setTrivialForCall(
+        ClassDecl->hasAttr<TrivialABIAttr>() ||
+        (ClassDecl->needsOverloadResolutionForCopyConstructor()
+             ? SpecialMemberIsTrivial(CopyConstructor, CXXCopyConstructor,
+                                      TAH_ConsiderTrivialABI)
+             : ClassDecl->hasTrivialCopyConstructorForCall()));
   }
 
   if (S)
@@ -15331,18 +15332,6 @@
                                                SC_None, nullptr);
   MoveConstructor->setParams(FromParam);
 
-  MoveConstructor->setTrivial(
-      ClassDecl->needsOverloadResolutionForMoveConstructor()
-          ? SpecialMemberIsTrivial(MoveConstructor, CXXMoveConstructor)
-          : ClassDecl->hasTrivialMoveConstructor());
-
-  MoveConstructor->setTrivialForCall(
-      ClassDecl->hasAttr<TrivialABIAttr>() ||
-      (ClassDecl->needsOverloadResolutionForMoveConstructor()
-           ? SpecialMemberIsTrivial(MoveConstructor, CXXMoveConstructor,
-                                    TAH_ConsiderTrivialABI)
-           : ClassDecl->hasTrivialMoveConstructorForCall()));
-
   // Note that we have declared this constructor.
   ++getASTContext().NumImplicitMoveConstructorsDeclared;
 
@@ -15352,6 +15341,18 @@
   if (ShouldDeleteSpecialMember(MoveConstructor, CXXMoveConstructor)) {
     ClassDecl->setImplicitMoveConstructorIsDeleted();
     SetDeclDeleted(MoveConstructor, ClassLoc);
+  } else {
+    MoveConstructor->setTrivial(
+        ClassDecl->needsOverloadResolutionForMoveConstructor()
+            ? SpecialMemberIsTrivial(MoveConstructor, CXXMoveConstructor)
+            : ClassDecl->hasTrivialMoveConstructor());
+
+    MoveConstructor->setTrivialForCall(
+        ClassDecl->hasAttr<TrivialABIAttr>() ||
+        (ClassDecl->needsOverloadResolutionForMoveConstructor()
+             ? SpecialMemberIsTrivial(MoveConstructor, CXXMoveConstructor,
+                                      TAH_ConsiderTrivialABI)
+             : ClassDecl->hasTrivialMoveConstructorForCall()));
   }
 
   if (S)
@@ -17569,6 +17570,9 @@
   //  A deleted function is implicitly inline.
   Fn->setImplicitlyInline();
   Fn->setDeletedAsWritten();
+
+  Fn->setTrivial(true);
+  Fn->setTrivialForCall(true);
 }
 
 void Sema::SetDeclDefaulted(Decl *Dcl, SourceLocation DefaultLoc) {
Index: clang/docs/ReleaseNotes.rst
===================================================================
--- clang/docs/ReleaseNotes.rst
+++ clang/docs/ReleaseNotes.rst
@@ -715,6 +715,9 @@
   classified such types as non-POD (for the purposes of Itanium ABI). Clang now
   matches the gcc behavior (except on Darwin and PS4). You can switch back to
   the old ABI behavior with the flag: ``-fclang-abi-compat=15.0``.
+- Some types with implicitly deleted special member functions were accidentally
+  marked as non-trivially copyable. This has been fixed
+  (`#59624 <https://github.com/llvm/llvm-project/issues/59624>`_).
 
 OpenMP Support in Clang
 -----------------------
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to