Sema: Accept @_implementationOnly on non-public structs

Gate it behind CheckImplementationOnly.
This commit is contained in:
Alexis Laferrière
2025-10-21 15:48:56 -07:00
parent 62ee4486d7
commit 71035a51de
3 changed files with 23 additions and 2 deletions

View File

@@ -474,7 +474,7 @@ SIMPLE_DECL_ATTR(_alwaysEmitIntoClient, AlwaysEmitIntoClient,
83)
SIMPLE_DECL_ATTR(_implementationOnly, ImplementationOnly,
OnImport | OnFunc | OnConstructor | OnVar | OnSubscript,
OnImport | OnFunc | OnConstructor | OnVar | OnSubscript | OnStruct,
UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | UnreachableInABIAttr,
84)

View File

@@ -3946,6 +3946,9 @@ ERROR(implementation_only_override_import_without_attr,none,
"override of %kindonly0 imported as implementation-only must be declared "
"'@_implementationOnly'",
(const ValueDecl *))
ERROR(implementation_only_on_structs_feature,none,
"'@_implementationOnly' on structs requires "
"'-enable-experimental-feature CheckImplementationOnly'", ())
ERROR(import_attr_conflict,none,
"%0 inconsistently imported with %1",
@@ -4128,7 +4131,7 @@ WARNING(attr_has_no_effect_on_decl_with_access_level,none,
(DeclAttribute, AccessLevel))
ERROR(attr_not_on_decl_with_invalid_access_level,none,
"'%0' may not be used on "
"%select{private|fileprivate|internal|package|%error|%error}1 declarations",
"%select{private|fileprivate|internal|package|public|%error}1 declarations",
(DeclAttribute, AccessLevel))
ERROR(attr_has_no_effect_decl_not_available_before,none,

View File

@@ -4995,7 +4995,25 @@ AttributeChecker::visitImplementationOnlyAttr(ImplementationOnlyAttr *attr) {
return;
}
// @_implementationOnly on structs only applies to non-public types.
auto *VD = cast<ValueDecl>(D);
if (isa<StructDecl>(VD)) {
if (!Ctx.LangOpts.hasFeature(Feature::CheckImplementationOnly)) {
diagnoseAndRemoveAttr(attr,
diag::implementation_only_on_structs_feature);
return;
}
auto access =
VD->getFormalAccessScope(/*useDC=*/nullptr,
/*treatUsableFromInlineAsPublic=*/true);
if (access.isPublicOrPackage())
diagnoseAndRemoveAttr(
attr, diag::attr_not_on_decl_with_invalid_access_level,
attr, access.accessLevelForDiagnostics());
return;
}
auto *overridden = VD->getOverriddenDecl();
if (!overridden) {
diagnoseAndRemoveAttr(attr, diag::implementation_only_decl_non_override);