@@ -2149,6 +2149,63 @@ namespace {
2149
2149
}
2150
2150
};
2151
2151
2152
+ // / Search the member tables for this class and its superclasses and try to identify the nearest VarDecl
2153
+ // / that serves as a base for an override. We have to do this ourselves because Objective-C has no
2154
+ // / semantic notion of overrides, and freely allows users to refine the type of any member property in a
2155
+ // / derived class.
2156
+ // /
2157
+ // / The override must be the nearest possible one so there are not breaks in the override chain. That is,
2158
+ // / suppose C refines B refines A and each successively redeclares a member with a different type. It
2159
+ // / should be the case that the nearest override from C is B and from B is A. If the override point from
2160
+ // / C were A, then B would record an override on A as well and we would introduce a semantic ambiguity.
2161
+ // /
2162
+ // / There is also a special case for finding a method that stomps over a getter. If this is the case and no
2163
+ // / override point is identified, we will not import the property to force users to explicitly call the method.
2164
+ static std::pair<VarDecl *, bool >
2165
+ identifyNearestOverridenDecl (ClangImporter::Implementation &Impl,
2166
+ DeclContext *dc,
2167
+ const clang::ObjCPropertyDecl *decl,
2168
+ Identifier name,
2169
+ ClassDecl *subject) {
2170
+ bool foundMethod = false ;
2171
+ for (; subject; (subject = subject->getSuperclassDecl ())) {
2172
+ llvm::SmallVector<ValueDecl *, 8 > lookup;
2173
+ auto found = Impl.MembersForNominal .find (subject);
2174
+ if (found != Impl.MembersForNominal .end ()) {
2175
+ lookup.append (found->second .begin (), found->second .end ());
2176
+ namelookup::pruneLookupResultSet (dc, NL_QualifiedDefault, lookup);
2177
+ }
2178
+
2179
+ for (auto *&result : lookup) {
2180
+ // Skip declarations that don't match the name we're looking for.
2181
+ if (result->getBaseName () != name)
2182
+ continue ;
2183
+
2184
+ if (auto *fd = dyn_cast<FuncDecl>(result)) {
2185
+ if (fd->isInstanceMember () != decl->isInstanceProperty ())
2186
+ continue ;
2187
+
2188
+ if (fd->getFullName ().getArgumentNames ().empty ()) {
2189
+ foundMethod = true ;
2190
+ }
2191
+ } else {
2192
+ auto *var = cast<VarDecl>(result);
2193
+ if (var->isInstanceMember () != decl->isInstanceProperty ())
2194
+ continue ;
2195
+
2196
+ // If the selectors of the getter match in Objective-C, we have an
2197
+ // override.
2198
+ if (var->getObjCGetterSelector () ==
2199
+ Impl.importSelector (decl->getGetterName ())) {
2200
+ return {var, foundMethod};
2201
+ }
2202
+ }
2203
+ }
2204
+ }
2205
+
2206
+ return {nullptr , foundMethod};
2207
+ }
2208
+
2152
2209
// / Convert Clang declarations into the corresponding Swift
2153
2210
// / declarations.
2154
2211
class SwiftDeclConverter
@@ -5013,47 +5070,14 @@ namespace {
5013
5070
// property. If so, suppress the property; the user will have to use
5014
5071
// the methods directly, to avoid ambiguities.
5015
5072
if (auto *subject = dc->getSelfClassDecl ()) {
5016
- bool foundMethod = false ;
5017
-
5018
5073
if (auto *classDecl = dyn_cast<ClassDecl>(dc)) {
5019
5074
// Start looking into the superclass.
5020
5075
subject = classDecl->getSuperclassDecl ();
5021
5076
}
5022
5077
5023
- for (; subject; (subject = subject->getSuperclassDecl ())) {
5024
- llvm::SmallVector<ValueDecl *, 8 > lookup;
5025
- auto found = Impl.MembersForNominal .find (subject);
5026
- if (found != Impl.MembersForNominal .end ()) {
5027
- lookup.append (found->second .begin (), found->second .end ());
5028
- namelookup::pruneLookupResultSet (dc, NL_QualifiedDefault, lookup);
5029
- }
5030
-
5031
- for (auto *&result : lookup) {
5032
- // Skip declarations that don't match the name we're looking for.
5033
- if (result->getBaseName () != name)
5034
- continue ;
5035
-
5036
- if (auto *fd = dyn_cast<FuncDecl>(result)) {
5037
- if (fd->isInstanceMember () != decl->isInstanceProperty ())
5038
- continue ;
5039
-
5040
- if (fd->getFullName ().getArgumentNames ().empty ()) {
5041
- foundMethod = true ;
5042
- }
5043
- } else {
5044
- auto *var = cast<VarDecl>(result);
5045
- if (var->isInstanceMember () != decl->isInstanceProperty ())
5046
- continue ;
5047
-
5048
- // If the selectors of the getter match in Objective-C, we have an
5049
- // override.
5050
- if (var->getObjCGetterSelector () ==
5051
- Impl.importSelector (decl->getGetterName ())) {
5052
- overridden = var;
5053
- }
5054
- }
5055
- }
5056
- }
5078
+ bool foundMethod = false ;
5079
+ std::tie (overridden, foundMethod)
5080
+ = identifyNearestOverridenDecl (Impl, dc, decl, name, subject);
5057
5081
5058
5082
if (foundMethod && !overridden)
5059
5083
return nullptr ;
0 commit comments