Skip to content

Commit 0c51dda

Browse files
committed
Sema: Pull @_implementationOnly override checking out of ExportabilityChecker
1 parent bce6620 commit 0c51dda

File tree

4 files changed

+59
-37
lines changed

4 files changed

+59
-37
lines changed

lib/Sema/TypeCheckAccess.cpp

Lines changed: 0 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1737,48 +1737,13 @@ class ExportabilityChecker : public DeclVisitor<ExportabilityChecker> {
17371737
return true;
17381738
}
17391739

1740-
void checkOverride(const ValueDecl *VD) {
1741-
const ValueDecl *overridden = VD->getOverriddenDecl();
1742-
if (!overridden)
1743-
return;
1744-
1745-
auto *SF = VD->getDeclContext()->getParentSourceFile();
1746-
assert(SF && "checking a non-source declaration?");
1747-
1748-
ModuleDecl *M = overridden->getModuleContext();
1749-
if (SF->isImportedImplementationOnly(M)) {
1750-
VD->diagnose(diag::implementation_only_override_import_without_attr,
1751-
overridden->getDescriptiveKind())
1752-
.fixItInsert(VD->getAttributeInsertionLoc(false),
1753-
"@_implementationOnly ");
1754-
overridden->diagnose(diag::overridden_here);
1755-
return;
1756-
}
1757-
1758-
if (overridden->getAttrs().hasAttribute<ImplementationOnlyAttr>()) {
1759-
VD->diagnose(diag::implementation_only_override_without_attr,
1760-
overridden->getDescriptiveKind())
1761-
.fixItInsert(VD->getAttributeInsertionLoc(false),
1762-
"@_implementationOnly ");
1763-
overridden->diagnose(diag::overridden_here);
1764-
return;
1765-
}
1766-
1767-
// FIXME: Check storage decls where the setter is in a separate module from
1768-
// the getter, which is a thing Objective-C can do. The ClangImporter
1769-
// doesn't make this easy, though, because it just gives the setter the same
1770-
// DeclContext as the property or subscript, which means we've lost the
1771-
// information about whether its module was implementation-only imported.
1772-
}
1773-
17741740
void visit(Decl *D) {
17751741
if (D->isInvalid() || D->isImplicit())
17761742
return;
17771743

17781744
if (auto *VD = dyn_cast<ValueDecl>(D)) {
17791745
if (shouldSkipChecking(VD))
17801746
return;
1781-
checkOverride(VD);
17821747
}
17831748

17841749
// Note: references to @_spi and @_implementationOnly declarations from
@@ -1828,8 +1793,6 @@ class ExportabilityChecker : public DeclVisitor<ExportabilityChecker> {
18281793
if (shouldSkipChecking(theVar))
18291794
return;
18301795

1831-
checkOverride(theVar);
1832-
18331796
// Only check the type of individual variables if we didn't check an
18341797
// enclosing TypedPattern.
18351798
if (seenVars.count(theVar) || theVar->isInvalid())

lib/Sema/TypeCheckDecl.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ const ConstructorDecl *findNonImplicitRequiredInit(const ConstructorDecl *CD);
3333

3434
// Implemented in TypeCheckDeclOverride.cpp
3535
bool checkOverrides(ValueDecl *decl);
36+
void checkImplementationOnlyOverride(const ValueDecl *VD);
3637

3738
// Implemented in TypeCheckStorage.cpp
3839
void setBoundVarsTypeError(Pattern *pattern, ASTContext &ctx);

lib/Sema/TypeCheckDeclOverride.cpp

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2156,3 +2156,53 @@ bool IsABICompatibleOverrideRequest::evaluate(Evaluator &evaluator,
21562156
return derivedInterfaceTy->matches(overrideInterfaceTy,
21572157
TypeMatchFlags::AllowABICompatible);
21582158
}
2159+
2160+
void swift::checkImplementationOnlyOverride(const ValueDecl *VD) {
2161+
if (VD->isImplicit())
2162+
return;
2163+
2164+
if (VD->getAttrs().hasAttribute<ImplementationOnlyAttr>())
2165+
return;
2166+
2167+
if (isa<AccessorDecl>(VD))
2168+
return;
2169+
2170+
// Is this part of the module's API or ABI?
2171+
AccessScope accessScope =
2172+
VD->getFormalAccessScope(nullptr,
2173+
/*treatUsableFromInlineAsPublic*/true);
2174+
if (!accessScope.isPublic())
2175+
return;
2176+
2177+
const ValueDecl *overridden = VD->getOverriddenDecl();
2178+
if (!overridden)
2179+
return;
2180+
2181+
auto *SF = VD->getDeclContext()->getParentSourceFile();
2182+
assert(SF && "checking a non-source declaration?");
2183+
2184+
ModuleDecl *M = overridden->getModuleContext();
2185+
if (SF->isImportedImplementationOnly(M)) {
2186+
VD->diagnose(diag::implementation_only_override_import_without_attr,
2187+
overridden->getDescriptiveKind())
2188+
.fixItInsert(VD->getAttributeInsertionLoc(false),
2189+
"@_implementationOnly ");
2190+
overridden->diagnose(diag::overridden_here);
2191+
return;
2192+
}
2193+
2194+
if (overridden->getAttrs().hasAttribute<ImplementationOnlyAttr>()) {
2195+
VD->diagnose(diag::implementation_only_override_without_attr,
2196+
overridden->getDescriptiveKind())
2197+
.fixItInsert(VD->getAttributeInsertionLoc(false),
2198+
"@_implementationOnly ");
2199+
overridden->diagnose(diag::overridden_here);
2200+
return;
2201+
}
2202+
2203+
// FIXME: Check storage decls where the setter is in a separate module from
2204+
// the getter, which is a thing Objective-C can do. The ClangImporter
2205+
// doesn't make this easy, though, because it just gives the setter the same
2206+
// DeclContext as the property or subscript, which means we've lost the
2207+
// information about whether its module was implementation-only imported.
2208+
}

lib/Sema/TypeCheckDeclPrimary.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1551,6 +1551,8 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
15511551
}
15521552
}
15531553

1554+
checkImplementationOnlyOverride(VD);
1555+
15541556
if (VD->getDeclContext()->getSelfClassDecl()) {
15551557
if (VD->getValueInterfaceType()->hasDynamicSelfType()) {
15561558
if (VD->hasStorage())
@@ -1772,6 +1774,8 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
17721774
}
17731775
}
17741776

1777+
checkImplementationOnlyOverride(SD);
1778+
17751779
// Compute these requests in case they emit diagnostics.
17761780
(void) SD->isGetterMutating();
17771781
(void) SD->isSetterMutating();
@@ -2364,6 +2368,8 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
23642368
}
23652369
}
23662370

2371+
checkImplementationOnlyOverride(FD);
2372+
23672373
if (requiresDefinition(FD) && !FD->hasBody()) {
23682374
// Complain if we should have a body.
23692375
FD->diagnose(diag::func_decl_without_brace);
@@ -2672,6 +2678,8 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
26722678
}
26732679
}
26742680

2681+
checkImplementationOnlyOverride(CD);
2682+
26752683
// If this initializer overrides a 'required' initializer, it must itself
26762684
// be marked 'required'.
26772685
if (!CD->getAttrs().hasAttribute<RequiredAttr>()) {

0 commit comments

Comments
 (0)