Index: include/clang/Basic/AttrDocs.td =================================================================== --- include/clang/Basic/AttrDocs.td +++ include/clang/Basic/AttrDocs.td @@ -2566,6 +2566,7 @@ Attribute ``trivial_abi`` has no effect in the following cases: - The class directly declares a virtual base or virtual methods. +- The class doesn't have a copy or move constructor that isn't 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: Index: lib/Sema/SemaDeclCXX.cpp =================================================================== --- lib/Sema/SemaDeclCXX.cpp +++ lib/Sema/SemaDeclCXX.cpp @@ -7868,6 +7868,25 @@ RD.dropAttr(); }; + // Ill-formed if the copy and move constructors are deleted. + auto HasNonDeletedCopyOrMoveConstructor = [&]() { + 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(); + return; + } + // Ill-formed if the struct has virtual functions. if (RD.isPolymorphic()) { PrintDiagAndRemoveAttr(); Index: test/SemaObjCXX/attr-trivial-abi.mm =================================================================== --- test/SemaObjCXX/attr-trivial-abi.mm +++ test/SemaObjCXX/attr-trivial-abi.mm @@ -95,3 +95,36 @@ }; S17 s17; + +namespace deletedCopyMoveConstructor { + struct __attribute__((trivial_abi)) CopyMoveDeleted { // expected-warning {{'trivial_abi' cannot be applied to 'CopyMoveDeleted'}} + CopyMoveDeleted(const CopyMoveDeleted &) = delete; + CopyMoveDeleted(CopyMoveDeleted &&) = delete; + }; + + struct __attribute__((trivial_abi)) S18 { // expected-warning {{'trivial_abi' cannot be applied to 'S18'}} + CopyMoveDeleted a; + S18(const S18 &); + S18(S18 &&); + }; + + 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'}} + 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. + }; +}