Demangling ambiguity for templated conversion operators

Mike Herrick mjh at edg.com
Tue Aug 10 19:36:57 UTC 2010


I was doing some "house cleaning" and came upon this apparent demangling ambiguity in the IA-64 ABI that we ran into a while back (unrelated to recent SFINAE discussions).  I thought I'd highlight it here along with the demangler heuristic we implemented as a workaround in case that information is useful to other implementers.

Take this example:

$ cat ex.c
  template <class T> struct A { };
  template <class T> struct B { };
  struct S {
   template <class T> operator T();
  } s;
  void f() {
   s.operator A< A<int> >();
   s.operator A< B< A<int> > >();
  }
$ g++450 -c ex.c
$ nm -u ex.o
                 U _ZN1ScvT_I1AI1BIS2_IiEEEEEv
                 U _ZN1ScvT_I1AIS2_IiEEEEv
$ nm -u -C ex.o
                 U S::operator A<B<B<int> > ><A<B<B<int> > > >()
                 U _ZN1ScvT_I1AIS2_IiEEEEv

GNU (and EDG and others) can't correctly demangle these names (the substitutions are wrong in the first demangled name above).

I believe the problem arises when using this rule for a template conversion function:

	<operator-name> ::= cv <type>	# (cast)

In the case for "_ZN1ScvT_I1AIS2_IiEEEEv" above, after the demangler sees the "cv", it's presented with "T_I1AIS2_IiEEEEv" and asked to demangle a <type>, but <type> can be either "T_" (a <template-param>) or "T_I1AIS2_IiEEE" (a <template-template-param> <template-args>).  As far as I can tell, there's no way to know if the <template-args> are part of the <type> or belong to an enclosing production (i.e., <template-prefix> <template-args> -- where <template-prefix> is reduced to <operator-name>).

Here's an example that produces both cases depending on whether or not FOO is defined:

  template <class T> struct A { };
  struct S {
  #ifdef FOO
    template <class T> operator T();
  #else
    template <template <class> class T> operator T<int>();
  #endif
  } s;
  void f() {
    s.operator A<int>();
  }

We've made a change to our demangler to initially not parse any <template-args> as part of the <type> when demangling a conversion function, but if the demangling fails, it makes a second attempt, this time allowing <template-args> as part of the <type>.  With these changes, we now give these demangled names (for the initial example):

$ nm -u ex.o | edg_decode
                 U S::operator T1<A<B<A<int>>>>()
                 U S::operator T1<A<A<int>>>()

Mike Herrick
Edison Design Group




More information about the cxx-abi-dev mailing list