@@ -5827,21 +5827,6 @@ findImplsGivenInterface(ClassDecl *classDecl, Identifier categoryName) {
5827
5827
impls.push_back (ext);
5828
5828
}
5829
5829
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
-
5845
5830
return impls;
5846
5831
}
5847
5832
@@ -5872,10 +5857,26 @@ findInterfaceGivenImpl(ClassDecl *classDecl, ExtensionDecl *ext) {
5872
5857
}
5873
5858
5874
5859
static 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 ())
5877
5863
return ObjCInterfaceAndImplementation ();
5878
5864
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
+
5879
5880
return ObjCInterfaceAndImplementation (interface, impls.front ());
5880
5881
}
5881
5882
@@ -5924,31 +5925,103 @@ findContextInterfaceAndImplementation(DeclContext *dc) {
5924
5925
// look for extensions implementing it.
5925
5926
5926
5927
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 ());
5928
6010
}
5929
6011
5930
6012
ObjCInterfaceAndImplementation ObjCInterfaceAndImplementationRequest::
5931
6013
evaluate (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
5933
6015
// `@_objcImplementation` attribute. Let's resolve that.
5934
6016
// (Also directing nulls here, where they'll early-return.)
5935
6017
if (auto ty = dyn_cast_or_null<NominalTypeDecl>(decl))
5936
6018
return findContextInterfaceAndImplementation (ty);
5937
6019
else if (auto ext = dyn_cast<ExtensionDecl>(decl))
5938
6020
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);
5939
6024
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.
5952
6025
return {};
5953
6026
}
5954
6027
0 commit comments