Skip to content

Commit df26b25

Browse files
authored
Merge pull request #9360 from jrose-apple/VTablePlaceholder
Add a new MissingMemberDecl and use it to handle non-deserializable class members
2 parents 30482a0 + 384b2a6 commit df26b25

27 files changed

+438
-49
lines changed

include/swift/AST/Attr.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,9 @@ class DeclAttribute : public AttributeBase {
299299
OnParam = 1 << 30,
300300
OnModule = 1 << 31,
301301

302+
// Cannot have any attributes.
303+
OnMissingMember = 0,
304+
302305
// More coarse-grained aggregations for use in Attr.def.
303306
OnOperator = OnInfixOperator|OnPrefixOperator|OnPostfixOperator,
304307

include/swift/AST/Decl.h

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ enum class DescriptiveDeclKind : uint8_t {
140140
DidSet,
141141
EnumElement,
142142
Module,
143+
MissingMember,
143144
};
144145

145146
/// Keeps track of stage of circularity checking for the given protocol.
@@ -602,6 +603,15 @@ class alignas(1 << DeclAlignInBits) Decl {
602603
enum { NumIfConfigDeclBits = NumDeclBits + 1 };
603604
static_assert(NumIfConfigDeclBits <= 32, "fits in an unsigned");
604605

606+
class MissingMemberDeclBitfields {
607+
friend class MissingMemberDecl;
608+
unsigned : NumDeclBits;
609+
610+
unsigned NumberOfVTableEntries : 2;
611+
};
612+
enum { NumMissingMemberDeclBits = NumDeclBits + 2 };
613+
static_assert(NumMissingMemberDeclBits <= 32, "fits in an unsigned");
614+
605615
protected:
606616
union {
607617
DeclBitfields DeclBits;
@@ -626,6 +636,7 @@ class alignas(1 << DeclAlignInBits) Decl {
626636
ImportDeclBitfields ImportDeclBits;
627637
ExtensionDeclBitfields ExtensionDeclBits;
628638
IfConfigDeclBitfields IfConfigDeclBits;
639+
MissingMemberDeclBitfields MissingMemberDeclBits;
629640
uint32_t OpaqueBits;
630641
};
631642

@@ -6132,6 +6143,55 @@ class PostfixOperatorDecl : public OperatorDecl {
61326143
}
61336144
};
61346145

6146+
/// Represents a hole where a declaration should have been.
6147+
///
6148+
/// Among other things, these are used to keep vtable layout consistent.
6149+
class MissingMemberDecl : public Decl {
6150+
DeclName Name;
6151+
6152+
MissingMemberDecl(DeclContext *DC, DeclName name, unsigned vtableEntries)
6153+
: Decl(DeclKind::MissingMember, DC), Name(name) {
6154+
MissingMemberDeclBits.NumberOfVTableEntries = vtableEntries;
6155+
assert(getNumberOfVTableEntries() == vtableEntries && "not enough bits");
6156+
setImplicit();
6157+
}
6158+
public:
6159+
static MissingMemberDecl *
6160+
forMethod(ASTContext &ctx, DeclContext *DC, DeclName name,
6161+
bool hasNormalVTableEntry) {
6162+
assert(!name || name.isCompoundName());
6163+
return new (ctx) MissingMemberDecl(DC, name, hasNormalVTableEntry);
6164+
}
6165+
6166+
static MissingMemberDecl *
6167+
forInitializer(ASTContext &ctx, DeclContext *DC, DeclName name,
6168+
bool hasNormalVTableEntry,
6169+
bool hasAllocatingVTableEntry) {
6170+
unsigned entries = hasNormalVTableEntry + hasAllocatingVTableEntry;
6171+
return new (ctx) MissingMemberDecl(DC, name, entries);
6172+
}
6173+
6174+
DeclName getFullName() const {
6175+
return Name;
6176+
}
6177+
6178+
unsigned getNumberOfVTableEntries() const {
6179+
return MissingMemberDeclBits.NumberOfVTableEntries;
6180+
}
6181+
6182+
SourceLoc getLoc() const {
6183+
return SourceLoc();
6184+
}
6185+
6186+
SourceRange getSourceRange() const {
6187+
return SourceRange();
6188+
}
6189+
6190+
static bool classof(const Decl *D) {
6191+
return D->getKind() == DeclKind::MissingMember;
6192+
}
6193+
};
6194+
61356195
inline bool ValueDecl::isSettable(const DeclContext *UseDC,
61366196
const DeclRefExpr *base) const {
61376197
if (auto vd = dyn_cast<VarDecl>(this)) {

include/swift/AST/DeclNodes.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ DECL(EnumCase, Decl)
9393
CONTEXT_DECL(TopLevelCode, Decl)
9494
DECL(IfConfig, Decl)
9595
DECL(PrecedenceGroup, Decl)
96+
DECL(MissingMember, Decl)
9697

9798
ABSTRACT_DECL(Operator, Decl)
9899
OPERATOR_DECL(InfixOperator, OperatorDecl)

include/swift/AST/PrintOptions.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,9 @@ struct PrintOptions {
238238
/// Whether to skip parameter type attributes
239239
bool SkipParameterTypeAttributes = false;
240240

241+
/// Whether to skip placeholder members.
242+
bool SkipMissingMemberPlaceholders = true;
243+
241244
/// Whether to print a long attribute like '\@available' on a separate line
242245
/// from the declaration or other attributes.
243246
bool PrintLongAttrsOnSeparateLines = false;
@@ -489,6 +492,7 @@ struct PrintOptions {
489492
result.AbstractAccessors = false;
490493
result.PrintAccessibility = true;
491494
result.SkipEmptyExtensionDecls = false;
495+
result.SkipMissingMemberPlaceholders = false;
492496
return result;
493497
}
494498

include/swift/SIL/SILVTableVisitor.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,8 @@ template <class T> class SILVTableVisitor {
9494
maybeAddMethod(fd);
9595
else if (auto *cd = dyn_cast<ConstructorDecl>(member))
9696
maybeAddConstructor(cd);
97+
else if (auto *placeholder = dyn_cast<MissingMemberDecl>(member))
98+
asDerived().addPlaceholder(placeholder);
9799
}
98100
}
99101
};

include/swift/Serialization/ModuleFormat.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ const uint16_t VERSION_MAJOR = 0;
5454
/// in source control, you should also update the comment to briefly
5555
/// describe what change you made. The content of this comment isn't important;
5656
/// it just ensures a conflict if two people change the module format.
57-
const uint16_t VERSION_MINOR = 343; // Last change: new vtable entry flag
57+
const uint16_t VERSION_MINOR = 344; // Last change: ctor newly required flag
5858

5959
using DeclID = PointerEmbeddedInt<unsigned, 31>;
6060
using DeclIDField = BCFixed<31>;
@@ -859,6 +859,7 @@ namespace decls_block {
859859
DeclIDField, // overridden decl
860860
AccessibilityKindField, // accessibility
861861
BCFixed<1>, // requires a new vtable slot
862+
BCFixed<1>, // 'required' but overridden is not (used for recovery)
862863
BCArray<IdentifierIDField> // argument names
863864
// Trailed by its generic parameters, if any, followed by the parameter
864865
// patterns.

lib/AST/ASTDumper.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1110,6 +1110,13 @@ namespace {
11101110
printCommon(MD, "module");
11111111
PrintWithColorRAII(OS, ParenthesisColor) << ')';
11121112
}
1113+
1114+
void visitMissingMemberDecl(MissingMemberDecl *MMD) {
1115+
printCommon(MMD, "missing_member_decl ");
1116+
PrintWithColorRAII(OS, IdentifierColor)
1117+
<< '\"' << MMD->getFullName() << '\"';
1118+
PrintWithColorRAII(OS, ParenthesisColor) << ')';
1119+
}
11131120
};
11141121
} // end anonymous namespace
11151122

lib/AST/ASTPrinter.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1644,6 +1644,9 @@ bool swift::shouldPrint(const Decl *D, PrintOptions &Options) {
16441644
return false;
16451645
}
16461646

1647+
if (Options.SkipMissingMemberPlaceholders && isa<MissingMemberDecl>(D))
1648+
return false;
1649+
16471650
if (Options.SkipDeinit && isa<DestructorDecl>(D)) {
16481651
return false;
16491652
}
@@ -3215,6 +3218,12 @@ void PrintAST::visitPostfixOperatorDecl(PostfixOperatorDecl *decl) {
32153218

32163219
void PrintAST::visitModuleDecl(ModuleDecl *decl) { }
32173220

3221+
void PrintAST::visitMissingMemberDecl(MissingMemberDecl *decl) {
3222+
Printer << "/* placeholder for ";
3223+
recordDeclLoc(decl, [&]{ Printer << decl->getFullName(); });
3224+
Printer << " */";
3225+
}
3226+
32183227
void PrintAST::visitBraceStmt(BraceStmt *stmt) {
32193228
Printer << "{";
32203229
printASTNodes(stmt->getElements());

lib/AST/ASTScope.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -929,6 +929,7 @@ ASTScope *ASTScope::createIfNeeded(const ASTScope *parent, Decl *decl) {
929929
case DeclKind::Param:
930930
case DeclKind::EnumElement:
931931
case DeclKind::IfConfig:
932+
case DeclKind::MissingMember:
932933
// These declarations do not introduce scopes.
933934
return nullptr;
934935

lib/AST/ASTWalker.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,10 @@ class Traversal : public ASTVisitor<Traversal, Expr*, Stmt*,
260260
return doIt(SD->getElementTypeLoc());
261261
}
262262

263+
bool visitMissingMemberDecl(MissingMemberDecl *MMD) {
264+
return false;
265+
}
266+
263267
bool visitAbstractFunctionDecl(AbstractFunctionDecl *AFD) {
264268
#ifndef NDEBUG
265269
PrettyStackTraceDecl debugStack("walking into body of", AFD);

lib/AST/Decl.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ DescriptiveDeclKind Decl::getDescriptiveKind() const {
133133
TRIVIAL_KIND(EnumElement);
134134
TRIVIAL_KIND(Param);
135135
TRIVIAL_KIND(Module);
136+
TRIVIAL_KIND(MissingMember);
136137

137138
case DeclKind::Enum:
138139
return cast<EnumDecl>(this)->getGenericParams()
@@ -267,6 +268,7 @@ StringRef Decl::getDescriptiveKindName(DescriptiveDeclKind K) {
267268
ENTRY(MutableAddressor, "mutableAddress accessor");
268269
ENTRY(EnumElement, "enum element");
269270
ENTRY(Module, "module");
271+
ENTRY(MissingMember, "missing member placeholder");
270272
}
271273
#undef ENTRY
272274
llvm_unreachable("bad DescriptiveDeclKind");
@@ -736,6 +738,7 @@ ImportKind ImportDecl::getBestImportKind(const ValueDecl *VD) {
736738
case DeclKind::EnumCase:
737739
case DeclKind::IfConfig:
738740
case DeclKind::PrecedenceGroup:
741+
case DeclKind::MissingMember:
739742
llvm_unreachable("not a ValueDecl");
740743

741744
case DeclKind::AssociatedType:
@@ -1371,6 +1374,7 @@ bool ValueDecl::isDefinition() const {
13711374
case DeclKind::PostfixOperator:
13721375
case DeclKind::IfConfig:
13731376
case DeclKind::PrecedenceGroup:
1377+
case DeclKind::MissingMember:
13741378
assert(!isa<ValueDecl>(this));
13751379
llvm_unreachable("non-value decls shouldn't get here");
13761380

@@ -1412,6 +1416,7 @@ bool ValueDecl::isInstanceMember() const {
14121416
case DeclKind::PostfixOperator:
14131417
case DeclKind::IfConfig:
14141418
case DeclKind::PrecedenceGroup:
1419+
case DeclKind::MissingMember:
14151420
llvm_unreachable("Not a ValueDecl");
14161421

14171422
case DeclKind::Class:

lib/FrontendTool/ReferenceDependencies.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,7 @@ bool swift::emitReferenceDependencies(DiagnosticEngine &diags,
254254
case DeclKind::Constructor:
255255
case DeclKind::Destructor:
256256
case DeclKind::EnumElement:
257+
case DeclKind::MissingMember:
257258
llvm_unreachable("cannot appear at the top level of a file");
258259
}
259260
}

lib/IDE/CodeCompletion.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -535,6 +535,7 @@ CodeCompletionResult::getCodeCompletionDeclKind(const Decl *D) {
535535
case DeclKind::EnumCase:
536536
case DeclKind::TopLevelCode:
537537
case DeclKind::IfConfig:
538+
case DeclKind::MissingMember:
538539
llvm_unreachable("not expecting such a declaration result");
539540
case DeclKind::Module:
540541
return CodeCompletionDeclKind::Module;

lib/IRGen/ClassMetadataLayout.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,12 @@ class ClassMetadataScanner : public ClassMetadataLayout<Impl> {
181181
ClassDecl *forClass) {
182182
addPointer();
183183
}
184+
void addPlaceholder(MissingMemberDecl *MMD) {
185+
for (auto i : range(MMD->getNumberOfVTableEntries())) {
186+
(void)i;
187+
addPointer();
188+
}
189+
}
184190

185191
private:
186192
// Our layout here assumes that there will never be unclaimed space

lib/IRGen/GenClass.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1491,6 +1491,10 @@ namespace {
14911491
}
14921492
}
14931493

1494+
void visitMissingMemberDecl(MissingMemberDecl *placeholder) {
1495+
llvm_unreachable("should not IRGen classes with missing members");
1496+
}
1497+
14941498
void addIVarInitializer() {
14951499
if (auto fn = IGM.getAddrOfIVarInitDestroy(getClass(),
14961500
/*destroy*/ false,

lib/IRGen/GenDecl.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,8 @@ class CategoryInitializerVisitor
166166
void visitTypeDecl(TypeDecl *type) {
167167
// We'll visit nested types separately if necessary.
168168
}
169+
170+
void visitMissingMemberDecl(MissingMemberDecl *placeholder) {}
169171

170172
void visitFuncDecl(FuncDecl *method) {
171173
if (!requiresObjCMethodDescriptor(method)) return;
@@ -379,6 +381,8 @@ class ObjCProtocolInitializerVisitor
379381
// We'll visit nested types separately if necessary.
380382
}
381383

384+
void visitMissingMemberDecl(MissingMemberDecl *placeholder) {}
385+
382386
void visitAbstractFunctionDecl(AbstractFunctionDecl *method) {
383387
llvm::Constant *name, *imp, *types;
384388
emitObjCMethodDescriptorParts(IGM, method, /*extended*/true,
@@ -1668,6 +1672,9 @@ void IRGenModule::emitGlobalDecl(Decl *D) {
16681672
case DeclKind::Destructor:
16691673
llvm_unreachable("there are no global destructor");
16701674

1675+
case DeclKind::MissingMember:
1676+
llvm_unreachable("there are no global member placeholders");
1677+
16711678
case DeclKind::TypeAlias:
16721679
case DeclKind::GenericTypeParam:
16731680
case DeclKind::AssociatedType:
@@ -2927,6 +2934,7 @@ void IRGenModule::emitNestedTypeDecls(DeclRange members) {
29272934
case DeclKind::Destructor:
29282935
case DeclKind::EnumCase:
29292936
case DeclKind::EnumElement:
2937+
case DeclKind::MissingMember:
29302938
// Skip non-type members.
29312939
continue;
29322940

lib/IRGen/GenMeta.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3502,6 +3502,10 @@ namespace {
35023502
}
35033503
}
35043504

3505+
void addPlaceholder(MissingMemberDecl *) {
3506+
llvm_unreachable("cannot generate metadata with placeholders in it");
3507+
}
3508+
35053509
void addMethodOverride(SILDeclRef baseRef, SILDeclRef declRef) {}
35063510

35073511
void addGenericArgument(CanType argTy, ClassDecl *forClass) {

lib/SILGen/SILGen.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,7 @@ class LLVM_LIBRARY_VISIBILITY SILGenModule : public ASTVisitor<SILGenModule> {
224224
void visitConstructorDecl(ConstructorDecl *d) {}
225225
void visitDestructorDecl(DestructorDecl *d) {}
226226
void visitModuleDecl(ModuleDecl *d) { }
227+
void visitMissingMemberDecl(MissingMemberDecl *d) {}
227228

228229
void visitFuncDecl(FuncDecl *fd);
229230
void visitPatternBindingDecl(PatternBindingDecl *vd);

lib/SILGen/SILGenDecl.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1393,6 +1393,7 @@ void SILGenModule::emitExternalDefinition(Decl *d) {
13931393
case DeclKind::PostfixOperator:
13941394
case DeclKind::PrecedenceGroup:
13951395
case DeclKind::Module:
1396+
case DeclKind::MissingMember:
13961397
llvm_unreachable("Not a valid external definition for SILGen");
13971398
}
13981399
}

lib/SILGen/SILGenType.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,8 @@ class SILGenVTable : public SILVTableVisitor<SILGenVTable> {
203203
assert(result.second);
204204
(void) result;
205205
}
206+
207+
void addPlaceholder(MissingMemberDecl *) {}
206208
};
207209

208210
} // end anonymous namespace
@@ -823,6 +825,7 @@ class SILGenType : public TypeMemberVisitor<SILGenType> {
823825
void visitTypeAliasDecl(TypeAliasDecl *tad) {}
824826
void visitAbstractTypeParamDecl(AbstractTypeParamDecl *tpd) {}
825827
void visitModuleDecl(ModuleDecl *md) {}
828+
void visitMissingMemberDecl(MissingMemberDecl *) {}
826829
void visitNominalTypeDecl(NominalTypeDecl *ntd) {
827830
SILGenType(SGM, ntd).emitType();
828831
}
@@ -922,6 +925,7 @@ class SILGenExtension : public TypeMemberVisitor<SILGenExtension> {
922925
void visitTypeAliasDecl(TypeAliasDecl *tad) {}
923926
void visitAbstractTypeParamDecl(AbstractTypeParamDecl *tpd) {}
924927
void visitModuleDecl(ModuleDecl *md) {}
928+
void visitMissingMemberDecl(MissingMemberDecl *) {}
925929
void visitNominalTypeDecl(NominalTypeDecl *ntd) {
926930
SILGenType(SGM, ntd).emitType();
927931
}

0 commit comments

Comments
 (0)