Skip to content

Commit 0d0dd53

Browse files
committed
[Sema] Support pattern binding decls with -require-explicit-availability
1 parent ad7afe4 commit 0d0dd53

File tree

3 files changed

+71
-11
lines changed

3 files changed

+71
-11
lines changed

lib/Sema/TypeCheckAvailability.cpp

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2879,19 +2879,19 @@ static bool declNeedsExplicitAvailability(const Decl *decl) {
28792879
}
28802880

28812881
void swift::checkExplicitAvailability(Decl *decl) {
2882-
// Check only if the command line option was set.
2883-
if (!decl->getASTContext().LangOpts.RequireExplicitAvailability)
2882+
// Skip if the command line option was not set and
2883+
// accessors as we check the pattern binding decl instead.
2884+
if (!decl->getASTContext().LangOpts.RequireExplicitAvailability ||
2885+
isa<AccessorDecl>(decl))
28842886
return;
28852887

2886-
// Skip nominal type members as the type should be annotated.
2887-
auto declContext = decl->getDeclContext();
2888-
if (isa<NominalTypeDecl>(declContext))
2889-
return;
2888+
// Only look at decls at module level or in extensions.
2889+
// This could be changed to force having attributes on all decls.
2890+
if (!decl->getDeclContext()->isModuleScopeContext() &&
2891+
!isa<ExtensionDecl>(decl->getDeclContext())) return;
28902892

2891-
ValueDecl *valueDecl = dyn_cast<ValueDecl>(decl);
2892-
if (valueDecl == nullptr) {
2893+
if (auto extension = dyn_cast<ExtensionDecl>(decl)) {
28932894
// decl should be either a ValueDecl or an ExtensionDecl.
2894-
auto extension = cast<ExtensionDecl>(decl);
28952895
auto extended = extension->getExtendedNominal();
28962896
if (!extended || !extended->getFormalAccessScope().isPublic())
28972897
return;
@@ -2916,6 +2916,18 @@ void swift::checkExplicitAvailability(Decl *decl) {
29162916
});
29172917

29182918
if (!hasMembers && !hasProtocols) return;
2919+
2920+
} else if (auto pbd = dyn_cast<PatternBindingDecl>(decl)) {
2921+
// Check the first var instead.
2922+
if (pbd->getNumPatternEntries() == 0)
2923+
return;
2924+
2925+
llvm::SmallVector<VarDecl *, 2> vars;
2926+
pbd->getPattern(0)->collectVariables(vars);
2927+
if (vars.empty())
2928+
return;
2929+
2930+
decl = vars.front();
29192931
}
29202932

29212933
if (declNeedsExplicitAvailability(decl)) {

lib/Sema/TypeCheckDeclPrimary.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1629,6 +1629,8 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
16291629

16301630
checkAccessControl(PBD);
16311631

1632+
checkExplicitAvailability(PBD);
1633+
16321634
// If the initializers in the PBD aren't checked yet, do so now.
16331635
for (auto i : range(PBD->getNumPatternEntries())) {
16341636
if (!PBD->isInitialized(i))

test/attr/require_explicit_availability.swift

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
// Test the -require-explicit-availability flag
22
// REQUIRES: OS=macosx
33

4-
// RUN: %swiftc_driver -typecheck -parse-stdlib -target x86_64-apple-macosx10.10 -Xfrontend -verify -require-explicit-availability -require-explicit-availability-target "macOS 10.10" %s
5-
// RUN: %swiftc_driver -typecheck -parse-stdlib -target x86_64-apple-macosx10.10 -warnings-as-errors %s
4+
// RUN: %swiftc_driver -typecheck -parse-as-library -target x86_64-apple-macosx10.10 -Xfrontend -verify -require-explicit-availability -require-explicit-availability-target "macOS 10.10" %s
65

76
public struct S { // expected-warning {{public declarations should have an availability attribute when building with -require-explicit-availability}}
87
public func method() { }
@@ -91,3 +90,50 @@ public struct spiStruct {
9190
extension spiStruct {
9291
public func spiExtensionMethod() {}
9392
}
93+
94+
public var publicVar = S() // expected-warning {{public declarations should have an availability attribute when building with -require-explicit-availability}} {{1-1=@available(macOS 10.10, *)\n}}
95+
96+
@available(macOS 10.10, *)
97+
public var publicVarOk = S()
98+
99+
public var (a, b) = (S(), S()) // expected-warning {{public declarations should have an availability attribute when building with -require-explicit-availability}} {{1-1=@available(macOS 10.10, *)\n}}
100+
101+
@available(macOS 10.10, *)
102+
public var (c, d) = (S(), S())
103+
104+
public var _ = S() // expected-error {{global variable declaration does not bind any variables}}
105+
106+
public var implicitGet: S { // expected-warning {{public declarations should have an availability attribute when building with -require-explicit-availability}} {{1-1=@available(macOS 10.10, *)\n}}
107+
return S()
108+
}
109+
110+
@available(macOS 10.10, *)
111+
public var implicitGetOk: S {
112+
return S()
113+
}
114+
115+
public var computed: S { // expected-warning {{public declarations should have an availability attribute when building with -require-explicit-availability}} {{1-1=@available(macOS 10.10, *)\n}}
116+
get { return S() }
117+
set { }
118+
}
119+
120+
public var computedHalf: S { // expected-warning {{public declarations should have an availability attribute when building with -require-explicit-availability}} {{1-1=@available(macOS 10.10, *)\n}}
121+
@available(macOS 10.10, *)
122+
get { return S() }
123+
set { }
124+
}
125+
126+
// FIXME the following warning is not needed.
127+
public var computedOk: S { // expected-warning {{public declarations should have an availability attribute when building with -require-explicit-availability}} {{1-1=@available(macOS 10.10, *)\n}}
128+
@available(macOS 10.10, *)
129+
get { return S() }
130+
131+
@available(macOS 10.10, *)
132+
set { }
133+
}
134+
135+
@available(macOS 10.10, *)
136+
public var computedOk1: S {
137+
get { return S() }
138+
set { }
139+
}

0 commit comments

Comments
 (0)