mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Sema: Use ExportedLevel for isLayoutExposedToClients
This commit is contained in:
@@ -81,6 +81,7 @@ namespace swift {
|
||||
class DiagnosticEngine;
|
||||
class DynamicSelfType;
|
||||
class Type;
|
||||
enum class ExportedLevel;
|
||||
class Expr;
|
||||
struct ExternalSourceLocs;
|
||||
class CaptureListExpr;
|
||||
@@ -6749,10 +6750,7 @@ public:
|
||||
///
|
||||
/// From the standpoint of access control and exportability checking, this
|
||||
/// var will behave as if it was public, even if it is internal or private.
|
||||
///
|
||||
/// If \p applyImplicit, consider implicitly exposed layouts as well.
|
||||
/// This applies to non-resilient modules.
|
||||
bool isLayoutExposedToClients(bool applyImplicit = false) const;
|
||||
ExportedLevel isLayoutExposedToClients() const;
|
||||
|
||||
/// Is this a special debugger variable?
|
||||
bool isDebuggerVar() const { return Bits.VarDecl.IsDebuggerVar; }
|
||||
|
||||
@@ -115,7 +115,7 @@ public:
|
||||
}
|
||||
|
||||
bool visitVarDecl(const VarDecl *var) {
|
||||
if (var->isLayoutExposedToClients())
|
||||
if (var->isLayoutExposedToClients() == ExportedLevel::Exported)
|
||||
return true;
|
||||
|
||||
// Consider all lazy var storage as exportable.
|
||||
|
||||
@@ -1006,8 +1006,7 @@ ExportedLevel swift::isExported(const ValueDecl *VD) {
|
||||
|
||||
// Is this a stored property in a @frozen struct or class?
|
||||
if (auto *property = dyn_cast<VarDecl>(VD))
|
||||
if (property->isLayoutExposedToClients(/*applyImplicit=*/true))
|
||||
return ExportedLevel::Exported;
|
||||
return property->isLayoutExposedToClients();
|
||||
|
||||
// Case of an enum not marked @_implementationOnly in a non-resilient module?
|
||||
if (auto *EED = dyn_cast<EnumElementDecl>(VD))
|
||||
@@ -1020,7 +1019,7 @@ ExportedLevel swift::isExported(const ValueDecl *VD) {
|
||||
VD->getDeclContext()->getParentModule()->getResilienceStrategy() !=
|
||||
ResilienceStrategy::Resilient &&
|
||||
!VD->getAttrs().hasAttribute<ImplementationOnlyAttr>())
|
||||
return ExportedLevel::Exported;
|
||||
return ExportedLevel::ImplicitlyExported;
|
||||
|
||||
return ExportedLevel::None;
|
||||
}
|
||||
|
||||
@@ -2774,44 +2774,44 @@ bool VarDecl::isInitExposedToClients() const {
|
||||
if (getAttrs().hasAttribute<LazyAttr>())
|
||||
return false;
|
||||
|
||||
return hasInitialValue() && isLayoutExposedToClients();
|
||||
return hasInitialValue() &&
|
||||
isLayoutExposedToClients() == ExportedLevel::Exported;
|
||||
}
|
||||
|
||||
bool VarDecl::isLayoutExposedToClients(bool applyImplicit) const {
|
||||
ExportedLevel VarDecl::isLayoutExposedToClients() const {
|
||||
auto parent = dyn_cast<NominalTypeDecl>(getDeclContext());
|
||||
if (!parent) return false;
|
||||
if (isStatic()) return false;
|
||||
|
||||
auto M = getDeclContext()->getParentModule();
|
||||
auto nominalAccess =
|
||||
parent->getFormalAccessScope(/*useDC=*/nullptr,
|
||||
/*treatUsableFromInlineAsPublic=*/true);
|
||||
|
||||
// Resilient modules and classes hide layouts by default.
|
||||
bool layoutIsHiddenByDefault = !applyImplicit ||
|
||||
!getASTContext().LangOpts.hasFeature(Feature::CheckImplementationOnly) ||
|
||||
M->getResilienceStrategy() == ResilienceStrategy::Resilient;
|
||||
if (layoutIsHiddenByDefault) {
|
||||
if (!nominalAccess.isPublic())
|
||||
return false;
|
||||
|
||||
if (!parent->getAttrs().hasAttribute<FrozenAttr>() &&
|
||||
!parent->getAttrs().hasAttribute<FixedLayoutAttr>())
|
||||
return false;
|
||||
} else {
|
||||
// Non-resilient module: layouts are exposed by default unless marked
|
||||
// otherwise.
|
||||
if (parent->getAttrs().hasAttribute<ImplementationOnlyAttr>())
|
||||
return false;
|
||||
}
|
||||
if (!parent) return ExportedLevel::None;
|
||||
if (isStatic()) return ExportedLevel::None;
|
||||
|
||||
// Does it contribute to the layout?
|
||||
if (!hasStorage() &&
|
||||
!getAttrs().hasAttribute<LazyAttr>() &&
|
||||
!hasAttachedPropertyWrapper()) {
|
||||
return false;
|
||||
return ExportedLevel::None;
|
||||
}
|
||||
|
||||
return true;
|
||||
// Is it a member of a frozen type?
|
||||
auto nominalAccess =
|
||||
parent->getFormalAccessScope(/*useDC=*/nullptr,
|
||||
/*treatUsableFromInlineAsPublic=*/true);
|
||||
if (nominalAccess.isPublic() &&
|
||||
(parent->getAttrs().hasAttribute<FrozenAttr>() ||
|
||||
parent->getAttrs().hasAttribute<FixedLayoutAttr>()))
|
||||
return ExportedLevel::Exported;
|
||||
|
||||
// Is it a member of an `@_implementationOnly` type?
|
||||
if (parent->getAttrs().hasAttribute<ImplementationOnlyAttr>())
|
||||
return ExportedLevel::None;
|
||||
|
||||
auto M = getDeclContext()->getParentModule();
|
||||
if (getASTContext().LangOpts.hasFeature(Feature::CheckImplementationOnly) &&
|
||||
M->getResilienceStrategy() != ResilienceStrategy::Resilient) {
|
||||
// Non-resilient module expose layouts by default.
|
||||
return ExportedLevel::ImplicitlyExported;
|
||||
} else {
|
||||
// Resilient modules hide layouts by default.
|
||||
return ExportedLevel::None;
|
||||
}
|
||||
}
|
||||
|
||||
/// Check whether the given type representation will be
|
||||
|
||||
@@ -1498,7 +1498,7 @@ public:
|
||||
/// the struct instead of the VarDecl, and customize the diagnostics.
|
||||
static const ValueDecl *
|
||||
getFixedLayoutStructContext(const VarDecl *VD) {
|
||||
if (VD->isLayoutExposedToClients())
|
||||
if (VD->isLayoutExposedToClients() == ExportedLevel::Exported)
|
||||
return dyn_cast<NominalTypeDecl>(VD->getDeclContext());
|
||||
|
||||
return nullptr;
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include "swift/AST/ClangModuleLoader.h"
|
||||
#include "swift/AST/ConformanceLookup.h"
|
||||
#include "swift/AST/Decl.h"
|
||||
#include "swift/AST/DeclExportabilityVisitor.h"
|
||||
#include "swift/AST/DiagnosticsParse.h"
|
||||
#include "swift/AST/DiagnosticsSema.h"
|
||||
#include "swift/AST/Effects.h"
|
||||
@@ -1408,7 +1409,7 @@ void AttributeChecker::visitSPIAccessControlAttr(SPIAccessControlAttr *attr) {
|
||||
// Forbid stored properties marked SPI in frozen types.
|
||||
if (auto property = dyn_cast<VarDecl>(VD)) {
|
||||
if (auto NTD = dyn_cast<NominalTypeDecl>(D->getDeclContext())) {
|
||||
if (property->isLayoutExposedToClients() && !NTD->isSPI()) {
|
||||
if (property->isLayoutExposedToClients() == ExportedLevel::Exported && !NTD->isSPI()) {
|
||||
diagnoseAndRemoveAttr(attr,
|
||||
diag::spi_attribute_on_frozen_stored_properties,
|
||||
VD);
|
||||
|
||||
Reference in New Issue
Block a user