ahatanak updated this revision to Diff 185157.
ahatanak added a comment.
Add a note diagnostic to inform the user of the reason for not allowing
annotating a class with `trivial_abi`.
Repository:
rC Clang
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D57626/new/
https://reviews.llvm.org/D57626
Files:
include/clang/Basic/AttrDocs.td
include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaDeclCXX.cpp
test/SemaObjCXX/attr-trivial-abi.mm
Index: test/SemaObjCXX/attr-trivial-abi.mm
===================================================================
--- test/SemaObjCXX/attr-trivial-abi.mm
+++ test/SemaObjCXX/attr-trivial-abi.mm
@@ -10,23 +10,23 @@
int a;
};
-struct __attribute__((trivial_abi)) S2 { // expected-warning {{'trivial_abi' cannot be applied to 'S2'}}
+struct __attribute__((trivial_abi)) S2 { // expected-warning {{'trivial_abi' cannot be applied to 'S2'}} expected-note {{have __weak fields under ARC}}
__weak id a;
};
-struct __attribute__((trivial_abi)) S3 { // expected-warning {{'trivial_abi' cannot be applied to 'S3'}}
+struct __attribute__((trivial_abi)) S3 { // expected-warning {{'trivial_abi' cannot be applied to 'S3'}} expected-note {{are polymorphic}}
virtual void m();
};
struct S3_2 {
virtual void m();
-} __attribute__((trivial_abi)); // expected-warning {{'trivial_abi' cannot be applied to 'S3_2'}}
+} __attribute__((trivial_abi)); // expected-warning {{'trivial_abi' cannot be applied to 'S3_2'}} expected-note {{are polymorphic}}
struct S4 {
int a;
};
-struct __attribute__((trivial_abi)) S5 : public virtual S4 { // expected-warning {{'trivial_abi' cannot be applied to 'S5'}}
+struct __attribute__((trivial_abi)) S5 : public virtual S4 { // expected-warning {{'trivial_abi' cannot be applied to 'S5'}} expected-note {{have virtual bases}}
};
struct __attribute__((trivial_abi)) S9 : public S4 {
@@ -36,19 +36,19 @@
__weak id a;
};
-struct __attribute__((trivial_abi)) S12 { // expected-warning {{'trivial_abi' cannot be applied to 'S12'}}
+struct __attribute__((trivial_abi)) S12 { // expected-warning {{'trivial_abi' cannot be applied to 'S12'}} expected-note {{have __weak fields under ARC}}
__weak id a;
};
-struct __attribute__((trivial_abi)) S13 { // expected-warning {{'trivial_abi' cannot be applied to 'S13'}}
+struct __attribute__((trivial_abi)) S13 { // expected-warning {{'trivial_abi' cannot be applied to 'S13'}} expected-note {{have __weak fields under ARC}}
__weak id a[2];
};
-struct __attribute__((trivial_abi)) S7 { // expected-warning {{'trivial_abi' cannot be applied to 'S7'}}
+struct __attribute__((trivial_abi)) S7 { // expected-warning {{'trivial_abi' cannot be applied to 'S7'}} expected-note {{have fields of non-trivial class types}}
S6 a;
};
-struct __attribute__((trivial_abi)) S11 { // expected-warning {{'trivial_abi' cannot be applied to 'S11'}}
+struct __attribute__((trivial_abi)) S11 { // expected-warning {{'trivial_abi' cannot be applied to 'S11'}} expected-note {{have fields of non-trivial class types}}
S6 a[2];
};
@@ -66,7 +66,7 @@
S10<__weak id> p2;
template<>
-struct __attribute__((trivial_abi)) S10<id> { // expected-warning {{'trivial_abi' cannot be applied to 'S10<id>'}}
+struct __attribute__((trivial_abi)) S10<id> { // expected-warning {{'trivial_abi' cannot be applied to 'S10<id>'}} expected-note {{have __weak fields under ARC}}
__weak id a;
};
@@ -90,8 +90,41 @@
S16<int> s16;
template<class T>
-struct __attribute__((trivial_abi)) S17 { // expected-warning {{'trivial_abi' cannot be applied to 'S17'}}
+struct __attribute__((trivial_abi)) S17 { // expected-warning {{'trivial_abi' cannot be applied to 'S17'}} expected-note {{have __weak fields under ARC}}
__weak id a;
};
S17<int> s17;
+
+namespace deletedCopyMoveConstructor {
+ struct __attribute__((trivial_abi)) CopyMoveDeleted { // expected-warning {{'trivial_abi' cannot be applied to 'CopyMoveDeleted'}} expected-note {{"don't have non-deleted copy/move constructors}}
+ CopyMoveDeleted(const CopyMoveDeleted &) = delete;
+ CopyMoveDeleted(CopyMoveDeleted &&) = delete;
+ };
+
+ struct __attribute__((trivial_abi)) S18 { // expected-warning {{'trivial_abi' cannot be applied to 'S18'}} expected-note {{"don't have non-deleted copy/move constructors}}
+ 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'}} expected-note {{"don't have non-deleted copy/move constructors}}
+ 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: lib/Sema/SemaDeclCXX.cpp
===================================================================
--- lib/Sema/SemaDeclCXX.cpp
+++ lib/Sema/SemaDeclCXX.cpp
@@ -7860,27 +7860,53 @@
}
void Sema::checkIllFormedTrivialABIStruct(CXXRecordDecl &RD) {
- auto PrintDiagAndRemoveAttr = [&]() {
+ auto PrintDiagAndRemoveAttr = [&](unsigned N) {
// No diagnostics if this is a template instantiation.
- if (!isTemplateInstantiation(RD.getTemplateSpecializationKind()))
+ if (!isTemplateInstantiation(RD.getTemplateSpecializationKind())) {
Diag(RD.getAttr<TrivialABIAttr>()->getLocation(),
diag::ext_cannot_use_trivial_abi) << &RD;
+ Diag(RD.getAttr<TrivialABIAttr>()->getLocation(),
+ diag::note_cannot_use_trivial_abi_reason) << N;
+ }
RD.dropAttr<TrivialABIAttr>();
};
+ // 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(0);
+ return;
+ }
+
// Ill-formed if the struct has virtual functions.
if (RD.isPolymorphic()) {
- PrintDiagAndRemoveAttr();
+ PrintDiagAndRemoveAttr(1);
return;
}
for (const auto &B : RD.bases()) {
// Ill-formed if the base class is non-trivial for the purpose of calls or a
// virtual base.
- if ((!B.getType()->isDependentType() &&
- !B.getType()->getAsCXXRecordDecl()->canPassInRegisters()) ||
- B.isVirtual()) {
- PrintDiagAndRemoveAttr();
+ if (!B.getType()->isDependentType() &&
+ !B.getType()->getAsCXXRecordDecl()->canPassInRegisters()) {
+ PrintDiagAndRemoveAttr(2);
+ return;
+ }
+
+ if (B.isVirtual()) {
+ PrintDiagAndRemoveAttr(3);
return;
}
}
@@ -7890,14 +7916,14 @@
// non-trivial for the purpose of calls.
QualType FT = FD->getType();
if (FT.getObjCLifetime() == Qualifiers::OCL_Weak) {
- PrintDiagAndRemoveAttr();
+ PrintDiagAndRemoveAttr(4);
return;
}
if (const auto *RT = FT->getBaseElementTypeUnsafe()->getAs<RecordType>())
if (!RT->isDependentType() &&
!cast<CXXRecordDecl>(RT->getDecl())->canPassInRegisters()) {
- PrintDiagAndRemoveAttr();
+ PrintDiagAndRemoveAttr(5);
return;
}
}
Index: include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- include/clang/Basic/DiagnosticSemaKinds.td
+++ include/clang/Basic/DiagnosticSemaKinds.td
@@ -2946,6 +2946,11 @@
def ext_cannot_use_trivial_abi : ExtWarn<
"'trivial_abi' cannot be applied to %0">, InGroup<IgnoredAttributes>;
+def note_cannot_use_trivial_abi_reason : Note<
+ "'trivial_abi' is disallowed on classes that %select{"
+ "don't have non-deleted copy/move constructors|are polymorphic|"
+ "have bases of non-trivial class types|have virtual bases|"
+ "have __weak fields under ARC|have fields of non-trivial class types}0">;
// Availability attribute
def warn_availability_unknown_platform : Warning<
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:
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits