Skip to content

Commit 35a98aa

Browse files
committed
Fix enum inspection of a no-payload enum inside another enum
When a no-payload enum is stored inside a multi-payload enum, the outer enum may be using some of the extra high-order bits. So when we examine the inner enum, we should just strip those bits.
1 parent d113ea1 commit 35a98aa

File tree

2 files changed

+63
-0
lines changed

2 files changed

+63
-0
lines changed

stdlib/public/RemoteInspection/TypeLowering.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -450,6 +450,17 @@ class TrivialEnumTypeInfo: public EnumTypeInfo {
450450
}
451451
};
452452

453+
// Old bit hack for setting all the bits lower than
454+
// the highest set bit.
455+
static uint32_t maskForCount(uint32_t t) {
456+
t |= t >> 16;
457+
t |= t >> 8;
458+
t |= t >> 4;
459+
t |= t >> 2;
460+
t |= t >> 1;
461+
return t;
462+
}
463+
453464
// Enum with 2 or more non-payload cases and no payload cases
454465
class NoPayloadEnumTypeInfo: public EnumTypeInfo {
455466
public:
@@ -489,6 +500,9 @@ class NoPayloadEnumTypeInfo: public EnumTypeInfo {
489500
if (!reader.readInteger(address, getSize(), &tag)) {
490501
return false;
491502
}
503+
// Strip bits that might be used by a containing MPE:
504+
uint32_t mask = maskForCount(getNumCases());
505+
tag &= mask;
492506
if (tag < getNumCases()) {
493507
*CaseIndex = tag;
494508
return true;
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-build-swift -lswiftSwiftReflectionTest %s -o %t/reflect_Enum_values4
3+
// RUN: %target-codesign %t/reflect_Enum_values4
4+
5+
// RUN: %target-run %target-swift-reflection-test %t/reflect_Enum_values4 | tee /dev/stderr | %FileCheck %s --check-prefix=CHECK%target-ptrsize --check-prefix=CHECKALL --dump-input=fail %add_num_extra_inhabitants
6+
7+
// REQUIRES: objc_interop
8+
// REQUIRES: executable_test
9+
// UNSUPPORTED: use_os_stdlib
10+
11+
import SwiftReflectionTest
12+
13+
enum NonPayloadEnum {
14+
case one
15+
case two
16+
}
17+
18+
enum SmallMultipayloadEnum {
19+
case empty
20+
case a(NonPayloadEnum)
21+
case b(NonPayloadEnum)
22+
}
23+
24+
reflect(enumValue: SmallMultipayloadEnum.b(.two))
25+
26+
// CHECKALL: Reflecting an enum value.
27+
// CHECKALL-NEXT: Type reference:
28+
// CHECKALL-NEXT: (enum reflect_Enum_values4.SmallMultipayloadEnum)
29+
// CHECKALL-NEXT: Value: .b(.two)
30+
31+
reflect(enumValue: SmallMultipayloadEnum.empty)
32+
33+
// CHECKALL: Reflecting an enum value.
34+
// CHECKALL-NEXT: Type reference:
35+
// CHECKALL-NEXT: (enum reflect_Enum_values4.SmallMultipayloadEnum)
36+
// CHECKALL-NEXT: Value: .empty
37+
38+
reflect(enumValue: SmallMultipayloadEnum.a(.one))
39+
40+
// CHECKALL: Reflecting an enum value.
41+
// CHECKALL-NEXT: Type reference:
42+
// CHECKALL-NEXT: (enum reflect_Enum_values4.SmallMultipayloadEnum)
43+
// CHECKALL-NEXT: Value: .a(.one)
44+
45+
46+
doneReflecting()
47+
48+
// CHECKALL: Done.
49+

0 commit comments

Comments
 (0)