diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -754,6 +754,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 `_). OpenMP Support in Clang ----------------------- diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/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,11 +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 +14822,11 @@ if (ShouldDeleteSpecialMember(MoveAssignment, CXXMoveAssignment)) { ClassDecl->setImplicitMoveAssignmentIsDeleted(); SetDeclDeleted(MoveAssignment, ClassLoc); + } else { + MoveAssignment->setTrivial( + ClassDecl->needsOverloadResolutionForMoveAssignment() + ? SpecialMemberIsTrivial(MoveAssignment, CXXMoveAssignment) + : ClassDecl->hasTrivialMoveAssignment()); } if (S) @@ -15197,18 +15197,6 @@ /*TInfo=*/TSI, SC_None, nullptr); CopyConstructor->setParams(FromParam); - CopyConstructor->setTrivial( - ClassDecl->needsOverloadResolutionForCopyConstructor() - ? SpecialMemberIsTrivial(CopyConstructor, CXXCopyConstructor) - : ClassDecl->hasTrivialCopyConstructor()); - - CopyConstructor->setTrivialForCall( - ClassDecl->hasAttr() || - (ClassDecl->needsOverloadResolutionForCopyConstructor() - ? SpecialMemberIsTrivial(CopyConstructor, CXXCopyConstructor, - TAH_ConsiderTrivialABI) - : ClassDecl->hasTrivialCopyConstructorForCall())); - // Note that we have declared this constructor. ++getASTContext().NumImplicitCopyConstructorsDeclared; @@ -15218,6 +15206,18 @@ if (ShouldDeleteSpecialMember(CopyConstructor, CXXCopyConstructor)) { ClassDecl->setImplicitCopyConstructorIsDeleted(); SetDeclDeleted(CopyConstructor, ClassLoc); + } else { + CopyConstructor->setTrivial( + ClassDecl->needsOverloadResolutionForCopyConstructor() + ? SpecialMemberIsTrivial(CopyConstructor, CXXCopyConstructor) + : ClassDecl->hasTrivialCopyConstructor()); + + CopyConstructor->setTrivialForCall( + ClassDecl->hasAttr() || + (ClassDecl->needsOverloadResolutionForCopyConstructor() + ? SpecialMemberIsTrivial(CopyConstructor, CXXCopyConstructor, + TAH_ConsiderTrivialABI) + : ClassDecl->hasTrivialCopyConstructorForCall())); } if (S) @@ -15331,18 +15331,6 @@ SC_None, nullptr); MoveConstructor->setParams(FromParam); - MoveConstructor->setTrivial( - ClassDecl->needsOverloadResolutionForMoveConstructor() - ? SpecialMemberIsTrivial(MoveConstructor, CXXMoveConstructor) - : ClassDecl->hasTrivialMoveConstructor()); - - MoveConstructor->setTrivialForCall( - ClassDecl->hasAttr() || - (ClassDecl->needsOverloadResolutionForMoveConstructor() - ? SpecialMemberIsTrivial(MoveConstructor, CXXMoveConstructor, - TAH_ConsiderTrivialABI) - : ClassDecl->hasTrivialMoveConstructorForCall())); - // Note that we have declared this constructor. ++getASTContext().NumImplicitMoveConstructorsDeclared; @@ -15352,6 +15340,18 @@ if (ShouldDeleteSpecialMember(MoveConstructor, CXXMoveConstructor)) { ClassDecl->setImplicitMoveConstructorIsDeleted(); SetDeclDeleted(MoveConstructor, ClassLoc); + } else { + MoveConstructor->setTrivial( + ClassDecl->needsOverloadResolutionForMoveConstructor() + ? SpecialMemberIsTrivial(MoveConstructor, CXXMoveConstructor) + : ClassDecl->hasTrivialMoveConstructor()); + + MoveConstructor->setTrivialForCall( + ClassDecl->hasAttr() || + (ClassDecl->needsOverloadResolutionForMoveConstructor() + ? SpecialMemberIsTrivial(MoveConstructor, CXXMoveConstructor, + TAH_ConsiderTrivialABI) + : ClassDecl->hasTrivialMoveConstructorForCall())); } if (S) @@ -17569,6 +17569,9 @@ // A deleted function is implicitly inline. Fn->setImplicitlyInline(); Fn->setDeletedAsWritten(); + + Fn->setTrivial(true); + Fn->setTrivialForCall(true); } void Sema::SetDeclDefaulted(Decl *Dcl, SourceLocation DefaultLoc) { diff --git a/clang/test/AST/ast-dump-funcs.cpp b/clang/test/AST/ast-dump-funcs.cpp --- a/clang/test/AST/ast-dump-funcs.cpp +++ b/clang/test/AST/ast-dump-funcs.cpp @@ -54,10 +54,10 @@ virtual void g() = 0; // CHECK: CXXMethodDecl 0x{{[^ ]*}} col:16 g 'void ()' virtual pure - // CHECK: CXXConstructorDecl 0x{{[^ ]*}} col:8 implicit S 'void (const S &)' inline default_delete noexcept-unevaluated + // CHECK: CXXConstructorDecl 0x{{[^ ]*}} col:8 implicit S 'void (const S &)' inline default_delete trivial noexcept-unevaluated // CHECK: CXXConstructorDecl 0x{{[^ ]*}} col:8 implicit constexpr S 'void (S &&)' inline default noexcept-unevaluated - // CHECK: CXXMethodDecl 0x{{[^ ]*}} col:8 implicit operator= 'S &(const S &)' inline default_delete noexcept-unevaluated - // CHECK: CXXMethodDecl 0x{{[^ ]*}} col:8 implicit operator= 'S &(S &&)' inline default_delete noexcept-unevaluated + // CHECK: CXXMethodDecl 0x{{[^ ]*}} col:8 implicit operator= 'S &(const S &)' inline default_delete trivial noexcept-unevaluated + // CHECK: CXXMethodDecl 0x{{[^ ]*}} col:8 implicit operator= 'S &(S &&)' inline default_delete trivial noexcept-unevaluated // CHECK: CXXDestructorDecl 0x{{[^ ]*}} col:8 implicit ~S 'void ()' inline default noexcept-unevaluated }; @@ -70,9 +70,9 @@ // CHECK-NEXT: IntegerLiteral 0x{{[^ ]*}} 'int' 100 // CHECK-NEXT: OverrideAttr - // CHECK: CXXConstructorDecl 0x{{[^ ]*}} col:8 implicit T 'void (const T &)' inline default_delete noexcept-unevaluated - // CHECK: CXXMethodDecl 0x{{[^ ]*}} col:8 implicit operator= 'T &(const T &)' inline default_delete noexcept-unevaluated - // CHECK: CXXMethodDecl 0x{{[^ ]*}} col:8 implicit operator= 'T &(T &&)' inline default_delete noexcept-unevaluated + // CHECK: CXXConstructorDecl 0x{{[^ ]*}} col:8 implicit T 'void (const T &)' inline default_delete trivial noexcept-unevaluated + // CHECK: CXXMethodDecl 0x{{[^ ]*}} col:8 implicit operator= 'T &(const T &)' inline default_delete trivial noexcept-unevaluated + // CHECK: CXXMethodDecl 0x{{[^ ]*}} col:8 implicit operator= 'T &(T &&)' inline default_delete trivial noexcept-unevaluated // CHECK: CXXDestructorDecl 0x{{[^ ]*}} col:8 implicit ~T 'void ()' inline default noexcept-unevaluated }; diff --git a/clang/test/SemaCXX/GH59624.cpp b/clang/test/SemaCXX/GH59624.cpp new file mode 100644 --- /dev/null +++ b/clang/test/SemaCXX/GH59624.cpp @@ -0,0 +1,19 @@ +// 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 Bar{ + const Foo y; +}; + +// Deleted move assignment shouldn't make type non-trivially copyable: + +static_assert(__is_trivially_copyable(Bar), ""); + +}