Index: cfe/trunk/include/clang-c/Index.h =================================================================== --- cfe/trunk/include/clang-c/Index.h +++ cfe/trunk/include/clang-c/Index.h @@ -4293,6 +4293,12 @@ 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); + +/** * @} */ Index: cfe/trunk/lib/Index/CodegenNameGenerator.cpp =================================================================== --- cfe/trunk/lib/Index/CodegenNameGenerator.cpp +++ cfe/trunk/lib/Index/CodegenNameGenerator.cpp @@ -68,7 +68,38 @@ 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 @@ } 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) { Index: cfe/trunk/test/Index/print-objc-manglings.m =================================================================== --- cfe/trunk/test/Index/print-objc-manglings.m +++ cfe/trunk/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] + Index: cfe/trunk/tools/c-index-test/c-index-test.c =================================================================== --- cfe/trunk/tools/c-index-test/c-index-test.c +++ cfe/trunk/tools/c-index-test/c-index-test.c @@ -1563,10 +1563,19 @@ 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; } Index: cfe/trunk/tools/libclang/CIndex.cpp =================================================================== --- cfe/trunk/tools/libclang/CIndex.cpp +++ cfe/trunk/tools/libclang/CIndex.cpp @@ -4639,6 +4639,20 @@ 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); Index: cfe/trunk/tools/libclang/libclang.exports =================================================================== --- cfe/trunk/tools/libclang/libclang.exports +++ cfe/trunk/tools/libclang/libclang.exports @@ -23,6 +23,7 @@ clang_Cursor_getCommentRange clang_Cursor_getCXXManglings clang_Cursor_getMangling +clang_Cursor_getObjCManglings clang_Cursor_getParsedComment clang_Cursor_getRawCommentText clang_Cursor_getNumArguments