Skip to content

Commit e6fe6be

Browse files
authored
[IRGen] Include extra tag bytes in offset in layout strings (swiftlang#66259)
rdar://110088270 When extra tag bytes are used in single payload enums, the generated layout string does not include the tag bytes in its offset after the enum payload. This causes subsequent ref count operations to use the wrong memory location.
1 parent 12b62cb commit e6fe6be

File tree

3 files changed

+53
-0
lines changed

3 files changed

+53
-0
lines changed

lib/IRGen/TypeLayout.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,9 @@ class LayoutStringBuilder {
221221
refCountBytes += (3 * sizeof(uint64_t)) +
222222
(4 * IGM.getPointerSize().getValue()) +
223223
nestedRefCountBytes;
224+
225+
skip += enumData.extraTagByteCount;
226+
224227
break;
225228
}
226229

test/Interpreter/Inputs/layout_string_witnesses_types.swift

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,27 @@ public struct MixedEnumWrapperWrapperGeneric<T> {
350350
}
351351
}
352352

353+
public struct SinglePayloadEnumExtraTagBytesWrapper {
354+
let x: SinglePayloadEnumExtraTagBytes
355+
let y: SimpleClass
356+
357+
public init(x: SinglePayloadEnumExtraTagBytes, y: SimpleClass) {
358+
self.x = x
359+
self.y = y
360+
}
361+
}
362+
363+
public enum SinglePayloadEnumExtraTagBytes {
364+
case empty0
365+
case empty1
366+
case empty2
367+
case empty3
368+
case empty4
369+
case empty5
370+
case empty6
371+
case nonEmpty(WeakNativeWrapper)
372+
}
373+
353374
public struct ComplexNesting<A, B, C, D> {
354375
let pre: Filler = Filler()
355376
let a: NestedA<A>

test/Interpreter/layout_string_witnesses_static.swift

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -513,6 +513,35 @@ func testInternalEnumWrapper() {
513513

514514
testInternalEnumWrapper()
515515

516+
func testSinglePayloadEnumExtraTagBytesWrapper() {
517+
let ptr = UnsafeMutablePointer<SinglePayloadEnumExtraTagBytesWrapper>.allocate(capacity: 1)
518+
519+
do {
520+
let x = SinglePayloadEnumExtraTagBytesWrapper(x: .empty0, y: SimpleClass(x: 23))
521+
testInit(ptr, to: x)
522+
}
523+
524+
do {
525+
let y = SinglePayloadEnumExtraTagBytesWrapper(x: .empty0, y: SimpleClass(x: 28))
526+
527+
// CHECK-NEXT: Before deinit
528+
print("Before deinit")
529+
530+
// CHECK-NEXT: SimpleClass deinitialized!
531+
testAssign(ptr, from: y)
532+
}
533+
534+
// CHECK-NEXT: Before deinit
535+
print("Before deinit")
536+
537+
// CHECK-NEXT: SimpleClass deinitialized!
538+
testDestroy(ptr)
539+
540+
ptr.deallocate()
541+
}
542+
543+
testSinglePayloadEnumExtraTagBytesWrapper()
544+
516545
#if os(macOS)
517546
func testObjc() {
518547
let ptr = UnsafeMutablePointer<ObjcWrapper>.allocate(capacity: 1)

0 commit comments

Comments
 (0)