Skip to content

Commit 8b14600

Browse files
committed
[ClangImporter] Refactor availability attribute importing logic. NFC.
Refactor the PlatformAvailability logic for determining which Clang availability attributes are relevant when importing. The goal is to separate the logic for attribute relevance for a given platform from the logic to determine whether a deprecated attribute should be imported as unavailable in Swift. This also makes it possible for the "deprecated-as-unavailable" logic to refer to the underlying Clang declaration, which is functionality that will be used in a later commit. This commit has no intended functional change. Part of rdar://problem/48348822
1 parent f2c3c69 commit 8b14600

File tree

4 files changed

+104
-80
lines changed

4 files changed

+104
-80
lines changed

lib/ClangImporter/ClangAdapter.cpp

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -718,19 +718,17 @@ bool importer::isUnavailableInSwift(
718718
if (attr->getPlatform()->getName() == "swift")
719719
return true;
720720

721-
if (platformAvailability.filter &&
722-
!platformAvailability.filter(attr->getPlatform()->getName())) {
721+
if (!platformAvailability.isPlatformRelevant(
722+
attr->getPlatform()->getName())) {
723723
continue;
724724
}
725725

726-
if (platformAvailability.deprecatedAsUnavailableFilter) {
727-
llvm::VersionTuple version = attr->getDeprecated();
728-
if (version.empty())
729-
continue;
730-
if (platformAvailability.deprecatedAsUnavailableFilter(
731-
version.getMajor(), version.getMinor())) {
732-
return true;
733-
}
726+
727+
llvm::VersionTuple version = attr->getDeprecated();
728+
if (version.empty())
729+
continue;
730+
if (platformAvailability.treatDeprecatedAsUnavailable(decl, version)) {
731+
return true;
734732
}
735733
}
736734

lib/ClangImporter/ClangImporter.cpp

Lines changed: 77 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1684,65 +1684,88 @@ ModuleDecl *ClangImporter::getImportedHeaderModule() const {
16841684
return Impl.ImportedHeaderUnit->getParentModule();
16851685
}
16861686

1687-
PlatformAvailability::PlatformAvailability(LangOptions &langOpts) {
1688-
// Add filters to determine if a Clang availability attribute
1689-
// applies in Swift, and if so, what is the cutoff for deprecated
1690-
// declarations that are now considered unavailable in Swift.
1691-
1692-
if (langOpts.Target.isiOS() && !langOpts.Target.isTvOS()) {
1693-
if (!langOpts.EnableAppExtensionRestrictions) {
1694-
filter = [](StringRef Platform) { return Platform == "ios"; };
1695-
} else {
1696-
filter = [](StringRef Platform) {
1697-
return Platform == "ios" || Platform == "ios_app_extension";
1698-
};
1699-
}
1700-
// Anything deprecated in iOS 7.x and earlier is unavailable in Swift.
1701-
deprecatedAsUnavailableFilter = [](
1702-
unsigned major, llvm::Optional<unsigned> minor) { return major <= 7; };
1687+
PlatformAvailability::PlatformAvailability(LangOptions &langOpts)
1688+
: platformKind(targetPlatform(langOpts)) {
1689+
switch (platformKind) {
1690+
case PlatformKind::iOS:
1691+
case PlatformKind::iOSApplicationExtension:
1692+
case PlatformKind::tvOS:
1693+
case PlatformKind::tvOSApplicationExtension:
17031694
deprecatedAsUnavailableMessage =
17041695
"APIs deprecated as of iOS 7 and earlier are unavailable in Swift";
1705-
} else if (langOpts.Target.isTvOS()) {
1706-
if (!langOpts.EnableAppExtensionRestrictions) {
1707-
filter = [](StringRef Platform) { return Platform == "tvos"; };
1708-
} else {
1709-
filter = [](StringRef Platform) {
1710-
return Platform == "tvos" || Platform == "tvos_app_extension";
1711-
};
1712-
}
1713-
// Anything deprecated in iOS 7.x and earlier is unavailable in Swift.
1714-
deprecatedAsUnavailableFilter = [](
1715-
unsigned major, llvm::Optional<unsigned> minor) { return major <= 7; };
1716-
deprecatedAsUnavailableMessage =
1717-
"APIs deprecated as of iOS 7 and earlier are unavailable in Swift";
1718-
} else if (langOpts.Target.isWatchOS()) {
1719-
if (!langOpts.EnableAppExtensionRestrictions) {
1720-
filter = [](StringRef Platform) { return Platform == "watchos"; };
1721-
} else {
1722-
filter = [](StringRef Platform) {
1723-
return Platform == "watchos" || Platform == "watchos_app_extension";
1724-
};
1725-
}
1726-
// No deprecation filter on watchOS
1727-
deprecatedAsUnavailableFilter = [](
1728-
unsigned major, llvm::Optional<unsigned> minor) { return false; };
1696+
break;
1697+
1698+
case PlatformKind::watchOS:
1699+
case PlatformKind::watchOSApplicationExtension:
17291700
deprecatedAsUnavailableMessage = "";
1730-
} else if (langOpts.Target.isMacOSX()) {
1731-
if (!langOpts.EnableAppExtensionRestrictions) {
1732-
filter = [](StringRef Platform) { return Platform == "macos"; };
1733-
} else {
1734-
filter = [](StringRef Platform) {
1735-
return Platform == "macos" || Platform == "macos_app_extension";
1736-
};
1737-
}
1738-
// Anything deprecated in OSX 10.9.x and earlier is unavailable in Swift.
1739-
deprecatedAsUnavailableFilter = [](unsigned major,
1740-
llvm::Optional<unsigned> minor) {
1741-
return major < 10 ||
1742-
(major == 10 && (!minor.hasValue() || minor.getValue() <= 9));
1743-
};
1701+
break;
1702+
1703+
case PlatformKind::OSX:
1704+
case PlatformKind::OSXApplicationExtension:
17441705
deprecatedAsUnavailableMessage =
17451706
"APIs deprecated as of OS X 10.9 and earlier are unavailable in Swift";
1707+
break;
1708+
1709+
default:
1710+
break;
1711+
}
1712+
}
1713+
1714+
bool PlatformAvailability::isPlatformRelevant(StringRef name) const {
1715+
switch (platformKind) {
1716+
case PlatformKind::OSX:
1717+
return name == "macos";
1718+
case PlatformKind::OSXApplicationExtension:
1719+
return name == "macos" || name == "macos_app_extension";
1720+
1721+
case PlatformKind::iOS:
1722+
return name == "ios";
1723+
case PlatformKind::iOSApplicationExtension:
1724+
return name == "ios" || name == "ios_app_extension";
1725+
1726+
case PlatformKind::tvOS:
1727+
return name == "tvos";
1728+
case PlatformKind::tvOSApplicationExtension:
1729+
return name == "tvos" || name == "tvos_app_extension";
1730+
1731+
case PlatformKind::watchOS:
1732+
return name == "watchos";
1733+
case PlatformKind::watchOSApplicationExtension:
1734+
return name == "watchos" || name == "watchos_app_extension";
1735+
1736+
case PlatformKind::none:
1737+
return false;
1738+
}
1739+
1740+
llvm_unreachable("Unexpected platform");
1741+
}
1742+
1743+
bool PlatformAvailability::treatDeprecatedAsUnavailable(
1744+
const clang::Decl *clangDecl, const llvm::VersionTuple &version) const {
1745+
assert(!version.empty() && "Must provide version when deprecated");
1746+
unsigned major = version.getMajor();
1747+
Optional<unsigned> minor = version.getMinor();
1748+
1749+
switch (platformKind) {
1750+
case PlatformKind::OSX:
1751+
// Anything deprecated in OSX 10.9.x and earlier is unavailable in Swift.
1752+
return major < 10 ||
1753+
(major == 10 && (!minor.hasValue() || minor.getValue() <= 9));
1754+
1755+
case PlatformKind::iOS:
1756+
case PlatformKind::iOSApplicationExtension:
1757+
case PlatformKind::tvOS:
1758+
case PlatformKind::tvOSApplicationExtension:
1759+
// Anything deprecated in iOS 7.x and earlier is unavailable in Swift.
1760+
return major <= 7;
1761+
1762+
case PlatformKind::watchOS:
1763+
case PlatformKind::watchOSApplicationExtension:
1764+
// No deprecation filter on watchOS
1765+
return false;
1766+
1767+
default:
1768+
return false;
17461769
}
17471770
}
17481771

lib/ClangImporter/ImportDecl.cpp

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5913,10 +5913,10 @@ SwiftDeclConverter::findLatestIntroduction(const clang::Decl *D) {
59135913

59145914
// Does this availability attribute map to the platform we are
59155915
// currently targeting?
5916-
if (!Impl.platformAvailability.filter ||
5917-
!Impl.platformAvailability.filter(attr->getPlatform()->getName()))
5916+
if (!Impl.platformAvailability.isPlatformRelevant(
5917+
attr->getPlatform()->getName())) {
59185918
continue;
5919-
5919+
}
59205920
// Take advantage of the empty version being 0.0.0.0.
59215921
result = std::max(result, attr->getIntroduced());
59225922
}
@@ -7321,8 +7321,7 @@ void ClangImporter::Implementation::importAttributes(
73217321

73227322
// Does this availability attribute map to the platform we are
73237323
// currently targeting?
7324-
if (!platformAvailability.filter ||
7325-
!platformAvailability.filter(Platform))
7324+
if (!platformAvailability.isPlatformRelevant(Platform))
73267325
continue;
73277326

73287327
auto platformK =
@@ -7354,9 +7353,8 @@ void ClangImporter::Implementation::importAttributes(
73547353
llvm::VersionTuple deprecated = avail->getDeprecated();
73557354

73567355
if (!deprecated.empty()) {
7357-
if (platformAvailability.deprecatedAsUnavailableFilter &&
7358-
platformAvailability.deprecatedAsUnavailableFilter(
7359-
deprecated.getMajor(), deprecated.getMinor())) {
7356+
if (platformAvailability.treatDeprecatedAsUnavailable(ClangDecl,
7357+
deprecated)) {
73607358
AnyUnavailable = true;
73617359
PlatformAgnostic = PlatformAgnosticAvailabilityKind::Unavailable;
73627360
if (message.empty())

lib/ClangImporter/ImporterImpl.h

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -248,14 +248,19 @@ enum class FactoryAsInitKind {
248248

249249
namespace importer {
250250
struct PlatformAvailability {
251-
/// A predicate that indicates if the given platform should be
252-
/// considered for availability.
253-
std::function<bool(StringRef PlatformName)> filter;
254-
255-
/// A predicate that indicates if the given platform version should
256-
/// should be included in the cutoff of deprecated APIs marked unavailable.
257-
std::function<bool(unsigned major, llvm::Optional<unsigned> minor)>
258-
deprecatedAsUnavailableFilter;
251+
private:
252+
PlatformKind platformKind;
253+
254+
public:
255+
/// Returns true when the given platform should be considered for
256+
/// availabilityon imported declarations.
257+
bool isPlatformRelevant(StringRef platform) const;
258+
259+
/// Returns true when the given declaration with the given deprecation
260+
/// should be inlucded in the cutoff of imported deprecated APIs marked
261+
/// unavailable.
262+
bool treatDeprecatedAsUnavailable(const clang::Decl *clangDecl,
263+
const llvm::VersionTuple &version) const;
259264

260265
/// The message to embed for implicitly unavailability if a deprecated
261266
/// API is now unavailable.

0 commit comments

Comments
 (0)