[Bug c++/77489] Invalid mangling of static local variables

trippels at gcc dot gnu.org gcc-bugzilla@gcc.gnu.org
Mon Sep 5 16:07:00 GMT 2016


https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77489

--- Comment #2 from Markus Trippelsdorf <trippels at gcc dot gnu.org> ---
Untested patch:

diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c
index bd23260c0883..322f52944f41 100644
--- a/gcc/cp/mangle.c
+++ b/gcc/cp/mangle.c
@@ -1896,7 +1896,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
@@ -1909,7 +1910,11 @@ write_discriminator (const int discriminator)
   if (discriminator > 0)
     {
       write_char ('_');
+      if (discriminator - 1 >= 10)
+       write_char ('_');
       write_unsigned_number (discriminator - 1);
+      if (discriminator - 1 >= 10)
+       write_char ('_');
     }
 }

diff --git a/libiberty/cp-demangle.c b/libiberty/cp-demangle.c
index 1c2bce291797..47099c1d0391 100644
--- a/libiberty/cp-demangle.c
+++ b/libiberty/cp-demangle.c
@@ -3529,7 +3529,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.  */
@@ -3537,14 +3541,24 @@ 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;
 }


More information about the Gcc-bugs mailing list