Currently gcc mangles symbols wrongly when the discriminator is greater than ten. The fix is straightforward. The demangler now handles both the old and the new correct mangling.
Tested on ppc64le. OK for trunk? Thanks. libiberty: PR c++/77489 * cp-demangle.c (d_discriminator): Handle discriminator >= 10. * testsuite/demangle-expected: Add tests for discriminator. gcc/cp: PR c++/77489 * mangle.c (write_discriminator): Handle discriminator >= 10. diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c index 5f2fa35d29e8..ee75f4a25621 100644 --- a/gcc/cp/mangle.c +++ b/gcc/cp/mangle.c @@ -1952,7 +1952,8 @@ discriminator_for_string_literal (tree /*function*/, return 0; } -/* <discriminator> := _ <number> +/* <discriminator> := _ <number> # when number < 10 + := __ <number> _ # when number >= 10 The discriminator is used only for the second and later occurrences of the same name within a single function. In this case <number> is @@ -1965,7 +1966,11 @@ write_discriminator (const int discriminator) if (discriminator > 0) { write_char ('_'); + if (abi_version_at_least(11) && discriminator - 1 >= 10) + write_char ('_'); write_unsigned_number (discriminator - 1); + if (abi_version_at_least(11) && discriminator - 1 >= 10) + write_char ('_'); } } diff --git a/gcc/testsuite/g++.dg/abi/pr77489.C b/gcc/testsuite/g++.dg/abi/pr77489.C new file mode 100644 index 000000000000..f640bb6f0676 --- /dev/null +++ b/gcc/testsuite/g++.dg/abi/pr77489.C @@ -0,0 +1,62 @@ +// { dg-options -fabi-version=11 } + +extern void bar(int*); + +void foo() +{ + { + static int localVar = 0; + bar(&localVar); + } + { + static int localVar = 1; + bar(&localVar); + } + { + static int localVar = 2; + bar(&localVar); + } + { + static int localVar = 3; + bar(&localVar); + } + { + static int localVar = 4; + bar(&localVar); + } + { + static int localVar = 5; + bar(&localVar); + } + { + static int localVar = 6; + bar(&localVar); + } + { + static int localVar = 7; + bar(&localVar); + } + { + static int localVar = 8; + bar(&localVar); + } + { + static int localVar = 9; + bar(&localVar); + } + { + static int localVar = 10; + bar(&localVar); + } + { + static int localVar = 11; + bar(&localVar); + } + { + static int localVar = 12; + bar(&localVar); + } +} + +// { dg-final { scan-assembler "_ZZ3foovE8localVar__10_" } } +// { dg-final { scan-assembler "_ZZ3foovE8localVar__11_" } } diff --git a/libiberty/cp-demangle.c b/libiberty/cp-demangle.c index 15ef3b48785f..d84929eca20d 100644 --- a/libiberty/cp-demangle.c +++ b/libiberty/cp-demangle.c @@ -3609,7 +3609,11 @@ d_local_name (struct d_info *di) } } -/* <discriminator> ::= _ <(non-negative) number> +/* <discriminator> ::= _ <number> # when number < 10 + ::= __ <number> _ # when number >= 10 + + <discriminator> ::= _ <number> # when number >=10 + is also accepted to support gcc versions that wrongly mangled that way. We demangle the discriminator, but we don't print it out. FIXME: We should print it out in verbose mode. */ @@ -3617,14 +3621,28 @@ d_local_name (struct d_info *di) static int d_discriminator (struct d_info *di) { - int discrim; + int discrim, num_underscores = 1; if (d_peek_char (di) != '_') return 1; d_advance (di, 1); + if (d_peek_char (di) == '_') + { + ++num_underscores; + d_advance (di, 1); + } + discrim = d_number (di); if (discrim < 0) return 0; + if (num_underscores > 1 && discrim >= 10) + { + if (d_peek_char (di) == '_') + d_advance (di, 1); + else + return 0; + } + return 1; } diff --git a/libiberty/testsuite/demangle-expected b/libiberty/testsuite/demangle-expected index b65dcd3450e9..07e258fe58b3 100644 --- a/libiberty/testsuite/demangle-expected +++ b/libiberty/testsuite/demangle-expected @@ -4666,3 +4666,19 @@ void eat<int*, Foo()::{lambda(auto:1*, auto:2*)#6}>(int*&, Foo()::{lambda(auto:1 _Z3eatIPiZ3BarIsEvvEUlPsPT_PT0_E0_EvRS3_RS5_ void eat<int*, void Bar<short>()::{lambda(short*, auto:1*, auto:2*)#2}>(int*&, void Bar<short>()::{lambda(short*, auto:1*, auto:2*)#2}&) + +# PR 77489 +_ZZ3foovE8localVar_9 +foo()::localVar + +_ZZ3foovE8localVar_10 +foo()::localVar + +_ZZ3foovE8localVar__10_ +foo()::localVar + +_ZZ3foovE8localVar__9_ +_ZZ3foovE8localVar__9_ + +_ZZ3foovE8localVar__12 +_ZZ3foovE8localVar__12 -- Markus