1
- // ===--- Serialization.cpp - Read and write Swift modules -----------------===//
1
+ // ===--- Serialization.cpp - Read and write Swift modules -----------------===//
2
2
//
3
3
// This source file is part of the Swift.org open source project
4
4
//
@@ -3276,23 +3276,39 @@ class Serializer::DeclSerializer : public DeclVisitor<DeclSerializer> {
3276
3276
return count;
3277
3277
}
3278
3278
3279
- public:
3280
- // / Determine if \p decl is safe to deserialize when it's public
3281
- // / or otherwise needed by the client in normal builds, this should usually
3282
- // / correspond to logic in type-checking ensuring these safe decls don't
3283
- // / refer to implementation details. We have to be careful not to mark
3284
- // / anything needed by a client as unsafe as the client will reject reading
3285
- // / it, but at the same time keep the safety checks precise to avoid
3286
- // / XRef errors and such.
3287
- static bool isDeserializationSafe (const Decl *decl) {
3288
- if (auto ext = dyn_cast<ExtensionDecl>(decl)) {
3289
- // Consider extensions as safe as their extended type.
3279
+ class ExternallyAccessibleDeclVisitor
3280
+ : public DeclVisitor<ExternallyAccessibleDeclVisitor, bool > {
3281
+ public:
3282
+ ExternallyAccessibleDeclVisitor (){};
3283
+
3284
+ bool visit (const Decl *D) {
3285
+ if (auto value = dyn_cast<ValueDecl>(D)) {
3286
+ // A decl is externally accessible if it has a public access level.
3287
+ auto accessScope =
3288
+ value->getFormalAccessScope (/* useDC=*/ nullptr ,
3289
+ /* treatUsableFromInlineAsPublic=*/ true );
3290
+ if (accessScope.isPublic () || accessScope.isPackage ())
3291
+ return true ;
3292
+ }
3293
+
3294
+ return DeclVisitor<ExternallyAccessibleDeclVisitor, bool >::visit (
3295
+ const_cast <Decl *>(D));
3296
+ }
3297
+
3298
+ // Force all decl kinds to be handled explicitly.
3299
+ bool visitDecl (const Decl *D) = delete;
3300
+ bool visitValueDecl (const ValueDecl *valueDecl) = delete;
3301
+
3302
+ bool visitExtensionDecl (const ExtensionDecl *ext) {
3303
+ // Extensions must extend externally accessible types to be externally
3304
+ // accessible.
3290
3305
auto nominalType = ext->getExtendedNominal ();
3291
3306
if (!nominalType ||
3292
3307
!isDeserializationSafe (nominalType))
3293
3308
return false ;
3294
3309
3295
- // We can mark the extension unsafe only if it has no public members.
3310
+ // If the extension has any externally accessible members, then it is
3311
+ // externally accessible.
3296
3312
auto members = ext->getMembers ();
3297
3313
auto hasSafeMembers = std::any_of (members.begin (), members.end (),
3298
3314
[](const Decl *D) -> bool {
@@ -3303,26 +3319,28 @@ class Serializer::DeclSerializer : public DeclVisitor<DeclSerializer> {
3303
3319
if (hasSafeMembers)
3304
3320
return true ;
3305
3321
3306
- // We can mark the extension unsafe only if it has no public
3307
- // conformances .
3322
+ // If the extension has any externally accessible conformances, then it is
3323
+ // externally accessible .
3308
3324
auto protocols = ext->getLocalProtocols (ConformanceLookupKind::All);
3309
3325
bool hasSafeConformances = std::any_of (
3310
- protocols.begin (), protocols.end (), [](ProtocolDecl *protocol) {
3311
- return isDeserializationSafe (protocol);
3326
+ protocols.begin (), protocols.end (), [this ](ProtocolDecl *protocol) {
3327
+ return visit (protocol);
3312
3328
});
3313
3329
3314
3330
if (hasSafeConformances)
3315
3331
return true ;
3316
3332
3317
- // Truly empty extensions are safe, it may happen in swiftinterfaces.
3333
+ // Truly empty extensions are externally accessible. This can occur in
3334
+ // swiftinterfaces, for example.
3318
3335
if (members.empty () && protocols.size () == 0 )
3319
3336
return true ;
3320
3337
3321
3338
return false ;
3322
3339
}
3323
3340
3324
- if (auto pbd = dyn_cast<PatternBindingDecl>(decl)) {
3325
- // Pattern bindings are safe if any of their var decls are safe.
3341
+ bool visitPatternBindingDecl (const PatternBindingDecl *pbd) {
3342
+ // Pattern bindings are externally accessible if any of their var decls
3343
+ // are externally accessible.
3326
3344
for (auto i : range (pbd->getNumPatternEntries ())) {
3327
3345
if (auto *varDecl = pbd->getAnchoringVarDecl (i)) {
3328
3346
if (isDeserializationSafe (varDecl))
@@ -3333,44 +3351,86 @@ class Serializer::DeclSerializer : public DeclVisitor<DeclSerializer> {
3333
3351
return false ;
3334
3352
}
3335
3353
3336
- return isDeserializationSafe (cast<ValueDecl>(decl));
3337
- }
3338
-
3339
- static bool isDeserializationSafe (const ValueDecl *value) {
3340
- // A decl is safe if formally accessible publicly.
3341
- auto accessScope =
3342
- value->getFormalAccessScope (/* useDC=*/ nullptr ,
3343
- /* treatUsableFromInlineAsPublic=*/ true );
3344
- if (accessScope.isPublic () || accessScope.isPackage ())
3345
- return true ;
3346
-
3347
- if (auto accessor = dyn_cast<AccessorDecl>(value))
3348
- // Accessors are as safe as their storage.
3349
- if (isDeserializationSafe (accessor->getStorage ()))
3350
- return true ;
3351
-
3352
- // Frozen fields are always safe.
3353
- if (auto var = dyn_cast<VarDecl>(value)) {
3354
+ bool visitVarDecl (const VarDecl *var) {
3354
3355
if (var->isLayoutExposedToClients ())
3355
3356
return true ;
3356
3357
3357
- // Consider all lazy var storage as "safe" .
3358
+ // Consider all lazy var storage as externally accessible .
3358
3359
// FIXME: We should keep track of what lazy var is associated to the
3359
- // storage for them to preserve the same safeness .
3360
+ // storage for them to preserve the same accessibility .
3360
3361
if (var->isLazyStorageProperty ())
3361
3362
return true ;
3362
3363
3363
- // Property wrappers storage is as safe as the wrapped property.
3364
+ // Property wrapper storage is as externally accessible as the wrapped
3365
+ // property.
3364
3366
if (VarDecl *wrapped = var->getOriginalWrappedProperty ())
3365
- if (isDeserializationSafe (wrapped))
3367
+ if (visit (wrapped))
3366
3368
return true ;
3369
+
3370
+ return false ;
3367
3371
}
3368
3372
3369
- // Paramters don't have meaningful access control.
3370
- if (isa<ParamDecl>(value) || isa<GenericTypeParamDecl>(value))
3371
- return true ;
3373
+ bool visitAccessorDecl (const AccessorDecl *accessor) {
3374
+ // Accessors are as externally accessible as the storage.
3375
+ return visit (accessor->getStorage ());
3376
+ }
3377
+
3378
+ // ValueDecls with effectively public access are considered externally
3379
+ // accessible and are handled in visit(Decl *) above. Some specific kinds of
3380
+ // ValueDecls with additional, unique rules are handled individually above.
3381
+ // ValueDecls that are not effectively public and do not have unique rules
3382
+ // are by default externally inaccessable.
3383
+ #define DEFAULT_TO_ACCESS_LEVEL (KIND ) \
3384
+ bool visit##KIND##Decl(const KIND##Decl *D) { \
3385
+ static_assert (std::is_convertible<KIND##Decl *, ValueDecl *>::value, \
3386
+ " ##KIND##Decl must be a ValueDecl" ); \
3387
+ return false ; \
3388
+ }
3389
+ DEFAULT_TO_ACCESS_LEVEL (NominalType);
3390
+ DEFAULT_TO_ACCESS_LEVEL (OpaqueType);
3391
+ DEFAULT_TO_ACCESS_LEVEL (TypeAlias);
3392
+ DEFAULT_TO_ACCESS_LEVEL (AssociatedType);
3393
+ DEFAULT_TO_ACCESS_LEVEL (AbstractStorage);
3394
+ DEFAULT_TO_ACCESS_LEVEL (AbstractFunction);
3395
+ DEFAULT_TO_ACCESS_LEVEL (Macro);
3396
+ DEFAULT_TO_ACCESS_LEVEL (EnumElement);
3397
+
3398
+ #undef DEFAULT_TO_ACCESS_LEVEL
3399
+
3400
+ // There are several kinds of decls which we never expect to encounter in
3401
+ // external accessibility queries.
3402
+ #define UNREACHABLE (KIND ) \
3403
+ bool visit##KIND##Decl(const KIND##Decl *D) { \
3404
+ llvm_unreachable (" unexpected decl kind" ); \
3405
+ return true ; \
3406
+ }
3407
+ UNREACHABLE (Module);
3408
+ UNREACHABLE (TopLevelCode);
3409
+ UNREACHABLE (Import);
3410
+ UNREACHABLE (PoundDiagnostic);
3411
+ UNREACHABLE (Missing);
3412
+ UNREACHABLE (MissingMember);
3413
+ UNREACHABLE (MacroExpansion);
3414
+ UNREACHABLE (GenericTypeParam);
3415
+ UNREACHABLE (Param);
3416
+ UNREACHABLE (IfConfig);
3417
+ UNREACHABLE (PrecedenceGroup);
3418
+ UNREACHABLE (Operator);
3419
+ UNREACHABLE (EnumCase);
3420
+
3421
+ #undef UNREACHABLE
3422
+ };
3372
3423
3373
- return false ;
3424
+ public:
3425
+ // / Determine if \p decl is safe to deserialize when it's public
3426
+ // / or otherwise needed by the client in normal builds, this should usually
3427
+ // / correspond to logic in type-checking ensuring these safe decls don't
3428
+ // / refer to implementation details. We have to be careful not to mark
3429
+ // / anything needed by a client as unsafe as the client will reject reading
3430
+ // / it, but at the same time keep the safety checks precise to avoid
3431
+ // / XRef errors and such.
3432
+ static bool isDeserializationSafe (const Decl *decl) {
3433
+ return ExternallyAccessibleDeclVisitor ().visit (decl);
3374
3434
}
3375
3435
3376
3436
private:
0 commit comments