]> granicus.if.org Git - clang/commitdiff
MS ABI: Fix mangling of static methods and function references
authorReid Kleckner <reid@kleckner.net>
Wed, 5 Feb 2014 18:59:38 +0000 (18:59 +0000)
committerReid Kleckner <reid@kleckner.net>
Wed, 5 Feb 2014 18:59:38 +0000 (18:59 +0000)
Function references always use $1? like function pointers and never $E?
like var decl references.  Static methods are mangled like function
pointers.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@200869 91177308-0d34-0410-b5e6-96231b3b80d8

lib/AST/MicrosoftMangle.cpp
test/CodeGenCXX/mangle-ms-template-callback.cpp

index b2f74cf4d1e6c7bcc4a332ee5fc448a6533d8636..6ce7018be19a58728eb4067a2f8a2e9bfa65d81d 100644 (file)
@@ -1090,12 +1090,17 @@ void MicrosoftCXXNameMangler::mangleTemplateArg(const TemplateDecl *TD,
   }
   case TemplateArgument::Declaration: {
     const NamedDecl *ND = cast<NamedDecl>(TA.getAsDecl());
-    if (const FieldDecl *FD = dyn_cast<FieldDecl>(ND))
+    if (const FieldDecl *FD = dyn_cast<FieldDecl>(ND)) {
       mangleMemberDataPointer(cast<CXXRecordDecl>(FD->getParent()), FD);
-    else if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(ND))
-      mangleMemberFunctionPointer(MD->getParent(), MD);
-    else
+    } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) {
+      const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(ND);
+      if (MD && MD->isInstance())
+        mangleMemberFunctionPointer(MD->getParent(), MD);
+      else
+        mangle(ND, "$1?");
+    } else {
       mangle(ND, TA.isDeclForReferenceParam() ? "$E?" : "$1?");
+    }
     break;
   }
   case TemplateArgument::Integral:
index cfa4e880a5e53eae8d529cced5d39c7a601331f4..1a8f82fc82566c5904f30545315b65e4a9ffffe4 100644 (file)
@@ -70,3 +70,20 @@ void call_bar() {
 // CHECK: "\01??$bar@P_EAHH@Z@@YAXP_EAHH@Z@Z"
 // FYI blocks are not present in MSVS, so we're free to choose the spec.
 }
+
+template <void (*Fn)()> void WrapFnPtr() { Fn(); }
+template <void (&Fn)()> void WrapFnRef() { Fn(); }
+struct Thing {
+  static void VoidStaticMethod();
+};
+void VoidFn();
+void CallWrapper() {
+  WrapFnPtr<VoidFn>();
+  WrapFnRef<VoidFn>();
+  WrapFnPtr<Thing::VoidStaticMethod>();
+  WrapFnRef<Thing::VoidStaticMethod>();
+}
+// CHECK: call {{.*}} @"\01??$WrapFnPtr@$1?VoidFn@@YAXXZ@@YAXXZ"
+// CHECK: call {{.*}} @"\01??$WrapFnRef@$1?VoidFn@@YAXXZ@@YAXXZ"
+// CHECK: call {{.*}} @"\01??$WrapFnPtr@$1?VoidStaticMethod@Thing@@SAXXZ@@YAXXZ"
+// CHECK: call {{.*}} @"\01??$WrapFnRef@$1?VoidStaticMethod@Thing@@SAXXZ@@YAXXZ"