Skip to content

Commit 1efb638

Browse files
committed
[Sema] Add a helper function to get the innermost declaration with an
@available annotation.
1 parent e1de140 commit 1efb638

File tree

4 files changed

+24
-19
lines changed

4 files changed

+24
-19
lines changed

include/swift/AST/Decl.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -789,6 +789,9 @@ class alignas(1 << DeclAlignInBits) Decl {
789789
return Attrs;
790790
}
791791

792+
/// Returns the innermost enclosing decl with an availability annotation.
793+
const Decl *getInnermostDeclWithAvailability() const;
794+
792795
/// Returns the introduced OS version in the given platform kind specified
793796
/// by @available attribute.
794797
/// This function won't consider the parent context to get the information.

lib/AST/Decl.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,19 @@ StringRef Decl::getDescriptiveKindName(DescriptiveDeclKind K) {
351351
llvm_unreachable("bad DescriptiveDeclKind");
352352
}
353353

354+
const Decl *Decl::getInnermostDeclWithAvailability() const {
355+
const Decl *enclosingDecl = this;
356+
// Find the innermost enclosing declaration with an @available annotation.
357+
while (enclosingDecl != nullptr) {
358+
if (enclosingDecl->getAttrs().hasAttribute<AvailableAttr>())
359+
return enclosingDecl;
360+
361+
enclosingDecl = enclosingDecl->getDeclContext()->getAsDecl();
362+
}
363+
364+
return nullptr;
365+
}
366+
354367
Optional<llvm::VersionTuple>
355368
Decl::getIntroducedOSVersion(PlatformKind Kind) const {
356369
for (auto *attr: getAttrs()) {

lib/Sema/CodeSynthesis.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -566,17 +566,15 @@ configureInheritedDesignatedInitAttributes(ClassDecl *classDecl,
566566
// If the superclass has its own availability, make sure the synthesized
567567
// constructor is only as available as its superclass's constructor.
568568
if (superclassCtor->getAttrs().hasAttribute<AvailableAttr>()) {
569-
SmallVector<Decl *, 2> asAvailableAs;
569+
SmallVector<const Decl *, 2> asAvailableAs;
570570

571571
// We don't have to look at enclosing contexts of the superclass constructor,
572572
// because designated initializers must always be defined in the superclass
573573
// body, and we already enforce that a superclass is at least as available as
574574
// a subclass.
575575
asAvailableAs.push_back(superclassCtor);
576-
Decl *parentDecl = classDecl;
577-
while (parentDecl != nullptr) {
576+
if (auto *parentDecl = classDecl->getInnermostDeclWithAvailability()) {
578577
asAvailableAs.push_back(parentDecl);
579-
parentDecl = parentDecl->getDeclContext()->getAsDecl();
580578
}
581579
AvailabilityInference::applyInferredAvailableAttrs(
582580
ctor, asAvailableAs, ctx);

lib/Sema/TypeCheckStorage.cpp

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1967,19 +1967,8 @@ static AccessorDecl *createSetterPrototype(AbstractStorageDecl *storage,
19671967
assert(storage->requiresOpaqueAccessor(AccessorKind::Set));
19681968

19691969
// Copy availability from the accessor we'll synthesize the setter from.
1970-
SmallVector<Decl *, 2> asAvailableAs;
1971-
1972-
auto addEnclosingScopeAvailability = [&]() {
1973-
Decl *enclosingDecl = storage;
1974-
// Find the innermost enclosing declaration with an @available annotation.
1975-
while ((enclosingDecl = enclosingDecl->getDeclContext()->getAsDecl())) {
1976-
if (enclosingDecl->getAttrs().hasAttribute<AvailableAttr>()) {
1977-
asAvailableAs.push_back(enclosingDecl);
1978-
break;
1979-
}
1980-
}
1981-
};
1982-
1970+
SmallVector<const Decl *, 2> asAvailableAs;
1971+
19831972
// That could be a property wrapper...
19841973
if (auto var = dyn_cast<VarDecl>(storage)) {
19851974
if (var->hasAttachedPropertyWrapper()) {
@@ -1989,7 +1978,8 @@ static AccessorDecl *createSetterPrototype(AbstractStorageDecl *storage,
19891978
if (info.valueVar) {
19901979
if (auto setter = info.valueVar->getOpaqueAccessor(AccessorKind::Set)) {
19911980
asAvailableAs.push_back(setter);
1992-
addEnclosingScopeAvailability();
1981+
if (auto *enclosing = var->getInnermostDeclWithAvailability())
1982+
asAvailableAs.push_back(enclosing);
19931983
}
19941984
}
19951985
} else if (auto wrapperSynthesizedKind
@@ -2007,7 +1997,8 @@ static AccessorDecl *createSetterPrototype(AbstractStorageDecl *storage,
20071997
if (auto setter
20081998
= info.projectedValueVar->getOpaqueAccessor(AccessorKind::Set)){
20091999
asAvailableAs.push_back(setter);
2010-
addEnclosingScopeAvailability();
2000+
if (auto *enclosing = var->getInnermostDeclWithAvailability())
2001+
asAvailableAs.push_back(enclosing);
20112002
}
20122003
}
20132004
}

0 commit comments

Comments
 (0)