Skip to content

Commit 63c24af

Browse files
authored
Merge pull request swiftlang#80344 from swiftlang/egorzhdan/frt-tail-padding
[cxx-interop] Layout reference types that use tail padding of their bases correctly
2 parents dec124e + ba8ba57 commit 63c24af

File tree

4 files changed

+43
-8
lines changed

4 files changed

+43
-8
lines changed

lib/IRGen/GenClangDecl.cpp

+6-2
Original file line numberDiff line numberDiff line change
@@ -390,8 +390,12 @@ irgen::getBasesAndOffsets(const clang::CXXRecordDecl *decl) {
390390
continue;
391391

392392
auto offset = Size(layout.getBaseClassOffset(baseRecord).getQuantity());
393-
auto size =
394-
Size(decl->getASTContext().getTypeSizeInChars(baseType).getQuantity());
393+
// A base type might have different size and data size (sizeof != dsize).
394+
// Make sure we are using data size here, since fields of the derived type
395+
// might be packed into the base's tail padding.
396+
auto size = Size(decl->getASTContext()
397+
.getTypeInfoDataSizeInChars(baseType)
398+
.Width.getQuantity());
395399

396400
baseOffsetsAndSizes.push_back({baseRecord, offset, size});
397401
}

test/Interop/Cxx/foreign-reference/Inputs/inheritance.h

+21
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,27 @@ DerivedOutOfOrder : public BaseT, public DerivedWithVirtualDestructor {
7171
}
7272
};
7373

74+
struct
75+
__attribute__((swift_attr("import_reference")))
76+
__attribute__((swift_attr("retain:immortal")))
77+
__attribute__((swift_attr("release:immortal")))
78+
BaseAlign8 {
79+
long long field8 = 123;
80+
}; // sizeof=8, dsize=8, align=8
81+
82+
struct DerivedHasTailPadding : public BaseAlign8 {
83+
int field4 = 456;
84+
}; // sizeof=16, dsize=12, align=8
85+
86+
struct DerivedUsesBaseTailPadding : public DerivedHasTailPadding {
87+
short field2 = 789;
88+
89+
static DerivedUsesBaseTailPadding& getInstance() {
90+
static DerivedUsesBaseTailPadding singleton;
91+
return singleton;
92+
}
93+
}; // sizeof=16, dsize=14, align=8
94+
7495
SWIFT_BEGIN_NULLABILITY_ANNOTATIONS
7596

7697
namespace ImmortalRefereceExample {

test/Interop/Cxx/foreign-reference/inheritance-irgen.swift

+5
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,11 @@ blackHole(x.baseField)
1313
blackHole(x.derivedField)
1414
blackHole(x.leafField)
1515

16+
let y = DerivedUsesBaseTailPadding.getInstance()
17+
18+
blackHole(y.field2)
19+
blackHole(y.field4)
20+
1621
// CHECK: call ptr @{{.*}}returnValueType{{.*}}
1722
// CHECK-NOT: call void @{{.*}}RCRetain@{{.*}}ValueType(ptr @{{.*}})
1823
var x1 = BasicInheritanceExample.returnValueType()

test/Interop/Cxx/foreign-reference/inheritance.swift

+11-6
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@ func cast(_ s: SubT) -> BaseT {
1515
return cxxCast(s)
1616
}
1717

18-
var TemplatingTestSuite = TestSuite("Foreign references work with templates")
18+
var InheritanceTestSuite = TestSuite("Inheritance of foreign reference types")
1919

20-
TemplatingTestSuite.test("SubT") {
20+
InheritanceTestSuite.test("Templated cast to base") {
2121
let s: SubT = SubT.getSubT()
2222
expectFalse(s.isBase)
2323
let sc: BaseT = cast(s)
@@ -26,23 +26,28 @@ TemplatingTestSuite.test("SubT") {
2626
expectFalse(sc.isBase)
2727
}
2828

29-
TemplatingTestSuite.test("BaseT") {
29+
InheritanceTestSuite.test("Templated cast to itself") {
3030
let b: BaseT = BaseT.getBaseT()
3131
expectTrue(b.isBase)
3232
let bc: BaseT = cxxCast(b) // should instantiate I and O both to BaseT
3333
expectTrue(bc.isBase)
3434
}
3535

36-
TemplatingTestSuite.test("DerivedOutOfOrder") {
36+
InheritanceTestSuite.test("DerivedOutOfOrder") {
3737
let d = DerivedOutOfOrder.getInstance()
3838
expectEqual(123, d.baseField)
3939
expectEqual(456, d.derivedField)
4040
expectEqual(789, d.leafField)
4141
}
4242

43-
var FrtInheritanceTestSuite = TestSuite("Foreign references in C++ inheritance")
43+
InheritanceTestSuite.test("DerivedUsesBaseTailPadding") {
44+
let d = DerivedUsesBaseTailPadding.getInstance()
45+
expectEqual(123, d.field8)
46+
expectEqual(456, d.field4)
47+
expectEqual(789, d.field2)
48+
}
4449

45-
FrtInheritanceTestSuite.test("ParentChild") {
50+
InheritanceTestSuite.test("ParentChild") {
4651
let immortalRefType = ImmortalRefereceExample.returnImmortalRefType()
4752
expectTrue(
4853
type(of: immortalRefType) is AnyObject.Type,

0 commit comments

Comments
 (0)