[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
This commit is contained in:
Dave Lee 2017-09-22 16:58:57 +00:00
parent 78409ae639
commit d454549fce
6 changed files with 88 additions and 7 deletions

View File

@ -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);
/**
* @}
*/

View File

@ -68,7 +68,38 @@ struct CodegenNameGenerator::Implementation {
return Name;
}
enum ObjCKind {
ObjCClass,
ObjCMetaclass,
};
std::vector<std::string> getAllManglings(const ObjCContainerDecl *OCD) {
StringRef ClassName;
if (const auto *OID = dyn_cast<ObjCInterfaceDecl>(OCD))
ClassName = OID->getObjCRuntimeNameAsString();
else if (const auto *OID = dyn_cast<ObjCImplementationDecl>(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<std::string> getAllManglings(const Decl *D) {
if (const auto *OCD = dyn_cast<ObjCContainerDecl>(D))
return getAllManglings(OCD);
if (!(isa<CXXRecordDecl>(D) || isa<CXXMethodDecl>(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) {

View File

@ -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]

View File

@ -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;
}

View File

@ -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<ObjCInterfaceDecl>(D) || isa<ObjCImplementationDecl>(D)))
return nullptr;
ASTContext &Ctx = D->getASTContext();
index::CodegenNameGenerator CGNameGen(Ctx);
std::vector<std::string> Manglings = CGNameGen.getAllManglings(D);
return cxstring::createSet(Manglings);
}
CXString clang_getCursorDisplayName(CXCursor C) {
if (!clang_isDeclaration(C.kind))
return clang_getCursorSpelling(C);

View File

@ -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