@@ -747,6 +747,15 @@ void TBDGenVisitor::visitAbstractFunctionDecl(AbstractFunctionDecl *AFD) {
747747 if (AFD->hasAsync ()) {
748748 addAsyncFunctionPointerSymbol (SILDeclRef (AFD));
749749 }
750+
751+ // Skip non objc compatible methods or non-public methods.
752+ if (isa<DestructorDecl>(AFD) || !AFD->isObjC () ||
753+ AFD->getFormalAccess () != AccessLevel::Public)
754+ return ;
755+ if (auto *CD = dyn_cast<ClassDecl>(AFD->getDeclContext ()))
756+ recorder.addObjCMethod (CD, SILDeclRef (AFD));
757+ else if (auto *ED = dyn_cast<ExtensionDecl>(AFD->getDeclContext ()))
758+ recorder.addObjCMethod (ED, SILDeclRef (AFD));
750759}
751760
752761void TBDGenVisitor::visitFuncDecl (FuncDecl *FD) {
@@ -956,30 +965,9 @@ void TBDGenVisitor::visitClassDecl(ClassDecl *CD) {
956965 }
957966
958967 TBD.addMethodDescriptor (method);
959-
960- if (auto methodOrCtorOrDtor = method.getDecl ()) {
961- // Skip non objc compatible methods or non-public methods.
962- if (!methodOrCtorOrDtor->isObjC () ||
963- methodOrCtorOrDtor->getFormalAccess () != AccessLevel::Public)
964- return ;
965-
966- // only handle FuncDecl here. Initializers are handled in
967- // visitConstructorDecl.
968- if (isa<FuncDecl>(methodOrCtorOrDtor))
969- recorder.addObjCMethod (CD, method);
970- }
971968 }
972969
973- void addMethodOverride (SILDeclRef baseRef, SILDeclRef derivedRef) {
974- if (auto methodOrCtorOrDtor = derivedRef.getDecl ()) {
975- if (!methodOrCtorOrDtor->isObjC () ||
976- methodOrCtorOrDtor->getFormalAccess () != AccessLevel::Public)
977- return ;
978-
979- if (isa<FuncDecl>(methodOrCtorOrDtor))
980- recorder.addObjCMethod (CD, derivedRef);
981- }
982- }
970+ void addMethodOverride (SILDeclRef baseRef, SILDeclRef derivedRef) {}
983971
984972 void addPlaceholder (MissingMemberDecl *) {}
985973
@@ -1001,10 +989,6 @@ void TBDGenVisitor::visitConstructorDecl(ConstructorDecl *CD) {
1001989 addAsyncFunctionPointerSymbol (
1002990 SILDeclRef (CD, SILDeclRef::Kind::Initializer));
1003991 }
1004- if (auto parentClass = CD->getParent ()->getSelfClassDecl ()) {
1005- if (parentClass->isObjC () || CD->isObjC ())
1006- recorder.addObjCMethod (parentClass, SILDeclRef (CD));
1007- }
1008992 }
1009993
1010994 visitAbstractFunctionDecl (CD);
@@ -1397,8 +1381,11 @@ class APIGenRecorder final : public APIRecorder {
13971381 addOrGetObjCInterface (decl);
13981382 }
13991383
1400- void addObjCMethod (const ClassDecl *cls,
1401- SILDeclRef method) override {
1384+ void addObjCCategory (const ExtensionDecl *decl) override {
1385+ addOrGetObjCCategory (decl);
1386+ }
1387+
1388+ void addObjCMethod (const GenericContext *ctx, SILDeclRef method) override {
14021389 SmallString<128 > buffer;
14031390 StringRef name = getSelectorName (method, buffer);
14041391 apigen::APIAvailability availability;
@@ -1413,12 +1400,23 @@ class APIGenRecorder final : public APIRecorder {
14131400 access = apigen::APIAccess::Private;
14141401 }
14151402
1416- auto *clsRecord = addOrGetObjCInterface (cls);
1417- api.addObjCMethod (clsRecord, name, moduleLoc, access, isInstanceMethod,
1418- false , availability);
1403+ apigen::ObjCContainerRecord *record = nullptr ;
1404+ if (auto *cls = dyn_cast<ClassDecl>(ctx))
1405+ record = addOrGetObjCInterface (cls);
1406+ else if (auto *ext = dyn_cast<ExtensionDecl>(ctx))
1407+ record = addOrGetObjCCategory (ext);
1408+
1409+ if (record)
1410+ api.addObjCMethod (record, name, moduleLoc, access, isInstanceMethod,
1411+ false , availability);
14191412 }
14201413
14211414private:
1415+ // / Follow the naming schema that IRGen uses for Categories (see
1416+ // / ClassDataBuilder).
1417+ using CategoryNameKey = std::pair<const ClassDecl *, const ModuleDecl *>;
1418+ llvm::DenseMap<CategoryNameKey, unsigned > CategoryCounts;
1419+
14221420 apigen::APIAvailability getAvailability (const Decl *decl) {
14231421 bool unavailable = false ;
14241422 std::string introduced, obsoleted;
@@ -1475,11 +1473,46 @@ class APIGenRecorder final : public APIRecorder {
14751473 return cls;
14761474 }
14771475
1476+ void buildCategoryName (const ExtensionDecl *ext, const ClassDecl *cls,
1477+ SmallVectorImpl<char > &s) {
1478+ llvm::raw_svector_ostream os (s);
1479+ ModuleDecl *module = ext->getParentModule ();
1480+ os << module ->getName ();
1481+ unsigned categoryCount = CategoryCounts[{cls, module }]++;
1482+ if (categoryCount > 0 )
1483+ os << categoryCount;
1484+ }
1485+
1486+ apigen::ObjCCategoryRecord *addOrGetObjCCategory (const ExtensionDecl *decl) {
1487+ auto entry = categoryMap.find (decl);
1488+ if (entry != categoryMap.end ())
1489+ return entry->second ;
1490+
1491+ SmallString<128 > interfaceBuffer;
1492+ SmallString<128 > nameBuffer;
1493+ ClassDecl *cls = decl->getSelfClassDecl ();
1494+ auto interface = cls->getObjCRuntimeName (interfaceBuffer);
1495+ buildCategoryName (decl, cls, nameBuffer);
1496+ apigen::APIAvailability availability = getAvailability (decl);
1497+ apigen::APIAccess access =
1498+ decl->isSPI () ? apigen::APIAccess::Private : apigen::APIAccess::Public;
1499+ apigen::APILinkage linkage =
1500+ decl->getMaxAccessLevel () == AccessLevel::Public
1501+ ? apigen::APILinkage::Exported
1502+ : apigen::APILinkage::Internal;
1503+ auto category = api.addObjCCategory (nameBuffer, linkage, moduleLoc, access,
1504+ availability, interface);
1505+ categoryMap.try_emplace (decl, category);
1506+ return category;
1507+ }
1508+
14781509 apigen::API &api;
14791510 ModuleDecl *module ;
14801511 apigen::APILoc moduleLoc;
14811512
14821513 llvm::DenseMap<const ClassDecl*, apigen::ObjCInterfaceRecord*> classMap;
1514+ llvm::DenseMap<const ExtensionDecl *, apigen::ObjCCategoryRecord *>
1515+ categoryMap;
14831516};
14841517
14851518apigen::API APIGenRequest::evaluate (Evaluator &evaluator,
0 commit comments