Skip to content

Commit f7e2d14

Browse files
committed
[Serialization] Drop overridden relationship in constructors when safe
Deserialization recovery lead the compiler to drop public constructors overridding internal constructors. This limits the logic to dropping the overriding relationship instead of the whole constructor. This applies when the overriden constructor fails to deserialize and only when the overriding relationship was marked as not affecting ABI. rdar://104704832
1 parent 35553d9 commit f7e2d14

File tree

4 files changed

+36
-12
lines changed

4 files changed

+36
-12
lines changed

lib/Serialization/Deserialization.cpp

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3094,7 +3094,7 @@ class DeclDeserializer {
30943094
GenericSignatureID genericSigID;
30953095
uint8_t storedInitKind, rawAccessLevel;
30963096
DeclID overriddenID;
3097-
bool needsNewVTableEntry, firstTimeRequired;
3097+
bool overriddenAffectsABI, needsNewVTableEntry, firstTimeRequired;
30983098
unsigned numArgNames;
30993099
ArrayRef<uint64_t> argNameAndDependencyIDs;
31003100

@@ -3104,6 +3104,7 @@ class DeclDeserializer {
31043104
async, throws, storedInitKind,
31053105
genericSigID,
31063106
overriddenID,
3107+
overriddenAffectsABI,
31073108
rawAccessLevel,
31083109
needsNewVTableEntry,
31093110
firstTimeRequired,
@@ -3130,15 +3131,23 @@ class DeclDeserializer {
31303131
attrs.setRawAttributeChain(DAttrs);
31313132
}
31323133

3133-
auto overridden = MF.getDeclChecked(overriddenID);
3134-
if (!overridden) {
3134+
Expected<Decl *> overriddenOrError = MF.getDeclChecked(overriddenID);
3135+
Decl *overridden;
3136+
if (overriddenOrError) {
3137+
overridden = overriddenOrError.get();
3138+
} else {
3139+
if (overriddenAffectsABI || !ctx.LangOpts.EnableDeserializationRecovery) {
3140+
llvm::consumeError(overriddenOrError.takeError());
3141+
return llvm::make_error<OverrideError>(name, errorFlags,
3142+
numVTableEntries);
3143+
}
3144+
31353145
// Pass through deserialization errors.
3136-
if (overridden.errorIsA<FatalDeserializationError>())
3137-
return overridden.takeError();
3146+
if (overriddenOrError.errorIsA<FatalDeserializationError>())
3147+
return overriddenOrError.takeError();
31383148

3139-
llvm::consumeError(overridden.takeError());
3140-
return llvm::make_error<OverrideError>(
3141-
name, errorFlags, numVTableEntries);
3149+
llvm::consumeError(overriddenOrError.takeError());
3150+
overridden = nullptr;
31423151
}
31433152

31443153
for (auto dependencyID : argNameAndDependencyIDs.slice(numArgNames)) {
@@ -3198,7 +3207,7 @@ class DeclDeserializer {
31983207
ctx.evaluator.cacheOutput(NeedsNewVTableEntryRequest{ctor},
31993208
std::move(needsNewVTableEntry));
32003209

3201-
ctor->setOverriddenDecl(cast_or_null<ConstructorDecl>(overridden.get()));
3210+
ctor->setOverriddenDecl(cast_or_null<ConstructorDecl>(overridden));
32023211
if (auto *overridden = ctor->getOverriddenDecl()) {
32033212
if (!attributeChainContains<RequiredAttr>(DAttrs) ||
32043213
!overridden->isRequired()) {

lib/Serialization/ModuleFormat.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ const uint16_t SWIFTMODULE_VERSION_MAJOR = 0;
5858
/// describe what change you made. The content of this comment isn't important;
5959
/// it just ensures a conflict if two people change the module format.
6060
/// Don't worry about adhering to the 80-column limit for this line.
61-
const uint16_t SWIFTMODULE_VERSION_MINOR = 739; // CxxStdlib
61+
const uint16_t SWIFTMODULE_VERSION_MINOR = 741; // Constructor affects ABI
6262

6363
/// A standard hash seed used for all string hashes in a serialized module.
6464
///
@@ -1439,6 +1439,7 @@ namespace decls_block {
14391439
CtorInitializerKindField, // initializer kind
14401440
GenericSignatureIDField, // generic environment
14411441
DeclIDField, // overridden decl
1442+
BCFixed<1>, // whether the overridden decl affects ABI
14421443
AccessLevelField, // access level
14431444
BCFixed<1>, // requires a new vtable slot
14441445
BCFixed<1>, // 'required' but overridden is not (used for recovery)

lib/Serialization/Serialization.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4494,9 +4494,12 @@ class Serializer::DeclSerializer : public DeclVisitor<DeclSerializer> {
44944494
uint8_t rawAccessLevel = getRawStableAccessLevel(ctor->getFormalAccess());
44954495

44964496
bool firstTimeRequired = ctor->isRequired();
4497-
if (auto *overridden = ctor->getOverriddenDecl())
4497+
auto *overridden = ctor->getOverriddenDecl();
4498+
if (overridden) {
44984499
if (firstTimeRequired && overridden->isRequired())
44994500
firstTimeRequired = false;
4501+
}
4502+
bool overriddenAffectsABI = overriddenDeclAffectsABI(ctor, overridden);
45004503

45014504
unsigned abbrCode = S.DeclTypeAbbrCodes[ConstructorLayout::Code];
45024505
ConstructorLayout::emitRecord(S.Out, S.ScratchRecord, abbrCode,
@@ -4512,7 +4515,8 @@ class Serializer::DeclSerializer : public DeclVisitor<DeclSerializer> {
45124515
ctor->getInitKind()),
45134516
S.addGenericSignatureRef(
45144517
ctor->getGenericSignature()),
4515-
S.addDeclRef(ctor->getOverriddenDecl()),
4518+
S.addDeclRef(overridden),
4519+
overriddenAffectsABI,
45164520
rawAccessLevel,
45174521
ctor->needsNewVTableEntry(),
45184522
firstTimeRequired,

test/Serialization/Safety/override-internal-func.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
//--- Lib.swift
2020

2121
open class Base {
22+
internal init() {}
23+
2224
public func publicMethod() -> Int {
2325
return 1
2426
}
@@ -33,6 +35,10 @@ open class Base {
3335
}
3436

3537
open class Derived : Base {
38+
public override init() {
39+
super.init()
40+
}
41+
3642
open override func publicMethod() -> Int {
3743
return super.publicMethod() + 1
3844
}
@@ -63,3 +69,7 @@ public class OtherFinalDerived : Derived {
6369
return super.internalMethod() + 1
6470
}
6571
}
72+
73+
func foo() {
74+
let a = Derived()
75+
}

0 commit comments

Comments
 (0)