]> granicus.if.org Git - clang/commitdiff
Itanium ABI: Mangle <mangled-name> according to the ABI
authorDavid Majnemer <david.majnemer@gmail.com>
Wed, 18 Feb 2015 07:47:09 +0000 (07:47 +0000)
committerDavid Majnemer <david.majnemer@gmail.com>
Wed, 18 Feb 2015 07:47:09 +0000 (07:47 +0000)
We attempted to be compatible with GCC's buggy mangling for templates
with a declaration for a template argument.

However, we weren't completely successful in copying their bug in cases
like:
  char foo;
  template <char &C> decltype(C) f() { return foo; };
  template char &f<foo>();

Instead, just follow the ABI specification.  This fixes PR22621.

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

lib/AST/ItaniumMangle.cpp
test/CodeGenCXX/mangle-template.cpp
test/CodeGenCXX/mangle.cpp
test/CodeGenCXX/visibility.cpp

index 0d10bb1d990744da4b40599016400b39550e1f97..f56e242d374a85c2b49aaeceab007b596bd006ed 100644 (file)
@@ -286,7 +286,7 @@ public:
 #endif
   raw_ostream &getStream() { return Out; }
 
-  void mangle(const NamedDecl *D, StringRef Prefix = "_Z");
+  void mangle(const NamedDecl *D);
   void mangleCallOffset(int64_t NonVirtual, int64_t Virtual);
   void mangleNumber(const llvm::APSInt &I);
   void mangleNumber(int64_t Number);
@@ -445,11 +445,11 @@ bool ItaniumMangleContextImpl::shouldMangleCXXName(const NamedDecl *D) {
   return true;
 }
 
-void CXXNameMangler::mangle(const NamedDecl *D, StringRef Prefix) {
+void CXXNameMangler::mangle(const NamedDecl *D) {
   // <mangled-name> ::= _Z <encoding>
   //            ::= <data name>
   //            ::= <special-name>
-  Out << Prefix;
+  Out << "_Z";
   if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
     mangleFunctionEncoding(FD);
   else if (const VarDecl *VD = dyn_cast<VarDecl>(D))
@@ -3197,7 +3197,7 @@ recurse:
     default:
       //  <expr-primary> ::= L <mangled-name> E # external name
       Out << 'L';
-      mangle(D, "_Z");
+      mangle(D);
       Out << 'E';
       break;
 
@@ -3550,7 +3550,7 @@ void CXXNameMangler::mangleTemplateArg(TemplateArgument A) {
       const ValueDecl *D = DRE->getDecl();
       if (isa<VarDecl>(D) || isa<FunctionDecl>(D)) {
         Out << "L";
-        mangle(D, "_Z");
+        mangle(D);
         Out << 'E';
         break;
       }
@@ -3579,13 +3579,7 @@ void CXXNameMangler::mangleTemplateArg(TemplateArgument A) {
     Out << 'L';
     // References to external entities use the mangled name; if the name would
     // not normally be manged then mangle it as unqualified.
-    //
-    // FIXME: The ABI specifies that external names here should have _Z, but
-    // gcc leaves this off.
-    if (compensateMangling)
-      mangle(D, "_Z");
-    else
-      mangle(D, "Z");
+    mangle(D);
     Out << 'E';
 
     if (compensateMangling)
index 998096a57be4cb508693a0222a5e9f86aefff3fd..28db27173ec4fbc5dbada7e5f0ec354e4c037339 100644 (file)
@@ -4,7 +4,7 @@
 namespace test1 {
 int x;
 template <int& D> class T { };
-// CHECK: void @_ZN5test12f0ENS_1TILZNS_1xEEEE(
+// CHECK: void @_ZN5test12f0ENS_1TIL_ZNS_1xEEEE(
 void f0(T<x> a0) {}
 }
 
@@ -12,7 +12,7 @@ namespace test1 {
 // CHECK: void @_ZN5test12f0Ef
 void f0(float) {}
 template<void (&)(float)> struct t1 {};
-// CHECK: void @_ZN5test12f1ENS_2t1ILZNS_2f0EfEEE(
+// CHECK: void @_ZN5test12f1ENS_2t1IL_ZNS_2f0EfEEE(
 void f1(t1<f0> a0) {}
 }
 
@@ -49,11 +49,11 @@ int main(int) {}
 
 namespace test5 {
 template<void (&)(float)> struct t1 {};
-// CHECK: void @_ZN5test52f1ENS_2t1ILZ8test5_f0EEE(
+// CHECK: void @_ZN5test52f1ENS_2t1IL_Z8test5_f0EEE(
 void f1(t1<test5_f0> a0) {}
 
 template<int (&)(int)> struct t2 {};
-// CHECK: void @_ZN5test52f2ENS_2t2ILZ4mainEEE
+// CHECK: void @_ZN5test52f2ENS_2t2IL_Z4mainEEE
 void f2(t2<main> a0) {}
 }
 
@@ -164,11 +164,11 @@ namespace test12 {
   void use() {
     // CHECK-LABEL: define internal void @_ZN6test124testIFivEXadL_ZNS_L1fEvEEEEvv(
     test<int(), &f>();
-    // CHECK-LABEL: define internal void @_ZN6test124testIRFivELZNS_L1fEvEEEvv(
+    // CHECK-LABEL: define internal void @_ZN6test124testIRFivEL_ZNS_L1fEvEEEvv(
     test<int(&)(), f>();
     // CHECK-LABEL: define internal void @_ZN6test124testIPKiXadL_ZNS_L1nEEEEEvv(
     test<const int*, &n>();
-    // CHECK-LABEL: define internal void @_ZN6test124testIRKiLZNS_L1nEEEEvv(
+    // CHECK-LABEL: define internal void @_ZN6test124testIRKiL_ZNS_L1nEEEEvv(
     test<const int&, n>();
   }
 }
index e15d54086a64f78a116bb44a852c0da391b969d5..c12fe5014f89e3c4882a194b44c673fcd6a0efb7 100644 (file)
@@ -455,7 +455,7 @@ namespace test7 {
   void g(zed<&foo::bar>*)
   {}
 }
-// CHECK-LABEL: define weak_odr void @_ZN5test81AILZNS_1B5valueEEE3incEv
+// CHECK-LABEL: define weak_odr void @_ZN5test81AIL_ZNS_1B5valueEEE3incEv
 namespace test8 {
   template <int &counter> class A { void inc() { counter++; } };
   class B { public: static int value; };
index e0271099e2a9c6642f9bf2b27eaa975c8c3f5eb8..7239cbe00225189340a45d78cce636c4e94e9a26 100644 (file)
@@ -240,7 +240,7 @@ namespace Test7 {
   class B : public A {};
   B b; // top of file
 
-  // CHECK-LABEL: define linkonce_odr hidden void @_ZN5Test74ArefILZNS_1aEEE3fooEv()
+  // CHECK-LABEL: define linkonce_odr hidden void @_ZN5Test74ArefIL_ZNS_1aEEE3fooEv()
   void test() {
     Aref<a>::foo();
   }