@@ -44,13 +44,15 @@ class TBDGenVisitor : public ASTVisitor<TBDGenVisitor> {
44
44
bool FileHasEntryPoint;
45
45
bool SILSerializeWitnessTables;
46
46
47
+ bool InsideAbstractStorageDecl = false ;
48
+
47
49
void addSymbol (StringRef name) {
48
50
auto isNewValue = Symbols.insert (name).second ;
49
51
(void )isNewValue;
50
52
assert (isNewValue && " already inserted" );
51
53
}
52
54
53
- void addSymbol (SILDeclRef declRef, bool checkSILOnly = true );
55
+ void addSymbol (SILDeclRef declRef);
54
56
55
57
void addSymbol (LinkEntity entity) {
56
58
auto linkage =
@@ -85,8 +87,8 @@ class TBDGenVisitor : public ASTVisitor<TBDGenVisitor> {
85
87
addMembers (ED->getMembers ());
86
88
else if (auto NTD = dyn_cast<NominalTypeDecl>(D))
87
89
addMembers (NTD->getMembers ());
88
- else if (auto VD = dyn_cast<VarDecl >(D))
89
- VD ->getAllAccessorFunctions (members);
90
+ else if (auto ASD = dyn_cast<AbstractStorageDecl >(D))
91
+ ASD ->getAllAccessorFunctions (members);
90
92
91
93
for (auto member : members) {
92
94
ASTVisitor::visit (member);
@@ -103,20 +105,18 @@ class TBDGenVisitor : public ASTVisitor<TBDGenVisitor> {
103
105
// any information here is encoded elsewhere
104
106
}
105
107
106
- void visitSubscriptDecl (SubscriptDecl *SD) {
107
- // Any getters and setters etc. exist as independent FuncDecls in the AST,
108
- // so get processed elsewhere; subscripts don't have any symbols other than
109
- // these.
110
- }
111
-
112
108
void visitNominalTypeDecl (NominalTypeDecl *NTD);
113
109
114
110
void visitClassDecl (ClassDecl *CD);
115
111
112
+ void visitConstructorDecl (ConstructorDecl *CD);
113
+
116
114
void visitExtensionDecl (ExtensionDecl *ED);
117
115
118
116
void visitProtocolDecl (ProtocolDecl *PD);
119
117
118
+ void visitAbstractStorageDecl (AbstractStorageDecl *ASD);
119
+
120
120
void visitVarDecl (VarDecl *VD);
121
121
122
122
void visitDecl (Decl *D) { visitMembers (D); }
@@ -138,13 +138,13 @@ void TBDGenVisitor::visitPatternBindingDecl(PatternBindingDecl *PBD) {
138
138
auto declRef =
139
139
SILDeclRef (var, SILDeclRef::Kind::StoredPropertyInitializer);
140
140
// Stored property initializers for public properties are currently
141
- // public, even when the initializer is marked as SIL only (transparent) .
142
- addSymbol (declRef, /* checkSILOnly= */ false );
141
+ // public.
142
+ addSymbol (declRef);
143
143
}
144
144
}
145
145
}
146
146
147
- void TBDGenVisitor::addSymbol (SILDeclRef declRef, bool checkSILOnly ) {
147
+ void TBDGenVisitor::addSymbol (SILDeclRef declRef) {
148
148
bool isPrivate = !hasPublicVisibility (declRef.getLinkage (ForDefinition));
149
149
// Even private methods of open classes (specifically, private methods that
150
150
// are in the vtable) have public symbols, because external subclasses
@@ -155,7 +155,6 @@ void TBDGenVisitor::addSymbol(SILDeclRef declRef, bool checkSILOnly) {
155
155
// unconditionally, even if they're theoretically SIL only.
156
156
if (isPrivate) {
157
157
isPrivate = false ;
158
- checkSILOnly = false ;
159
158
}
160
159
break ;
161
160
case SubclassScope::Internal:
@@ -165,10 +164,9 @@ void TBDGenVisitor::addSymbol(SILDeclRef declRef, bool checkSILOnly) {
165
164
if (isPrivate)
166
165
return ;
167
166
168
- // (Most) transparent things don't exist, even if they're public.
169
- // FIXME: isTransparent should really be "is SIL only".
170
- if (checkSILOnly && declRef.isTransparent ())
171
- return ;
167
+ // FIXME: this includes too many symbols. There are some that are considered
168
+ // SIL-only, but it isn't obvious how to determine this (e.g. it seems that
169
+ // many, but not all, transparent functions result in object-file symbols)
172
170
173
171
addSymbol (declRef.mangle ());
174
172
}
@@ -256,6 +254,14 @@ void TBDGenVisitor::visitValueDecl(ValueDecl *VD) {
256
254
}
257
255
258
256
void TBDGenVisitor::visitAbstractFunctionDecl (AbstractFunctionDecl *AFD) {
257
+ if (auto FD = dyn_cast<FuncDecl>(AFD)) {
258
+ // Accessors also appear nested inside the storage decl, which we treat as
259
+ // the canonical location, so skip if we've got an accessor that isn't
260
+ // inside the var decl.
261
+ if (FD->getAccessorStorageDecl () && !InsideAbstractStorageDecl)
262
+ return ;
263
+ }
264
+
259
265
// Default arguments (of public functions) are public symbols, as the default
260
266
// values are computed at the call site.
261
267
auto index = 0 ;
@@ -275,25 +281,27 @@ void TBDGenVisitor::visitAbstractFunctionDecl(AbstractFunctionDecl *AFD) {
275
281
visitValueDecl (AFD);
276
282
}
277
283
284
+ void TBDGenVisitor::visitAbstractStorageDecl (AbstractStorageDecl *ASD) {
285
+ assert (!InsideAbstractStorageDecl &&
286
+ " unexpected nesting of abstract storage decls" );
287
+ InsideAbstractStorageDecl = true ;
288
+ visitMembers (ASD);
289
+ InsideAbstractStorageDecl = false ;
290
+ }
278
291
void TBDGenVisitor::visitVarDecl (VarDecl *VD) {
279
- if (isPrivateDecl (VD))
280
- return ;
281
-
282
292
// statically/globally stored variables have some special handling.
283
293
if (VD->hasStorage () && isGlobalOrStaticVar (VD)) {
284
294
// The actual variable has a symbol.
285
295
Mangle::ASTMangler mangler;
286
296
addSymbol (mangler.mangleEntity (VD, false ));
287
297
288
- // Variables in the main file don't get accessors, despite otherwise looking
289
- // like globals.
290
- if (!FileHasEntryPoint)
298
+ // Top-level variables (*not* statics) in the main file don't get accessors,
299
+ // despite otherwise looking like globals.
300
+ if (!FileHasEntryPoint || VD-> isStatic () )
291
301
addSymbol (SILDeclRef (VD, SILDeclRef::Kind::GlobalAccessor));
292
-
293
- // In this case, the members of the VarDecl don't also appear as top-level
294
- // decls, so we need to explicitly walk them.
295
- visitMembers (VD);
296
302
}
303
+
304
+ visitAbstractStorageDecl (VD);
297
305
}
298
306
299
307
void TBDGenVisitor::visitNominalTypeDecl (NominalTypeDecl *NTD) {
@@ -344,8 +352,7 @@ void TBDGenVisitor::visitClassDecl(ClassDecl *CD) {
344
352
continue ;
345
353
346
354
auto var = dyn_cast<VarDecl>(value);
347
- auto hasFieldOffset =
348
- !isGeneric && var && var->hasStorage () && !var->isStatic ();
355
+ auto hasFieldOffset = var && var->hasStorage () && !var->isStatic ();
349
356
if (hasFieldOffset) {
350
357
// FIXME: a field only has one sort of offset, but it is moderately
351
358
// non-trivial to compute which one. Including both is less painful than
@@ -354,10 +361,8 @@ void TBDGenVisitor::visitClassDecl(ClassDecl *CD) {
354
361
addSymbol (LinkEntity::forFieldOffset (var, /* isIndirect=*/ true ));
355
362
}
356
363
357
- // The non-allocating forms of the constructors and destructors.
358
- if (auto ctor = dyn_cast<ConstructorDecl>(value)) {
359
- addSymbol (SILDeclRef (ctor, SILDeclRef::Kind::Initializer));
360
- } else if (auto dtor = dyn_cast<DestructorDecl>(value)) {
364
+ // The non-allocating forms of the destructors.
365
+ if (auto dtor = dyn_cast<DestructorDecl>(value)) {
361
366
// ObjC classes don't have a symbol for their destructor.
362
367
if (!isObjC)
363
368
addSymbol (SILDeclRef (dtor, SILDeclRef::Kind::Destroyer));
@@ -367,6 +372,16 @@ void TBDGenVisitor::visitClassDecl(ClassDecl *CD) {
367
372
visitNominalTypeDecl (CD);
368
373
}
369
374
375
+ void TBDGenVisitor::visitConstructorDecl (ConstructorDecl *CD) {
376
+ if (CD->getParent ()->getAsClassOrClassExtensionContext ()) {
377
+ // Class constructors come in two forms, allocating and non-allocating. The
378
+ // default ValueDecl handling gives the allocating one, so we have to
379
+ // manually include the non-allocating one.
380
+ addSymbol (SILDeclRef (CD, SILDeclRef::Kind::Initializer));
381
+ }
382
+ visitAbstractFunctionDecl (CD);
383
+ }
384
+
370
385
void TBDGenVisitor::visitExtensionDecl (ExtensionDecl *ED) {
371
386
if (!ED->getExtendedType ()->isExistentialType ()) {
372
387
addConformances (ED);
@@ -380,14 +395,15 @@ void TBDGenVisitor::visitProtocolDecl(ProtocolDecl *PD) {
380
395
addSymbol (LinkEntity::forProtocolDescriptor (PD));
381
396
382
397
#ifndef NDEBUG
383
- // There's no (currently) relevant information about members of a protocol
384
- // at individual protocols, each conforming type has to handle them
385
- // individually. Let's assert this fact:
398
+ // There's no (currently) relevant information about members of a protocol at
399
+ // individual protocols, each conforming type has to handle them individually
400
+ // (NB. anything within an active IfConfigDecls also appears outside). Let's
401
+ // assert this fact:
386
402
for (auto *member : PD->getMembers ()) {
387
403
auto isExpectedKind =
388
404
isa<TypeAliasDecl>(member) || isa<AssociatedTypeDecl>(member) ||
389
405
isa<AbstractStorageDecl>(member) || isa<PatternBindingDecl>(member) ||
390
- isa<AbstractFunctionDecl>(member);
406
+ isa<AbstractFunctionDecl>(member) || isa<IfConfigDecl>(member) ;
391
407
assert (isExpectedKind &&
392
408
" unexpected member of protocol during TBD generation" );
393
409
}
0 commit comments