Skip to content

Commit 60731d9

Browse files
committed
Sema: Use ExportedLevel for isLayoutExposedToClients
1 parent bf951b1 commit 60731d9

File tree

6 files changed

+35
-37
lines changed

6 files changed

+35
-37
lines changed

include/swift/AST/Decl.h

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ namespace swift {
8181
class DiagnosticEngine;
8282
class DynamicSelfType;
8383
class Type;
84+
enum class ExportedLevel;
8485
class Expr;
8586
struct ExternalSourceLocs;
8687
class CaptureListExpr;
@@ -6749,10 +6750,7 @@ class VarDecl : public AbstractStorageDecl {
67496750
///
67506751
/// From the standpoint of access control and exportability checking, this
67516752
/// var will behave as if it was public, even if it is internal or private.
6752-
///
6753-
/// If \p applyImplicit, consider implicitly exposed layouts as well.
6754-
/// This applies to non-resilient modules.
6755-
bool isLayoutExposedToClients(bool applyImplicit = false) const;
6753+
ExportedLevel isLayoutExposedToClients() const;
67566754

67576755
/// Is this a special debugger variable?
67586756
bool isDebuggerVar() const { return Bits.VarDecl.IsDebuggerVar; }

include/swift/AST/DeclExportabilityVisitor.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ class DeclExportabilityVisitor
115115
}
116116

117117
bool visitVarDecl(const VarDecl *var) {
118-
if (var->isLayoutExposedToClients())
118+
if (var->isLayoutExposedToClients() == ExportedLevel::Exported)
119119
return true;
120120

121121
// Consider all lazy var storage as exportable.

lib/AST/Availability.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1006,8 +1006,7 @@ ExportedLevel swift::isExported(const ValueDecl *VD) {
10061006

10071007
// Is this a stored property in a @frozen struct or class?
10081008
if (auto *property = dyn_cast<VarDecl>(VD))
1009-
if (property->isLayoutExposedToClients(/*applyImplicit=*/true))
1010-
return ExportedLevel::Exported;
1009+
return property->isLayoutExposedToClients();
10111010

10121011
// Case of an enum not marked @_implementationOnly in a non-resilient module?
10131012
if (auto *EED = dyn_cast<EnumElementDecl>(VD))
@@ -1020,7 +1019,7 @@ ExportedLevel swift::isExported(const ValueDecl *VD) {
10201019
VD->getDeclContext()->getParentModule()->getResilienceStrategy() !=
10211020
ResilienceStrategy::Resilient &&
10221021
!VD->getAttrs().hasAttribute<ImplementationOnlyAttr>())
1023-
return ExportedLevel::Exported;
1022+
return ExportedLevel::ImplicitlyExported;
10241023

10251024
return ExportedLevel::None;
10261025
}

lib/AST/Decl.cpp

Lines changed: 27 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -2774,44 +2774,44 @@ bool VarDecl::isInitExposedToClients() const {
27742774
if (getAttrs().hasAttribute<LazyAttr>())
27752775
return false;
27762776

2777-
return hasInitialValue() && isLayoutExposedToClients();
2777+
return hasInitialValue() &&
2778+
isLayoutExposedToClients() == ExportedLevel::Exported;
27782779
}
27792780

2780-
bool VarDecl::isLayoutExposedToClients(bool applyImplicit) const {
2781+
ExportedLevel VarDecl::isLayoutExposedToClients() const {
27812782
auto parent = dyn_cast<NominalTypeDecl>(getDeclContext());
2782-
if (!parent) return false;
2783-
if (isStatic()) return false;
2783+
if (!parent) return ExportedLevel::None;
2784+
if (isStatic()) return ExportedLevel::None;
27842785

2785-
auto M = getDeclContext()->getParentModule();
2786+
// Does it contribute to the layout?
2787+
if (!hasStorage() &&
2788+
!getAttrs().hasAttribute<LazyAttr>() &&
2789+
!hasAttachedPropertyWrapper()) {
2790+
return ExportedLevel::None;
2791+
}
2792+
2793+
// Is it a member of a frozen type?
27862794
auto nominalAccess =
27872795
parent->getFormalAccessScope(/*useDC=*/nullptr,
27882796
/*treatUsableFromInlineAsPublic=*/true);
2797+
if (nominalAccess.isPublic() &&
2798+
(parent->getAttrs().hasAttribute<FrozenAttr>() ||
2799+
parent->getAttrs().hasAttribute<FixedLayoutAttr>()))
2800+
return ExportedLevel::Exported;
27892801

2790-
// Resilient modules and classes hide layouts by default.
2791-
bool layoutIsHiddenByDefault = !applyImplicit ||
2792-
!getASTContext().LangOpts.hasFeature(Feature::CheckImplementationOnly) ||
2793-
M->getResilienceStrategy() == ResilienceStrategy::Resilient;
2794-
if (layoutIsHiddenByDefault) {
2795-
if (!nominalAccess.isPublic())
2796-
return false;
2802+
// Is it a member of an `@_implementationOnly` type?
2803+
if (parent->getAttrs().hasAttribute<ImplementationOnlyAttr>())
2804+
return ExportedLevel::None;
27972805

2798-
if (!parent->getAttrs().hasAttribute<FrozenAttr>() &&
2799-
!parent->getAttrs().hasAttribute<FixedLayoutAttr>())
2800-
return false;
2806+
auto M = getDeclContext()->getParentModule();
2807+
if (getASTContext().LangOpts.hasFeature(Feature::CheckImplementationOnly) &&
2808+
M->getResilienceStrategy() != ResilienceStrategy::Resilient) {
2809+
// Non-resilient module expose layouts by default.
2810+
return ExportedLevel::ImplicitlyExported;
28012811
} else {
2802-
// Non-resilient module: layouts are exposed by default unless marked
2803-
// otherwise.
2804-
if (parent->getAttrs().hasAttribute<ImplementationOnlyAttr>())
2805-
return false;
2812+
// Resilient modules hide layouts by default.
2813+
return ExportedLevel::None;
28062814
}
2807-
2808-
if (!hasStorage() &&
2809-
!getAttrs().hasAttribute<LazyAttr>() &&
2810-
!hasAttachedPropertyWrapper()) {
2811-
return false;
2812-
}
2813-
2814-
return true;
28152815
}
28162816

28172817
/// Check whether the given type representation will be

lib/Sema/TypeCheckAccess.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1498,7 +1498,7 @@ class UsableFromInlineChecker : public AccessControlCheckerBase,
14981498
/// the struct instead of the VarDecl, and customize the diagnostics.
14991499
static const ValueDecl *
15001500
getFixedLayoutStructContext(const VarDecl *VD) {
1501-
if (VD->isLayoutExposedToClients())
1501+
if (VD->isLayoutExposedToClients() == ExportedLevel::Exported)
15021502
return dyn_cast<NominalTypeDecl>(VD->getDeclContext());
15031503

15041504
return nullptr;

lib/Sema/TypeCheckAttr.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include "swift/AST/ClangModuleLoader.h"
3131
#include "swift/AST/ConformanceLookup.h"
3232
#include "swift/AST/Decl.h"
33+
#include "swift/AST/DeclExportabilityVisitor.h"
3334
#include "swift/AST/DiagnosticsParse.h"
3435
#include "swift/AST/DiagnosticsSema.h"
3536
#include "swift/AST/Effects.h"
@@ -1408,7 +1409,7 @@ void AttributeChecker::visitSPIAccessControlAttr(SPIAccessControlAttr *attr) {
14081409
// Forbid stored properties marked SPI in frozen types.
14091410
if (auto property = dyn_cast<VarDecl>(VD)) {
14101411
if (auto NTD = dyn_cast<NominalTypeDecl>(D->getDeclContext())) {
1411-
if (property->isLayoutExposedToClients() && !NTD->isSPI()) {
1412+
if (property->isLayoutExposedToClients() == ExportedLevel::Exported && !NTD->isSPI()) {
14121413
diagnoseAndRemoveAttr(attr,
14131414
diag::spi_attribute_on_frozen_stored_properties,
14141415
VD);

0 commit comments

Comments
 (0)