Skip to content

Commit c20ddbb

Browse files
committed
[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 (cherry picked from commit 28b3d8e)
1 parent 3baa54f commit c20ddbb

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 = 499; // remove 'requires stored property inits'
55+
const uint16_t SWIFTMODULE_VERSION_MINOR = 500; // distinguish implicit raw values for enum cases
5656

5757
using DeclIDField = BCFixed<31>;
5858

@@ -1190,6 +1190,7 @@ namespace decls_block {
11901190
BCFixed<1>, // implicit?
11911191
BCFixed<1>, // has payload?
11921192
EnumElementRawValueKindField, // raw value kind
1193+
BCFixed<1>, // implicit raw value?
11931194
BCFixed<1>, // negative raw value?
11941195
IdentifierIDField, // raw value
11951196
BCFixed<1>, // default argument resilience expansion

lib/Serialization/Deserialization.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3668,7 +3668,7 @@ class swift::DeclDeserializer {
36683668
Expected<Decl *> deserializeEnumElement(ArrayRef<uint64_t> scratch,
36693669
StringRef blobData) {
36703670
DeclContextID contextID;
3671-
bool isImplicit; bool hasPayload; bool isNegative;
3671+
bool isImplicit, hasPayload, isRawValueImplicit, isNegative;
36723672
unsigned rawValueKindID;
36733673
IdentifierID rawValueData;
36743674
uint8_t rawResilienceExpansion;
@@ -3677,7 +3677,8 @@ class swift::DeclDeserializer {
36773677

36783678
decls_block::EnumElementLayout::readRecord(scratch, contextID,
36793679
isImplicit, hasPayload,
3680-
rawValueKindID, isNegative,
3680+
rawValueKindID,
3681+
isRawValueImplicit, isNegative,
36813682
rawValueData,
36823683
rawResilienceExpansion,
36833684
numArgNames,
@@ -3724,7 +3725,7 @@ class swift::DeclDeserializer {
37243725
case EnumElementRawValueKind::IntegerLiteral: {
37253726
auto literalText = MF.getIdentifierText(rawValueData);
37263727
auto literal = new (ctx) IntegerLiteralExpr(literalText, SourceLoc(),
3727-
/*implicit*/ true);
3728+
isRawValueImplicit);
37283729
if (isNegative)
37293730
literal->setNegative(SourceLoc());
37303731
elem->setRawValueExpr(literal);

lib/Serialization/Serialization.cpp

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3618,15 +3618,16 @@ void Serializer::writeDecl(const Decl *D) {
36183618

36193619
// We only serialize the raw values of @objc enums, because they're part
36203620
// of the ABI. That isn't the case for Swift enums.
3621-
auto RawValueKind = EnumElementRawValueKind::None;
3622-
bool Negative = false;
3621+
auto rawValueKind = EnumElementRawValueKind::None;
3622+
bool isNegative = false, isRawValueImplicit = false;
36233623
StringRef RawValueText;
36243624
if (elem->getParentEnum()->isObjC()) {
36253625
// Currently ObjC enums always have integer raw values.
3626-
RawValueKind = EnumElementRawValueKind::IntegerLiteral;
3626+
rawValueKind = EnumElementRawValueKind::IntegerLiteral;
36273627
auto ILE = cast<IntegerLiteralExpr>(elem->getRawValueExpr());
36283628
RawValueText = ILE->getDigitsText();
3629-
Negative = ILE->isNegative();
3629+
isNegative = ILE->isNegative();
3630+
isRawValueImplicit = ILE->isImplicit();
36303631
}
36313632

36323633
uint8_t rawResilienceExpansion =
@@ -3637,8 +3638,9 @@ void Serializer::writeDecl(const Decl *D) {
36373638
contextID,
36383639
elem->isImplicit(),
36393640
elem->hasAssociatedValues(),
3640-
(unsigned)RawValueKind,
3641-
Negative,
3641+
(unsigned)rawValueKind,
3642+
isRawValueImplicit,
3643+
isNegative,
36423644
addUniquedStringRef(RawValueText),
36433645
rawResilienceExpansion,
36443646
elem->getFullName().getArgumentNames().size()+1,

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.Int
@@ -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.Int
@@ -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)