Patchwork cp-demangle PATCH to handle C++ casts

login
register
mail settings
Submitter Jason Merrill
Date July 18, 2012, 7:50 p.m.
Message ID <50071396.7010408@redhat.com>
Download mbox | patch
Permalink /patch/171817/
State New
Headers show

Comments

Jason Merrill - July 18, 2012, 7:50 p.m.
When I ran the C++ testsuite with -fabi-version defaulting to 0, I 
noticed a couple of tests that failed because they were expecting the =2 
mangling.  I also noticed that the demangler didn't understand the 
correct mangling for new-style casts.

Tested x86_64-pc-linux-gnu, applying to trunk.

Patch

commit 295d8111c7b0ee35933d201d1001798be4fc0b68
Author: Jason Merrill <jason@redhat.com>
Date:   Wed Jul 18 15:28:02 2012 -0400

    	* cp-demangle.c (cplus_demangle_operators): Add *_cast.
    	(op_is_new_cast): New.
    	(d_expression, d_print_comp): Check it.

diff --git a/libiberty/cp-demangle.c b/libiberty/cp-demangle.c
index 27cc323..258aaa7 100644
--- a/libiberty/cp-demangle.c
+++ b/libiberty/cp-demangle.c
@@ -1582,11 +1582,13 @@  const struct demangle_operator_info cplus_demangle_operators[] =
   { "an", NL ("&"),         2 },
   { "at", NL ("alignof "),   1 },
   { "az", NL ("alignof "),   1 },
+  { "cc", NL ("const_cast"), 2 },
   { "cl", NL ("()"),        2 },
   { "cm", NL (","),         2 },
   { "co", NL ("~"),         1 },
   { "dV", NL ("/="),        2 },
   { "da", NL ("delete[] "), 1 },
+  { "dc", NL ("dynamic_cast"), 2 },
   { "de", NL ("*"),         1 },
   { "dl", NL ("delete "),   1 },
   { "ds", NL (".*"),        2 },
@@ -1626,8 +1628,10 @@  const struct demangle_operator_info cplus_demangle_operators[] =
   { "qu", NL ("?"),         3 },
   { "rM", NL ("%="),        2 },
   { "rS", NL (">>="),       2 },
+  { "rc", NL ("reinterpret_cast"), 2 },
   { "rm", NL ("%"),         2 },
   { "rs", NL (">>"),        2 },
+  { "sc", NL ("static_cast"), 2 },
   { "st", NL ("sizeof "),   1 },
   { "sz", NL ("sizeof "),   1 },
   { "tr", NL ("throw"),     0 },
@@ -2809,6 +2813,18 @@  d_exprlist (struct d_info *di, char terminator)
   return list;
 }
 
+/* Returns nonzero iff OP is an operator for a C++ cast: const_cast,
+   dynamic_cast, static_cast or reinterpret_cast.  */
+
+static int
+op_is_new_cast (struct demangle_component *op)
+{
+  const char *code = op->u.s_operator.op->code;
+  return (code[1] == 'c'
+	  && (code[0] == 's' || code[0] == 'd'
+	      || code[0] == 'c' || code[0] == 'r'));
+}
+
 /* <expression> ::= <(unary) operator-name> <expression>
                 ::= <(binary) operator-name> <expression> <expression>
                 ::= <(trinary) operator-name> <expression> <expression> <expression>
@@ -2971,7 +2987,10 @@  d_expression (struct d_info *di)
 	    struct demangle_component *left;
 	    struct demangle_component *right;
 
-	    left = d_expression (di);
+	    if (op_is_new_cast (op))
+	      left = cplus_demangle_type (di);
+	    else
+	      left = d_expression (di);
 	    if (!strcmp (code, "cl"))
 	      right = d_exprlist (di, 'E');
 	    else if (!strcmp (code, "dt") || !strcmp (code, "pt"))
@@ -4455,6 +4474,17 @@  d_print_comp (struct d_print_info *dpi, int options,
 	  return;
 	}
 
+      if (op_is_new_cast (d_left (dc)))
+	{
+	  d_print_expr_op (dpi, options, d_left (dc));
+	  d_append_char (dpi, '<');
+	  d_print_comp (dpi, options, d_left (d_right (dc)));
+	  d_append_string (dpi, ">(");
+	  d_print_comp (dpi, options, d_right (d_right (dc)));
+	  d_append_char (dpi, ')');
+	  return;
+	}
+
       /* We wrap an expression which uses the greater-than operator in
 	 an extra layer of parens so that it does not get confused
 	 with the '>' which ends the template parameters.  */
diff --git a/libiberty/testsuite/demangle-expected b/libiberty/testsuite/demangle-expected
index 58c1368..6b55d30 100644
--- a/libiberty/testsuite/demangle-expected
+++ b/libiberty/testsuite/demangle-expected
@@ -4081,6 +4081,9 @@  decltype (new auto({parm#1})) f<int>(int)
 --format=gnu-v3
 _Z1fIiERDaRKT_S1_
 auto& f<int>(int const&, int)
+--format=gnu-v3
+_Z1gILi1EEvR1AIXT_EER1BIXscbT_EE
+void g<1>(A<1>&, B<static_cast<bool>(1)>&)
 #
 # Ada (GNAT) tests.
 #
diff --git a/gcc/testsuite/g++.dg/abi/mangle3-2.C b/gcc/testsuite/g++.dg/abi/mangle3-2.C
new file mode 100644
index 0000000..ac85fb0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/mangle3-2.C
@@ -0,0 +1,20 @@ 
+// Test mangling of type casts
+// { dg-options "-fabi-version=0" }
+// { dg-do compile }
+
+template<int i> class A {};
+template<bool b> class B {};
+
+template<int i> void f(A<i> &, B<bool(i)> &) {}
+template<int i> void g(A<i> &, B<static_cast<bool>(i)> &) {}
+
+int main()
+{
+  A<1> a;
+  B<true> b;
+  f(a, b);
+  g(a, b);
+}
+
+// { dg-final { scan-assembler "\n_?_Z1fILi1EEvR1AIXT_EER1BIXcvbT_EE\[: \t\n\]" } }
+// { dg-final { scan-assembler "\n_?_Z1gILi1EEvR1AIXT_EER1BIXscbT_EE\[: \t\n\]" } }
diff --git a/gcc/testsuite/g++.dg/abi/mangle3.C b/gcc/testsuite/g++.dg/abi/mangle3.C
index a20b877..5f44f76 100644
--- a/gcc/testsuite/g++.dg/abi/mangle3.C
+++ b/gcc/testsuite/g++.dg/abi/mangle3.C
@@ -1,4 +1,5 @@ 
 // Test mangling of type casts
+// { dg-options "-fabi-version=2" }
 // { dg-do compile }
 
 template<int i> class A {};
diff --git a/gcc/testsuite/g++.dg/debug/nullptr01.C b/gcc/testsuite/g++.dg/debug/nullptr01.C
index ab08588..63c16ac 100644
--- a/gcc/testsuite/g++.dg/debug/nullptr01.C
+++ b/gcc/testsuite/g++.dg/debug/nullptr01.C
@@ -1,5 +1,5 @@ 
 // Test that debugging backends don't crash on NULLPTR_TYPE.
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++0x -fabi-version=0" }
 
 typedef decltype(nullptr) nullptr_t;
 
@@ -12,4 +12,4 @@  template <> nullptr_t g(A<nullptr_t>)
   nullptr_t local;
 }
 // { dg-final { scan-assembler "_Z1fDn" } }
-// { dg-final { scan-assembler "_Z1gI1AIDnEES1_T_" } }
+// { dg-final { scan-assembler "_Z1gI1AIDnEEDnT_" } }