Skip to content

Commit 3bb4f11

Browse files
committed
[Sema] Fix detection of required availability attributes on extensions
1 parent 9de171a commit 3bb4f11

File tree

2 files changed

+33
-16
lines changed

2 files changed

+33
-16
lines changed

lib/Sema/TypeCheckAvailability.cpp

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2854,21 +2854,26 @@ bool swift::diagnoseDeclAvailability(const ValueDecl *Decl,
28542854
return AW.diagAvailability(const_cast<ValueDecl *>(Decl), R, nullptr, Flags);
28552855
}
28562856

2857-
/// Should we warn that \p valueDecl needs an explicit availability annotation
2858-
/// in -require-explicit-availaiblity mode?
2859-
static bool declNeedsExplicitAvailability(const ValueDecl *valueDecl) {
2860-
AccessScope scope =
2861-
valueDecl->getFormalAccessScope(/*useDC*/nullptr,
2862-
/*treatUsableFromInlineAsPublic*/true);
2863-
if (!scope.isPublic() ||
2864-
valueDecl->getAttrs().hasAttribute<AlwaysEmitIntoClientAttr>())
2857+
/// Should we warn that \p decl needs an explicit availability annotation
2858+
/// in -require-explicit-availability mode?
2859+
static bool declNeedsExplicitAvailability(const Decl *decl) {
2860+
// Skip non-public decls.
2861+
if (auto valueDecl = dyn_cast<const ValueDecl>(decl)) {
2862+
AccessScope scope =
2863+
valueDecl->getFormalAccessScope(/*useDC*/nullptr,
2864+
/*treatUsableFromInlineAsPublic*/true);
2865+
if (!scope.isPublic())
2866+
return false;
2867+
}
2868+
2869+
if (decl->getAttrs().hasAttribute<AlwaysEmitIntoClientAttr>())
28652870
return false;
28662871

28672872
// Warn on decls without an introduction version.
2868-
auto &ctx = valueDecl->getASTContext();
2869-
auto safeRangeUnderApprox = AvailabilityInference::availableRange(valueDecl, ctx);
2873+
auto &ctx = decl->getASTContext();
2874+
auto safeRangeUnderApprox = AvailabilityInference::availableRange(decl, ctx);
28702875
return !safeRangeUnderApprox.getOSVersion().hasLowerEndpoint() &&
2871-
!valueDecl->getAttrs().isUnavailable(ctx);
2876+
!decl->getAttrs().isUnavailable(ctx);
28722877
}
28732878

28742879
void swift::checkExplicitAvailability(Decl *decl) {
@@ -2885,8 +2890,8 @@ void swift::checkExplicitAvailability(Decl *decl) {
28852890
if (valueDecl == nullptr) {
28862891
// decl should be either a ValueDecl or an ExtensionDecl.
28872892
auto extension = cast<ExtensionDecl>(decl);
2888-
valueDecl = extension->getExtendedNominal();
2889-
if (!valueDecl)
2893+
auto extended = extension->getExtendedNominal();
2894+
if (!extended || !extended->getFormalAccessScope().isPublic())
28902895
return;
28912896

28922897
// Skip extensions without public members or conformances.
@@ -2911,10 +2916,11 @@ void swift::checkExplicitAvailability(Decl *decl) {
29112916
if (!hasMembers && !hasProtocols) return;
29122917
}
29132918

2914-
if (declNeedsExplicitAvailability(valueDecl)) {
2919+
if (declNeedsExplicitAvailability(decl)) {
29152920
auto diag = decl->diagnose(diag::public_decl_needs_availability);
29162921

2917-
auto suggestPlatform = decl->getASTContext().LangOpts.RequireExplicitAvailabilityTarget;
2922+
auto suggestPlatform =
2923+
decl->getASTContext().LangOpts.RequireExplicitAvailabilityTarget;
29182924
if (!suggestPlatform.empty()) {
29192925
auto InsertLoc = decl->getAttrs().getStartLoc(/*forModifiers=*/false);
29202926
if (InsertLoc.isInvalid())
@@ -2927,7 +2933,7 @@ void swift::checkExplicitAvailability(Decl *decl) {
29272933
{
29282934
llvm::raw_string_ostream Out(AttrText);
29292935

2930-
auto &ctx = valueDecl->getASTContext();
2936+
auto &ctx = decl->getASTContext();
29312937
StringRef OriginalIndent = Lexer::getIndentationForLine(
29322938
ctx.SourceMgr, InsertLoc);
29332939
Out << "@available(" << suggestPlatform << ", *)\n"

test/attr/require_explicit_availability.swift

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,11 @@ extension S { // expected-warning {{public declarations should have an availabil
5252
public func warnForPublicMembers() { } // expected-warning {{public declarations should have an availability attribute when building with -require-explicit-availability}} {{3-3=@available(macOS 10.10, *)\n }}
5353
}
5454

55+
@available(macOS 10.1, *)
56+
extension S {
57+
public func okWhenTheExtensionHasAttribute() { }
58+
}
59+
5560
extension S {
5661
internal func dontWarnWithoutPublicMembers() { }
5762
private func dontWarnWithoutPublicMembers1() { }
@@ -68,3 +73,9 @@ open class OpenClass { } // expected-warning {{public declarations should have a
6873
private class PrivateClass { }
6974

7075
extension PrivateClass { }
76+
77+
@available(macOS 10.1, *)
78+
public protocol PublicProtocol { }
79+
80+
@available(macOS 10.1, *)
81+
extension S : PublicProtocol { }

0 commit comments

Comments
 (0)