compnerd created this revision.
compnerd added reviewers: rjmccall, rnk.
Herald added a subscriber: cfe-commits.

Add support for mangling ObjC protocol conformances in MS ABI as if they are 
COM interfaces.  By diverging from the itanium mangling of `objc_protocol` 
prefixed names, this approach allows for a semi-reasonable, albeit of 
questionable sanity, undecoration via existing tooling.  There is also the 
possibility of adding an extension and taking part of the namespace to add the 
conformance via the `L` and `Z` "modifiers", but the existing tooling would not 
be able to properly undecorated the symbol even though incidentally `undname` 
currently produces something legible while wine's implementation is not able to 
cope with the extension.

This allows for the disambiguation of overloads where the parameter differs 
only in the protocol conformance of the ObjC type, e.g.

  @protocol P;
  void f(std::vector<id>);
  void f(std::vector<id<P>>);

which clang would previously fail due to the mangling being identical as the 
protocol conformance was ignored.


Repository:
  rC Clang

https://reviews.llvm.org/D42508

Files:
  lib/AST/MicrosoftMangle.cpp
  test/CodeGenObjCXX/msabi-protocol-conformance.mm


Index: test/CodeGenObjCXX/msabi-protocol-conformance.mm
===================================================================
--- /dev/null
+++ test/CodeGenObjCXX/msabi-protocol-conformance.mm
@@ -0,0 +1,25 @@
+// RUN: %clang_cc1 -triple thumbv7-windows-msvc -fobjc-runtime=ios-6.0 -o - 
-emit-llvm %s | FileCheck %s
+
+@protocol P;
+@protocol Q;
+
+@class I;
+
+void f(id<P>) {}
+// CHECK-LABEL: "\01?f@@YAXPAU?$objc_object@YP@@@@@Z"
+
+void f(id<P, Q>) {}
+// CHECK-LABEL: "\01?f@@YAXPAU?$objc_object@YP@@YQ@@@@@Z"
+
+void f(Class<P>) {}
+// CHECK-LABEL: "\01?f@@YAXPAU?$objc_class@YP@@@@@Z"
+
+void f(Class<P, Q>) {}
+// CHECK-LABEL: "\01?f@@YAXPAU?$objc_class@YP@@YQ@@@@@Z"
+
+void f(I<P> *) {}
+// CHECK-LABEL: "\01?f@@YAXPAU?$I@YP@@@@@Z"
+
+void f(I<P, Q> *) {}
+// CHECK-LABEL: "\01?f@@YAXPAU?$I@YP@@YQ@@@@@Z"
+
Index: lib/AST/MicrosoftMangle.cpp
===================================================================
--- lib/AST/MicrosoftMangle.cpp
+++ lib/AST/MicrosoftMangle.cpp
@@ -2451,9 +2451,27 @@

 void MicrosoftCXXNameMangler::mangleType(const ObjCObjectType *T, Qualifiers,
                                          SourceRange Range) {
-  // We don't allow overloading by different protocol qualification,
-  // so mangling them isn't necessary.
-  mangleType(T->getBaseType(), Range, QMM_Drop);
+  if (T->qual_empty())
+    return mangleType(T->getBaseType(), Range, QMM_Drop);
+
+  mangleTagTypeKind(TTK_Struct);
+
+  Out << "?$";
+  if (T->isObjCId())
+    mangleSourceName("objc_object");
+  else if (T->isObjCClass())
+    mangleSourceName("objc_class");
+  else
+    mangleSourceName(T->getInterface()->getName());
+
+  for (const auto &Q : T->quals()) {
+    Out << 'Y';
+    mangleSourceName(Q->getName());
+    Out << '@';
+  }
+  Out << '@';
+
+  Out << '@';
 }

 void MicrosoftCXXNameMangler::mangleType(const BlockPointerType *T,


Index: test/CodeGenObjCXX/msabi-protocol-conformance.mm
===================================================================
--- /dev/null
+++ test/CodeGenObjCXX/msabi-protocol-conformance.mm
@@ -0,0 +1,25 @@
+// RUN: %clang_cc1 -triple thumbv7-windows-msvc -fobjc-runtime=ios-6.0 -o - -emit-llvm %s | FileCheck %s
+
+@protocol P;
+@protocol Q;
+
+@class I;
+
+void f(id<P>) {}
+// CHECK-LABEL: "\01?f@@YAXPAU?$objc_object@YP@@@@@Z"
+
+void f(id<P, Q>) {}
+// CHECK-LABEL: "\01?f@@YAXPAU?$objc_object@YP@@YQ@@@@@Z"
+
+void f(Class<P>) {}
+// CHECK-LABEL: "\01?f@@YAXPAU?$objc_class@YP@@@@@Z"
+
+void f(Class<P, Q>) {}
+// CHECK-LABEL: "\01?f@@YAXPAU?$objc_class@YP@@YQ@@@@@Z"
+
+void f(I<P> *) {}
+// CHECK-LABEL: "\01?f@@YAXPAU?$I@YP@@@@@Z"
+
+void f(I<P, Q> *) {}
+// CHECK-LABEL: "\01?f@@YAXPAU?$I@YP@@YQ@@@@@Z"
+
Index: lib/AST/MicrosoftMangle.cpp
===================================================================
--- lib/AST/MicrosoftMangle.cpp
+++ lib/AST/MicrosoftMangle.cpp
@@ -2451,9 +2451,27 @@

 void MicrosoftCXXNameMangler::mangleType(const ObjCObjectType *T, Qualifiers,
                                          SourceRange Range) {
-  // We don't allow overloading by different protocol qualification,
-  // so mangling them isn't necessary.
-  mangleType(T->getBaseType(), Range, QMM_Drop);
+  if (T->qual_empty())
+    return mangleType(T->getBaseType(), Range, QMM_Drop);
+
+  mangleTagTypeKind(TTK_Struct);
+
+  Out << "?$";
+  if (T->isObjCId())
+    mangleSourceName("objc_object");
+  else if (T->isObjCClass())
+    mangleSourceName("objc_class");
+  else
+    mangleSourceName(T->getInterface()->getName());
+
+  for (const auto &Q : T->quals()) {
+    Out << 'Y';
+    mangleSourceName(Q->getName());
+    Out << '@';
+  }
+  Out << '@';
+
+  Out << '@';
 }

 void MicrosoftCXXNameMangler::mangleType(const BlockPointerType *T,
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to