From d454549fce04dfedda6cc2825b66efca94effe3f Mon Sep 17 00:00:00 2001 From: Dave Lee Date: Fri, 22 Sep 2017 16:58:57 +0000 Subject: [PATCH] [index] Generate class & metaclass manglings for objc Summary: ObjC classes have two associated symbols, one for the class and one for the metaclass. This change overloads `CodegenNameGenerator::getAllManglings` to produce both class and metaclass symbols. While this function is called by `clang_Cursor_getCXXManglings`, it's only called for CXXRecordDecl and CXXMethodDecl, and so libclang's behavior is unchanged. Reviewers: arphaman, abdulras, alexshap, compnerd Reviewed By: compnerd Subscribers: compnerd Differential Revision: https://reviews.llvm.org/D37671 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@313997 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang-c/Index.h | 6 +++++ lib/Index/CodegenNameGenerator.cpp | 39 +++++++++++++++++++++++++++--- test/Index/print-objc-manglings.m | 18 ++++++++++++++ tools/c-index-test/c-index-test.c | 17 ++++++++++--- tools/libclang/CIndex.cpp | 14 +++++++++++ tools/libclang/libclang.exports | 1 + 6 files changed, 88 insertions(+), 7 deletions(-) create mode 100644 test/Index/print-objc-manglings.m diff --git a/include/clang-c/Index.h b/include/clang-c/Index.h index b5d994783f..c72be56fdc 100644 --- a/include/clang-c/Index.h +++ b/include/clang-c/Index.h @@ -4292,6 +4292,12 @@ CINDEX_LINKAGE CXString clang_Cursor_getMangling(CXCursor); */ CINDEX_LINKAGE CXStringSet *clang_Cursor_getCXXManglings(CXCursor); +/** + * \brief Retrieve the CXStrings representing the mangled symbols of the ObjC + * class interface or implementation at the cursor. + */ +CINDEX_LINKAGE CXStringSet *clang_Cursor_getObjCManglings(CXCursor); + /** * @} */ diff --git a/lib/Index/CodegenNameGenerator.cpp b/lib/Index/CodegenNameGenerator.cpp index 92740b0570..bf52e2108b 100644 --- a/lib/Index/CodegenNameGenerator.cpp +++ b/lib/Index/CodegenNameGenerator.cpp @@ -68,7 +68,38 @@ struct CodegenNameGenerator::Implementation { return Name; } + enum ObjCKind { + ObjCClass, + ObjCMetaclass, + }; + + std::vector getAllManglings(const ObjCContainerDecl *OCD) { + StringRef ClassName; + if (const auto *OID = dyn_cast(OCD)) + ClassName = OID->getObjCRuntimeNameAsString(); + else if (const auto *OID = dyn_cast(OCD)) + ClassName = OID->getObjCRuntimeNameAsString(); + + if (ClassName.empty()) + return {}; + + auto Mangle = [&](ObjCKind Kind, StringRef ClassName) -> std::string { + SmallString<40> Mangled; + auto Prefix = getClassSymbolPrefix(Kind, OCD->getASTContext()); + llvm::Mangler::getNameWithPrefix(Mangled, Prefix + ClassName, DL); + return Mangled.str(); + }; + + return { + Mangle(ObjCClass, ClassName), + Mangle(ObjCMetaclass, ClassName), + }; + } + std::vector getAllManglings(const Decl *D) { + if (const auto *OCD = dyn_cast(D)) + return getAllManglings(OCD); + if (!(isa(D) || isa(D))) return {}; @@ -135,12 +166,14 @@ private: } void writeObjCClassName(const ObjCInterfaceDecl *D, raw_ostream &OS) { - OS << getClassSymbolPrefix(); + OS << getClassSymbolPrefix(ObjCClass, D->getASTContext()); OS << D->getObjCRuntimeNameAsString(); } - static StringRef getClassSymbolPrefix() { - return "OBJC_CLASS_$_"; + static StringRef getClassSymbolPrefix(ObjCKind Kind, const ASTContext &Context) { + if (Context.getLangOpts().ObjCRuntime.isGNUFamily()) + return Kind == ObjCMetaclass ? "_OBJC_METACLASS_" : "_OBJC_CLASS_"; + return Kind == ObjCMetaclass ? "OBJC_METACLASS_$_" : "OBJC_CLASS_$_"; } std::string getMangledStructor(const NamedDecl *ND, unsigned StructorType) { diff --git a/test/Index/print-objc-manglings.m b/test/Index/print-objc-manglings.m new file mode 100644 index 0000000000..1e7983ec61 --- /dev/null +++ b/test/Index/print-objc-manglings.m @@ -0,0 +1,18 @@ +// RUN: c-index-test -write-pch %t.macho.ast -target i686-apple-darwin %s +// RUN: c-index-test -test-print-manglings %t.macho.ast | FileCheck --check-prefix=MACHO %s + +// RUN: c-index-test -write-pch %t.itanium.ast -target i686-pc-linux-gnu %s +// RUN: c-index-test -test-print-manglings %t.itanium.ast | FileCheck --check-prefix=ITANIUM %s + +@interface C +@end + +// MACHO: ObjCInterfaceDecl=C{{.*}} [mangled=_OBJC_CLASS_$_C] [mangled=_OBJC_METACLASS_$_C] +// ITANIUM: ObjCInterfaceDecl=C{{.*}} [mangled=_OBJC_CLASS_C] [mangled=_OBJC_METACLASS_C] + +@implementation C +@end + +// MACHO: ObjCImplementationDecl=C{{.*}} (Definition) [mangled=_OBJC_CLASS_$_C] [mangled=_OBJC_METACLASS_$_C] +// ITANIUM: ObjCImplementationDecl=C{{.*}} (Definition) [mangled=_OBJC_CLASS_C] [mangled=_OBJC_METACLASS_C] + diff --git a/tools/c-index-test/c-index-test.c b/tools/c-index-test/c-index-test.c index cf3581e259..a11e03c846 100644 --- a/tools/c-index-test/c-index-test.c +++ b/tools/c-index-test/c-index-test.c @@ -1563,10 +1563,19 @@ static enum CXChildVisitResult PrintManglings(CXCursor cursor, CXCursor p, return CXChildVisit_Continue; PrintCursor(cursor, NULL); Manglings = clang_Cursor_getCXXManglings(cursor); - for (I = 0, E = Manglings->Count; I < E; ++I) - printf(" [mangled=%s]", clang_getCString(Manglings->Strings[I])); - clang_disposeStringSet(Manglings); - printf("\n"); + if (Manglings) { + for (I = 0, E = Manglings->Count; I < E; ++I) + printf(" [mangled=%s]", clang_getCString(Manglings->Strings[I])); + clang_disposeStringSet(Manglings); + printf("\n"); + } + Manglings = clang_Cursor_getObjCManglings(cursor); + if (Manglings) { + for (I = 0, E = Manglings->Count; I < E; ++I) + printf(" [mangled=%s]", clang_getCString(Manglings->Strings[I])); + clang_disposeStringSet(Manglings); + printf("\n"); + } return CXChildVisit_Recurse; } diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp index 6d120bcab4..26b1f5e2b1 100644 --- a/tools/libclang/CIndex.cpp +++ b/tools/libclang/CIndex.cpp @@ -4639,6 +4639,20 @@ CXStringSet *clang_Cursor_getCXXManglings(CXCursor C) { return cxstring::createSet(Manglings); } +CXStringSet *clang_Cursor_getObjCManglings(CXCursor C) { + if (clang_isInvalid(C.kind) || !clang_isDeclaration(C.kind)) + return nullptr; + + const Decl *D = getCursorDecl(C); + if (!(isa(D) || isa(D))) + return nullptr; + + ASTContext &Ctx = D->getASTContext(); + index::CodegenNameGenerator CGNameGen(Ctx); + std::vector Manglings = CGNameGen.getAllManglings(D); + return cxstring::createSet(Manglings); +} + CXString clang_getCursorDisplayName(CXCursor C) { if (!clang_isDeclaration(C.kind)) return clang_getCursorSpelling(C); diff --git a/tools/libclang/libclang.exports b/tools/libclang/libclang.exports index 62a233ebec..fb4547a867 100644 --- a/tools/libclang/libclang.exports +++ b/tools/libclang/libclang.exports @@ -23,6 +23,7 @@ clang_Cursor_getBriefCommentText clang_Cursor_getCommentRange clang_Cursor_getCXXManglings clang_Cursor_getMangling +clang_Cursor_getObjCManglings clang_Cursor_getParsedComment clang_Cursor_getRawCommentText clang_Cursor_getNumArguments -- 2.40.0