Skip to content

Commit 8c50f67

Browse files
committed
Sema: Factor out common logic for finding enclosing declaration availability
A common operation for availability checking is determining whether some lexically enclosing declaration matches a condition. This commit factors out that logic. NFC. Swift SVN r27181
1 parent f87788f commit 8c50f67

File tree

4 files changed

+49
-34
lines changed

4 files changed

+49
-34
lines changed

lib/Sema/MiscDiagnostics.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -487,7 +487,7 @@ static bool diagAvailability(TypeChecker &TC, const ValueDecl *D,
487487
// to an unavailable default constructor of a super class).
488488
// We need to handle these properly. rdar://problem/20024980 tracks this.
489489
if (!TC.getLangOpts().EnableAvailabilityCheckingInImplicitFunctions &&
490-
TypeChecker::isInsideImplicitFunction(DC)) {
490+
TC.isInsideImplicitFunction(R, DC)) {
491491
return false;
492492
}
493493

@@ -549,7 +549,7 @@ static bool diagAvailability(TypeChecker &TC, const ValueDecl *D,
549549
}
550550

551551
// Diagnose for deprecation
552-
if (const AvailabilityAttr *Attr = TC.getDeprecated(D)) {
552+
if (const AvailabilityAttr *Attr = TypeChecker::getDeprecated(D)) {
553553
TC.diagnoseDeprecated(R, DC, Attr, D->getFullName());
554554
}
555555

lib/Sema/TypeCheckType.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -963,7 +963,7 @@ static bool checkTypeDeclAvailability(Decl *TypeDecl, IdentTypeRepr *IdType,
963963
return true;
964964
}
965965

966-
if (auto *Attr = TC.getDeprecated(TypeDecl)) {
966+
if (auto *Attr = TypeChecker::getDeprecated(TypeDecl)) {
967967
TC.diagnoseDeprecated(CI->getSourceRange(), DC, Attr,
968968
CI->getIdentifier());
969969
}

lib/Sema/TypeChecker.cpp

Lines changed: 42 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1921,21 +1921,8 @@ void TypeChecker::diagnosePotentialAccessorUnavailability(
19211921
Reason.getRequiredOSVersionRange(), *this);
19221922
}
19231923

1924-
bool TypeChecker::isInsideImplicitFunction(const DeclContext *DC) {
1925-
do {
1926-
auto *AFD = dyn_cast<AbstractFunctionDecl>(DC);
1927-
if (AFD && AFD->isImplicit()) {
1928-
return true;
1929-
}
1930-
1931-
DC = DC->getParent();
1932-
} while (DC);
1933-
1934-
return false;
1935-
}
1936-
19371924
const AvailabilityAttr *TypeChecker::getDeprecated(const Decl *D) {
1938-
if (auto *Attr = D->getAttrs().getDeprecated(Context))
1925+
if (auto *Attr = D->getAttrs().getDeprecated(D->getASTContext()))
19391926
return Attr;
19401927

19411928
// Treat extensions methods as deprecated if their extension
@@ -1948,37 +1935,36 @@ const AvailabilityAttr *TypeChecker::getDeprecated(const Decl *D) {
19481935
return nullptr;
19491936
}
19501937

1951-
/// Returns true if the reference is lexically contained in a declaration
1952-
/// that is deprecated on all deployment targets.
1953-
static bool isInsideDeprecatedDeclaration(SourceRange ReferenceRange,
1954-
const DeclContext *ReferenceDC,
1955-
TypeChecker &TC) {
1938+
/// Returns true if some declaration lexically enclosing the reference
1939+
/// matches the passed in predicate and false otherwise.
1940+
static bool someEnclosingDeclMatches(SourceRange ReferenceRange,
1941+
const DeclContext *ReferenceDC,
1942+
TypeChecker &TC,
1943+
std::function<bool(const Decl *)> Pred) {
19561944
ASTContext &Ctx = TC.Context;
19571945

19581946
// Climb the DeclContext hierarchy to see if any of the containing
1959-
// declarations are deprecated on on all deployment targets.
1947+
// declarations matches the predicate.
19601948
const DeclContext *DC = ReferenceDC;
19611949
do {
19621950
auto *D = DC->getInnermostDeclarationDeclContext();
19631951
if (!D)
19641952
break;
19651953

1966-
if (D->getAttrs().getDeprecated(Ctx)) {
1954+
if (Pred(D)) {
19671955
return true;
19681956
}
19691957

19701958
// If we are in an accessor, check to see if the associated
1971-
// property is deprecated.
1959+
// property is matches the predicate.
19721960
auto *FD = dyn_cast<FuncDecl>(D);
1973-
if (FD && FD->isAccessor() &&
1974-
TC.getDeprecated(FD->getAccessorStorageDecl())) {
1961+
if (FD && FD->isAccessor() && Pred(FD->getAccessorStorageDecl())) {
19751962
return true;
19761963
}
19771964

19781965
DC = DC->getParent();
19791966
} while (DC);
19801967

1981-
19821968
// Search the AST starting from our innermost declaration context to see if
19831969
// if the reference is inside a property declaration but not inside an
19841970
// accessor (this can happen for the TypeRepr for the declared type of a
@@ -1991,8 +1977,12 @@ static bool isInsideDeprecatedDeclaration(SourceRange ReferenceRange,
19911977
if (!ReferenceDC->isTypeContext() && !ReferenceDC->isModuleScopeContext())
19921978
return false;
19931979

1980+
// Don't search for a containing declaration if we don't have a source range.
1981+
if (ReferenceRange.isInvalid())
1982+
return false;
1983+
19941984
const Decl *DeclToSearch =
1995-
findContainingDeclaration(ReferenceRange, ReferenceDC, Ctx.SourceMgr);
1985+
findContainingDeclaration(ReferenceRange, ReferenceDC, Ctx.SourceMgr);
19961986

19971987
// We may not be able to find a declaration to search if the ReferenceRange
19981988
// is invalid (i.e., we are in synthesized code).
@@ -2011,14 +2001,38 @@ static bool isInsideDeprecatedDeclaration(SourceRange ReferenceRange,
20112001
if (FoundDeclarationNode.hasValue()) {
20122002
const Decl *D = FoundDeclarationNode.getValue().get<Decl *>();
20132003
D = abstractSyntaxDeclForAvailabilityAttribute(D);
2014-
if (TC.getDeprecated(D)) {
2004+
if (Pred(D)) {
20152005
return true;
20162006
}
20172007
}
20182008

20192009
return false;
20202010
}
20212011

2012+
bool TypeChecker::isInsideImplicitFunction(SourceRange ReferenceRange,
2013+
const DeclContext *DC) {
2014+
std::function<bool(const Decl *)> IsInsideImplicitFunc = [](const Decl *D) {
2015+
auto *AFD = dyn_cast<AbstractFunctionDecl>(D);
2016+
return AFD && AFD->isImplicit();
2017+
};
2018+
2019+
return someEnclosingDeclMatches(ReferenceRange, DC, *this,
2020+
IsInsideImplicitFunc);
2021+
}
2022+
2023+
/// Returns true if the reference is lexically contained in a declaration
2024+
/// that is deprecated on all deployment targets.
2025+
static bool isInsideDeprecatedDeclaration(SourceRange ReferenceRange,
2026+
const DeclContext *ReferenceDC,
2027+
TypeChecker &TC) {
2028+
std::function<bool(const Decl *)> IsDeprecated = [](const Decl *D) {
2029+
return D->getAttrs().getDeprecated(D->getASTContext());
2030+
};
2031+
2032+
return someEnclosingDeclMatches(ReferenceRange, ReferenceDC, TC,
2033+
IsDeprecated);
2034+
}
2035+
20222036
void TypeChecker::diagnoseDeprecated(SourceRange ReferenceRange,
20232037
const DeclContext *ReferenceDC,
20242038
const AvailabilityAttr *Attr,
@@ -2035,7 +2049,7 @@ void TypeChecker::diagnoseDeprecated(SourceRange ReferenceRange,
20352049
// a deprecated API element. rdar://problem/20024980 tracks these
20362050
// special-case diagnostics.
20372051
if (!getLangOpts().EnableAvailabilityCheckingInImplicitFunctions &&
2038-
isInsideImplicitFunction(ReferenceDC)) {
2052+
isInsideImplicitFunction(ReferenceRange, ReferenceDC)) {
20392053
return;
20402054
}
20412055

lib/Sema/TypeChecker.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1331,13 +1331,14 @@ class TypeChecker final : public LazyResolver {
13311331
const DeclContext *ReferenceDC, const UnavailabilityReason &Reason,
13321332
bool ForInout);
13331333

1334-
/// Returns true if the declaration context or any of its parents is an
1334+
/// Returns true if the reference or any of its parents is an
13351335
/// implicit function.
1336-
static bool isInsideImplicitFunction(const DeclContext *DC);
1336+
bool isInsideImplicitFunction(SourceRange ReferenceRange,
1337+
const DeclContext *DC);
13371338

13381339
/// Returns the availability attribute indicating deprecation if the
13391340
/// declaration is deprecated or null otherwise.
1340-
const AvailabilityAttr *getDeprecated(const Decl *D);
1341+
static const AvailabilityAttr *getDeprecated(const Decl *D);
13411342

13421343
/// Emits a diagnostic for a reference to a declaration that is deprecated.
13431344
void diagnoseDeprecated(SourceRange SourceRange,

0 commit comments

Comments
 (0)