@@ -5827,21 +5827,6 @@ findImplsGivenInterface(ClassDecl *classDecl, Identifier categoryName) {
58275827 impls.push_back (ext);
58285828 }
58295829
5830- if (impls.size () > 1 ) {
5831- llvm::sort (impls, OrderDecls ());
5832-
5833- auto &diags = classDecl->getASTContext ().Diags ;
5834- for (auto extraImpl : llvm::ArrayRef<Decl *>(impls).drop_front ()) {
5835- auto attr = extraImpl->getAttrs ().getAttribute <ObjCImplementationAttr>();
5836- attr->setCategoryNameInvalid ();
5837-
5838- diags.diagnose (attr->getLocation (), diag::objc_implementation_two_impls,
5839- categoryName, classDecl)
5840- .fixItRemove (attr->getRangeWithAt ());
5841- diags.diagnose (impls.front (), diag::previous_objc_implementation);
5842- }
5843- }
5844-
58455830 return impls;
58465831}
58475832
@@ -5872,10 +5857,26 @@ findInterfaceGivenImpl(ClassDecl *classDecl, ExtensionDecl *ext) {
58725857}
58735858
58745859static ObjCInterfaceAndImplementation
5875- constructResult (Decl *interface, llvm::TinyPtrVector<Decl *> impls) {
5876- if (impls.empty ())
5860+ constructResult (Decl *interface, llvm::TinyPtrVector<Decl *> &impls,
5861+ Decl *diagnoseOn, Identifier categoryName) {
5862+ if (!interface || impls.empty ())
58775863 return ObjCInterfaceAndImplementation ();
58785864
5865+ if (impls.size () > 1 ) {
5866+ llvm::sort (impls, OrderDecls ());
5867+
5868+ auto &diags = interface->getASTContext ().Diags ;
5869+ for (auto extraImpl : llvm::ArrayRef<Decl *>(impls).drop_front ()) {
5870+ auto attr = extraImpl->getAttrs ().getAttribute <ObjCImplementationAttr>();
5871+ attr->setCategoryNameInvalid ();
5872+
5873+ diags.diagnose (attr->getLocation (), diag::objc_implementation_two_impls,
5874+ categoryName, diagnoseOn)
5875+ .fixItRemove (attr->getRangeWithAt ());
5876+ diags.diagnose (impls.front (), diag::previous_objc_implementation);
5877+ }
5878+ }
5879+
58795880 return ObjCInterfaceAndImplementation (interface, impls.front ());
58805881}
58815882
@@ -5924,31 +5925,103 @@ findContextInterfaceAndImplementation(DeclContext *dc) {
59245925 // look for extensions implementing it.
59255926
59265927 auto implDecls = findImplsGivenInterface (classDecl, categoryName);
5927- return constructResult (interfaceDecl, implDecls);
5928+ return constructResult (interfaceDecl, implDecls, classDecl, categoryName);
5929+ }
5930+
5931+ static void lookupRelatedFuncs (AbstractFunctionDecl *func,
5932+ SmallVectorImpl<ValueDecl *> &results) {
5933+ DeclName swiftName;
5934+ if (auto accessor = dyn_cast<AccessorDecl>(func))
5935+ swiftName = accessor->getStorage ()->getName ();
5936+ else
5937+ swiftName = func->getName ();
5938+
5939+ if (auto ty = func->getDeclContext ()->getSelfNominalTypeDecl ()) {
5940+ ty->lookupQualified ({ ty }, DeclNameRef (swiftName), func->getLoc (),
5941+ NL_QualifiedDefault | NL_IgnoreAccessControl, results);
5942+ }
5943+ else {
5944+ auto mod = func->getDeclContext ()->getParentModule ();
5945+ mod->lookupQualified (mod, DeclNameRef (swiftName), func->getLoc (),
5946+ NL_RemoveOverridden | NL_IgnoreAccessControl, results);
5947+ }
5948+ }
5949+
5950+ static ObjCInterfaceAndImplementation
5951+ findFunctionInterfaceAndImplementation (AbstractFunctionDecl *func) {
5952+ if (!func)
5953+ return {};
5954+
5955+ // If this isn't either a clang import or an implementation, there's no point
5956+ // doing any work here.
5957+ if (!func->hasClangNode () && !func->isObjCImplementation ())
5958+ return {};
5959+
5960+ OptionalEnum<AccessorKind> accessorKind;
5961+ if (auto accessor = dyn_cast<AccessorDecl>(func))
5962+ accessorKind = accessor->getAccessorKind ();
5963+
5964+ StringRef clangName = func->getCDeclName ();
5965+ if (clangName.empty ())
5966+ return {};
5967+
5968+ SmallVector<ValueDecl *, 4 > results;
5969+ lookupRelatedFuncs (func, results);
5970+
5971+ // Classify the `results` as either the interface or an implementation.
5972+ // (Multiple implementations are invalid but utterable.)
5973+ Decl *interface = nullptr ;
5974+ TinyPtrVector<Decl *> impls;
5975+
5976+ for (ValueDecl *result : results) {
5977+ AbstractFunctionDecl *resultFunc = nullptr ;
5978+ if (accessorKind) {
5979+ if (auto resultStorage = dyn_cast<AbstractStorageDecl>(result))
5980+ resultFunc = resultStorage->getAccessor (*accessorKind);
5981+ }
5982+ else
5983+ resultFunc = dyn_cast<AbstractFunctionDecl>(result);
5984+
5985+ if (!resultFunc)
5986+ continue ;
5987+
5988+ if (resultFunc->getCDeclName () != clangName)
5989+ continue ;
5990+
5991+ if (resultFunc->hasClangNode ()) {
5992+ if (interface) {
5993+ // This clang name is overloaded. That should only happen with C++
5994+ // functions/methods, which aren't currently supported.
5995+ return {};
5996+ }
5997+ interface = result;
5998+ } else if (resultFunc->isObjCImplementation ()) {
5999+ impls.push_back (result);
6000+ }
6001+ }
6002+
6003+ // If we found enough decls to construct a result, `func` should be among them
6004+ // somewhere.
6005+ assert (interface == nullptr || impls.empty () ||
6006+ interface == func || llvm::is_contained (impls, func));
6007+
6008+ return constructResult (interface, impls, interface,
6009+ /* categoryName=*/ Identifier ());
59286010}
59296011
59306012ObjCInterfaceAndImplementation ObjCInterfaceAndImplementationRequest::
59316013evaluate (Evaluator &evaluator, Decl *decl) const {
5932- // These have direct links to their counterparts through the
6014+ // Types and extensions have direct links to their counterparts through the
59336015 // `@_objcImplementation` attribute. Let's resolve that.
59346016 // (Also directing nulls here, where they'll early-return.)
59356017 if (auto ty = dyn_cast_or_null<NominalTypeDecl>(decl))
59366018 return findContextInterfaceAndImplementation (ty);
59376019 else if (auto ext = dyn_cast<ExtensionDecl>(decl))
59386020 return findContextInterfaceAndImplementation (ext);
6021+ // Abstract functions have to be matched through their @_cdecl attributes.
6022+ else if (auto func = dyn_cast<AbstractFunctionDecl>(decl))
6023+ return findFunctionInterfaceAndImplementation (func);
59396024
5940- // Anything else is resolved by first locating the context's interface and
5941- // impl, then matching it to its counterpart. (Instead of calling
5942- // `findContextInterfaceAndImplementation()` directly, we'll use the request
5943- // recursively to take advantage of caching.)
5944- auto contextDecl = decl->getDeclContext ()->getAsDecl ();
5945- if (!contextDecl)
5946- return {};
5947-
5948- ObjCInterfaceAndImplementationRequest req (contextDecl);
5949- /* auto contextPair =*/ evaluateOrDefault (evaluator, req, {});
5950-
5951- // TODO: Implement member matching.
59526025 return {};
59536026}
59546027
0 commit comments