Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions lib/IRGen/GenClangDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -390,8 +390,12 @@ irgen::getBasesAndOffsets(const clang::CXXRecordDecl *decl) {
continue;

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

baseOffsetsAndSizes.push_back({baseRecord, offset, size});
}
Expand Down
21 changes: 21 additions & 0 deletions test/Interop/Cxx/foreign-reference/Inputs/inheritance.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,27 @@ DerivedOutOfOrder : public BaseT, public DerivedWithVirtualDestructor {
}
};

struct
__attribute__((swift_attr("import_reference")))
__attribute__((swift_attr("retain:immortal")))
__attribute__((swift_attr("release:immortal")))
BaseAlign8 {
long long field8 = 123;
}; // sizeof=8, dsize=8, align=8

struct DerivedHasTailPadding : public BaseAlign8 {
int field4 = 456;
}; // sizeof=16, dsize=12, align=8

struct DerivedUsesBaseTailPadding : public DerivedHasTailPadding {
short field2 = 789;

static DerivedUsesBaseTailPadding& getInstance() {
static DerivedUsesBaseTailPadding singleton;
return singleton;
}
}; // sizeof=16, dsize=14, align=8

SWIFT_BEGIN_NULLABILITY_ANNOTATIONS

namespace ImmortalRefereceExample {
Expand Down
5 changes: 5 additions & 0 deletions test/Interop/Cxx/foreign-reference/inheritance-irgen.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ blackHole(x.baseField)
blackHole(x.derivedField)
blackHole(x.leafField)

let y = DerivedUsesBaseTailPadding.getInstance()

blackHole(y.field2)
blackHole(y.field4)

// CHECK: call ptr @{{.*}}returnValueType{{.*}}
// CHECK-NOT: call void @{{.*}}RCRetain@{{.*}}ValueType(ptr @{{.*}})
var x1 = BasicInheritanceExample.returnValueType()
Expand Down
17 changes: 11 additions & 6 deletions test/Interop/Cxx/foreign-reference/inheritance.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ func cast(_ s: SubT) -> BaseT {
return cxxCast(s)
}

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

TemplatingTestSuite.test("SubT") {
InheritanceTestSuite.test("Templated cast to base") {
let s: SubT = SubT.getSubT()
expectFalse(s.isBase)
let sc: BaseT = cast(s)
Expand All @@ -26,23 +26,28 @@ TemplatingTestSuite.test("SubT") {
expectFalse(sc.isBase)
}

TemplatingTestSuite.test("BaseT") {
InheritanceTestSuite.test("Templated cast to itself") {
let b: BaseT = BaseT.getBaseT()
expectTrue(b.isBase)
let bc: BaseT = cxxCast(b) // should instantiate I and O both to BaseT
expectTrue(bc.isBase)
}

TemplatingTestSuite.test("DerivedOutOfOrder") {
InheritanceTestSuite.test("DerivedOutOfOrder") {
let d = DerivedOutOfOrder.getInstance()
expectEqual(123, d.baseField)
expectEqual(456, d.derivedField)
expectEqual(789, d.leafField)
}

var FrtInheritanceTestSuite = TestSuite("Foreign references in C++ inheritance")
InheritanceTestSuite.test("DerivedUsesBaseTailPadding") {
let d = DerivedUsesBaseTailPadding.getInstance()
expectEqual(123, d.field8)
expectEqual(456, d.field4)
expectEqual(789, d.field2)
}

FrtInheritanceTestSuite.test("ParentChild") {
InheritanceTestSuite.test("ParentChild") {
let immortalRefType = ImmortalRefereceExample.returnImmortalRefType()
expectTrue(
type(of: immortalRefType) is AnyObject.Type,
Expand Down