Skip to content

Commit 18d4f63

Browse files
authored
Merge pull request #31962 from hamishknight/a-selection-of-cleanups
2 parents f8e3c40 + 7bb2749 commit 18d4f63

File tree

3 files changed

+66
-108
lines changed

3 files changed

+66
-108
lines changed

include/swift/AST/Decl.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4117,8 +4117,8 @@ class ClassDecl final : public NominalTypeDecl {
41174117
///
41184118
/// \param isInstance Whether we are looking for an instance method
41194119
/// (vs. a class method).
4120-
MutableArrayRef<AbstractFunctionDecl *> lookupDirect(ObjCSelector selector,
4121-
bool isInstance);
4120+
TinyPtrVector<AbstractFunctionDecl *> lookupDirect(ObjCSelector selector,
4121+
bool isInstance);
41224122

41234123
/// Record the presence of an @objc method with the given selector.
41244124
void recordObjCMethod(AbstractFunctionDecl *method, ObjCSelector selector);

lib/AST/NameLookup.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1309,7 +1309,7 @@ void ClassDecl::createObjCMethodLookup() {
13091309
});
13101310
}
13111311

1312-
MutableArrayRef<AbstractFunctionDecl *>
1312+
TinyPtrVector<AbstractFunctionDecl *>
13131313
ClassDecl::lookupDirect(ObjCSelector selector, bool isInstance) {
13141314
if (!ObjCMethodLookup) {
13151315
createObjCMethodLookup();
@@ -1325,7 +1325,7 @@ ClassDecl::lookupDirect(ObjCSelector selector, bool isInstance) {
13251325
stored.Generation = ctx.getCurrentGeneration();
13261326
}
13271327

1328-
return { stored.Methods.begin(), stored.Methods.end() };
1328+
return stored.Methods;
13291329
}
13301330

13311331
void ClassDecl::recordObjCMethod(AbstractFunctionDecl *method,

lib/Sema/TypeCheckDeclObjC.cpp

Lines changed: 62 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -1886,12 +1886,7 @@ bool swift::fixDeclarationObjCName(InFlightDiagnostic &diag, const ValueDecl *de
18861886

18871887
namespace {
18881888
/// Produce a deterministic ordering of the given declarations.
1889-
class OrderDeclarations {
1890-
SourceManager &SrcMgr;
1891-
1892-
public:
1893-
OrderDeclarations(SourceManager &srcMgr) : SrcMgr(srcMgr) { }
1894-
1889+
struct OrderDeclarations {
18951890
bool operator()(ValueDecl *lhs, ValueDecl *rhs) const {
18961891
// If the declarations come from different modules, order based on the
18971892
// module.
@@ -1912,6 +1907,7 @@ namespace {
19121907
}
19131908

19141909
// Prefer the declaration that comes first in the source file.
1910+
const auto &SrcMgr = lhsSF->getASTContext().SourceMgr;
19151911
return SrcMgr.isBeforeInBuffer(lhs->getLoc(), rhs->getLoc());
19161912
}
19171913

@@ -1924,57 +1920,43 @@ namespace {
19241920
} // end anonymous namespace
19251921

19261922
/// Lookup for an Objective-C method with the given selector in the
1927-
/// given class or any of its superclasses.
1928-
static AbstractFunctionDecl *lookupObjCMethodInClass(
1929-
ClassDecl *classDecl,
1930-
ObjCSelector selector,
1931-
bool isInstanceMethod,
1932-
bool isInitializer,
1933-
SourceManager &srcMgr,
1934-
bool inheritingInits = true) {
1935-
if (!classDecl)
1936-
return nullptr;
1923+
/// given class or any of its superclasses. We intentionally don't respect
1924+
/// access control, since everything is visible to the Objective-C runtime.
1925+
static AbstractFunctionDecl *
1926+
lookupOverridenObjCMethod(ClassDecl *classDecl, AbstractFunctionDecl *method,
1927+
bool inheritingInits = true) {
1928+
assert(classDecl);
19371929

19381930
// Look for an Objective-C method in this class.
1939-
auto methods = classDecl->lookupDirect(selector, isInstanceMethod);
1931+
auto methods = classDecl->lookupDirect(method->getObjCSelector(),
1932+
method->isObjCInstanceMethod());
19401933
if (!methods.empty()) {
19411934
// If we aren't inheriting initializers, remove any initializers from the
19421935
// list.
1943-
if (!inheritingInits &&
1944-
std::find_if(methods.begin(), methods.end(),
1945-
[](AbstractFunctionDecl *func) {
1946-
return isa<ConstructorDecl>(func);
1947-
}) != methods.end()) {
1948-
SmallVector<AbstractFunctionDecl *, 4> nonInitMethods;
1949-
std::copy_if(methods.begin(), methods.end(),
1950-
std::back_inserter(nonInitMethods),
1951-
[&](AbstractFunctionDecl *func) {
1952-
return !isa<ConstructorDecl>(func);
1953-
});
1954-
if (nonInitMethods.empty())
1936+
if (!inheritingInits) {
1937+
llvm::erase_if(methods, [](AbstractFunctionDecl *afd) {
1938+
return isa<ConstructorDecl>(afd);
1939+
});
1940+
if (methods.empty())
19551941
return nullptr;
1956-
1957-
return *std::min_element(nonInitMethods.begin(), nonInitMethods.end(),
1958-
OrderDeclarations(srcMgr));
19591942
}
1960-
19611943
return *std::min_element(methods.begin(), methods.end(),
1962-
OrderDeclarations(srcMgr));
1944+
OrderDeclarations());
19631945
}
19641946

1965-
// Recurse into the superclass.
1947+
// If we've reached the bottom of the inheritance heirarchy, we're done.
19661948
if (!classDecl->hasSuperclass())
19671949
return nullptr;
19681950

19691951
// Determine whether we are (still) inheriting initializers.
1970-
inheritingInits = inheritingInits &&
1971-
classDecl->inheritsSuperclassInitializers();
1972-
if (isInitializer && !inheritingInits)
1952+
if (!classDecl->inheritsSuperclassInitializers())
1953+
inheritingInits = false;
1954+
1955+
if (isa<ConstructorDecl>(method) && !inheritingInits)
19731956
return nullptr;
19741957

1975-
return lookupObjCMethodInClass(classDecl->getSuperclassDecl(), selector,
1976-
isInstanceMethod, isInitializer, srcMgr,
1977-
inheritingInits);
1958+
return lookupOverridenObjCMethod(classDecl->getSuperclassDecl(), method,
1959+
inheritingInits);
19781960
}
19791961

19801962
bool swift::diagnoseUnintendedObjCMethodOverrides(SourceFile &sf) {
@@ -1986,7 +1968,7 @@ bool swift::diagnoseUnintendedObjCMethodOverrides(SourceFile &sf) {
19861968
return false;
19871969

19881970
// Sort the methods by declaration order.
1989-
std::sort(methods.begin(), methods.end(), OrderDeclarations(Ctx.SourceMgr));
1971+
std::sort(methods.begin(), methods.end(), OrderDeclarations());
19901972

19911973
// For each Objective-C method declared in this file, check whether
19921974
// it overrides something in one of its superclasses. We
@@ -2022,18 +2004,13 @@ bool swift::diagnoseUnintendedObjCMethodOverrides(SourceFile &sf) {
20222004
if (!classDecl->hasSuperclass())
20232005
continue;
20242006

2025-
// Look for a method that we have overridden in one of our
2026-
// superclasses.
2007+
// Look for a method that we have overridden in one of our superclasses by
2008+
// virtue of having the same selector.
20272009
// Note: This should be treated as a lookup for intra-module dependency
20282010
// purposes, but a subclass already depends on its superclasses and any
20292011
// extensions for many other reasons.
2030-
auto selector = method->getObjCSelector();
2031-
AbstractFunctionDecl *overriddenMethod
2032-
= lookupObjCMethodInClass(classDecl->getSuperclassDecl(),
2033-
selector,
2034-
method->isObjCInstanceMethod(),
2035-
isa<ConstructorDecl>(method),
2036-
Ctx.SourceMgr);
2012+
auto *overriddenMethod =
2013+
lookupOverridenObjCMethod(classDecl->getSuperclassDecl(), method);
20372014
if (!overriddenMethod)
20382015
continue;
20392016

@@ -2051,18 +2028,18 @@ bool swift::diagnoseUnintendedObjCMethodOverrides(SourceFile &sf) {
20512028
// Diagnose the override.
20522029
auto methodDiagInfo = getObjCMethodDiagInfo(method);
20532030
auto overriddenDiagInfo = getObjCMethodDiagInfo(overriddenMethod);
2054-
Ctx.Diags.diagnose(method, diag::objc_override_other,
2055-
methodDiagInfo.first,
2056-
methodDiagInfo.second,
2057-
overriddenDiagInfo.first,
2058-
overriddenDiagInfo.second,
2059-
selector,
2060-
overriddenMethod->getDeclContext()
2061-
->getDeclaredInterfaceType());
2031+
2032+
Ctx.Diags.diagnose(
2033+
method, diag::objc_override_other, methodDiagInfo.first,
2034+
methodDiagInfo.second, overriddenDiagInfo.first,
2035+
overriddenDiagInfo.second, method->getObjCSelector(),
2036+
overriddenMethod->getDeclContext()->getDeclaredInterfaceType());
2037+
20622038
const ValueDecl *overriddenDecl = overriddenMethod;
20632039
if (overriddenMethod->isImplicit())
20642040
if (auto accessor = dyn_cast<AccessorDecl>(overriddenMethod))
20652041
overriddenDecl = accessor->getStorage();
2042+
20662043
Ctx.Diags.diagnose(overriddenDecl, diag::objc_declared_here,
20672044
overriddenDiagInfo.first, overriddenDiagInfo.second);
20682045

@@ -2073,7 +2050,7 @@ bool swift::diagnoseUnintendedObjCMethodOverrides(SourceFile &sf) {
20732050
}
20742051

20752052
/// Retrieve the source file for the given Objective-C member conflict.
2076-
static MutableArrayRef<AbstractFunctionDecl *>
2053+
static TinyPtrVector<AbstractFunctionDecl *>
20772054
getObjCMethodConflictDecls(const SourceFile::ObjCMethodConflict &conflict) {
20782055
ClassDecl *classDecl = std::get<0>(conflict);
20792056
ObjCSelector selector = std::get<1>(conflict);
@@ -2082,45 +2059,13 @@ getObjCMethodConflictDecls(const SourceFile::ObjCMethodConflict &conflict) {
20822059
return classDecl->lookupDirect(selector, isInstanceMethod);
20832060
}
20842061

2085-
/// Given a set of conflicting Objective-C methods, remove any methods
2086-
/// that are legitimately overridden in Objective-C, i.e., because
2087-
/// they occur in different modules, one is defined in the class, and
2088-
/// the other is defined in an extension (category) thereof.
2089-
static void removeValidObjCConflictingMethods(
2090-
MutableArrayRef<AbstractFunctionDecl *> &methods) {
2091-
// Erase any invalid or stub declarations. We don't want to complain about
2092-
// them, because we might already have complained about
2093-
// redeclarations based on Swift matching.
2094-
auto newEnd = std::remove_if(methods.begin(), methods.end(),
2095-
[&](AbstractFunctionDecl *method) {
2096-
if (method->isInvalid())
2097-
return true;
2098-
2099-
if (auto ad = dyn_cast<AccessorDecl>(method)) {
2100-
return ad->getStorage()->isInvalid();
2101-
}
2102-
2103-
if (auto ctor
2104-
= dyn_cast<ConstructorDecl>(method)) {
2105-
if (ctor->hasStubImplementation())
2106-
return true;
2107-
2108-
return false;
2109-
}
2110-
2111-
return false;
2112-
});
2113-
methods = methods.slice(0, newEnd - methods.begin());
2114-
}
2115-
21162062
bool swift::diagnoseObjCMethodConflicts(SourceFile &sf) {
21172063
// If there were no conflicts, we're done.
21182064
if (sf.ObjCMethodConflicts.empty())
21192065
return false;
21202066

21212067
auto &Ctx = sf.getASTContext();
2122-
2123-
OrderDeclarations ordering(Ctx.SourceMgr);
2068+
OrderDeclarations ordering;
21242069

21252070
// Sort the set of conflicts so we get a deterministic order for
21262071
// diagnostics. We use the first conflicting declaration in each set to
@@ -2140,8 +2085,23 @@ bool swift::diagnoseObjCMethodConflicts(SourceFile &sf) {
21402085

21412086
auto methods = getObjCMethodConflictDecls(conflict);
21422087

2143-
// Prune out cases where it is acceptable to have a conflict.
2144-
removeValidObjCConflictingMethods(methods);
2088+
// Erase any invalid or stub declarations. We don't want to complain about
2089+
// them, because we might already have complained about redeclarations
2090+
// based on Swift matching.
2091+
llvm::erase_if(methods, [](AbstractFunctionDecl *afd) -> bool {
2092+
if (afd->isInvalid())
2093+
return true;
2094+
2095+
if (auto ad = dyn_cast<AccessorDecl>(afd))
2096+
return ad->getStorage()->isInvalid();
2097+
2098+
if (auto *ctor = dyn_cast<ConstructorDecl>(afd)) {
2099+
if (ctor->hasStubImplementation())
2100+
return true;
2101+
}
2102+
return false;
2103+
});
2104+
21452105
if (methods.size() < 2)
21462106
continue;
21472107

@@ -2150,22 +2110,23 @@ bool swift::diagnoseObjCMethodConflicts(SourceFile &sf) {
21502110

21512111
// If the first method is in an extension and the second is not, swap them
21522112
// so the primary diagnostic is on the extension method.
2113+
MutableArrayRef<AbstractFunctionDecl *> methodsRef(methods);
21532114
if (isa<ExtensionDecl>(methods[0]->getDeclContext()) &&
21542115
!isa<ExtensionDecl>(methods[1]->getDeclContext())) {
2155-
std::swap(methods[0], methods[1]);
2116+
std::swap(methodsRef[0], methodsRef[1]);
21562117

21572118
// Within a source file, use our canonical ordering.
21582119
} else if (methods[0]->getParentSourceFile() ==
21592120
methods[1]->getParentSourceFile() &&
21602121
!ordering(methods[0], methods[1])) {
2161-
std::swap(methods[0], methods[1]);
2122+
std::swap(methodsRef[0], methodsRef[1]);
21622123
}
21632124

21642125
// Otherwise, fall back to the order in which the declarations were type
21652126
// checked.
21662127

21672128
auto originalMethod = methods.front();
2168-
auto conflictingMethods = methods.slice(1);
2129+
auto conflictingMethods = methodsRef.slice(1);
21692130

21702131
auto origDiagInfo = getObjCMethodDiagInfo(originalMethod);
21712132
for (auto conflictingDecl : conflictingMethods) {
@@ -2182,12 +2143,9 @@ bool swift::diagnoseObjCMethodConflicts(SourceFile &sf) {
21822143
Ctx.Diags.diagnose(originalDecl, diag::invalid_redecl_prev,
21832144
originalDecl->getBaseName());
21842145
} else {
2185-
Ctx.Diags.diagnose(conflictingDecl, diag::objc_redecl,
2186-
diagInfo.first,
2187-
diagInfo.second,
2188-
origDiagInfo.first,
2189-
origDiagInfo.second,
2190-
selector);
2146+
Ctx.Diags.diagnose(conflictingDecl, diag::objc_redecl, diagInfo.first,
2147+
diagInfo.second, origDiagInfo.first,
2148+
origDiagInfo.second, selector);
21912149
Ctx.Diags.diagnose(originalDecl, diag::objc_declared_here,
21922150
origDiagInfo.first, origDiagInfo.second);
21932151
}

0 commit comments

Comments
 (0)