Skip to content

Commit 863f987

Browse files
committed
[interop] C++ record should use AddressOnly type layout only when it's non-trivial for purpose of calls
A record that's non trivia for purpose of calls, as defined in Itanium ABI is allowed to have non-trivial copy/move assignment operators, but it most not have non-trivial constructors or destructors. This change ensures that a C++ record with a non-trivial copy assignment operator but trivial other members can be passed/returned directly by value, so that the compiler can accept the returned value correctly when calling a C++ function.
1 parent de56acc commit 863f987

File tree

3 files changed

+16
-4
lines changed

3 files changed

+16
-4
lines changed

include/swift/AST/Decl.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4294,6 +4294,12 @@ class StructDecl final : public NominalTypeDecl {
42944294
Bits.StructDecl.HasUnreferenceableStorage = v;
42954295
}
42964296

4297+
/// Does this struct represent a non-trivial (for the purpose of calls, as
4298+
/// defined by Itanium ABI) C++ record. A C++ record is considered non-trivial
4299+
/// for the purpose of calls if either its constructor, copy-constructor, or
4300+
/// destructor is non-trivial. As such, a C++ record with a non-trivial
4301+
/// copy-assignment operator but other trivial members is considered to be
4302+
/// trivial.
42974303
bool isCxxNonTrivial() const { return Bits.StructDecl.IsCxxNonTrivial; }
42984304

42994305
void setIsCxxNonTrivial(bool v) { Bits.StructDecl.IsCxxNonTrivial = v; }

lib/ClangImporter/ImportDecl.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2394,9 +2394,15 @@ namespace {
23942394
}
23952395

23962396
if (cxxRecordDecl) {
2397+
auto isNonTrivialForPurposeOfCalls =
2398+
[](const clang::CXXRecordDecl *decl) -> bool {
2399+
return decl->hasNonTrivialCopyConstructor() ||
2400+
decl->hasNonTrivialMoveConstructor() ||
2401+
!decl->hasTrivialDestructor();
2402+
};
23972403
if (auto structResult = dyn_cast<StructDecl>(result))
23982404
structResult->setIsCxxNonTrivial(
2399-
!cxxRecordDecl->isTriviallyCopyable());
2405+
isNonTrivialForPurposeOfCalls(cxxRecordDecl));
24002406

24012407
for (auto &getterAndSetter : Impl.GetterSetterMap) {
24022408
auto getter = getterAndSetter.second.first;

test/Interop/Cxx/class/type-classification-loadable-silgen.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,17 +54,17 @@ func pass(s: StructWithSubobjectDefaultedCopyConstructor) {
5454

5555
// CHECK-LABEL: sil hidden [ossa] @$s4main4pass{{.*[ (]}}StructWithCopyAssignment)
5656
func pass(s: StructWithCopyAssignment) {
57-
// CHECK: bb0(%0 : $*StructWithCopyAssignment):
57+
// CHECK: bb0(%0 : $StructWithCopyAssignment):
5858
}
5959

6060
// CHECK-LABEL: sil hidden [ossa] @$s4main4pass{{.*[ (]}}StructWithInheritedCopyAssignment)
6161
func pass(s: StructWithInheritedCopyAssignment) {
62-
// CHECK: bb0(%0 : $*StructWithInheritedCopyAssignment):
62+
// CHECK: bb0(%0 : $StructWithInheritedCopyAssignment):
6363
}
6464

6565
// CHECK-LABEL: sil hidden [ossa] @$s4main4pass{{.*[ (]}}StructWithSubobjectCopyAssignment)
6666
func pass(s: StructWithSubobjectCopyAssignment) {
67-
// CHECK: bb0(%0 : $*StructWithSubobjectCopyAssignment):
67+
// CHECK: bb0(%0 : $StructWithSubobjectCopyAssignment):
6868
}
6969

7070
// CHECK-LABEL: sil hidden [ossa] @$s4main4pass{{.*[ (]}}StructWithDestructor)

0 commit comments

Comments
 (0)