@@ -1227,7 +1227,7 @@ bool AbstractStorageDecl::hasFixedLayout() const {
12271227
12281228 // Private and (unversioned) internal variables always have a
12291229 // fixed layout.
1230- if (getEffectiveAccess () != Accessibility::Public)
1230+ if (getEffectiveAccess () < Accessibility::Public)
12311231 return true ;
12321232
12331233 // Check for an explicit @_fixed_layout attribute.
@@ -1794,12 +1794,9 @@ SourceLoc ValueDecl::getAttributeInsertionLoc(bool forModifier) const {
17941794 return resultLoc.isValid () ? resultLoc : getStartLoc ();
17951795}
17961796
1797- // / Returns true if \p VD needs to be treated as publicly-accessible at the SIL,
1798- // / LLVM, and machine levels.
1799- // /
1800- // / The most common causes of this are -enable-testing and versioned non-public
1801- // / declarations.
1802- static bool isInternalDeclEffectivelyPublic (const ValueDecl *VD) {
1797+ // / Returns true if \p VD needs to be treated as publicly-accessible
1798+ // / at the SIL, LLVM, and machine levels due to being versioned.
1799+ static bool isVersionedInternalDecl (const ValueDecl *VD) {
18031800 assert (VD->getFormalAccess () == Accessibility::Internal);
18041801
18051802 if (VD->getAttrs ().hasAttribute <VersionedAttr>())
@@ -1810,21 +1807,43 @@ static bool isInternalDeclEffectivelyPublic(const ValueDecl *VD) {
18101807 if (ASD->getAttrs ().hasAttribute <VersionedAttr>())
18111808 return true ;
18121809
1813- if (VD->getModuleContext ()->isTestingEnabled ())
1814- return true ;
1815-
18161810 return false ;
18171811}
18181812
1813+ // / Return the accessibility of an internal or public declaration
1814+ // / that's been testably imported.
1815+ static Accessibility getTestableAccess (const ValueDecl *decl) {
1816+ // Non-final classes are considered open to @testable importers.
1817+ if (auto cls = dyn_cast<ClassDecl>(decl)) {
1818+ if (!cls->isFinal ())
1819+ return Accessibility::Open;
1820+
1821+ // Non-final overridable class members are considered open to
1822+ // @testable importers.
1823+ } else if (decl->isPotentiallyOverridable ()) {
1824+ if (!cast<ValueDecl>(decl)->isFinal ())
1825+ return Accessibility::Open;
1826+ }
1827+
1828+ // Everything else is considered public.
1829+ return Accessibility::Public;
1830+ }
1831+
18191832Accessibility ValueDecl::getEffectiveAccess () const {
18201833 Accessibility effectiveAccess = getFormalAccess ();
18211834
18221835 // Handle @testable.
18231836 switch (effectiveAccess) {
18241837 case Accessibility::Public:
1838+ if (getModuleContext ()->isTestingEnabled ())
1839+ effectiveAccess = getTestableAccess (this );
1840+ break ;
1841+ case Accessibility::Open:
18251842 break ;
18261843 case Accessibility::Internal:
1827- if (isInternalDeclEffectivelyPublic (this ))
1844+ if (getModuleContext ()->isTestingEnabled ())
1845+ effectiveAccess = getTestableAccess (this );
1846+ else if (isVersionedInternalDecl (this ))
18281847 effectiveAccess = Accessibility::Public;
18291848 break ;
18301849 case Accessibility::FilePrivate:
@@ -1856,13 +1875,14 @@ Accessibility ValueDecl::getEffectiveAccess() const {
18561875}
18571876
18581877Accessibility ValueDecl::getFormalAccessImpl (const DeclContext *useDC) const {
1859- assert (getFormalAccess () == Accessibility::Internal &&
1878+ assert ((getFormalAccess () == Accessibility::Internal ||
1879+ getFormalAccess () == Accessibility::Public) &&
18601880 " should be able to fast-path non-internal cases" );
18611881 assert (useDC && " should fast-path non-scoped cases" );
18621882 if (auto *useSF = dyn_cast<SourceFile>(useDC->getModuleScopeContext ()))
18631883 if (useSF->hasTestableImport (getModuleContext ()))
1864- return Accessibility::Public ;
1865- return Accessibility::Internal ;
1884+ return getTestableAccess ( this ) ;
1885+ return getFormalAccess () ;
18661886}
18671887
18681888const DeclContext *
@@ -1908,6 +1928,7 @@ ValueDecl::getFormalAccessScope(const DeclContext *useDC) const {
19081928 case Accessibility::Internal:
19091929 return result->getParentModule ();
19101930 case Accessibility::Public:
1931+ case Accessibility::Open:
19111932 return nullptr ;
19121933 }
19131934
@@ -1947,7 +1968,7 @@ Type TypeDecl::getDeclaredInterfaceType() const {
19471968bool NominalTypeDecl::hasFixedLayout () const {
19481969 // Private and (unversioned) internal types always have a
19491970 // fixed layout.
1950- if (getEffectiveAccess () != Accessibility::Public)
1971+ if (getEffectiveAccess () < Accessibility::Public)
19511972 return true ;
19521973
19531974 // Check for an explicit @_fixed_layout attribute.
0 commit comments