zoecarver updated this revision to Diff 308526.
zoecarver added a comment.
- Update wording in AttrDocs
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D92361/new/
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,10 @@
// 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 }
+// CHECK: [[STRUCT_HAS_MEMBER_COPY_MOVE_DELETED:%.*]] = type { [[STRUCT_COPY_MOVE_DELETED]] }
struct __attribute__((trivial_abi)) Small {
int *p;
@@ -55,6 +59,45 @@
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() {}
+};
+
+struct __attribute__((trivial_abi)) HasMemberCopyMoveDeleted {
+ CopyMoveDeleted member;
+};
+
+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)) HasMembersCopyDeletedAndMoveDeleted {
+ CopyDeleted m1;
+ MoveDeleted m2;
+};
+
// CHECK-LABEL: define i64 @_ZThn8_N2D02m0Ev(
// CHECK: %[[RETVAL:.*]] = alloca %[[STRUCT_SMALL]], align 8
// CHECK: %[[CALL:.*]] = tail call i64 @_ZN2D02m0Ev(
@@ -262,3 +305,31 @@
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;
+}
+
+// CHECK: define void @_Z28testHasMemberCopyMoveDeleted24HasMemberCopyMoveDeleted(i64 %{{.*}})
+// CHECK: call [[STRUCT_HAS_MEMBER_COPY_MOVE_DELETED]]* @_ZN24HasMemberCopyMoveDeletedD1Ev([[STRUCT_HAS_MEMBER_COPY_MOVE_DELETED]]*
+// CHECK: ret void
+void testHasMemberCopyMoveDeleted(HasMemberCopyMoveDeleted) { }
+
+// CHECK: define void @_Z39testHasMembersCopyDeletedAndMoveDeleted35HasMembersCopyDeletedAndMoveDeleted(i64 %{{.*}})
+// CHECK: ret void
+void testHasMembersCopyDeletedAndMoveDeleted(HasMembersCopyDeletedAndMoveDeleted) { }
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 (or completely
+deleted) copy/move constructors or a non-trivial destructor 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
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits