1- // ===--- Serialization.cpp - Read and write Swift modules -----------------===//
1+ // ===--- Serialization.cpp - Read and write Swift modules -----------------===//
22//
33// This source file is part of the Swift.org open source project
44//
@@ -3276,23 +3276,39 @@ class Serializer::DeclSerializer : public DeclVisitor<DeclSerializer> {
32763276 return count;
32773277 }
32783278
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.
32903305 auto nominalType = ext->getExtendedNominal ();
32913306 if (!nominalType ||
32923307 !isDeserializationSafe (nominalType))
32933308 return false ;
32943309
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.
32963312 auto members = ext->getMembers ();
32973313 auto hasSafeMembers = std::any_of (members.begin (), members.end (),
32983314 [](const Decl *D) -> bool {
@@ -3303,26 +3319,28 @@ class Serializer::DeclSerializer : public DeclVisitor<DeclSerializer> {
33033319 if (hasSafeMembers)
33043320 return true ;
33053321
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 .
33083324 auto protocols = ext->getLocalProtocols (ConformanceLookupKind::All);
33093325 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);
33123328 });
33133329
33143330 if (hasSafeConformances)
33153331 return true ;
33163332
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.
33183335 if (members.empty () && protocols.size () == 0 )
33193336 return true ;
33203337
33213338 return false ;
33223339 }
33233340
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.
33263344 for (auto i : range (pbd->getNumPatternEntries ())) {
33273345 if (auto *varDecl = pbd->getAnchoringVarDecl (i)) {
33283346 if (isDeserializationSafe (varDecl))
@@ -3333,44 +3351,86 @@ class Serializer::DeclSerializer : public DeclVisitor<DeclSerializer> {
33333351 return false ;
33343352 }
33353353
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) {
33543355 if (var->isLayoutExposedToClients ())
33553356 return true ;
33563357
3357- // Consider all lazy var storage as "safe" .
3358+ // Consider all lazy var storage as externally accessible .
33583359 // 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 .
33603361 if (var->isLazyStorageProperty ())
33613362 return true ;
33623363
3363- // Property wrappers storage is as safe as the wrapped property.
3364+ // Property wrapper storage is as externally accessible as the wrapped
3365+ // property.
33643366 if (VarDecl *wrapped = var->getOriginalWrappedProperty ())
3365- if (isDeserializationSafe (wrapped))
3367+ if (visit (wrapped))
33663368 return true ;
3369+
3370+ return false ;
33673371 }
33683372
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+ };
33723423
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);
33743434 }
33753435
33763436private:
0 commit comments