diff mbox

[C++] Fix PR77489 -- mangling of discriminator >= 10

Message ID 20170111114829.GA288@x4
State New
Headers show

Commit Message

Markus Trippelsdorf Jan. 11, 2017, 11:48 a.m. UTC
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.

+_ZZ3foovE8localVar__12

Comments

Jakub Jelinek Jan. 11, 2017, 12:03 p.m. UTC | #1
On Wed, Jan 11, 2017 at 12:48:29PM +0100, Markus Trippelsdorf wrote:
> @@ -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 ('_');

Formatting nits, there should be space before (11).

> +// { dg-final { scan-assembler "_ZZ3foovE8localVar__10_" } }
> +// { dg-final { scan-assembler "_ZZ3foovE8localVar__11_" } }

Would be nice to also
// { dg-final { scan-assembler "_ZZ3foovE8localVar_9" } }

Otherwise, I defer to Jason (primarily whether this doesn't need
ABI version 12).

	Jakub
Markus Trippelsdorf Jan. 12, 2017, 7:36 a.m. UTC | #2
On 2017.01.11 at 13:03 +0100, Jakub Jelinek wrote:
> On Wed, Jan 11, 2017 at 12:48:29PM +0100, Markus Trippelsdorf wrote:
> > @@ -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 ('_');
> 
> Formatting nits, there should be space before (11).
> 
> > +// { dg-final { scan-assembler "_ZZ3foovE8localVar__10_" } }
> > +// { dg-final { scan-assembler "_ZZ3foovE8localVar__11_" } }
> 
> Would be nice to also
> // { dg-final { scan-assembler "_ZZ3foovE8localVar_9" } }
> 
> Otherwise, I defer to Jason (primarily whether this doesn't need
> ABI version 12).

Thanks for review. I will fix these issues. 
Jason said on IRC that he is fine with ABI version 11.

Ok for trunk?
Jason Merrill Jan. 17, 2017, 6:26 p.m. UTC | #3
On Thu, Jan 12, 2017 at 2:36 AM, Markus Trippelsdorf
<markus@trippelsdorf.de> wrote:
> On 2017.01.11 at 13:03 +0100, Jakub Jelinek wrote:
>> On Wed, Jan 11, 2017 at 12:48:29PM +0100, Markus Trippelsdorf wrote:
>> > @@ -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 ('_');
>>
>> Formatting nits, there should be space before (11).
>>
>> > +// { dg-final { scan-assembler "_ZZ3foovE8localVar__10_" } }
>> > +// { dg-final { scan-assembler "_ZZ3foovE8localVar__11_" } }
>>
>> Would be nice to also
>> // { dg-final { scan-assembler "_ZZ3foovE8localVar_9" } }
>>
>> Otherwise, I defer to Jason (primarily whether this doesn't need
>> ABI version 12).
>
> Thanks for review. I will fix these issues.
> Jason said on IRC that he is fine with ABI version 11.
>
> Ok for trunk?

This also needs the same (invoke.texi and warning) changes that Nathan
pointed out on your other mangling patch.

Jason
diff mbox

Patch

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