Skip to content

Commit f3f8b62

Browse files
authored
Merge pull request #8715 from jrose-apple/deserialization-recovery-for-inits
[Serialization] Drop overriding initializers with missing bases.
2 parents 2a2731a + abdaaef commit f3f8b62

File tree

4 files changed

+268
-76
lines changed

4 files changed

+268
-76
lines changed

include/swift/Serialization/ModuleFile.h

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -526,15 +526,6 @@ class ModuleFile : public LazyMemberLoader {
526526
GenericContext *genericDecl,
527527
serialization::GenericEnvironmentID envID);
528528

529-
/// Populates the vector with members of a DeclContext from \c DeclTypeCursor.
530-
///
531-
/// Returns true if there is an error.
532-
///
533-
/// Note: this destroys the cursor's position in the stream. Furthermore,
534-
/// because it reads from the cursor, it is not possible to reset the cursor
535-
/// after reading. Nothing should ever follow a MEMBERS record.
536-
bool readMembers(SmallVectorImpl<Decl *> &Members);
537-
538529
/// Populates the protocol's default witness table.
539530
///
540531
/// Returns true if there is an error.

lib/Serialization/Deserialization.cpp

Lines changed: 98 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -299,17 +299,32 @@ namespace {
299299
const char XRefError::ID = '\0';
300300

301301
class OverrideError : public llvm::ErrorInfo<OverrideError> {
302+
public:
303+
enum Kind {
304+
Normal,
305+
DesignatedInitializer
306+
};
307+
308+
private:
302309
friend ErrorInfo;
303310
static const char ID;
304311

305312
DeclName name;
313+
Kind kind;
314+
306315
public:
307-
explicit OverrideError(DeclName name) : name(name) {}
316+
317+
explicit OverrideError(DeclName name, Kind kind = Normal)
318+
: name(name), kind(kind) {}
308319

309320
void log(raw_ostream &OS) const override {
310321
OS << "could not find '" << name << "' in parent class";
311322
}
312323

324+
Kind getKind() const {
325+
return kind;
326+
}
327+
313328
std::error_code convertToErrorCode() const override {
314329
// This is a deprecated part of llvm::Error, so we just return a very
315330
// generic value.
@@ -1235,47 +1250,6 @@ GenericEnvironment *ModuleFile::getGenericEnvironment(
12351250
;
12361251
}
12371252

1238-
bool ModuleFile::readMembers(SmallVectorImpl<Decl *> &Members) {
1239-
using namespace decls_block;
1240-
1241-
auto entry = DeclTypeCursor.advance();
1242-
if (entry.Kind != llvm::BitstreamEntry::Record)
1243-
return true;
1244-
1245-
SmallVector<uint64_t, 16> memberIDBuffer;
1246-
1247-
unsigned kind = DeclTypeCursor.readRecord(entry.ID, memberIDBuffer);
1248-
assert(kind == MEMBERS);
1249-
(void)kind;
1250-
1251-
ArrayRef<uint64_t> rawMemberIDs;
1252-
decls_block::MembersLayout::readRecord(memberIDBuffer, rawMemberIDs);
1253-
1254-
if (rawMemberIDs.empty())
1255-
return false;
1256-
1257-
Members.reserve(rawMemberIDs.size());
1258-
for (DeclID rawID : rawMemberIDs) {
1259-
Expected<Decl *> D = getDeclChecked(rawID);
1260-
if (!D) {
1261-
if (!getContext().LangOpts.EnableDeserializationRecovery)
1262-
fatal(D.takeError());
1263-
1264-
// Silently drop the member if it had an override-related problem.
1265-
llvm::handleAllErrors(D.takeError(),
1266-
[](const OverrideError &) { /* expected */ },
1267-
[this](std::unique_ptr<llvm::ErrorInfoBase> unhandled) {
1268-
fatal(std::move(unhandled));
1269-
});
1270-
continue;
1271-
}
1272-
assert(D.get() && "unchecked error deserializing next member");
1273-
Members.push_back(D.get());
1274-
}
1275-
1276-
return false;
1277-
}
1278-
12791253
bool ModuleFile::readDefaultWitnessTable(ProtocolDecl *proto) {
12801254
using namespace decls_block;
12811255

@@ -2735,6 +2709,29 @@ ModuleFile::getDeclChecked(DeclID DID, Optional<DeclContext *> ForcedContext) {
27352709
genericEnvID, interfaceID,
27362710
overriddenID, rawAccessLevel,
27372711
argNameIDs);
2712+
2713+
// Resolve the name ids.
2714+
SmallVector<Identifier, 2> argNames;
2715+
for (auto argNameID : argNameIDs)
2716+
argNames.push_back(getIdentifier(argNameID));
2717+
DeclName name(ctx, ctx.Id_init, argNames);
2718+
2719+
Optional<swift::CtorInitializerKind> initKind =
2720+
getActualCtorInitializerKind(storedInitKind);
2721+
2722+
auto overridden = getDeclChecked(overriddenID);
2723+
if (!overridden) {
2724+
llvm::handleAllErrors(overridden.takeError(),
2725+
[](const XRefError &) { /* expected */ },
2726+
[this](std::unique_ptr<llvm::ErrorInfoBase> unhandled) {
2727+
fatal(std::move(unhandled));
2728+
});
2729+
auto kind = OverrideError::Normal;
2730+
if (initKind == CtorInitializerKind::Designated)
2731+
kind = OverrideError::DesignatedInitializer;
2732+
return llvm::make_error<OverrideError>(name, kind);
2733+
}
2734+
27382735
auto parent = getDeclContext(contextID);
27392736
if (declOrOffset.isComplete())
27402737
return declOrOffset;
@@ -2743,16 +2740,10 @@ ModuleFile::getDeclChecked(DeclID DID, Optional<DeclContext *> ForcedContext) {
27432740
if (declOrOffset.isComplete())
27442741
return declOrOffset;
27452742

2746-
// Resolve the name ids.
2747-
SmallVector<Identifier, 2> argNames;
2748-
for (auto argNameID : argNameIDs)
2749-
argNames.push_back(getIdentifier(argNameID));
2750-
27512743
OptionalTypeKind failability = OTK_None;
27522744
if (auto actualFailability = getActualOptionalTypeKind(rawFailability))
27532745
failability = *actualFailability;
27542746

2755-
DeclName name(ctx, ctx.Id_init, argNames);
27562747
auto ctor =
27572748
createDecl<ConstructorDecl>(name, SourceLoc(),
27582749
failability, /*FailabilityLoc=*/SourceLoc(),
@@ -2802,11 +2793,10 @@ ModuleFile::getDeclChecked(DeclID DID, Optional<DeclContext *> ForcedContext) {
28022793
ctor->setImplicit();
28032794
if (hasStubImplementation)
28042795
ctor->setStubImplementation(true);
2805-
if (auto initKind = getActualCtorInitializerKind(storedInitKind))
2806-
ctor->setInitKind(*initKind);
2807-
if (auto overridden
2808-
= dyn_cast_or_null<ConstructorDecl>(getDecl(overriddenID)))
2809-
ctor->setOverriddenDecl(overridden);
2796+
if (initKind.hasValue())
2797+
ctor->setInitKind(initKind.getValue());
2798+
if (auto overriddenCtor = cast_or_null<ConstructorDecl>(overridden.get()))
2799+
ctor->setOverriddenDecl(overriddenCtor);
28102800
break;
28112801
}
28122802

@@ -2834,7 +2824,7 @@ ModuleFile::getDeclChecked(DeclID DID, Optional<DeclContext *> ForcedContext) {
28342824
if (!overridden) {
28352825
llvm::handleAllErrors(overridden.takeError(),
28362826
[](const XRefError &) { /* expected */ },
2837-
[this](std::unique_ptr<llvm::ErrorInfoBase> unhandled){
2827+
[this](std::unique_ptr<llvm::ErrorInfoBase> unhandled) {
28382828
fatal(std::move(unhandled));
28392829
});
28402830
return llvm::make_error<OverrideError>(name);
@@ -4432,28 +4422,69 @@ Expected<Type> ModuleFile::getTypeChecked(TypeID TID) {
44324422
return typeOrOffset;
44334423
}
44344424

4435-
void ModuleFile::loadAllMembers(Decl *D, uint64_t contextData) {
4436-
PrettyStackTraceDecl trace("loading members for", D);
4425+
void ModuleFile::loadAllMembers(Decl *container, uint64_t contextData) {
4426+
PrettyStackTraceDecl trace("loading members for", container);
44374427
++NumMemberListsLoaded;
44384428

4439-
BCOffsetRAII restoreOffset(DeclTypeCursor);
4440-
DeclTypeCursor.JumpToBit(contextData);
4441-
SmallVector<Decl *, 16> members;
4442-
bool Err = readMembers(members);
4443-
assert(!Err && "unable to read members");
4444-
(void)Err;
4445-
44464429
IterableDeclContext *IDC;
4447-
if (auto *nominal = dyn_cast<NominalTypeDecl>(D))
4430+
if (auto *nominal = dyn_cast<NominalTypeDecl>(container))
44484431
IDC = nominal;
44494432
else
4450-
IDC = cast<ExtensionDecl>(D);
4433+
IDC = cast<ExtensionDecl>(container);
4434+
4435+
BCOffsetRAII restoreOffset(DeclTypeCursor);
4436+
DeclTypeCursor.JumpToBit(contextData);
4437+
auto entry = DeclTypeCursor.advance();
4438+
if (entry.Kind != llvm::BitstreamEntry::Record) {
4439+
error();
4440+
return;
4441+
}
4442+
4443+
SmallVector<uint64_t, 16> memberIDBuffer;
4444+
4445+
unsigned kind = DeclTypeCursor.readRecord(entry.ID, memberIDBuffer);
4446+
assert(kind == decls_block::MEMBERS);
4447+
(void)kind;
4448+
4449+
ArrayRef<uint64_t> rawMemberIDs;
4450+
decls_block::MembersLayout::readRecord(memberIDBuffer, rawMemberIDs);
4451+
4452+
if (rawMemberIDs.empty())
4453+
return;
4454+
4455+
SmallVector<Decl *, 16> members;
4456+
members.reserve(rawMemberIDs.size());
4457+
for (DeclID rawID : rawMemberIDs) {
4458+
Expected<Decl *> next = getDeclChecked(rawID);
4459+
if (!next) {
4460+
if (!getContext().LangOpts.EnableDeserializationRecovery)
4461+
fatal(next.takeError());
4462+
4463+
// Drop the member if it had an override-related problem.
4464+
auto handleMissingOverrideBase = [container](const OverrideError &error) {
4465+
if (error.getKind() != OverrideError::DesignatedInitializer)
4466+
return;
4467+
auto *containingClass = dyn_cast<ClassDecl>(container);
4468+
if (!containingClass)
4469+
return;
4470+
containingClass->setHasMissingDesignatedInitializers();
4471+
};
4472+
llvm::handleAllErrors(next.takeError(),
4473+
handleMissingOverrideBase,
4474+
[this](std::unique_ptr<llvm::ErrorInfoBase> unhandled) {
4475+
fatal(std::move(unhandled));
4476+
});
4477+
continue;
4478+
}
4479+
assert(next.get() && "unchecked error deserializing next member");
4480+
members.push_back(next.get());
4481+
}
44514482

44524483
for (auto member : members)
44534484
IDC->addMember(member);
44544485

4455-
if (auto *proto = dyn_cast<ProtocolDecl>(D)) {
4456-
PrettyStackTraceDecl trace("reading default witness table for", D);
4486+
if (auto *proto = dyn_cast<ProtocolDecl>(container)) {
4487+
PrettyStackTraceDecl trace("reading default witness table for", proto);
44574488
bool Err = readDefaultWitnessTable(proto);
44584489
assert(!Err && "unable to read default witness table");
44594490
(void)Err;

test/Serialization/Recovery/Inputs/custom-modules/Overrides.h

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,3 +68,50 @@
6868
// - (nonnull Element)objectAtIndexedSubscript:(nonnull id)key;
6969
#endif
7070
@end
71+
72+
73+
@interface DesignatedInitDisappearsBase : Object
74+
- (nonnull instancetype)init __attribute__((objc_designated_initializer));
75+
- (nonnull instancetype)initConvenience:(long)value;
76+
#if !BAD
77+
- (nonnull instancetype)initWithValue:(long)value __attribute__((objc_designated_initializer));
78+
#else
79+
//- (nonnull instancetype)initWithValue:(long)value __attribute__((objc_designated_initializer));
80+
#endif
81+
@end
82+
83+
@interface OnlyDesignatedInitDisappearsBase : Object
84+
- (nonnull instancetype)initConvenience:(long)value;
85+
#if !BAD
86+
- (nonnull instancetype)initWithValue:(long)value __attribute__((objc_designated_initializer));
87+
#else
88+
//- (nonnull instancetype)initWithValue:(long)value __attribute__((objc_designated_initializer));
89+
#endif
90+
@end
91+
92+
@interface ConvenienceInitDisappearsBase : Object
93+
- (nonnull instancetype)init __attribute__((objc_designated_initializer));
94+
- (nonnull instancetype)initConvenience:(long)value;
95+
#if !BAD
96+
- (nonnull instancetype)initWithValue:(long)value;
97+
#else
98+
//- (nonnull instancetype)initWithValue:(long)value;
99+
#endif
100+
@end
101+
102+
@interface UnknownInitDisappearsBase : Object
103+
- (nonnull instancetype)init;
104+
#if !BAD
105+
- (nonnull instancetype)initWithValue:(long)value;
106+
#else
107+
//- (nonnull instancetype)initWithValue:(long)value;
108+
#endif
109+
@end
110+
111+
@interface OnlyUnknownInitDisappearsBase : Object
112+
#if !BAD
113+
- (nonnull instancetype)initWithValue:(long)value;
114+
#else
115+
//- (nonnull instancetype)initWithValue:(long)value;
116+
#endif
117+
@end

0 commit comments

Comments
 (0)