title: Issue with type name demangling
body: <p>I was creating a template class that transforms a type into a string describing it, eg <code>typeinfo&lt;int(*)()&gt;::name()</code> returns the string <code>"int(*)()"</code> (up to whitespace). Initially I had tons of special cases to work around the fact that <code>typeid(...).name()</code> strips off reference qualifiers and top-level cv-qualifiers, but then I remembered that passing a type as a template parameter will preserve these. So, using the ABI header, I ended up with something like this:</p>
  
  <pre class="lang-c prettyprint-override"><code>#include &lt;iostream&gt;
  #include &lt;typeinfo&gt;
  #include &lt;string&gt;
  #include &lt;cxxabi.h&gt;
  
  using namespace std;
  
  string demangle(const char* mangledName) {
      int status;
      char* result = abi::__cxa_demangle(mangledName, nullptr, nullptr, &amp;status);
      switch(status) {
      case -1:
          cerr &lt;&lt; "Out of memory!" &lt;&lt; endl;
          exit(1);
      case -2:
          return mangledName;
      case -3: // Should never happen, but just in case?
          return mangledName;
      }
      string name = result;
      free(result);
      return name;
  }
  
  template&lt;typename T&gt; struct preserve_qualifiers {};
  
  template&lt;typename T&gt; class typeinfo {
      using wrap = preserve_qualifiers&lt;T&gt;;
  public:
      static const string name() {
          string name = demangle(typeid(wrap).name());
          int i = name.find_first_of('&lt;');
          if(i == string::npos) return name;
          int j = name.length() - i - 2;
          return name.substr(i + 1, j);
      }
  };
  
  #define TypeOut(...) cout \
      &lt;&lt; "Type " #__VA_ARGS__ ": " &lt;&lt; endl \
      &lt;&lt; "  Mangled: " &lt;&lt; typeid(__VA_ARGS__).name() &lt;&lt; endl \
      &lt;&lt; "  Demangled: " &lt;&lt; demangle(typeid(__VA_ARGS__).name()) &lt;&lt; endl \
      &lt;&lt; "  typeinfo&lt;&gt;: " &lt;&lt; typeinfo&lt;__VA_ARGS__&gt;::name() &lt;&lt; endl
  class A {};
  template&lt;typename T&gt; class F {};
  template&lt;int T&gt; class G {};
  template&lt;template&lt;typename&gt; class T&gt; class H {};
  template&lt;template&lt;int&gt; class T&gt; class I {};
  template&lt;typename... T&gt; class J {};
  template&lt;int... T&gt; class K {};
  template&lt;template&lt;typename&gt; class... T&gt; class L {};
  template&lt;template&lt;int&gt; class... T&gt; class M {};
  template&lt;template&lt;typename&gt; class... T&gt; class N {};
  template&lt;template&lt;template&lt;typename&gt; class...&gt; class... T&gt; class O {};
  struct bits {int i : 4, j : 2;};
  template&lt;typename T, int n&gt; struct bits2 {T val : n;};
  
  int main(int argc, char* argv[]) {
      TypeOut(void(*volatile)(void(*const)()));
      TypeOut(int (A::*)());
      TypeOut(int (A::*)()const);
      TypeOut(int (A::*const)());
  #ifdef __clang__
      TypeOut(int (A::*)()&amp;);
      TypeOut(int (A::*)()&amp;&amp;);
  #endif
      TypeOut(F&lt;int&gt;);
      TypeOut(G&lt;3&gt;);
      TypeOut(H&lt;F&gt;);
      TypeOut(I&lt;G&gt;);
      TypeOut(J&lt;int&gt;);
      TypeOut(K&lt;3&gt;);
      TypeOut(L&lt;F&gt;);
      TypeOut(M&lt;G&gt;);
      TypeOut(N&lt;F,F,F&gt;);
      TypeOut(O&lt;N,N&gt;);
  }
  </code></pre>
  
  <p>This compiles and works (nearly) perfectly in GCC (4.8). However, GCC doesn't support the ref-qualifiers on member functions, so tried it in Clang as well (3.2) to see if it would work. It doesn't. It compiles fine, and runs without issue, but most of the template names are not demangled, and nor are the ref-qualified member functions.</p>
  
  <p><a href="http://ideone.com/05yxL">Here</a> is the GCC output from ideone (the code was tweaked slightly since ideone's version of GCC doesn't support nullptr or alias declarations). Notice the missing const qualifier in the function parameter. That's the only thing that didn't work as I'd hoped in GCC. It's the same in Clang, too, which I suppose isn't especially surprising. (What's surprising is that it's missing at all, not that GCC and Clang are consistent on it.)</p>
  
  <p>Unfortunately, when compiling and running with Clang, the variadic templated classes could not be demangled. For example, J was mangled to <code>1JIJiEE</code> instead of the <code>1JIIiEE</code> that GCC chose.</p>
  
  <p>Selected output from clang (showing only the ones that didn't work)</p>
  
  <pre><code>Type int (A::*)()&amp;: 
    Mangled: M1AFivRE
    Demangled: M1AFivRE
    typeinfo&lt;&gt;: 19preserve_qualifiersIM1AFivREE
  Type int (A::*)()&amp;&amp;: 
    Mangled: M1AFivOE
    Demangled: M1AFivOE
    typeinfo&lt;&gt;: 19preserve_qualifiersIM1AFivOEE
  Type J&lt;int&gt;: 
    Mangled: 1JIJiEE
    Demangled: 1JIJiEE
    typeinfo&lt;&gt;: 19preserve_qualifiersI1JIJiEEE
  Type K&lt;3&gt;: 
    Mangled: 1KIJLi3EEE
    Demangled: 1KIJLi3EEE
    typeinfo&lt;&gt;: 19preserve_qualifiersI1KIJLi3EEEE
  Type L&lt;F&gt;: 
    Mangled: 1LIJ1FEE
    Demangled: 1LIJ1FEE
    typeinfo&lt;&gt;: 19preserve_qualifiersI1LIJ1FEEE
  Type M&lt;G&gt;: 
    Mangled: 1MIJ1GEE
    Demangled: 1MIJ1GEE
    typeinfo&lt;&gt;: 19preserve_qualifiersI1MIJ1GEEE
  Type N&lt;F,F,F&gt;: 
    Mangled: 1NIJ1FS0_S0_EE
    Demangled: 1NIJ1FS0_S0_EE
    typeinfo&lt;&gt;: 19preserve_qualifiersI1NIJ1FS1_S1_EEE
  Type O&lt;N,N&gt;: 
    Mangled: 1OIJ1NS0_EE
    Demangled: 1OIJ1NS0_EE
    typeinfo&lt;&gt;: 19preserve_qualifiersI1OIJ1NS1_EEE
  </code></pre>
  
  <p>Does anyone have any idea how this might be resolved? Is it a bug in clang? (Or maybe a bug in GCC?) My first suspicion was a version incompatibility between the C++ ABI being linked with my code and the C++ ABI that clang is using. The fact that the issue only occurs with new C++11 features (member function ref-qualifiers and variadic templates) seems to support this suspicion... though r-value references (for example) don't have a problem.</p>
  
  <p>In case it's relevant, I'm on Mac OSX Lion, and GCC 4.8 and clang 3.2 were installed from MacPorts. I'm using the following commands for compilation:</p>
  
  <pre><code>clang++-mp-3.2 -isystem/usr/local/include/c++/v1 -stdlib=libc++ -std=gnu++11 typeinfo-min.cpp -o typeinfofun-clang
  G++-mp-4.8 -std=gnu++11 typeinfo-min.cpp -o typeinfofun-gcc
  </code></pre>
  
  <p>The isystem flag seems to be required in order to allow clang to find the libc++ headers (which was necessary when I was using <code>&lt;type_traits&gt;</code> for the more complicated version of this). Without it, it can't even find <code>&lt;iostream&gt;</code>.</p>
  
  <p>(As an additional note, this issue does affect the more complicated version as well, since class names were — probably unsurprisingly — not among the specializations for complicated types, and thus just used the ABI demangle call.)</p>
  
  <p>(Also as an aside, I'm curious about the portability of this. I know it's not necessary in MSVC since that returns the unmangled name from <code>typeid(...).name()</code>, but apart from that...)</p>