@@ -1886,12 +1886,7 @@ bool swift::fixDeclarationObjCName(InFlightDiagnostic &diag, const ValueDecl *de
18861886
18871887namespace {
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
19801962bool 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 *>
20772054getObjCMethodConflictDecls (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-
21162062bool 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