Skip to content

Commit 9bb2744

Browse files
authored
Merge pull request #71614 from tshortli/unavailable-decl-optimization-application-extensions
AST: Don't optimize decls that are unavailable in extensions
2 parents 3decd81 + 2967b80 commit 9bb2744

File tree

8 files changed

+94
-36
lines changed

8 files changed

+94
-36
lines changed

include/swift/AST/Attr.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2655,7 +2655,8 @@ class DeclAttributes {
26552655
/// Finds the most-specific platform-specific attribute that is
26562656
/// active for the current platform.
26572657
const AvailableAttr *
2658-
findMostSpecificActivePlatform(const ASTContext &ctx) const;
2658+
findMostSpecificActivePlatform(const ASTContext &ctx,
2659+
bool ignoreAppExtensions = false) const;
26592660

26602661
/// Returns the first @available attribute that indicates
26612662
/// a declaration is unavailable, or the first one that indicates it's
@@ -2664,7 +2665,8 @@ class DeclAttributes {
26642665

26652666
/// Returns the first @available attribute that indicates
26662667
/// a declaration is unavailable, or null otherwise.
2667-
const AvailableAttr *getUnavailable(const ASTContext &ctx) const;
2668+
const AvailableAttr *getUnavailable(const ASTContext &ctx,
2669+
bool ignoreAppExtensions = false) const;
26682670

26692671
/// Returns the first @available attribute that indicates
26702672
/// a declaration is deprecated on all deployment targets, or null otherwise.

include/swift/AST/Decl.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1289,7 +1289,8 @@ class alignas(1 << DeclAlignInBits) Decl : public ASTAllocated<Decl> {
12891289
getSemanticAvailableRangeAttr() const;
12901290

12911291
/// Retrieve the @available attribute that makes this declaration unavailable,
1292-
/// if any.
1292+
/// if any. If \p ignoreAppExtensions is true then attributes for app
1293+
/// extension platforms are ignored.
12931294
///
12941295
/// This attribute may come from an enclosing decl since availability is
12951296
/// inherited. The second member of the returned pair is the decl that owns
@@ -1298,7 +1299,7 @@ class alignas(1 << DeclAlignInBits) Decl : public ASTAllocated<Decl> {
12981299
/// Note that this notion of unavailability is broader than that which is
12991300
/// checked by \c AvailableAttr::isUnavailable.
13001301
llvm::Optional<std::pair<const AvailableAttr *, const Decl *>>
1301-
getSemanticUnavailableAttr() const;
1302+
getSemanticUnavailableAttr(bool ignoreAppExtensions = false) const;
13021303

13031304
/// Returns true if this declaration should be considered available during
13041305
/// SIL/IR lowering. A declaration would not be available during lowering if,

include/swift/AST/PlatformKind.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,12 @@ StringRef prettyPlatformString(PlatformKind platform);
5757
llvm::Optional<PlatformKind>
5858
basePlatformForExtensionPlatform(PlatformKind Platform);
5959

60+
/// Returns true if \p Platform represents and application extension platform,
61+
/// e.g. `iOSApplicationExtension`.
62+
inline bool isApplicationExtensionPlatform(PlatformKind Platform) {
63+
return basePlatformForExtensionPlatform(Platform).has_value();
64+
}
65+
6066
/// Returns whether the passed-in platform is active, given the language
6167
/// options. A platform is active if either it is the target platform or its
6268
/// AppExtension variant is the target platform. For example, OS X is

include/swift/AST/TypeCheckRequests.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3985,16 +3985,18 @@ class SemanticAvailableRangeAttrRequest
39853985

39863986
class SemanticUnavailableAttrRequest
39873987
: public SimpleRequest<SemanticUnavailableAttrRequest,
3988-
llvm::Optional<AvailableAttrDeclPair>(const Decl *),
3988+
llvm::Optional<AvailableAttrDeclPair>(
3989+
const Decl *decl, bool ignoreAppExtensions),
39893990
RequestFlags::Cached> {
39903991
public:
39913992
using SimpleRequest::SimpleRequest;
39923993

39933994
private:
39943995
friend SimpleRequest;
39953996

3996-
llvm::Optional<AvailableAttrDeclPair> evaluate(Evaluator &evaluator,
3997-
const Decl *decl) const;
3997+
llvm::Optional<AvailableAttrDeclPair>
3998+
evaluate(Evaluator &evaluator, const Decl *decl,
3999+
bool ignoreAppExtensions) const;
39984000

39994001
public:
40004002
bool isCached() const { return true; }

lib/AST/Attr.cpp

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,8 @@ DeclAttributes::isUnavailableInSwiftVersion(
337337
}
338338

339339
const AvailableAttr *
340-
DeclAttributes::findMostSpecificActivePlatform(const ASTContext &ctx) const{
340+
DeclAttributes::findMostSpecificActivePlatform(const ASTContext &ctx,
341+
bool ignoreAppExtensions) const {
341342
const AvailableAttr *bestAttr = nullptr;
342343

343344
for (auto attr : *this) {
@@ -354,6 +355,9 @@ DeclAttributes::findMostSpecificActivePlatform(const ASTContext &ctx) const{
354355
if (!avAttr->isActivePlatform(ctx))
355356
continue;
356357

358+
if (ignoreAppExtensions && isApplicationExtensionPlatform(avAttr->Platform))
359+
continue;
360+
357361
// We have an attribute that is active for the platform, but
358362
// is it more specific than our current best?
359363
if (!bestAttr || inheritsAvailabilityFromPlatform(avAttr->Platform,
@@ -407,10 +411,12 @@ DeclAttributes::getPotentiallyUnavailable(const ASTContext &ctx) const {
407411
return potential;
408412
}
409413

410-
const AvailableAttr *DeclAttributes::getUnavailable(
411-
const ASTContext &ctx) const {
414+
const AvailableAttr *
415+
DeclAttributes::getUnavailable(const ASTContext &ctx,
416+
bool ignoreAppExtensions) const {
412417
const AvailableAttr *conditional = nullptr;
413-
const AvailableAttr *bestActive = findMostSpecificActivePlatform(ctx);
418+
const AvailableAttr *bestActive =
419+
findMostSpecificActivePlatform(ctx, ignoreAppExtensions);
414420

415421
for (auto Attr : *this)
416422
if (auto AvAttr = dyn_cast<AvailableAttr>(Attr)) {
@@ -429,6 +435,10 @@ const AvailableAttr *DeclAttributes::getUnavailable(
429435
!AvAttr->isPackageDescriptionVersionSpecific())
430436
continue;
431437

438+
if (ignoreAppExtensions &&
439+
isApplicationExtensionPlatform(AvAttr->Platform))
440+
continue;
441+
432442
// Unconditional unavailable.
433443
if (AvAttr->isUnconditionallyUnavailable())
434444
return AvAttr;

lib/AST/Availability.cpp

Lines changed: 30 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -302,30 +302,47 @@ bool Decl::isAvailableAsSPI() const {
302302
}
303303

304304
llvm::Optional<AvailableAttrDeclPair>
305-
SemanticUnavailableAttrRequest::evaluate(Evaluator &evaluator,
306-
const Decl *decl) const {
305+
SemanticUnavailableAttrRequest::evaluate(Evaluator &evaluator, const Decl *decl,
306+
bool ignoreAppExtensions) const {
307307
// Directly marked unavailable.
308-
if (auto attr = decl->getAttrs().getUnavailable(decl->getASTContext()))
308+
if (auto attr = decl->getAttrs().getUnavailable(decl->getASTContext(),
309+
ignoreAppExtensions))
309310
return std::make_pair(attr, decl);
310311

311312
if (auto *parent =
312313
AvailabilityInference::parentDeclForInferredAvailability(decl))
313-
return parent->getSemanticUnavailableAttr();
314+
return parent->getSemanticUnavailableAttr(ignoreAppExtensions);
314315

315316
return llvm::None;
316317
}
317318

318-
llvm::Optional<AvailableAttrDeclPair> Decl::getSemanticUnavailableAttr() const {
319+
llvm::Optional<AvailableAttrDeclPair>
320+
Decl::getSemanticUnavailableAttr(bool ignoreAppExtensions) const {
319321
auto &eval = getASTContext().evaluator;
320-
return evaluateOrDefault(eval, SemanticUnavailableAttrRequest{this},
321-
llvm::None);
322+
return evaluateOrDefault(
323+
eval, SemanticUnavailableAttrRequest{this, ignoreAppExtensions},
324+
llvm::None);
322325
}
323326

324-
static bool isUnconditionallyUnavailable(const Decl *D) {
325-
if (auto unavailableAttrAndDecl = D->getSemanticUnavailableAttr())
326-
return unavailableAttrAndDecl->first->isUnconditionallyUnavailable();
327+
static bool shouldStubOrSkipUnavailableDecl(const Decl *D) {
328+
// Don't trust unavailability on declarations from clang modules.
329+
if (isa<ClangModuleUnit>(D->getDeclContext()->getModuleScopeContext()))
330+
return false;
331+
332+
auto unavailableAttrAndDecl =
333+
D->getSemanticUnavailableAttr(/*ignoreAppExtensions=*/true);
334+
if (!unavailableAttrAndDecl)
335+
return false;
327336

328-
return false;
337+
// getSemanticUnavailableAttr() can return an @available attribute that makes
338+
// its declaration unavailable conditionally due to deployment target. Only
339+
// stub or skip a declaration that is unavailable regardless of deployment
340+
// target.
341+
auto *unavailableAttr = unavailableAttrAndDecl->first;
342+
if (!unavailableAttr->isUnconditionallyUnavailable())
343+
return false;
344+
345+
return true;
329346
}
330347

331348
static UnavailableDeclOptimization
@@ -343,10 +360,7 @@ bool Decl::isAvailableDuringLowering() const {
343360
UnavailableDeclOptimization::Complete)
344361
return true;
345362

346-
if (isa<ClangModuleUnit>(getDeclContext()->getModuleScopeContext()))
347-
return true;
348-
349-
return !isUnconditionallyUnavailable(this);
363+
return !shouldStubOrSkipUnavailableDecl(this);
350364
}
351365

352366
bool Decl::requiresUnavailableDeclABICompatibilityStubs() const {
@@ -356,10 +370,7 @@ bool Decl::requiresUnavailableDeclABICompatibilityStubs() const {
356370
UnavailableDeclOptimization::Stub)
357371
return false;
358372

359-
if (isa<ClangModuleUnit>(getDeclContext()->getModuleScopeContext()))
360-
return false;
361-
362-
return isUnconditionallyUnavailable(this);
373+
return shouldStubOrSkipUnavailableDecl(this);
363374
}
364375

365376
bool UnavailabilityReason::requiresDeploymentTargetOrEarlier(

lib/AST/PlatformKind.cpp

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -109,10 +109,6 @@ swift::basePlatformForExtensionPlatform(PlatformKind Platform) {
109109
llvm_unreachable("bad PlatformKind");
110110
}
111111

112-
static bool isApplicationExtensionPlatform(PlatformKind Platform) {
113-
return basePlatformForExtensionPlatform(Platform).has_value();
114-
}
115-
116112
static bool isPlatformActiveForTarget(PlatformKind Platform,
117113
const llvm::Triple &Target,
118114
bool EnableAppExtensionRestrictions) {

test/SILGen/unavailable_decl_optimization_stub_macos.swift

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1-
// RUN: %target-swift-emit-silgen -target %target-swift-abi-5.8-triple -module-name Test -parse-as-library %s -verify -unavailable-decl-optimization=stub | %FileCheck %s --check-prefixes=CHECK-SWIFT5_8
2-
// RUN: %target-swift-emit-silgen -target %target-swift-abi-5.9-triple -module-name Test -parse-as-library %s -verify -unavailable-decl-optimization=stub | %FileCheck %s --check-prefixes=CHECK-SWIFT5_9
1+
// RUN: %target-swift-emit-silgen -target %target-swift-abi-5.8-triple -module-name Test -parse-as-library %s -verify -unavailable-decl-optimization=stub | %FileCheck %s --check-prefixes=CHECK,CHECK-SWIFT5_8
2+
// RUN: %target-swift-emit-silgen -target %target-swift-abi-5.8-triple -module-name Test -parse-as-library %s -verify -unavailable-decl-optimization=stub -application-extension | %FileCheck %s --check-prefixes=CHECK,CHECK-SWIFT5_8
3+
// RUN: %target-swift-emit-silgen -target %target-swift-abi-5.9-triple -module-name Test -parse-as-library %s -verify -unavailable-decl-optimization=stub | %FileCheck %s --check-prefixes=CHECK,CHECK-SWIFT5_9
4+
// RUN: %target-swift-emit-silgen -target %target-swift-abi-5.9-triple -module-name Test -parse-as-library %s -verify -unavailable-decl-optimization=stub -application-extension | %FileCheck %s --check-prefixes=CHECK,CHECK-SWIFT5_9
35

46
// REQUIRES: OS=macosx
57

@@ -19,3 +21,31 @@ public func unavailableFunc() {}
1921
@available(*, unavailable)
2022
@inlinable public func unavailableInlinableFunc() {}
2123

24+
// CHECK-LABEL: sil{{.*}}@$s4Test22unavailableOnMacOSFuncyyF
25+
// CHECK-SWIFT5_8: [[FNREF:%.*]] = function_ref @$ss36_diagnoseUnavailableCodeReached_aeics5NeverOyF : $@convention(thin) () -> Never
26+
// CHECK-SWIFT5_9: [[FNREF:%.*]] = function_ref @$ss31_diagnoseUnavailableCodeReacheds5NeverOyF : $@convention(thin) () -> Never
27+
// CHECK-NEXT: [[APPLY:%.*]] = apply [[FNREF]]()
28+
// CHECK: } // end sil function '$s4Test22unavailableOnMacOSFuncyyF'
29+
@available(macOS, unavailable)
30+
public func unavailableOnMacOSFunc() {}
31+
32+
// CHECK-LABEL: sil{{.*}}@$s4Test31unavailableOnMacOSExtensionFuncyyF
33+
// CHECK-NOT: function_ref @$ss36_diagnoseUnavailableCodeReached{{.*}} : $@convention(thin) () -> Never
34+
// CHECK: } // end sil function '$s4Test31unavailableOnMacOSExtensionFuncyyF'
35+
@available(macOSApplicationExtension, unavailable)
36+
public func unavailableOnMacOSExtensionFunc() {}
37+
38+
// CHECK-LABEL: sil{{.*}}@$s4Test021unavailableOnMacOSAndD15OSExtensionFuncyyF
39+
// CHECK-SWIFT5_8: [[FNREF:%.*]] = function_ref @$ss36_diagnoseUnavailableCodeReached_aeics5NeverOyF : $@convention(thin) () -> Never
40+
// CHECK-SWIFT5_9: [[FNREF:%.*]] = function_ref @$ss31_diagnoseUnavailableCodeReacheds5NeverOyF : $@convention(thin) () -> Never
41+
// CHECK-NEXT: [[APPLY:%.*]] = apply [[FNREF]]()
42+
// CHECK: } // end sil function '$s4Test021unavailableOnMacOSAndD15OSExtensionFuncyyF'
43+
@available(macOS, unavailable)
44+
@available(macOSApplicationExtension, unavailable) // FIXME: Seems like this should be diagnosed as redundant
45+
public func unavailableOnMacOSAndMacOSExtensionFunc() {}
46+
47+
// CHECK-LABEL: sil{{.*}}@$s4Test20unavailableOniOSFuncyyF
48+
// CHECK-NOT: function_ref @$ss36_diagnoseUnavailableCodeReached{{.*}} : $@convention(thin) () -> Never
49+
// CHECK: } // end sil function '$s4Test20unavailableOniOSFuncyyF'
50+
@available(iOS, unavailable)
51+
public func unavailableOniOSFunc() {}

0 commit comments

Comments
 (0)