Files
swift-mirror/test/Interop/Cxx/class/zero-sized-field.swift
Egor Zhdan ee5f7ad262 [cxx-interop] Do not crash when emitting layout of std::string
If a `[[no_unique_address]]` field has zero size according to Clang, and field has a type that isn't representable in Swift, Swift would previously try to add an opaque field of size 1 for it.

This is wrong and was causing crashes for `std::string` while emitting a padding field:
```
_LIBCPP_NO_UNIQUE_ADDRESS ::std::__compressed_pair_padding<T1> _LIBCPP_CONCAT3(__padding1_, __LINE__, _);
```

rdar://151941799
(cherry picked from commit a7c174431f)
2025-05-30 17:33:31 +01:00

97 lines
2.5 KiB
Swift

// RUN: %empty-directory(%t/index)
// RUN: %target-run-simple-swift(-I %S/Inputs/ -Xfrontend -enable-experimental-cxx-interop -Xcc -std=c++20 -Xfrontend -index-store-path -Xfrontend %t/index)
//
// REQUIRES: executable_test
import StdlibUnittest
import MemberVariables
var FieldsTestSuite = TestSuite("Generating code with zero sized fields")
func takeTypeWithZeroSizedMember(_ x: HasZeroSizedField) {}
FieldsTestSuite.test("Zero sized field") {
var s = HasZeroSizedField()
s.a = 5
s.set_c(7)
takeTypeWithZeroSizedMember(s)
let s2 = s
let _ : Empty.type = 6
expectEqual(s.a, 5)
expectEqual(s.a, s.get_a())
expectEqual(s2.c, 7)
expectEqual(s2.c, s2.get_c())
expectEqual(takesZeroSizedInCpp(s2), 5)
expectEqual(s.b.getNum(), 42)
}
FieldsTestSuite.test("Optional field padding reused") {
var s = ReuseOptionalFieldPadding()
let opt = s.getOptional()
expectEqual(Int(opt.pointee), 2)
s.c = 5
expectEqual(Int(s.offset()), MemoryLayout<ReuseOptionalFieldPadding>.offset(of: \.c)!)
expectEqual(s.c, 5)
expectEqual(s.get_c(), 5)
s.set_c(6)
expectEqual(s.c, 6)
expectEqual(s.get_c(), 6)
let s2 = s
expectEqual(s2.c, 6)
expectEqual(s2.get_c(), 6)
}
FieldsTestSuite.test("Typedef'd optional field padding reused") {
var s = ReuseOptionalFieldPaddingWithTypedef()
s.c = 5
expectEqual(Int(s.offset()), MemoryLayout<ReuseOptionalFieldPadding>.offset(of: \.c)!)
expectEqual(s.c, 5)
expectEqual(s.get_c(), 5)
s.set_c(6)
expectEqual(s.c, 6)
expectEqual(s.get_c(), 6)
let s2 = s
expectEqual(s2.c, 6)
expectEqual(s2.get_c(), 6)
}
FieldsTestSuite.test("Non-standard-layout field padding reused") {
var s = ReuseNonStandardLayoutFieldPadding()
s.c = 5
expectEqual(Int(s.offset()), MemoryLayout<ReuseNonStandardLayoutFieldPadding>.offset(of: \.c)!)
expectEqual(s.c, 5)
expectEqual(s.get_c(), 5)
s.set_c(6)
expectEqual(s.c, 6)
expectEqual(s.get_c(), 6)
let s2 = s
expectEqual(s2.c, 6)
expectEqual(s2.get_c(), 6)
}
FieldsTestSuite.test("Non-standard-layout field padding in templated class reused") {
var s = ReuseDependentFieldPaddingInt()
s.c = 5
expectEqual(Int(s.offset()), MemoryLayout<ReuseDependentFieldPaddingInt>.offset(of: \.c)!)
expectEqual(s.c, 5)
expectEqual(s.get_c(), 5)
s.set_c(6)
expectEqual(s.c, 6)
expectEqual(s.get_c(), 6)
let s2 = s
expectEqual(s2.c, 6)
expectEqual(s2.get_c(), 6)
}
FieldsTestSuite.test("Last field is no unique address") {
var s = LastFieldNoUniqueAddress()
s.c = 5
expectEqual(s.c, 5)
s.c = 6
expectEqual(s.c, 6)
}
runAllTests()