Skip to content

Commit 84d3618

Browse files
authored
[TBDGen] Track unavailable declarations against the active platform for (#73284)
api generation This resolves the bug where apijson files recorded declarations as unavailable purely because it was unavailable on a unrelated platforms. Resolves: rdar://113552185
1 parent 7757c34 commit 84d3618

File tree

2 files changed

+140
-9
lines changed

2 files changed

+140
-9
lines changed

lib/IRGen/TBDGen.cpp

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -766,22 +766,27 @@ class APIGenRecorder final : public APIRecorder {
766766
llvm::DenseMap<CategoryNameKey, unsigned> CategoryCounts;
767767

768768
apigen::APIAvailability getAvailability(const Decl *decl) {
769-
bool unavailable = false;
769+
std::optional<bool> unavailable;
770770
std::string introduced, obsoleted;
771+
bool hasFallbackUnavailability = false;
771772
auto platform = targetPlatform(module->getASTContext().LangOpts);
772773
for (auto *attr : decl->getAttrs()) {
773774
if (auto *ava = dyn_cast<AvailableAttr>(attr)) {
774-
if (ava->isUnconditionallyUnavailable())
775-
unavailable = true;
776-
if (ava->Platform == platform) {
777-
if (ava->Introduced)
778-
introduced = ava->Introduced->getAsString();
779-
if (ava->Obsoleted)
780-
obsoleted = ava->Obsoleted->getAsString();
775+
if (ava->Platform == PlatformKind::none) {
776+
hasFallbackUnavailability = ava->isUnconditionallyUnavailable();
777+
continue;
781778
}
779+
if (ava->Platform != platform)
780+
continue;
781+
unavailable = ava->isUnconditionallyUnavailable();
782+
if (ava->Introduced)
783+
introduced = ava->Introduced->getAsString();
784+
if (ava->Obsoleted)
785+
obsoleted = ava->Obsoleted->getAsString();
782786
}
783787
}
784-
return {introduced, obsoleted, unavailable};
788+
return {introduced, obsoleted,
789+
unavailable.value_or(hasFallbackUnavailability)};
785790
}
786791

787792
StringRef getSelectorName(SILDeclRef method, SmallString<128> &buffer) {

test/APIJSON/availability.swift

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
// REQUIRES: objc_interop, OS=macosx
2+
// RUN: %empty-directory(%t)
3+
// RUN: %empty-directory(%t/ModuleCache)
4+
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t) %s -typecheck -parse-as-library -emit-module-interface-path %t/MyModule.swiftinterface -enable-library-evolution -module-name MyModule -swift-version 5 -emit-api-descriptor-path %t/api.json -target arm64-apple-macos12
5+
// RUN: %validate-json %t/api.json | %FileCheck %s
6+
7+
@available(iOS 13.0, *)
8+
@available(macOS 10.10, *)
9+
@available(tvOS, unavailable)
10+
@available(watchOS 10.0, *)
11+
public class A {}
12+
13+
@available(*, unavailable)
14+
public func callUnavailable() {}
15+
16+
@available(macOS 10.10, *)
17+
@available(*, unavailable)
18+
public func availableOnlyOnActiveOS() {}
19+
20+
@available(tvOS, unavailable)
21+
public func unavailableOnSeperateOS() {}
22+
23+
extension A {
24+
@available(macOS 12, *)
25+
public func getA() -> Void {}
26+
27+
@available(macOS, unavailable)
28+
public func getUnavailableA() -> Void {}
29+
}
30+
31+
// CHECK: {
32+
// CHECK-NEXT: "target": "arm64-apple-macos12",
33+
// CHECK-NEXT: "globals": [
34+
// CHECK-NEXT: {
35+
// CHECK-NEXT: "name": "_$s8MyModule15callUnavailableyyF",
36+
// CHECK-NEXT: "access": "public",
37+
// CHECK-NEXT: "file": "SOURCE_DIR/test/APIJSON/availability.swift",
38+
// CHECK-NEXT: "linkage": "exported",
39+
// CHECK-NEXT: "unavailable": true
40+
// CHECK-NEXT: },
41+
// CHECK-NEXT: {
42+
// CHECK-NEXT: "name": "_$s8MyModule1AC15getUnavailableAyyF",
43+
// CHECK-NEXT: "access": "public",
44+
// CHECK-NEXT: "file": "SOURCE_DIR/test/APIJSON/availability.swift",
45+
// CHECK-NEXT: "linkage": "exported",
46+
// CHECK-NEXT: "unavailable": true
47+
// CHECK-NEXT: },
48+
// CHECK-NEXT: {
49+
// CHECK-NEXT: "name": "_$s8MyModule1AC4getAyyF",
50+
// CHECK-NEXT: "access": "public",
51+
// CHECK-NEXT: "file": "SOURCE_DIR/test/APIJSON/availability.swift",
52+
// CHECK-NEXT: "linkage": "exported",
53+
// CHECK-NEXT: "introduced": "12"
54+
// CHECK-NEXT: },
55+
// CHECK-NEXT: {
56+
// CHECK-NEXT: "name": "_$s8MyModule1ACMa",
57+
// CHECK-NEXT: "access": "public",
58+
// CHECK-NEXT: "file": "SOURCE_DIR/test/APIJSON/availability.swift",
59+
// CHECK-NEXT: "linkage": "exported",
60+
// CHECK-NEXT: "introduced": "10.10"
61+
// CHECK-NEXT: },
62+
// CHECK-NEXT: {
63+
// CHECK-NEXT: "name": "_$s8MyModule1ACMm",
64+
// CHECK-NEXT: "access": "public",
65+
// CHECK-NEXT: "file": "SOURCE_DIR/test/APIJSON/availability.swift",
66+
// CHECK-NEXT: "linkage": "exported",
67+
// CHECK-NEXT: "introduced": "10.10"
68+
// CHECK-NEXT: },
69+
// CHECK-NEXT: {
70+
// CHECK-NEXT: "name": "_$s8MyModule1ACMn",
71+
// CHECK-NEXT: "access": "public",
72+
// CHECK-NEXT: "file": "SOURCE_DIR/test/APIJSON/availability.swift",
73+
// CHECK-NEXT: "linkage": "exported",
74+
// CHECK-NEXT: "introduced": "10.10"
75+
// CHECK-NEXT: },
76+
// CHECK-NEXT: {
77+
// CHECK-NEXT: "name": "_$s8MyModule1ACMo",
78+
// CHECK-NEXT: "access": "public",
79+
// CHECK-NEXT: "file": "SOURCE_DIR/test/APIJSON/availability.swift",
80+
// CHECK-NEXT: "linkage": "exported",
81+
// CHECK-NEXT: "introduced": "10.10"
82+
// CHECK-NEXT: },
83+
// CHECK-NEXT: {
84+
// CHECK-NEXT: "name": "_$s8MyModule1ACMu",
85+
// CHECK-NEXT: "access": "public",
86+
// CHECK-NEXT: "file": "SOURCE_DIR/test/APIJSON/availability.swift",
87+
// CHECK-NEXT: "linkage": "exported",
88+
// CHECK-NEXT: "introduced": "10.10"
89+
// CHECK-NEXT: },
90+
// CHECK-NEXT: {
91+
// CHECK-NEXT: "name": "_$s8MyModule1ACN",
92+
// CHECK-NEXT: "access": "public",
93+
// CHECK-NEXT: "file": "SOURCE_DIR/test/APIJSON/availability.swift",
94+
// CHECK-NEXT: "linkage": "exported",
95+
// CHECK-NEXT: "introduced": "10.10"
96+
// CHECK-NEXT: },
97+
// CHECK-NEXT: {
98+
// CHECK-NEXT: "name": "_$s8MyModule1ACfD",
99+
// CHECK-NEXT: "access": "public",
100+
// CHECK-NEXT: "file": "SOURCE_DIR/test/APIJSON/availability.swift",
101+
// CHECK-NEXT: "linkage": "exported"
102+
// CHECK-NEXT: },
103+
// CHECK-NEXT: {
104+
// CHECK-NEXT: "name": "_$s8MyModule1ACfd",
105+
// CHECK-NEXT: "access": "public",
106+
// CHECK-NEXT: "file": "SOURCE_DIR/test/APIJSON/availability.swift",
107+
// CHECK-NEXT: "linkage": "exported"
108+
// CHECK-NEXT: },
109+
// CHECK-NEXT: {
110+
// CHECK-NEXT: "name": "_$s8MyModule23availableOnlyOnActiveOSyyF",
111+
// CHECK-NEXT: "access": "public",
112+
// CHECK-NEXT: "file": "SOURCE_DIR/test/APIJSON/availability.swift",
113+
// CHECK-NEXT: "linkage": "exported",
114+
// CHECK-NEXT: "introduced": "10.10"
115+
// CHECK-NEXT: },
116+
// CHECK-NEXT: {
117+
// CHECK-NEXT: "name": "_$s8MyModule23unavailableOnSeperateOSyyF",
118+
// CHECK-NEXT: "access": "public",
119+
// CHECK-NEXT: "file": "SOURCE_DIR/test/APIJSON/availability.swift",
120+
// CHECK-NEXT: "linkage": "exported"
121+
// CHECK-NEXT: }
122+
// CHECK-NEXT: ],
123+
// CHECK-NEXT: "interfaces": [],
124+
// CHECK-NEXT: "categories": [],
125+
// CHECK-NEXT: "version": "1.0"
126+
// CHECK-NEXT: }

0 commit comments

Comments
 (0)