llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: None (pcc) <details> <summary>Changes</summary> C++17 added the following requirement for a class to be trivially copyable: "that has at least one non-deleted copy constructor, move constructor, copy assignment operator, or move assignment operator". However, this was not implemented. Fix it. --- Full diff: https://github.com/llvm/llvm-project/pull/94831.diff 3 Files Affected: - (modified) clang/include/clang/AST/CXXRecordDeclDefinitionBits.def (+3) - (modified) clang/lib/AST/DeclCXX.cpp (+21-4) - (modified) clang/test/SemaCXX/type-traits.cpp (+8) ``````````diff diff --git a/clang/include/clang/AST/CXXRecordDeclDefinitionBits.def b/clang/include/clang/AST/CXXRecordDeclDefinitionBits.def index cdf0804680ad0..55cd45348d29d 100644 --- a/clang/include/clang/AST/CXXRecordDeclDefinitionBits.def +++ b/clang/include/clang/AST/CXXRecordDeclDefinitionBits.def @@ -249,4 +249,7 @@ FIELD(HasDeclaredCopyAssignmentWithConstParam, 1, MERGE_OR) /// base classes or fields have a no-return destructor FIELD(IsAnyDestructorNoReturn, 1, NO_MERGE) +/// The special members of this class which were deleted. +FIELD(HasDeletedSpecialMembers, 6, MERGE_OR) + #undef FIELD diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp index 7f2c786547b9b..a3de4d3654006 100644 --- a/clang/lib/AST/DeclCXX.cpp +++ b/clang/lib/AST/DeclCXX.cpp @@ -109,9 +109,9 @@ CXXRecordDecl::DefinitionData::DefinitionData(CXXRecordDecl *D) ImplicitCopyAssignmentHasConstParam(true), HasDeclaredCopyConstructorWithConstParam(false), HasDeclaredCopyAssignmentWithConstParam(false), - IsAnyDestructorNoReturn(false), IsLambda(false), - IsParsingBaseSpecifiers(false), ComputedVisibleConversions(false), - HasODRHash(false), Definition(D) {} + IsAnyDestructorNoReturn(false), HasDeletedSpecialMembers(0), + IsLambda(false), IsParsingBaseSpecifiers(false), + ComputedVisibleConversions(false), HasODRHash(false), Definition(D) {} CXXBaseSpecifier *CXXRecordDecl::DefinitionData::getBasesSlowCase() const { return Bases.get(Definition->getASTContext().getExternalSource()); @@ -586,6 +586,14 @@ bool CXXRecordDecl::isTriviallyCopyable() const { if (hasNonTrivialMoveAssignment()) return false; // -- has a trivial destructor. if (!hasTrivialDestructor()) return false; + // C++17 [class]p6: that has at least one non-deleted copy constructor, move + // constructor, copy assignment operator, or move assignment operator, + if (getASTContext().getLangOpts().CPlusPlus17 && + (data().HasDeletedSpecialMembers & + (SMF_CopyAssignment | SMF_CopyConstructor | SMF_MoveAssignment | + SMF_MoveConstructor)) == (SMF_CopyAssignment | SMF_CopyConstructor | + SMF_MoveAssignment | SMF_MoveConstructor)) + return false; return true; } @@ -1446,7 +1454,10 @@ void CXXRecordDecl::addedEligibleSpecialMemberFunction(const CXXMethodDecl *MD, // out whether it's trivial yet (not until we get to the end of the // class). We'll handle this method in // finishedDefaultedOrDeletedMember. - } else if (MD->isTrivial()) { + return; + } + + if (MD->isTrivial()) { data().HasTrivialSpecialMembers |= SMKind; data().HasTrivialSpecialMembersForCall |= SMKind; } else if (MD->isTrivialForCall()) { @@ -1462,6 +1473,10 @@ void CXXRecordDecl::addedEligibleSpecialMemberFunction(const CXXMethodDecl *MD, if (!MD->isUserProvided()) data().DeclaredNonTrivialSpecialMembersForCall |= SMKind; } + + if (MD->isDeleted()) { + data().HasDeletedSpecialMembers |= SMKind; + } } void CXXRecordDecl::finishedDefaultedOrDeletedMember(CXXMethodDecl *D) { @@ -1499,6 +1514,8 @@ void CXXRecordDecl::finishedDefaultedOrDeletedMember(CXXMethodDecl *D) { data().HasTrivialSpecialMembers |= SMKind; else data().DeclaredNonTrivialSpecialMembers |= SMKind; + if (D->isDeleted()) + data().HasDeletedSpecialMembers |= SMKind; } } diff --git a/clang/test/SemaCXX/type-traits.cpp b/clang/test/SemaCXX/type-traits.cpp index d40605f56f1ed..27b0d204d5690 100644 --- a/clang/test/SemaCXX/type-traits.cpp +++ b/clang/test/SemaCXX/type-traits.cpp @@ -1377,7 +1377,11 @@ void is_trivial2() static_assert(__is_trivial(UnionAr)); static_assert(__is_trivial(TrivialStruct)); static_assert(__is_trivial(AllDefaulted)); +#if __cplusplus >= 201703L + static_assert(!__is_trivial(AllDeleted)); +#else static_assert(__is_trivial(AllDeleted)); +#endif static_assert(!__is_trivial(void)); static_assert(!__is_trivial(NonTrivialStruct)); @@ -1419,7 +1423,11 @@ void is_trivially_copyable2() static_assert(__is_trivially_copyable(TrivialStruct)); static_assert(__is_trivially_copyable(NonTrivialStruct)); static_assert(__is_trivially_copyable(AllDefaulted)); +#if __cplusplus >= 201703L + static_assert(!__is_trivially_copyable(AllDeleted)); +#else static_assert(__is_trivially_copyable(AllDeleted)); +#endif static_assert(!__is_trivially_copyable(void)); static_assert(!__is_trivially_copyable(SuperNonTrivialStruct)); `````````` </details> https://github.com/llvm/llvm-project/pull/94831 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits