[Sema] Intro @_spiOnly attribute and import filter

Introduce the attribute and basic import filter logic.
This commit is contained in:
Alexis Laferrière
2022-08-25 09:40:58 -07:00
parent cf8f61d76b
commit aaaef3411e
8 changed files with 29 additions and 3 deletions

View File

@@ -768,6 +768,11 @@ SIMPLE_DECL_ATTR(typeWrapper, TypeWrapper,
ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove,
134)
SIMPLE_DECL_ATTR(_spiOnly, SPIOnly,
OnImport | UserInaccessible |
ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove,
135)
// If you're adding a new underscored attribute here, please document it in
// docs/ReferenceGuides/UnderscoredAttributes.md.

View File

@@ -88,7 +88,11 @@ enum class ImportFlags {
WeakLinked = 0x40,
/// Used for DenseMap.
Reserved = 0x80
Reserved = 0x80,
/// The imported module can only be referenced from SPI decls, or
/// implementation details.
SPIOnly = 0x100
};
/// \see ImportFlags

View File

@@ -696,11 +696,13 @@ public:
Default = 1 << 1,
/// Include imports declared with `@_implementationOnly`.
ImplementationOnly = 1 << 2,
/// Include imports of SPIs declared with `@_spi`
/// Include imports of SPIs declared with `@_spi`.
SPIAccessControl = 1 << 3,
/// Include imports declared with `@_spiOnly`.
SPIOnly = 1 << 4,
/// Include imports shadowed by a cross-import overlay. Unshadowed imports
/// are included whether or not this flag is specified.
ShadowedByCrossImportOverlay = 1 << 4
ShadowedByCrossImportOverlay = 1 << 5
};
/// \sa getImportedModules
using ImportFilter = OptionSet<ImportFilterKind>;

View File

@@ -195,6 +195,7 @@ ImportSet &ImportCache::getImportSet(const DeclContext *dc) {
file->getImportedModules(imports,
{ModuleDecl::ImportFilterKind::Default,
ModuleDecl::ImportFilterKind::ImplementationOnly,
ModuleDecl::ImportFilterKind::SPIOnly,
ModuleDecl::ImportFilterKind::SPIAccessControl});
}
@@ -279,6 +280,7 @@ ImportCache::getAllAccessPathsNotShadowedBy(const ModuleDecl *mod,
file->getImportedModules(stack,
{ModuleDecl::ImportFilterKind::Default,
ModuleDecl::ImportFilterKind::ImplementationOnly,
ModuleDecl::ImportFilterKind::SPIOnly,
ModuleDecl::ImportFilterKind::SPIAccessControl});
}

View File

@@ -1596,6 +1596,8 @@ SourceFile::getImportedModules(SmallVectorImpl<ImportedModule> &modules,
requiredFilter |= ModuleDecl::ImportFilterKind::Exported;
else if (desc.options.contains(ImportFlags::ImplementationOnly))
requiredFilter |= ModuleDecl::ImportFilterKind::ImplementationOnly;
else if (desc.options.contains(ImportFlags::SPIOnly))
requiredFilter |= ModuleDecl::ImportFilterKind::SPIOnly;
else if (desc.options.contains(ImportFlags::SPIAccessControl))
requiredFilter |= ModuleDecl::ImportFilterKind::SPIAccessControl;
else
@@ -1904,6 +1906,7 @@ SourceFile::collectLinkLibraries(ModuleDecl::LinkLibraryCallback callback) const
ModuleDecl::ImportFilter topLevelFilter = filter;
topLevelFilter |= ModuleDecl::ImportFilterKind::ImplementationOnly;
topLevelFilter |= ModuleDecl::ImportFilterKind::SPIOnly;
topLevel->getImportedModules(stack, topLevelFilter);
// Make sure the top-level module is first; we want pre-order-ish traversal.
@@ -2600,6 +2603,7 @@ canBeUsedForCrossModuleOptimization(DeclContext *ctxt) const {
// @_implementationOnly or @_spi.
ModuleDecl::ImportFilter filter = {
ModuleDecl::ImportFilterKind::ImplementationOnly,
ModuleDecl::ImportFilterKind::SPIOnly,
ModuleDecl::ImportFilterKind::SPIAccessControl
};
SmallVector<ImportedModule, 4> results;

View File

@@ -536,6 +536,9 @@ UnboundImport::UnboundImport(ImportDecl *ID)
if (ID->getAttrs().hasAttribute<ImplementationOnlyAttr>())
import.options |= ImportFlags::ImplementationOnly;
if (ID->getAttrs().hasAttribute<SPIOnlyAttr>())
import.options |= ImportFlags::SPIOnly;
if (auto *privateImportAttr =
ID->getAttrs().getAttribute<PrivateImportAttr>()) {
import.options |= ImportFlags::PrivateImport;

View File

@@ -296,6 +296,7 @@ public:
void visitResultBuilderAttr(ResultBuilderAttr *attr);
void visitImplementationOnlyAttr(ImplementationOnlyAttr *attr);
void visitSPIOnlyAttr(SPIOnlyAttr *attr);
void visitNonEphemeralAttr(NonEphemeralAttr *attr);
void checkOriginalDefinedInAttrs(ArrayRef<OriginallyDefinedInAttr *> Attrs);
@@ -3908,6 +3909,10 @@ AttributeChecker::visitImplementationOnlyAttr(ImplementationOnlyAttr *attr) {
// it won't necessarily be able to say why.
}
void
AttributeChecker::visitSPIOnlyAttr(SPIOnlyAttr *attr) {
}
void AttributeChecker::visitTypeSequenceAttr(TypeSequenceAttr *attr) {
if (!isa<GenericTypeParamDecl>(D)) {
attr->setInvalid();

View File

@@ -1582,6 +1582,7 @@ namespace {
UNINTERESTING_ATTR(Frozen)
UNINTERESTING_ATTR(HasInitialValue)
UNINTERESTING_ATTR(ImplementationOnly)
UNINTERESTING_ATTR(SPIOnly)
UNINTERESTING_ATTR(Custom)
UNINTERESTING_ATTR(PropertyWrapper)
UNINTERESTING_ATTR(TypeWrapper)