@@ -2191,10 +2191,13 @@ namespace {
2191
2191
if (fd->isInstanceMember () != decl->isInstanceProperty ())
2192
2192
continue ;
2193
2193
2194
- assert (fd->getName ().getArgumentNames ().empty ());
2194
+ // We only care about methods with no arguments, because they can
2195
+ // shadow imported properties.
2196
+ if (!fd->getName ().getArgumentNames ().empty ())
2197
+ continue ;
2198
+
2195
2199
foundMethod = true ;
2196
- } else {
2197
- auto *var = cast<VarDecl>(result);
2200
+ } else if (auto *var = dyn_cast<VarDecl>(result)) {
2198
2201
if (var->isInstanceMember () != decl->isInstanceProperty ())
2199
2202
continue ;
2200
2203
@@ -2280,7 +2283,7 @@ namespace {
2280
2283
return getVersion () == getActiveSwiftVersion ();
2281
2284
}
2282
2285
2283
- void recordMemberInContext (DeclContext *dc, ValueDecl *member) {
2286
+ void recordMemberInContext (const DeclContext *dc, ValueDecl *member) {
2284
2287
assert (member && " Attempted to record null member!" );
2285
2288
auto *nominal = dc->getSelfNominalTypeDecl ();
2286
2289
auto name = member->getBaseName ();
@@ -4170,33 +4173,51 @@ namespace {
4170
4173
bool isInstance, const DeclContext *dc,
4171
4174
llvm::function_ref<bool (AbstractFunctionDecl *fn)> filter) {
4172
4175
// We only need to perform this check for classes.
4173
- auto classDecl
4174
- = dc->getDeclaredInterfaceType ()->getClassOrBoundGenericClass ();
4176
+ auto *classDecl = dc->getSelfClassDecl ();
4175
4177
if (!classDecl)
4176
4178
return false ;
4177
4179
4178
- // Make sure we don't search in Clang modules for this method.
4179
- ++Impl.ActiveSelectors [{selector, isInstance}];
4180
-
4181
- // Look for a matching imported or deserialized member.
4182
- bool result = false ;
4183
- for (auto decl : classDecl->lookupDirect (selector, isInstance)) {
4184
- if ((decl->getClangDecl ()
4185
- || !decl->getDeclContext ()->getParentSourceFile ())
4186
- && importedName.getDeclName () == decl->getName ()
4187
- && filter (decl)) {
4188
- result = true ;
4189
- break ;
4180
+ auto matchesImportedDecl = [&](Decl *member) -> bool {
4181
+ auto *afd = dyn_cast<AbstractFunctionDecl>(member);
4182
+ if (!afd)
4183
+ return false ;
4184
+
4185
+ // Instance-ness must match.
4186
+ if (afd->isObjCInstanceMethod () != isInstance)
4187
+ return false ;
4188
+
4189
+ // Both the selector and imported name must match.
4190
+ if (afd->getObjCSelector () != selector ||
4191
+ importedName.getDeclName () != afd->getName ()) {
4192
+ return false ;
4190
4193
}
4191
- }
4192
4194
4193
- // Restore the previous active count in the active-selector mapping.
4194
- auto activeCount = Impl.ActiveSelectors .find ({selector, isInstance});
4195
- --activeCount->second ;
4196
- if (activeCount->second == 0 )
4197
- Impl.ActiveSelectors .erase (activeCount);
4195
+ // Finally, the provided filter must match.
4196
+ return filter (afd);
4197
+ };
4198
4198
4199
- return result;
4199
+ // First check to see if we've already imported a method with the same
4200
+ // selector.
4201
+ auto importedMembers = Impl.MembersForNominal .find (classDecl);
4202
+ if (importedMembers != Impl.MembersForNominal .end ()) {
4203
+ auto baseName = importedName.getDeclName ().getBaseName ();
4204
+ auto membersForName = importedMembers->second .find (baseName);
4205
+ if (membersForName != importedMembers->second .end ()) {
4206
+ return llvm::any_of (membersForName->second , matchesImportedDecl);
4207
+ }
4208
+ }
4209
+
4210
+ // Then, for a deserialized Swift class, check to see if it has brought in
4211
+ // any matching @objc methods.
4212
+ if (classDecl->wasDeserialized ()) {
4213
+ auto &ctx = Impl.SwiftContext ;
4214
+ TinyPtrVector<AbstractFunctionDecl *> deserializedMethods;
4215
+ ctx.loadObjCMethods (classDecl, selector, isInstance,
4216
+ /* prevGeneration*/ 0 , deserializedMethods,
4217
+ /* swiftOnly*/ true );
4218
+ return llvm::any_of (deserializedMethods, matchesImportedDecl);
4219
+ }
4220
+ return false ;
4200
4221
}
4201
4222
4202
4223
Decl *importObjCMethodDecl (const clang::ObjCMethodDecl *decl,
@@ -4448,6 +4469,9 @@ namespace {
4448
4469
// If this method overrides another method, mark it as such.
4449
4470
recordObjCOverride (result);
4450
4471
4472
+ // Make a note that we've imported this method into this context.
4473
+ recordMemberInContext (dc, result);
4474
+
4451
4475
// Record the error convention.
4452
4476
if (errorConvention) {
4453
4477
result->setForeignErrorConvention (*errorConvention);
@@ -4484,14 +4508,6 @@ namespace {
4484
4508
Impl.addAlternateDecl (result, cast<ValueDecl>(imported));
4485
4509
}
4486
4510
}
4487
-
4488
- // We only care about recording methods with no arguments here, because
4489
- // they can shadow imported properties.
4490
- if (!isa<AccessorDecl>(result) &&
4491
- result->getName ().getArgumentNames ().empty ()) {
4492
- recordMemberInContext (dc, result);
4493
- }
4494
-
4495
4511
return result;
4496
4512
}
4497
4513
@@ -6461,6 +6477,7 @@ ConstructorDecl *SwiftDeclConverter::importConstructor(
6461
6477
/* GenericParams=*/ nullptr , const_cast <DeclContext *>(dc));
6462
6478
6463
6479
addObjCAttribute (result, selector);
6480
+ recordMemberInContext (dc, result);
6464
6481
6465
6482
Impl.recordImplicitUnwrapForDecl (result,
6466
6483
importedType.isImplicitlyUnwrapped ());
@@ -6668,14 +6685,24 @@ SwiftDeclConverter::importSubscript(Decl *decl,
6668
6685
};
6669
6686
6670
6687
auto findCounterpart = [&](clang::Selector sel) -> FuncDecl * {
6671
- // If the declaration we're starting from is in a class, first
6672
- // look for a class member with the appropriate selector.
6688
+ // If the declaration we're starting from is in a class, first check to see
6689
+ // if we've already imported an instance method with a matching selector.
6673
6690
if (auto classDecl = decl->getDeclContext ()->getSelfClassDecl ()) {
6674
6691
auto swiftSel = Impl.importSelector (sel);
6675
- for (auto found : classDecl->lookupDirect (swiftSel, true )) {
6676
- if (auto foundFunc = dyn_cast<FuncDecl>(found))
6677
- if (foundFunc->hasClangNode ())
6678
- return foundFunc;
6692
+ auto importedMembers = Impl.MembersForNominal .find (classDecl);
6693
+ if (importedMembers != Impl.MembersForNominal .end ()) {
6694
+ for (auto membersForName : importedMembers->second ) {
6695
+ for (auto *member : membersForName.second ) {
6696
+ // Must be an instance method.
6697
+ auto *afd = dyn_cast<FuncDecl>(member);
6698
+ if (!afd || !afd->isInstanceMember ())
6699
+ continue ;
6700
+
6701
+ // Selector must match.
6702
+ if (afd->getObjCSelector () == swiftSel)
6703
+ return afd;
6704
+ }
6705
+ }
6679
6706
}
6680
6707
}
6681
6708
0 commit comments