]> granicus.if.org Git - clang/commitdiff
[index] Generate class & metaclass manglings for objc
authorDave Lee <davelee.com@gmail.com>
Fri, 22 Sep 2017 16:58:57 +0000 (16:58 +0000)
committerDave Lee <davelee.com@gmail.com>
Fri, 22 Sep 2017 16:58:57 +0000 (16:58 +0000)
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
lib/Index/CodegenNameGenerator.cpp
test/Index/print-objc-manglings.m [new file with mode: 0644]
tools/c-index-test/c-index-test.c
tools/libclang/CIndex.cpp
tools/libclang/libclang.exports

index b5d994783f5d75697e4f46d80b942516c2818faa..c72be56fdc712ab37426b7a4515bbfedc1a72d57 100644 (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);
+
 /**
  * @}
  */
index 92740b05703b526594ecc26755e8946ee63f9ffd..bf52e2108baaf8c2ad417c85294df0f4e8563a12 100644 (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) {
diff --git a/test/Index/print-objc-manglings.m b/test/Index/print-objc-manglings.m
new file mode 100644 (file)
index 0000000..1e7983e
--- /dev/null
@@ -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 cf3581e259f7ee22c7e378506fcd7db8f7889f8f..a11e03c846e8b4df15b8b3d9b4debe3cd747f91e 100644 (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;
 }
 
index 6d120bcab4d9599e2637cc6cdb3de4cf7cdddd22..26b1f5e2b1d531e730c24ddaa1aa97226c9fc2aa 100644 (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);
index 62a233ebec330211169f41c2921a36c668e490cb..fb4547a867df32f666598d58583264163ab1e7f1 100644 (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