38
38
using namespace swift ;
39
39
40
40
ExportContext::ExportContext (DeclContext *DC, FragileFunctionKind kind,
41
- bool spi, bool exported, bool implicit,
42
- bool deprecated )
41
+ bool spi, bool exported, bool implicit, bool deprecated,
42
+ Optional<PlatformKind> unavailablePlatformKind )
43
43
: DC(DC), FragileKind(kind) {
44
44
SPI = spi;
45
45
Exported = exported;
46
46
Implicit = implicit;
47
47
Deprecated = deprecated;
48
- Reason = ExportabilityReason::General;
48
+ if (unavailablePlatformKind) {
49
+ Unavailable = 1 ;
50
+ Platform = unsigned (*unavailablePlatformKind);
51
+ } else {
52
+ Unavailable = 0 ;
53
+ Platform = 0 ;
54
+ }
55
+
56
+ Reason = unsigned (ExportabilityReason::General);
49
57
}
50
58
51
59
bool swift::isExported (const ValueDecl *VD) {
@@ -141,28 +149,39 @@ static void forEachOuterDecl(DeclContext *DC, Fn fn) {
141
149
}
142
150
143
151
static void computeExportContextBits (Decl *D,
144
- bool *implicit, bool *deprecated) {
152
+ bool *implicit, bool *deprecated,
153
+ Optional<PlatformKind> *unavailablePlatformKind) {
145
154
if (D->isImplicit ())
146
155
*implicit = true ;
147
156
148
- if (D->getAttrs ().getDeprecated (D->getASTContext ()))
157
+ auto &Ctx = D->getASTContext ();
158
+
159
+ if (D->getAttrs ().getDeprecated (Ctx))
149
160
*deprecated = true ;
150
161
162
+ if (auto *A = D->getAttrs ().getUnavailable (Ctx)) {
163
+ *unavailablePlatformKind = A->Platform ;
164
+ }
165
+
151
166
if (auto *PBD = dyn_cast<PatternBindingDecl>(D)) {
152
167
for (unsigned i = 0 , e = PBD->getNumPatternEntries (); i < e; ++i) {
153
168
if (auto *VD = PBD->getAnchoringVarDecl (i))
154
- computeExportContextBits (VD, implicit, deprecated);
169
+ computeExportContextBits (VD, implicit, deprecated,
170
+ unavailablePlatformKind);
155
171
}
156
172
}
157
173
}
158
174
159
175
ExportContext ExportContext::forDeclSignature (Decl *D) {
160
176
bool implicit = false ;
161
177
bool deprecated = false ;
162
- computeExportContextBits (D, &implicit, &deprecated);
178
+ Optional<PlatformKind> unavailablePlatformKind;
179
+ computeExportContextBits (D, &implicit, &deprecated,
180
+ &unavailablePlatformKind);
163
181
forEachOuterDecl (D->getDeclContext (),
164
182
[&](Decl *D) {
165
- computeExportContextBits (D, &implicit, &deprecated);
183
+ computeExportContextBits (D, &implicit, &deprecated,
184
+ &unavailablePlatformKind);
166
185
});
167
186
168
187
auto *DC = D->getInnermostDeclContext ();
@@ -182,15 +201,18 @@ ExportContext ExportContext::forDeclSignature(Decl *D) {
182
201
183
202
bool exported = ::isExported (D);
184
203
185
- return ExportContext (DC, fragileKind, spi, exported, implicit, deprecated);
204
+ return ExportContext (DC, fragileKind, spi, exported, implicit, deprecated,
205
+ unavailablePlatformKind);
186
206
}
187
207
188
208
ExportContext ExportContext::forFunctionBody (DeclContext *DC) {
189
209
bool implicit = false ;
190
210
bool deprecated = false ;
211
+ Optional<PlatformKind> unavailablePlatformKind;
191
212
forEachOuterDecl (DC,
192
213
[&](Decl *D) {
193
- computeExportContextBits (D, &implicit, &deprecated);
214
+ computeExportContextBits (D, &implicit, &deprecated,
215
+ &unavailablePlatformKind);
194
216
});
195
217
196
218
auto fragileKind = DC->getFragileFunctionKind ();
@@ -204,12 +226,13 @@ ExportContext ExportContext::forFunctionBody(DeclContext *DC) {
204
226
assert (fragileKind.kind == FragileFunctionKind::None);
205
227
}
206
228
207
- return ExportContext (DC, fragileKind, spi, exported, implicit, deprecated);
229
+ return ExportContext (DC, fragileKind, spi, exported, implicit, deprecated,
230
+ unavailablePlatformKind);
208
231
}
209
232
210
233
ExportContext ExportContext::withReason (ExportabilityReason reason) const {
211
234
auto copy = *this ;
212
- copy.Reason = reason;
235
+ copy.Reason = unsigned ( reason) ;
213
236
return copy;
214
237
}
215
238
@@ -219,13 +242,19 @@ ExportContext ExportContext::withExported(bool exported) const {
219
242
return copy;
220
243
}
221
244
245
+ Optional<PlatformKind> ExportContext::getUnavailablePlatformKind () const {
246
+ if (Unavailable)
247
+ return PlatformKind (Platform);
248
+ return None;
249
+ }
250
+
222
251
bool ExportContext::mustOnlyReferenceExportedDecls () const {
223
252
return Exported || FragileKind.kind != FragileFunctionKind::None;
224
253
}
225
254
226
255
Optional<ExportabilityReason> ExportContext::getExportabilityReason () const {
227
256
if (Exported)
228
- return Reason;
257
+ return ExportabilityReason ( Reason) ;
229
258
return None;
230
259
}
231
260
@@ -1644,62 +1673,15 @@ const AvailableAttr *TypeChecker::getDeprecated(const Decl *D) {
1644
1673
return nullptr ;
1645
1674
}
1646
1675
1647
- // / Returns true if some declaration lexically enclosing the reference
1648
- // / matches the passed in predicate and false otherwise.
1649
- static bool
1650
- someEnclosingDeclMatches (SourceRange ReferenceRange,
1651
- const DeclContext *ReferenceDC,
1652
- llvm::function_ref<bool (const Decl *)> Pred) {
1653
- // Climb the DeclContext hierarchy to see if any of the containing
1654
- // declarations matches the predicate.
1655
- const DeclContext *DC = ReferenceDC;
1656
- while (true ) {
1657
- auto *D = DC->getInnermostDeclarationDeclContext ();
1658
- if (!D)
1659
- break ;
1660
-
1661
- if (Pred (D)) {
1662
- return true ;
1663
- }
1664
-
1665
- // If we are in an accessor, check to see if the associated
1666
- // property matches the predicate.
1667
- if (auto accessor = dyn_cast<AccessorDecl>(D)) {
1668
- if (Pred (accessor->getStorage ()))
1669
- return true ;
1670
- }
1671
-
1672
- DC = D->getDeclContext ();
1673
- }
1674
-
1675
- // Search the AST starting from our innermost declaration context to see if
1676
- // if the reference is inside a property declaration but not inside an
1677
- // accessor (this can happen for the TypeRepr for the declared type of a
1678
- // property, for example).
1679
- // We can't rely on the DeclContext hierarchy climb above because properties
1680
- // do not introduce a new DeclContext.
1681
-
1682
- // Don't search for a containing declaration if we don't have a source range.
1683
- if (ReferenceRange.isInvalid ())
1684
- return false ;
1685
-
1686
- ASTContext &Ctx = ReferenceDC->getASTContext ();
1687
- const Decl *DeclToSearch =
1688
- findContainingDeclaration (ReferenceRange, ReferenceDC, Ctx.SourceMgr );
1689
-
1690
- // We may not be able to find a declaration to search if the ReferenceRange
1691
- // isn't useful (i.e., we are in synthesized code).
1692
- if (!DeclToSearch)
1693
- return false ;
1694
-
1695
- return Pred (abstractSyntaxDeclForAvailableAttribute (DeclToSearch));
1696
- }
1697
-
1698
1676
// / Returns true if the reference or any of its parents is an
1699
1677
// / unconditional unavailable declaration for the same platform.
1700
1678
static bool isInsideCompatibleUnavailableDeclaration (
1701
- const ValueDecl *referencedD, SourceRange ReferenceRange,
1702
- const DeclContext *ReferenceDC, const AvailableAttr *attr) {
1679
+ const ValueDecl *D, ExportContext where,
1680
+ const AvailableAttr *attr) {
1681
+ auto referencedPlatform = where.getUnavailablePlatformKind ();
1682
+ if (!referencedPlatform)
1683
+ return false ;
1684
+
1703
1685
if (!attr->isUnconditionallyUnavailable ()) {
1704
1686
return false ;
1705
1687
}
@@ -1708,20 +1690,13 @@ static bool isInsideCompatibleUnavailableDeclaration(
1708
1690
// but allow the use of types.
1709
1691
PlatformKind platform = attr->Platform ;
1710
1692
if (platform == PlatformKind::none &&
1711
- !isa<TypeDecl>(referencedD )) {
1693
+ !isa<TypeDecl>(D )) {
1712
1694
return false ;
1713
1695
}
1714
1696
1715
- auto IsUnavailable = [platform](const Decl *D) {
1716
- auto EnclosingUnavailable =
1717
- D->getAttrs ().getUnavailable (D->getASTContext ());
1718
- return EnclosingUnavailable &&
1719
- (EnclosingUnavailable->Platform == platform ||
1720
- inheritsAvailabilityFromPlatform (platform,
1721
- EnclosingUnavailable->Platform ));
1722
- };
1723
-
1724
- return someEnclosingDeclMatches (ReferenceRange, ReferenceDC, IsUnavailable);
1697
+ return (*referencedPlatform == platform ||
1698
+ inheritsAvailabilityFromPlatform (platform,
1699
+ *referencedPlatform));
1725
1700
}
1726
1701
1727
1702
static void fixItAvailableAttrRename (InFlightDiagnostic &diag,
@@ -2201,8 +2176,8 @@ void swift::diagnoseUnavailableOverride(ValueDecl *override,
2201
2176
return ;
2202
2177
}
2203
2178
2204
- diagnoseExplicitUnavailability (base, override -> getLoc (),
2205
- override ->getDeclContext () ,
2179
+ ExportContext where = ExportContext::forDeclSignature ( override );
2180
+ diagnoseExplicitUnavailability (base, override ->getLoc (), where ,
2206
2181
/* Flags*/ None,
2207
2182
[&](InFlightDiagnostic &diag) {
2208
2183
ParsedDeclName parsedName = parseDeclName (attr->Rename );
@@ -2235,10 +2210,10 @@ void swift::diagnoseUnavailableOverride(ValueDecl *override,
2235
2210
// / marked as unavailable, either through "unavailable" or "obsoleted:".
2236
2211
bool swift::diagnoseExplicitUnavailability (const ValueDecl *D,
2237
2212
SourceRange R,
2238
- const DeclContext *DC ,
2213
+ ExportContext Where ,
2239
2214
const ApplyExpr *call,
2240
2215
DeclAvailabilityFlags Flags) {
2241
- return diagnoseExplicitUnavailability (D, R, DC , Flags,
2216
+ return diagnoseExplicitUnavailability (D, R, Where , Flags,
2242
2217
[=](InFlightDiagnostic &diag) {
2243
2218
fixItAvailableAttrRename (diag, R, D, AvailableAttr::isUnavailable (D),
2244
2219
call);
@@ -2309,7 +2284,7 @@ bool isSubscriptReturningString(const ValueDecl *D, ASTContext &Context) {
2309
2284
bool swift::diagnoseExplicitUnavailability (
2310
2285
const ValueDecl *D,
2311
2286
SourceRange R,
2312
- const DeclContext *DC ,
2287
+ ExportContext Where ,
2313
2288
DeclAvailabilityFlags Flags,
2314
2289
llvm::function_ref<void (InFlightDiagnostic &)> attachRenameFixIts) {
2315
2290
auto *Attr = AvailableAttr::isUnavailable (D);
@@ -2320,9 +2295,8 @@ bool swift::diagnoseExplicitUnavailability(
2320
2295
// unavailability is OK -- the eventual caller can't call the
2321
2296
// enclosing code in the same situations it wouldn't be able to
2322
2297
// call this code.
2323
- if (isInsideCompatibleUnavailableDeclaration (D, R, DC, Attr)) {
2298
+ if (isInsideCompatibleUnavailableDeclaration (D, Where, Attr))
2324
2299
return false ;
2325
- }
2326
2300
2327
2301
SourceLoc Loc = R.Start ;
2328
2302
DeclName Name;
@@ -2776,9 +2750,7 @@ AvailabilityWalker::diagAvailability(ConcreteDeclRef declRef, SourceRange R,
2776
2750
}
2777
2751
}
2778
2752
2779
- auto *DC = Where.getDeclContext ();
2780
-
2781
- if (diagnoseExplicitUnavailability (D, R, DC, call, Flags))
2753
+ if (diagnoseExplicitUnavailability (D, R, Where, call, Flags))
2782
2754
return true ;
2783
2755
2784
2756
// Make sure not to diagnose an accessor's deprecation if we already
@@ -2794,6 +2766,8 @@ AvailabilityWalker::diagAvailability(ConcreteDeclRef declRef, SourceRange R,
2794
2766
&& isa<ProtocolDecl>(D))
2795
2767
return false ;
2796
2768
2769
+ auto *DC = Where.getDeclContext ();
2770
+
2797
2771
// Diagnose (and possibly signal) for potential unavailability
2798
2772
auto maybeUnavail = TypeChecker::checkDeclarationAvailability (D, R.Start , DC);
2799
2773
if (maybeUnavail.hasValue ()) {
0 commit comments