https://gcc.gnu.org/bugzilla/show_bug.cgi?id=127002
--- Comment #2 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
The bug is in mangling of non-static data members of the local classes.
template <auto N>
void foo ();
consteval auto
bar (bool x)
{
struct A { int a; };
return x ? ^^A : ^^A::a;
}
consteval auto
baz (bool x)
{
struct A { int a; };
return x ? ^^A : ^^A::a;
}
void
qux ()
{
foo <bar (true)> ();
foo <baz (true)> ();
foo <bar (false)> ();
foo <baz (false)> ();
}
This calls
call _Z3fooITnDaLDmtyZ3barbE1AEEvv
call _Z3fooITnDaLDmtyZ3bazbE1AEEvv
call _Z3fooITnDaLDmdm1A1aEEvv
call _Z3fooITnDaLDmdm1A1aEEvv
In the mangling of the local types it uses ty with Z3barbE1A argument, which
contains both the function and the local class in it.
But the mangling of bar()::A::a and baz ()::A::a is identical, dm with 1A1a
argument.
<prefix> in the Itanium mangling ABI unfortunately doesn't include the
containing function for local classes etc.
We have in the current mangling grammar for reflections various spots using
<prefix>:
::= en <prefix> <unqualified-name> # enumerator
::= ta <alias prefix> <alias unqualified-name>
[ <alias template-args> ] _ <type> # type alias
::= dm <prefix> <unqualified-name> # ns data member
::= da <prefix> [ <nonnegative number> ] _ # empty anon union
# data member
::= un <prefix> [ <nonnegative number> ] _ # unnamed bitfld
::= ct [ <prefix> ] <unqualified-name> # class template
::= ft [ <prefix> ] <unqualified-name> # function template
::= vt [ <prefix> ] <unqualified-name> # variable template
::= at [ <prefix> ] <unqualified-name> # alias template
::= co [ <prefix> ] <unqualified-name> # concept
::= na [ <prefix> ] <unqualified-name> # namespace alias
::= ns [ <prefix> ] <unqualified-name> # namespace
Some of these are non-issue, namespace/namespace alias can't appear in local
functions, neither concept, nor class/function/variable/alias templates.
But the rest certainly can appear there, as shown by the testcase below:
#include <meta>
template <auto N>
void foo ();
template <int N>
consteval auto
bar ()
{
int n = N & ~1;
enum E { E1 };
using A = int;
struct B { int b; union {}; int : 0; };
switch (n)
{
case 0: return ^^E1;
case 2: return ^^A;
case 4: return ^^B::b;
case 6: return members_of (^^B, std::meta::access_context::current ())[2];
case 8: return members_of (^^B, std::meta::access_context::current ())[3];
default: return ^^::;
}
}
void
qux ()
{
foo <bar <0> ()> ();
foo <bar <1> ()> ();
foo <bar <2> ()> ();
foo <bar <3> ()> ();
foo <bar <4> ()> ();
foo <bar <5> ()> ();
foo <bar <6> ()> ();
foo <bar <7> ()> ();
foo <bar <8> ()> ();
foo <bar <9> ()> ();
}
This mangles as
call _Z3fooITnDaLDmen1E2E1EEvv
call _Z3fooITnDaLDmen1E2E1EEvv
call _Z3fooITnDaLDmta1A_iEEvv
call _Z3fooITnDaLDmta1A_iEEvv
call _Z3fooITnDaLDmdm1B1bEEvv
call _Z3fooITnDaLDmdm1B1bEEvv
call _Z3fooITnDaLDmda1B_EEvv
call _Z3fooITnDaLDmda1B_EEvv
call _Z3fooITnDaLDmun1B_EEvv
call _Z3fooITnDaLDmun1B_EEvv
and so in each case the pair of adjacent calls mangles the same. But none of
them should be the same, they are all local entities inside of different
function template instantiations.
So, for the local names when used in en/ta/dm/da/un we need some different
grammar
to encode the https://itanium-cxx-abi.github.io/cxx-abi/abi.html#mangling-scope
stuff
in there, but not sure what exactly.