Skip to content

Commit 7bd5850

Browse files
committed
[AST] Intro and use isSPI and getSPIGroups
1 parent fd4feac commit 7bd5850

File tree

6 files changed

+46
-34
lines changed

6 files changed

+46
-34
lines changed

include/swift/AST/Decl.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -927,6 +927,16 @@ class alignas(1 << DeclAlignInBits) Decl {
927927
/// @_originalDefinedIn attribute, this function returns this module name.
928928
StringRef getAlternateModuleName() const;
929929

930+
// Is this Decl an SPI? It can be directly marked with @_spi or is defined in
931+
// an @_spi context.
932+
bool isSPI() const;
933+
934+
// List the SPI groups declared with @_spi or inherited by this decl.
935+
//
936+
// SPI groups are inherited from the parent contexts only if the local decl
937+
// doesn't declare any @_spi.
938+
ArrayRef<Identifier> getSPIGroups() const;
939+
930940
/// Emit a diagnostic tied to this declaration.
931941
template<typename ...ArgTypes>
932942
InFlightDiagnostic diagnose(

include/swift/AST/TypeCheckerTypeIDZone.def

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -105,9 +105,6 @@ SWIFT_REQUEST(TypeChecker, IsDynamicRequest, bool(ValueDecl *),
105105
SeparatelyCached, NoLocationInfo)
106106
SWIFT_REQUEST(TypeChecker, IsFinalRequest, bool(ValueDecl *), SeparatelyCached,
107107
NoLocationInfo)
108-
SWIFT_REQUEST(TypeChecker, SPIGroupsRequest,
109-
llvm::ArrayRef<Identifier>(Decl *),
110-
Cached, NoLocationInfo)
111108
SWIFT_REQUEST(TypeChecker, IsGetterMutatingRequest, bool(AbstractStorageDecl *),
112109
SeparatelyCached, NoLocationInfo)
113110
SWIFT_REQUEST(TypeChecker, IsImplicitlyUnwrappedOptionalRequest,
@@ -210,6 +207,9 @@ SWIFT_REQUEST(TypeChecker, PreCheckFunctionBuilderRequest,
210207
SWIFT_REQUEST(TypeChecker, ResolveImplicitMemberRequest,
211208
bool(NominalTypeDecl *, ImplicitMemberAction), Uncached,
212209
NoLocationInfo)
210+
SWIFT_REQUEST(TypeChecker, SPIGroupsRequest,
211+
llvm::ArrayRef<Identifier>(Decl *),
212+
Cached, NoLocationInfo)
213213
SWIFT_REQUEST(TypeChecker, SynthesizeMemberwiseInitRequest,
214214
ConstructorDecl *(NominalTypeDecl *), Cached, NoLocationInfo)
215215
SWIFT_REQUEST(TypeChecker, HasDefaultInitRequest,

lib/AST/ASTPrinter.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -156,8 +156,7 @@ PrintOptions PrintOptions::printSwiftInterfaceFile(bool preferTypeRepr,
156156
return true;
157157

158158
// Always print SPI decls if `PrintSPIs`.
159-
if (options.PrintSPIs &&
160-
VD->getAttrs().hasAttribute<SPIAccessControlAttr>())
159+
if (options.PrintSPIs && VD->isSPI())
161160
return true;
162161

163162
return false;

lib/AST/Decl.cpp

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3209,8 +3209,7 @@ static AccessLevel getAdjustedFormalAccess(const ValueDecl *VD,
32093209
if (!useSF) return access;
32103210
if (useSF->hasTestableOrPrivateImport(access, VD))
32113211
return getMaximallyOpenAccessFor(VD);
3212-
} else if (!treatSPIAsPublic &&
3213-
VD->getAttrs().hasAttribute<SPIAccessControlAttr>()) {
3212+
} else if (!treatSPIAsPublic && VD->isSPI()) {
32143213
// Restrict access to SPI decls.
32153214
return AccessLevel::Internal;
32163215
}
@@ -3368,9 +3367,7 @@ getAccessScopeForFormalAccess(const ValueDecl *VD,
33683367
case AccessLevel::Open: {
33693368
if (useDC) {
33703369
auto *useSF = dyn_cast<SourceFile>(useDC->getModuleScopeContext());
3371-
if (useSF &&
3372-
VD->getAttrs().hasAttribute<SPIAccessControlAttr>() &&
3373-
!useSF->isImportedAsSPI(VD))
3370+
if (useSF && VD->isSPI() && !useSF->isImportedAsSPI(VD))
33743371
return AccessScope(VD->getModuleContext(), /*private*/false);
33753372
}
33763373
return AccessScope::getPublic();
@@ -3482,9 +3479,7 @@ static bool checkAccess(const DeclContext *useDC, const ValueDecl *VD,
34823479
case AccessLevel::Open: {
34833480
if (useDC) {
34843481
auto *useSF = dyn_cast<SourceFile>(useDC->getModuleScopeContext());
3485-
if (useSF &&
3486-
VD->getAttrs().hasAttribute<SPIAccessControlAttr>() &&
3487-
!useSF->isImportedAsSPI(VD))
3482+
if (useSF && VD->isSPI() && !useSF->isImportedAsSPI(VD))
34883483
return false;
34893484
}
34903485
return true;

lib/AST/Module.cpp

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1825,10 +1825,7 @@ bool SourceFile::isImportedAsSPI(const ValueDecl *targetDecl) const {
18251825
lookupImportedSPIGroups(targetModule, importedSPIGroups);
18261826
if (importedSPIGroups.empty()) return false;
18271827

1828-
auto declSPIGroups = evaluateOrDefault(
1829-
targetDecl->getASTContext().evaluator,
1830-
SPIGroupsRequest{ targetDecl },
1831-
ArrayRef<Identifier>());
1828+
auto declSPIGroups = targetDecl->getSPIGroups();
18321829

18331830
// Note: If we reach a point where there are many SPI imports or SPI groups
18341831
// on decls we could optimize this further by using a set.
@@ -1840,15 +1837,30 @@ bool SourceFile::isImportedAsSPI(const ValueDecl *targetDecl) const {
18401837
return false;
18411838
}
18421839

1843-
llvm::Expected<llvm::ArrayRef<Identifier>>
1844-
SPIGroupsRequest::evaluate(Evaluator &evaluator, const Decl *decl) const {
1845-
// Applies only to public ValueDecls and ExtensionDecls.
1846-
if (auto vd = dyn_cast<ValueDecl>(decl)) {
1840+
bool Decl::isSPI() const {
1841+
return !getSPIGroups().empty();
1842+
}
1843+
1844+
ArrayRef<Identifier> Decl::getSPIGroups() const {
1845+
if (auto vd = dyn_cast<ValueDecl>(this)) {
18471846
if (vd->getFormalAccess() < AccessLevel::Public)
18481847
return ArrayRef<Identifier>();
1849-
} else if (!isa<ExtensionDecl>(decl))
1848+
} else if (!isa<ExtensionDecl>(this))
18501849
return ArrayRef<Identifier>();
18511850

1851+
return evaluateOrDefault(getASTContext().evaluator,
1852+
SPIGroupsRequest{ this },
1853+
ArrayRef<Identifier>());
1854+
}
1855+
1856+
llvm::Expected<llvm::ArrayRef<Identifier>>
1857+
SPIGroupsRequest::evaluate(Evaluator &evaluator, const Decl *decl) const {
1858+
// Applies only to public ValueDecls and ExtensionDecls.
1859+
if (auto vd = dyn_cast<ValueDecl>(decl))
1860+
assert(vd->getFormalAccess() >= AccessLevel::Public);
1861+
else
1862+
assert(isa<ExtensionDecl>(decl));
1863+
18521864
// First, look for local attributes.
18531865
llvm::SetVector<Identifier> spiGroups;
18541866
for (auto attr : decl->getAttrs().getAttributes<SPIAccessControlAttr>())
@@ -1861,19 +1873,15 @@ SPIGroupsRequest::evaluate(Evaluator &evaluator, const Decl *decl) const {
18611873
// Then in the extended nominal type.
18621874
if (auto extension = dyn_cast<ExtensionDecl>(decl)) {
18631875
auto extended = extension->getExtendedNominal();
1864-
auto extSPIs = evaluateOrDefault(ctx.evaluator,
1865-
SPIGroupsRequest{ extended },
1866-
ArrayRef<Identifier>());
1876+
auto extSPIs = extended->getSPIGroups();
18671877
if (!extSPIs.empty()) return extSPIs;
18681878
}
18691879

18701880
// And finally in the parent context.
18711881
auto parent = decl->getDeclContext();
18721882
if (auto parentD = parent->getAsDecl()) {
18731883
if (!isa<ModuleDecl>(parentD)) {
1874-
return evaluateOrDefault(ctx.evaluator,
1875-
SPIGroupsRequest{ parentD },
1876-
ArrayRef<Identifier>());
1884+
return parentD->getSPIGroups();
18771885
}
18781886
}
18791887
}

lib/Sema/TypeCheckAccess.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -288,8 +288,7 @@ void AccessControlCheckerBase::checkTypeAccessImpl(
288288
// If in SPI mode, don't report SPI use from within the same module.
289289
if (auto CITR = dyn_cast<ComponentIdentTypeRepr>(complainRepr)) {
290290
const ValueDecl *VD = CITR->getBoundDecl();
291-
if (useDC->getParentModule() == VD->getModuleContext() &&
292-
VD->getAttrs().hasAttribute<SPIAccessControlAttr>())
291+
if (useDC->getParentModule() == VD->getModuleContext() && VD->isSPI())
293292
return;
294293
}
295294
}
@@ -319,8 +318,7 @@ void AccessControlCheckerBase::checkTypeAccess(
319318
context->getFormalAccessScope(
320319
context->getDeclContext(), checkUsableFromInline);
321320

322-
auto fromSPI = static_cast<FromSPI>(
323-
context->getAttrs().hasAttribute<SPIAccessControlAttr>());
321+
auto fromSPI = static_cast<FromSPI>(context->isSPI());
324322
checkTypeAccessImpl(type, typeRepr, contextAccessScope, DC, mayBeInferred,
325323
fromSPI, diagnose);
326324
}
@@ -381,8 +379,10 @@ void AccessControlCheckerBase::checkGenericParamAccess(
381379
};
382380

383381
auto *DC = ownerDecl->getDeclContext();
384-
auto fromSPI = static_cast<FromSPI>(
385-
ownerDecl->getAttrs().hasAttribute<SPIAccessControlAttr>());
382+
auto fromSPI = FromSPI::No;
383+
if (auto ownerValueDecl = dyn_cast<ValueDecl>(ownerDecl)) {
384+
fromSPI = static_cast<FromSPI>(ownerValueDecl->isSPI());
385+
}
386386

387387
for (auto param : *params) {
388388
if (param->getInherited().empty())

0 commit comments

Comments
 (0)