Skip to content

Commit 28b3d8e

Browse files
authored
[Serialization] Preserve whether a raw value is explicit (#26324)
...which allows the AST printer to correctly choose whether to print it, which means it can be printed in a module interface in a non-WMO build, which is necessary for @objc enums to have a correct run-time representation when clients use that interface. rdar://problem/53469608
1 parent 71c4c16 commit 28b3d8e

File tree

5 files changed

+30
-11
lines changed

5 files changed

+30
-11
lines changed

include/swift/Serialization/ModuleFormat.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ const uint16_t SWIFTMODULE_VERSION_MAJOR = 0;
5252
/// describe what change you made. The content of this comment isn't important;
5353
/// it just ensures a conflict if two people change the module format.
5454
/// Don't worry about adhering to the 80-column limit for this line.
55-
const uint16_t SWIFTMODULE_VERSION_MINOR = 503; // remove 'requires stored property inits'
55+
const uint16_t SWIFTMODULE_VERSION_MINOR = 504; // distinguish implicit raw values for enum cases
5656

5757
using DeclIDField = BCFixed<31>;
5858

@@ -1194,6 +1194,7 @@ namespace decls_block {
11941194
BCFixed<1>, // implicit?
11951195
BCFixed<1>, // has payload?
11961196
EnumElementRawValueKindField, // raw value kind
1197+
BCFixed<1>, // implicit raw value?
11971198
BCFixed<1>, // negative raw value?
11981199
IdentifierIDField, // raw value
11991200
BCVBR<5>, // number of parameter name components

lib/Serialization/Deserialization.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3663,15 +3663,16 @@ class swift::DeclDeserializer {
36633663
Expected<Decl *> deserializeEnumElement(ArrayRef<uint64_t> scratch,
36643664
StringRef blobData) {
36653665
DeclContextID contextID;
3666-
bool isImplicit; bool hasPayload; bool isNegative;
3666+
bool isImplicit, hasPayload, isRawValueImplicit, isNegative;
36673667
unsigned rawValueKindID;
36683668
IdentifierID rawValueData;
36693669
unsigned numArgNames;
36703670
ArrayRef<uint64_t> argNameAndDependencyIDs;
36713671

36723672
decls_block::EnumElementLayout::readRecord(scratch, contextID,
36733673
isImplicit, hasPayload,
3674-
rawValueKindID, isNegative,
3674+
rawValueKindID,
3675+
isRawValueImplicit, isNegative,
36753676
rawValueData,
36763677
numArgNames,
36773678
argNameAndDependencyIDs);
@@ -3717,7 +3718,7 @@ class swift::DeclDeserializer {
37173718
case EnumElementRawValueKind::IntegerLiteral: {
37183719
auto literalText = MF.getIdentifierText(rawValueData);
37193720
auto literal = new (ctx) IntegerLiteralExpr(literalText, SourceLoc(),
3720-
/*implicit*/ true);
3721+
isRawValueImplicit);
37213722
if (isNegative)
37223723
literal->setNegative(SourceLoc());
37233724
elem->setRawValueExpr(literal);

lib/Serialization/Serialization.cpp

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3586,24 +3586,26 @@ class Serializer::DeclSerializer : public DeclVisitor<DeclSerializer> {
35863586

35873587
// We only serialize the raw values of @objc enums, because they're part
35883588
// of the ABI. That isn't the case for Swift enums.
3589-
auto RawValueKind = EnumElementRawValueKind::None;
3590-
bool Negative = false;
3589+
auto rawValueKind = EnumElementRawValueKind::None;
3590+
bool isNegative = false, isRawValueImplicit = false;
35913591
StringRef RawValueText;
35923592
if (elem->getParentEnum()->isObjC()) {
35933593
// Currently ObjC enums always have integer raw values.
3594-
RawValueKind = EnumElementRawValueKind::IntegerLiteral;
3594+
rawValueKind = EnumElementRawValueKind::IntegerLiteral;
35953595
auto ILE = cast<IntegerLiteralExpr>(elem->getRawValueExpr());
35963596
RawValueText = ILE->getDigitsText();
3597-
Negative = ILE->isNegative();
3597+
isNegative = ILE->isNegative();
3598+
isRawValueImplicit = ILE->isImplicit();
35983599
}
35993600

36003601
unsigned abbrCode = S.DeclTypeAbbrCodes[EnumElementLayout::Code];
36013602
EnumElementLayout::emitRecord(S.Out, S.ScratchRecord, abbrCode,
36023603
contextID,
36033604
elem->isImplicit(),
36043605
elem->hasAssociatedValues(),
3605-
(unsigned)RawValueKind,
3606-
Negative,
3606+
(unsigned)rawValueKind,
3607+
isRawValueImplicit,
3608+
isNegative,
36073609
S.addUniquedStringRef(RawValueText),
36083610
elem->getFullName().getArgumentNames().size()+1,
36093611
nameComponentsAndDependencies);

test/ParseableInterface/Inputs/enums-layout-helper.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ public enum FutureproofEnum: Int {
66
case b = 10
77
// CHECK-NEXT: case c{{$}}
88
case c = 100
9+
// CHECK-NEXT: case d{{$}}
10+
case d
911
}
1012

1113
// CHECK-LABEL: public enum FrozenEnum : Swift.Int
@@ -16,6 +18,8 @@ public enum FutureproofEnum: Int {
1618
case b = 10
1719
// CHECK-NEXT: case c{{$}}
1820
case c = 100
21+
// CHECK-NEXT: case d{{$}}
22+
case d
1923
}
2024

2125
// CHECK-LABEL: public enum FutureproofObjCEnum : Swift.Int32
@@ -26,6 +30,8 @@ public enum FutureproofEnum: Int {
2630
case b = 10
2731
// CHECK-NEXT: case c = 100{{$}}
2832
case c = 100
33+
// CHECK-NEXT: case d{{$}}
34+
case d
2935
}
3036

3137
// CHECK-LABEL: public enum FrozenObjCEnum : Swift.Int32
@@ -36,6 +42,8 @@ public enum FutureproofEnum: Int {
3642
case b = 10
3743
// CHECK-NEXT: case c = 100{{$}}
3844
case c = 100
45+
// CHECK-NEXT: case d{{$}}
46+
case d
3947
}
4048

4149
// CHECK-LABEL: indirect public enum FutureproofIndirectEnum

test/ParseableInterface/enums-layout.swift

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,15 @@
11
// RUN: %empty-directory(%t)
2-
// RUN: %target-swift-frontend -emit-module-interface-path %t/Lib.swiftinterface -typecheck -enable-library-evolution -enable-objc-interop -disable-objc-attr-requires-foundation-module -swift-version 5 %S/Inputs/enums-layout-helper.swift -module-name Lib
2+
// RUN: %target-build-swift -emit-module-interface-path %t/Lib.swiftinterface -emit-module -o %t/unused.swiftmodule -enable-library-evolution -Xfrontend -enable-objc-interop -Xfrontend -disable-objc-attr-requires-foundation-module -swift-version 5 %S/Inputs/enums-layout-helper.swift -module-name Lib
33
// RUN: %FileCheck %S/Inputs/enums-layout-helper.swift < %t/Lib.swiftinterface
44
// RUN: %target-swift-frontend -enable-objc-interop -O -emit-ir -primary-file %s -I %t -Xllvm -swiftmergefunc-threshold=0 | %FileCheck %s
55

6+
// Try again using a single-frontend build.
7+
// RUN: %empty-directory(%t)
8+
// RUN: %target-build-swift -force-single-frontend-invocation -emit-module-interface-path %t/Lib.swiftinterface -emit-module -o %t/unused.swiftmodule -enable-library-evolution -Xfrontend -enable-objc-interop -Xfrontend -disable-objc-attr-requires-foundation-module -swift-version 5 %S/Inputs/enums-layout-helper.swift -module-name Lib
9+
// RUN: %FileCheck %S/Inputs/enums-layout-helper.swift < %t/Lib.swiftinterface
10+
// RUN: %target-swift-frontend -enable-objc-interop -O -emit-ir -primary-file %s -I %t -Xllvm -swiftmergefunc-threshold=0 | %FileCheck %s
11+
12+
613
import Lib
714

815
// CHECK-LABEL: define{{.+}}testFutureproofEnum

0 commit comments

Comments
 (0)