Skip to content

Commit a24c2ae

Browse files
committed
sema: diagnose @_spi_available on all platforms
@_spi_available should only be used when the symbol is publically available in some deployment platforms, otherwise we should use @_spi.
1 parent 965a966 commit a24c2ae

File tree

5 files changed

+32
-4
lines changed

5 files changed

+32
-4
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1637,6 +1637,9 @@ ERROR(originally_definedin_must_not_before_available_version,none,
16371637
"symbols are moved to the current module before they were available in "
16381638
"the OSs", ())
16391639

1640+
WARNING(spi_preferred_over_spi_available,none,
1641+
"symbols that are @_spi_available on all platforms should use @_spi instead", ())
1642+
16401643
// Alignment attribute
16411644
ERROR(alignment_not_power_of_two,none,
16421645
"alignment value must be a power of two", ())

lib/Sema/TypeCheckAttr.cpp

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,7 @@ class AttributeChecker : public AttributeVisitor<AttributeChecker> {
328328

329329
void visitCompilerInitializedAttr(CompilerInitializedAttr *attr);
330330

331+
void checkAvailableAttrs(ArrayRef<AvailableAttr *> Attrs);
331332
void checkBackDeployAttrs(ArrayRef<BackDeployAttr *> Attrs);
332333

333334
void visitKnownToBeLocalAttr(KnownToBeLocalAttr *attr);
@@ -1421,8 +1422,9 @@ void TypeChecker::checkDeclAttributes(Decl *D) {
14211422
TypeChecker::applyAccessNote(VD);
14221423

14231424
AttributeChecker Checker(D);
1424-
// We need to check all OriginallyDefinedInAttr and BackDeployAttr relative
1425-
// to each other, so collect them and check in batch later.
1425+
// We need to check all availableAttrs, OriginallyDefinedInAttr and
1426+
// BackDeployAttr relative to each other, so collect them and check in batch later.
1427+
llvm::SmallVector<AvailableAttr *, 4> availableAttrs;
14261428
llvm::SmallVector<BackDeployAttr *, 4> backDeployAttrs;
14271429
llvm::SmallVector<OriginallyDefinedInAttr*, 4> ODIAttrs;
14281430
for (auto attr : D->getAttrs()) {
@@ -1436,6 +1438,10 @@ void TypeChecker::checkDeclAttributes(Decl *D) {
14361438
} else if (auto *BD = dyn_cast<BackDeployAttr>(attr)) {
14371439
backDeployAttrs.push_back(BD);
14381440
} else {
1441+
// check @available attribute both collectively and individually.
1442+
if (auto *AV = dyn_cast<AvailableAttr>(attr)) {
1443+
availableAttrs.push_back(AV);
1444+
}
14391445
// Otherwise, check it.
14401446
Checker.visit(attr);
14411447
}
@@ -1475,6 +1481,7 @@ void TypeChecker::checkDeclAttributes(Decl *D) {
14751481
else
14761482
Checker.diagnoseAndRemoveAttr(attr, diag::invalid_decl_attribute, attr);
14771483
}
1484+
Checker.checkAvailableAttrs(availableAttrs);
14781485
Checker.checkBackDeployAttrs(backDeployAttrs);
14791486
Checker.checkOriginalDefinedInAttrs(ODIAttrs);
14801487
}
@@ -4002,6 +4009,17 @@ void AttributeChecker::checkOriginalDefinedInAttrs(
40024009
}
40034010
}
40044011

4012+
void AttributeChecker::checkAvailableAttrs(ArrayRef<AvailableAttr *> Attrs) {
4013+
if (Attrs.empty())
4014+
return;
4015+
// If all available are spi available, we should use @_spi instead.
4016+
if (std::all_of(Attrs.begin(), Attrs.end(), [](AvailableAttr *AV) {
4017+
return AV->IsSPI;
4018+
})) {
4019+
diagnose(D->getLoc(), diag::spi_preferred_over_spi_available);
4020+
};
4021+
}
4022+
40054023
void AttributeChecker::checkBackDeployAttrs(ArrayRef<BackDeployAttr *> Attrs) {
40064024
if (Attrs.empty())
40074025
return;

test/Sema/spi-available-context.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,11 @@
33
// RUN: %target-typecheck-verify-swift -target %target-cpu-apple-macosx11.9 -library-level api
44

55
@_spi_available(macOS 10.4, *)
6+
@available(iOS 8.0, *)
67
public protocol Foo { }
78

89
@_spi_available(macOS 10.4, *)
10+
@available(iOS 8.0, *)
911
public class Bar {
1012
public var foo: Foo?
1113
}

test/Sema/spi-available-inline.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,11 @@
33
// RUN: %target-typecheck-verify-swift -target %target-cpu-apple-macosx11.9 -library-level api
44

55
@_spi_available(macOS 10.4, *)
6+
@available(iOS 8.0, *)
67
public class MacOSSPIClass { public init() {} }
78

89
@_spi_available(iOS 8.0, *)
10+
@available(macOS 10.4, *)
911
public class iOSSPIClass { public init() {} }
1012

1113
@inlinable public func foo() {

test/attr/spi_available.swift

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
// RUN: %target-typecheck-verify-swift
22

33
@_spi_available(*, deprecated, renamed: "another") // expected-error {{SPI available only supports introducing version on specific platform}}
4-
public class SPIClass1 {}
4+
public class SPIClass1 {} // expected-warning {{symbols that are @_spi_available on all platforms should use @_spi instead}}
55

66
@_spi_available(*, unavailable) // expected-error {{SPI available only supports introducing version on specific platform}}
7-
public class SPIClass2 {}
7+
public class SPIClass2 {} // expected-warning {{symbols that are @_spi_available on all platforms should use @_spi instead}}
88

99
@_spi_available(AlienPlatform 5.2, *) // expected-warning {{unrecognized platform name 'AlienPlatform'}}
1010
public class SPIClass3 {}
11+
12+
@_spi_available(macOS 10.4, *)
13+
public class SPIClass4 {} // expected-warning {{symbols that are @_spi_available on all platforms should use @_spi instead}}

0 commit comments

Comments
 (0)