@@ -1886,12 +1886,7 @@ bool swift::fixDeclarationObjCName(InFlightDiagnostic &diag, const ValueDecl *de
1886
1886
1887
1887
namespace {
1888
1888
// / 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 {
1895
1890
bool operator ()(ValueDecl *lhs, ValueDecl *rhs) const {
1896
1891
// If the declarations come from different modules, order based on the
1897
1892
// module.
@@ -1912,6 +1907,7 @@ namespace {
1912
1907
}
1913
1908
1914
1909
// Prefer the declaration that comes first in the source file.
1910
+ const auto &SrcMgr = lhsSF->getASTContext ().SourceMgr ;
1915
1911
return SrcMgr.isBeforeInBuffer (lhs->getLoc (), rhs->getLoc ());
1916
1912
}
1917
1913
@@ -1924,57 +1920,43 @@ namespace {
1924
1920
} // end anonymous namespace
1925
1921
1926
1922
// / 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);
1937
1929
1938
1930
// 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 ());
1940
1933
if (!methods.empty ()) {
1941
1934
// If we aren't inheriting initializers, remove any initializers from the
1942
1935
// 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 ())
1955
1941
return nullptr ;
1956
-
1957
- return *std::min_element (nonInitMethods.begin (), nonInitMethods.end (),
1958
- OrderDeclarations (srcMgr));
1959
1942
}
1960
-
1961
1943
return *std::min_element (methods.begin (), methods.end (),
1962
- OrderDeclarations (srcMgr ));
1944
+ OrderDeclarations ());
1963
1945
}
1964
1946
1965
- // Recurse into the superclass .
1947
+ // If we've reached the bottom of the inheritance heirarchy, we're done .
1966
1948
if (!classDecl->hasSuperclass ())
1967
1949
return nullptr ;
1968
1950
1969
1951
// 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)
1973
1956
return nullptr ;
1974
1957
1975
- return lookupObjCMethodInClass (classDecl->getSuperclassDecl (), selector,
1976
- isInstanceMethod, isInitializer, srcMgr,
1977
- inheritingInits);
1958
+ return lookupOverridenObjCMethod (classDecl->getSuperclassDecl (), method,
1959
+ inheritingInits);
1978
1960
}
1979
1961
1980
1962
bool swift::diagnoseUnintendedObjCMethodOverrides (SourceFile &sf) {
@@ -1986,7 +1968,7 @@ bool swift::diagnoseUnintendedObjCMethodOverrides(SourceFile &sf) {
1986
1968
return false ;
1987
1969
1988
1970
// Sort the methods by declaration order.
1989
- std::sort (methods.begin (), methods.end (), OrderDeclarations (Ctx. SourceMgr ));
1971
+ std::sort (methods.begin (), methods.end (), OrderDeclarations ());
1990
1972
1991
1973
// For each Objective-C method declared in this file, check whether
1992
1974
// it overrides something in one of its superclasses. We
@@ -2022,18 +2004,13 @@ bool swift::diagnoseUnintendedObjCMethodOverrides(SourceFile &sf) {
2022
2004
if (!classDecl->hasSuperclass ())
2023
2005
continue ;
2024
2006
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 .
2027
2009
// Note: This should be treated as a lookup for intra-module dependency
2028
2010
// purposes, but a subclass already depends on its superclasses and any
2029
2011
// 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);
2037
2014
if (!overriddenMethod)
2038
2015
continue ;
2039
2016
@@ -2051,18 +2028,18 @@ bool swift::diagnoseUnintendedObjCMethodOverrides(SourceFile &sf) {
2051
2028
// Diagnose the override.
2052
2029
auto methodDiagInfo = getObjCMethodDiagInfo (method);
2053
2030
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
+
2062
2038
const ValueDecl *overriddenDecl = overriddenMethod;
2063
2039
if (overriddenMethod->isImplicit ())
2064
2040
if (auto accessor = dyn_cast<AccessorDecl>(overriddenMethod))
2065
2041
overriddenDecl = accessor->getStorage ();
2042
+
2066
2043
Ctx.Diags .diagnose (overriddenDecl, diag::objc_declared_here,
2067
2044
overriddenDiagInfo.first , overriddenDiagInfo.second );
2068
2045
@@ -2073,7 +2050,7 @@ bool swift::diagnoseUnintendedObjCMethodOverrides(SourceFile &sf) {
2073
2050
}
2074
2051
2075
2052
// / Retrieve the source file for the given Objective-C member conflict.
2076
- static MutableArrayRef <AbstractFunctionDecl *>
2053
+ static TinyPtrVector <AbstractFunctionDecl *>
2077
2054
getObjCMethodConflictDecls (const SourceFile::ObjCMethodConflict &conflict) {
2078
2055
ClassDecl *classDecl = std::get<0 >(conflict);
2079
2056
ObjCSelector selector = std::get<1 >(conflict);
@@ -2082,45 +2059,13 @@ getObjCMethodConflictDecls(const SourceFile::ObjCMethodConflict &conflict) {
2082
2059
return classDecl->lookupDirect (selector, isInstanceMethod);
2083
2060
}
2084
2061
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
-
2116
2062
bool swift::diagnoseObjCMethodConflicts (SourceFile &sf) {
2117
2063
// If there were no conflicts, we're done.
2118
2064
if (sf.ObjCMethodConflicts .empty ())
2119
2065
return false ;
2120
2066
2121
2067
auto &Ctx = sf.getASTContext ();
2122
-
2123
- OrderDeclarations ordering (Ctx.SourceMgr );
2068
+ OrderDeclarations ordering;
2124
2069
2125
2070
// Sort the set of conflicts so we get a deterministic order for
2126
2071
// diagnostics. We use the first conflicting declaration in each set to
@@ -2140,8 +2085,23 @@ bool swift::diagnoseObjCMethodConflicts(SourceFile &sf) {
2140
2085
2141
2086
auto methods = getObjCMethodConflictDecls (conflict);
2142
2087
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
+
2145
2105
if (methods.size () < 2 )
2146
2106
continue ;
2147
2107
@@ -2150,22 +2110,23 @@ bool swift::diagnoseObjCMethodConflicts(SourceFile &sf) {
2150
2110
2151
2111
// If the first method is in an extension and the second is not, swap them
2152
2112
// so the primary diagnostic is on the extension method.
2113
+ MutableArrayRef<AbstractFunctionDecl *> methodsRef (methods);
2153
2114
if (isa<ExtensionDecl>(methods[0 ]->getDeclContext ()) &&
2154
2115
!isa<ExtensionDecl>(methods[1 ]->getDeclContext ())) {
2155
- std::swap (methods [0 ], methods [1 ]);
2116
+ std::swap (methodsRef [0 ], methodsRef [1 ]);
2156
2117
2157
2118
// Within a source file, use our canonical ordering.
2158
2119
} else if (methods[0 ]->getParentSourceFile () ==
2159
2120
methods[1 ]->getParentSourceFile () &&
2160
2121
!ordering (methods[0 ], methods[1 ])) {
2161
- std::swap (methods [0 ], methods [1 ]);
2122
+ std::swap (methodsRef [0 ], methodsRef [1 ]);
2162
2123
}
2163
2124
2164
2125
// Otherwise, fall back to the order in which the declarations were type
2165
2126
// checked.
2166
2127
2167
2128
auto originalMethod = methods.front ();
2168
- auto conflictingMethods = methods .slice (1 );
2129
+ auto conflictingMethods = methodsRef .slice (1 );
2169
2130
2170
2131
auto origDiagInfo = getObjCMethodDiagInfo (originalMethod);
2171
2132
for (auto conflictingDecl : conflictingMethods) {
@@ -2182,12 +2143,9 @@ bool swift::diagnoseObjCMethodConflicts(SourceFile &sf) {
2182
2143
Ctx.Diags .diagnose (originalDecl, diag::invalid_redecl_prev,
2183
2144
originalDecl->getBaseName ());
2184
2145
} 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);
2191
2149
Ctx.Diags .diagnose (originalDecl, diag::objc_declared_here,
2192
2150
origDiagInfo.first , origDiagInfo.second );
2193
2151
}
0 commit comments