This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]