Skip to content

Commit 93a3465

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 4665053 commit 93a3465

File tree

4 files changed

+37
-13
lines changed

4 files changed

+37
-13
lines changed

lib/Serialization/Deserialization.cpp

Lines changed: 17 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,22 @@ 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 {
31353139
// Pass through deserialization errors.
3136-
if (overridden.errorIsA<FatalDeserializationError>())
3137-
return overridden.takeError();
3140+
if (overriddenOrError.errorIsA<FatalDeserializationError>())
3141+
return overriddenOrError.takeError();
31383142

3139-
llvm::consumeError(overridden.takeError());
3140-
return llvm::make_error<OverrideError>(
3141-
name, errorFlags, numVTableEntries);
3143+
llvm::consumeError(overriddenOrError.takeError());
3144+
if (overriddenAffectsABI || !ctx.LangOpts.EnableDeserializationRecovery) {
3145+
return llvm::make_error<OverrideError>(name, errorFlags,
3146+
numVTableEntries);
3147+
}
3148+
3149+
overridden = nullptr;
31423150
}
31433151

31443152
for (auto dependencyID : argNameAndDependencyIDs.slice(numArgNames)) {
@@ -3198,7 +3206,7 @@ class DeclDeserializer {
31983206
ctx.evaluator.cacheOutput(NeedsNewVTableEntryRequest{ctor},
31993207
std::move(needsNewVTableEntry));
32003208

3201-
ctor->setOverriddenDecl(cast_or_null<ConstructorDecl>(overridden.get()));
3209+
ctor->setOverriddenDecl(cast_or_null<ConstructorDecl>(overridden));
32023210
if (auto *overridden = ctor->getOverriddenDecl()) {
32033211
if (!attributeChainContains<RequiredAttr>(DAttrs) ||
32043212
!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 = 741; // SIL pack types
61+
const uint16_t SWIFTMODULE_VERSION_MINOR = 742; // Constructor affects ABI
6262

6363
/// A standard hash seed used for all string hashes in a serialized module.
6464
///
@@ -1455,6 +1455,7 @@ namespace decls_block {
14551455
CtorInitializerKindField, // initializer kind
14561456
GenericSignatureIDField, // generic environment
14571457
DeclIDField, // overridden decl
1458+
BCFixed<1>, // whether the overridden decl affects ABI
14581459
AccessLevelField, // access level
14591460
BCFixed<1>, // requires a new vtable slot
14601461
BCFixed<1>, // 'required' but overridden is not (used for recovery)

lib/Serialization/Serialization.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3535,7 +3535,8 @@ class Serializer::DeclSerializer : public DeclVisitor<DeclSerializer> {
35353535
// its overrides after they've been compiled: if the declaration is '@objc'
35363536
// and 'dynamic'. In that case, all accesses to the method or property will
35373537
// go through the Objective-C method tables anyway.
3538-
if (overridden->hasClangNode() || overridden->shouldUseObjCDispatch())
3538+
if (!isa<ConstructorDecl>(override) &&
3539+
(overridden->hasClangNode() || overridden->shouldUseObjCDispatch()))
35393540
return false;
35403541

35413542
// In a public-override-internal case, the override doesn't have ABI
@@ -4499,9 +4500,12 @@ class Serializer::DeclSerializer : public DeclVisitor<DeclSerializer> {
44994500
uint8_t rawAccessLevel = getRawStableAccessLevel(ctor->getFormalAccess());
45004501

45014502
bool firstTimeRequired = ctor->isRequired();
4502-
if (auto *overridden = ctor->getOverriddenDecl())
4503+
auto *overridden = ctor->getOverriddenDecl();
4504+
if (overridden) {
45034505
if (firstTimeRequired && overridden->isRequired())
45044506
firstTimeRequired = false;
4507+
}
4508+
bool overriddenAffectsABI = overriddenDeclAffectsABI(ctor, overridden);
45054509

45064510
unsigned abbrCode = S.DeclTypeAbbrCodes[ConstructorLayout::Code];
45074511
ConstructorLayout::emitRecord(S.Out, S.ScratchRecord, abbrCode,
@@ -4517,7 +4521,8 @@ class Serializer::DeclSerializer : public DeclVisitor<DeclSerializer> {
45174521
ctor->getInitKind()),
45184522
S.addGenericSignatureRef(
45194523
ctor->getGenericSignature()),
4520-
S.addDeclRef(ctor->getOverriddenDecl()),
4524+
S.addDeclRef(overridden),
4525+
overriddenAffectsABI,
45214526
rawAccessLevel,
45224527
ctor->needsNewVTableEntry(),
45234528
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)