Skip to content

Commit d56ce31

Browse files
authored
[Clang] Non-polymorphic trivially relocatable types can have [[trivial_abi]] (#143111)
Use the definition of trivially relocatable types to short-circuit some checks for trivial_abi. Note that this is mostly a no-op as there is a lot of overlap between trivial_abi and trivial relocatability (ie, I can't envision a scenario in which there would be a trivially relocatable type that would not be eligible for trivial_abi based on its special member function... which is good!) Note that for bases and members, we need to check CanPassInRegister rather than just relocation. So we do these checks first, which leads to better diagnostics.
1 parent 591678b commit d56ce31

File tree

5 files changed

+47
-36
lines changed

5 files changed

+47
-36
lines changed

clang/include/clang/Sema/Sema.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8680,6 +8680,7 @@ class Sema final : public SemaBase {
86808680
// FIXME: This is in Sema because it requires
86818681
// overload resolution, can we move to ASTContext?
86828682
bool IsCXXTriviallyRelocatableType(QualType T);
8683+
bool IsCXXTriviallyRelocatableType(const CXXRecordDecl &RD);
86838684

86848685
//// Determines if a type is replaceable
86858686
/// according to the C++26 rules.

clang/lib/Sema/SemaDeclCXX.cpp

Lines changed: 26 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -10571,29 +10571,6 @@ void Sema::checkIllFormedTrivialABIStruct(CXXRecordDecl &RD) {
1057110571
RD.dropAttr<TrivialABIAttr>();
1057210572
};
1057310573

10574-
// Ill-formed if the copy and move constructors are deleted.
10575-
auto HasNonDeletedCopyOrMoveConstructor = [&]() {
10576-
// If the type is dependent, then assume it might have
10577-
// implicit copy or move ctor because we won't know yet at this point.
10578-
if (RD.isDependentType())
10579-
return true;
10580-
if (RD.needsImplicitCopyConstructor() &&
10581-
!RD.defaultedCopyConstructorIsDeleted())
10582-
return true;
10583-
if (RD.needsImplicitMoveConstructor() &&
10584-
!RD.defaultedMoveConstructorIsDeleted())
10585-
return true;
10586-
for (const CXXConstructorDecl *CD : RD.ctors())
10587-
if (CD->isCopyOrMoveConstructor() && !CD->isDeleted())
10588-
return true;
10589-
return false;
10590-
};
10591-
10592-
if (!HasNonDeletedCopyOrMoveConstructor()) {
10593-
PrintDiagAndRemoveAttr(0);
10594-
return;
10595-
}
10596-
1059710574
// Ill-formed if the struct has virtual functions.
1059810575
if (RD.isPolymorphic()) {
1059910576
PrintDiagAndRemoveAttr(1);
@@ -10637,6 +10614,32 @@ void Sema::checkIllFormedTrivialABIStruct(CXXRecordDecl &RD) {
1063710614
return;
1063810615
}
1063910616
}
10617+
10618+
if (IsCXXTriviallyRelocatableType(RD))
10619+
return;
10620+
10621+
// Ill-formed if the copy and move constructors are deleted.
10622+
auto HasNonDeletedCopyOrMoveConstructor = [&]() {
10623+
// If the type is dependent, then assume it might have
10624+
// implicit copy or move ctor because we won't know yet at this point.
10625+
if (RD.isDependentType())
10626+
return true;
10627+
if (RD.needsImplicitCopyConstructor() &&
10628+
!RD.defaultedCopyConstructorIsDeleted())
10629+
return true;
10630+
if (RD.needsImplicitMoveConstructor() &&
10631+
!RD.defaultedMoveConstructorIsDeleted())
10632+
return true;
10633+
for (const CXXConstructorDecl *CD : RD.ctors())
10634+
if (CD->isCopyOrMoveConstructor() && !CD->isDeleted())
10635+
return true;
10636+
return false;
10637+
};
10638+
10639+
if (!HasNonDeletedCopyOrMoveConstructor()) {
10640+
PrintDiagAndRemoveAttr(0);
10641+
return;
10642+
}
1064010643
}
1064110644

1064210645
void Sema::checkIncorrectVTablePointerAuthenticationAttribute(

clang/lib/Sema/SemaTypeTraits.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -300,13 +300,13 @@ Sema::CheckCXX2CRelocatableAndReplaceable(const CXXRecordDecl *D) {
300300
return Info;
301301
}
302302

303-
static bool IsCXXTriviallyRelocatableType(Sema &S, const CXXRecordDecl *RD) {
303+
bool Sema::IsCXXTriviallyRelocatableType(const CXXRecordDecl &RD) {
304304
if (std::optional<ASTContext::CXXRecordDeclRelocationInfo> Info =
305-
S.getASTContext().getRelocationInfoForCXXRecord(RD))
305+
getASTContext().getRelocationInfoForCXXRecord(&RD))
306306
return Info->IsRelocatable;
307307
ASTContext::CXXRecordDeclRelocationInfo Info =
308-
S.CheckCXX2CRelocatableAndReplaceable(RD);
309-
S.getASTContext().setRelocationInfoForCXXRecord(RD, Info);
308+
CheckCXX2CRelocatableAndReplaceable(&RD);
309+
getASTContext().setRelocationInfoForCXXRecord(&RD, Info);
310310
return Info.IsRelocatable;
311311
}
312312

@@ -330,7 +330,7 @@ bool Sema::IsCXXTriviallyRelocatableType(QualType Type) {
330330
return true;
331331

332332
if (const auto *RD = BaseElementType->getAsCXXRecordDecl())
333-
return ::IsCXXTriviallyRelocatableType(*this, RD);
333+
return IsCXXTriviallyRelocatableType(*RD);
334334

335335
return false;
336336
}
@@ -672,7 +672,7 @@ static bool IsTriviallyRelocatableType(Sema &SemaRef, QualType T) {
672672
return false;
673673

674674
if (const auto *RD = BaseElementType->getAsCXXRecordDecl();
675-
RD && !RD->isPolymorphic() && IsCXXTriviallyRelocatableType(SemaRef, RD))
675+
RD && !RD->isPolymorphic() && SemaRef.IsCXXTriviallyRelocatableType(*RD))
676676
return true;
677677

678678
if (const auto *RD = BaseElementType->getAsRecordDecl())

clang/test/SemaCXX/attr-trivial-abi.cpp

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11
2-
// RUN: %clang_cc1 -fsyntax-only -verify %s -triple x86_64-windows-msvc -std=c++11
3-
// RUN: %clang_cc1 -fsyntax-only -verify %s -triple x86_64-scei-ps4 -std=c++11
1+
// RUN: %clang_cc1 -fsyntax-only -verify=expected,itanium %s -triple x86_64-unknown-linux -std=c++11
2+
// RUN: %clang_cc1 -fsyntax-only -verify=expected,windows %s -triple x86_64-windows-msvc -std=c++11
3+
// RUN: %clang_cc1 -fsyntax-only -verify=expected,scei %s -triple x86_64-scei-ps4 -std=c++11
44

55

66
void __attribute__((trivial_abi)) foo(); // expected-warning {{'trivial_abi' attribute only applies to classes}}
@@ -165,7 +165,10 @@ static_assert(!__builtin_is_cpp_trivially_relocatable(CopyMoveDeleted), "");
165165

166166
#endif
167167

168-
struct __attribute__((trivial_abi)) S18 { // expected-warning {{'trivial_abi' cannot be applied to 'S18'}} expected-note {{copy constructors and move constructors are all deleted}}
168+
struct __attribute__((trivial_abi)) S18 { // expected-warning {{'trivial_abi' cannot be applied to 'S18'}} \
169+
// itanium-note {{'trivial_abi' is disallowed on 'S18' because it has a field of a non-trivial class type}} \
170+
// windows-note {{'trivial_abi' is disallowed on 'S18' because it has a field of a non-trivial class type}} \
171+
// scei-note {{'trivial_abi' is disallowed on 'S18' because its copy constructors and move constructors are all deleted}}
169172
CopyMoveDeleted a;
170173
};
171174
#ifdef __ORBIS__
@@ -195,7 +198,10 @@ struct __attribute__((trivial_abi)) MoveDeleted {
195198
};
196199
static_assert(__is_trivially_relocatable(MoveDeleted), ""); // expected-warning{{deprecated}}
197200
static_assert(!__builtin_is_cpp_trivially_relocatable(MoveDeleted), "");
198-
struct __attribute__((trivial_abi)) S19 { // expected-warning {{'trivial_abi' cannot be applied to 'S19'}} expected-note {{copy constructors and move constructors are all deleted}}
201+
struct __attribute__((trivial_abi)) S19 { // expected-warning {{'trivial_abi' cannot be applied to 'S19'}} \
202+
// itanium-note {{'trivial_abi' is disallowed on 'S19' because its copy constructors and move constructors are all deleted}} \
203+
// windows-note {{'trivial_abi' is disallowed on 'S19' because it has a field of a non-trivial class type}} \
204+
// scei-note {{'trivial_abi' is disallowed on 'S19' because its copy constructors and move constructors are all deleted}}
199205
CopyDeleted a;
200206
MoveDeleted b;
201207
};

clang/test/SemaObjCXX/attr-trivial-abi.mm

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %clang_cc1 -std=c++11 -fobjc-runtime-has-weak -fobjc-weak -fobjc-arc -fsyntax-only -verify %s
1+
// RUN: %clang_cc1 -std=c++11 -fobjc-runtime-has-weak -fobjc-weak -fobjc-arc -triple x86_64-apple-darwin -fsyntax-only -verify %s
22

33
void __attribute__((trivial_abi)) foo(); // expected-warning {{'trivial_abi' attribute only applies to classes}}
44

@@ -108,7 +108,8 @@ struct __attribute__((trivial_abi)) CopyMoveDeleted { // expected-warning {{'tri
108108
CopyMoveDeleted(CopyMoveDeleted &&) = delete;
109109
};
110110

111-
struct __attribute__((trivial_abi)) S18 { // expected-warning {{'trivial_abi' cannot be applied to 'S18'}} expected-note {{copy constructors and move constructors are all deleted}}
111+
struct __attribute__((trivial_abi)) S18 { // expected-warning {{'trivial_abi' cannot be applied to 'S18'}} \
112+
// expected-note {{'trivial_abi' is disallowed on 'S18' because it has a field of a non-trivial class type}}
112113
CopyMoveDeleted a;
113114
};
114115

0 commit comments

Comments
 (0)