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]

C++ PATCH: Two mangling patches (template-ids and vectors)


I've previously discussed how to manage vector mangling; the patch I'm checking in now only enables the new mangling with -fabi-version=4 (or =0), though I hope to implement a transition scheme for 4.5.

The other patch fixes a problem whereby we were unable to mangle a return type like decltype(f<T>(args)), which people writing C++0x have been running into a fail amount. I've waited a while for feedback on the ABI list, but haven't gotten any, so I'm just going to go ahead.

Tested x86_64-pc-linux-gnu, applied to trunk.
commit fe2c6a532c188a242d8f5e03b4f7656bb8758de3
Author: Jason Merrill <jason@redhat.com>
Date:   Mon Dec 21 18:46:33 2009 -0500

    	PR c++/4926
    	PR c++/38600
    	* mangle.c (write_unqualified_id): Split out from write_expression.
    	(write_unqualified_name): Call it.
    	(write_member_name): Likewise.
    	(write_expression): Support TEMPLATE_ID_EXPR.
    	Disambiguate operator names.

diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c
index 37293f1..ca15dab 100644
--- a/gcc/cp/mangle.c
+++ b/gcc/cp/mangle.c
@@ -1117,10 +1117,55 @@ write_template_prefix (const tree node)
     <local-source-name>	::= L <source-name> <discriminator> */
 
 static void
+write_unqualified_id (tree identifier)
+{
+  if (IDENTIFIER_TYPENAME_P (identifier))
+    write_conversion_operator_name (TREE_TYPE (identifier));
+  else if (IDENTIFIER_OPNAME_P (identifier))
+    {
+      int i;
+      const char *mangled_name = NULL;
+
+      /* Unfortunately, there is no easy way to go from the
+	 name of the operator back to the corresponding tree
+	 code.  */
+      for (i = 0; i < MAX_TREE_CODES; ++i)
+	if (operator_name_info[i].identifier == identifier)
+	  {
+	    /* The ABI says that we prefer binary operator
+	       names to unary operator names.  */
+	    if (operator_name_info[i].arity == 2)
+	      {
+		mangled_name = operator_name_info[i].mangled_name;
+		break;
+	      }
+	    else if (!mangled_name)
+	      mangled_name = operator_name_info[i].mangled_name;
+	  }
+	else if (assignment_operator_name_info[i].identifier
+		 == identifier)
+	  {
+	    mangled_name
+	      = assignment_operator_name_info[i].mangled_name;
+	    break;
+	  }
+      write_string (mangled_name);
+    }
+  else
+    write_source_name (identifier);
+}
+
+static void
 write_unqualified_name (const tree decl)
 {
   MANGLE_TRACE_TREE ("unqualified-name", decl);
 
+  if (TREE_CODE (decl) == IDENTIFIER_NODE)
+    {
+      write_unqualified_id (decl);
+      return;
+    }
+
   if (DECL_NAME (decl) == NULL_TREE)
     {
       gcc_assert (DECL_ASSEMBLER_NAME_SET_P (decl));
@@ -2312,7 +2357,7 @@ static void
 write_member_name (tree member)
 {
   if (TREE_CODE (member) == IDENTIFIER_NODE)
-    write_source_name (member);
+    write_unqualified_id (member);
   else if (DECL_P (member))
     write_unqualified_name (member);
   else if (TREE_CODE (member) == TEMPLATE_ID_EXPR)
@@ -2435,57 +2480,9 @@ write_expression (tree expr)
 	write_expression (member);
       else
 	{
-	  tree template_args;
-
 	  write_string ("sr");
 	  write_type (scope);
-	  /* If MEMBER is a template-id, separate the template
-	     from the arguments.  */
-	  if (TREE_CODE (member) == TEMPLATE_ID_EXPR)
-	    {
-	      template_args = TREE_OPERAND (member, 1);
-	      member = TREE_OPERAND (member, 0);
-	    }
-	  else
-	    template_args = NULL_TREE;
-	  /* Write out the name of the MEMBER.  */
-	  if (IDENTIFIER_TYPENAME_P (member))
-	    write_conversion_operator_name (TREE_TYPE (member));
-	  else if (IDENTIFIER_OPNAME_P (member))
-	    {
-	      int i;
-	      const char *mangled_name = NULL;
-
-	      /* Unfortunately, there is no easy way to go from the
-		 name of the operator back to the corresponding tree
-		 code.  */
-	      for (i = 0; i < MAX_TREE_CODES; ++i)
-		if (operator_name_info[i].identifier == member)
-		  {
-		    /* The ABI says that we prefer binary operator
-		       names to unary operator names.  */
-		    if (operator_name_info[i].arity == 2)
-		      {
-			mangled_name = operator_name_info[i].mangled_name;
-			break;
-		      }
-		    else if (!mangled_name)
-		      mangled_name = operator_name_info[i].mangled_name;
-		  }
-		else if (assignment_operator_name_info[i].identifier
-			 == member)
-		  {
-		    mangled_name
-		      = assignment_operator_name_info[i].mangled_name;
-		    break;
-		  }
-	      write_string (mangled_name);
-	    }
-	  else
-	    write_source_name (member);
-	  /* Write out the template arguments.  */
-	  if (template_args)
-	    write_template_args (template_args);
+	  write_member_name (member);
 	}
     }
   else if (TREE_CODE (expr) == INDIRECT_REF
@@ -2494,6 +2491,25 @@ write_expression (tree expr)
     {
       write_expression (TREE_OPERAND (expr, 0));
     }
+  else if (TREE_CODE (expr) == IDENTIFIER_NODE)
+    {
+      /* An operator name appearing as a dependent name needs to be
+	 specially marked to disambiguate between a use of the operator
+	 name and a use of the operator in an expression.  */
+      if (IDENTIFIER_OPNAME_P (expr))
+	write_string ("on");
+      write_unqualified_id (expr);
+    }
+  else if (TREE_CODE (expr) == TEMPLATE_ID_EXPR)
+    {
+      tree fn = TREE_OPERAND (expr, 0);
+      if (is_overloaded_fn (fn))
+	fn = DECL_NAME (get_first_fn (fn));
+      if (IDENTIFIER_OPNAME_P (fn))
+	write_string ("on");
+      write_unqualified_id (fn);
+      write_template_args (TREE_OPERAND (expr, 1));
+    }
   else
     {
       int i, len;
@@ -2560,10 +2576,7 @@ write_expression (tree expr)
 		&& type_dependent_expression_p_push (expr))
 	      fn = DECL_NAME (get_first_fn (fn));
 
-	    if (TREE_CODE (fn) == IDENTIFIER_NODE)
-	      write_source_name (fn);
-	    else
-	      write_expression (fn);
+	    write_expression (fn);
 	  }
 
 	  for (i = 0; i < call_expr_nargs (expr); ++i)
diff --git a/gcc/testsuite/g++.dg/abi/mangle35.C b/gcc/testsuite/g++.dg/abi/mangle35.C
new file mode 100644
index 0000000..78d9933
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/mangle35.C
@@ -0,0 +1,13 @@
+// PR c++/38600
+// { dg-final { scan-assembler "_Z3barIiE1AIX3fooIT_EEEv" } }
+
+template<void (*)()> struct A {};
+
+template<typename> void foo();
+
+template<typename T> A<foo<T> > bar();
+
+void baz()
+{
+  bar<int>();
+}
diff --git a/gcc/testsuite/g++.dg/abi/mangle37.C b/gcc/testsuite/g++.dg/abi/mangle37.C
new file mode 100644
index 0000000..7270861
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/mangle37.C
@@ -0,0 +1,35 @@
+// Testcase for mangling of expressions involving operator names.
+// { dg-options -std=c++0x }
+// { dg-final { scan-assembler "_Z1fI1AEDTclonplfp_fp_EET_" } }
+// { dg-final { scan-assembler "_Z1gI1AEDTclonplIT_Efp_fp_EES1_" } }
+// { dg-final { scan-assembler "_Z1hI1AEDTcldtfp_miEET_" } }
+// { dg-final { scan-assembler "_Z1iI1AEDTcldtfp_srT_miEES1_" } }
+// { dg-final { scan-assembler "_Z1jI1AEDTcldtfp_cvPT_EES1_" } }
+
+struct A {
+  void operator-();
+  template <class T>
+  operator T();
+};
+template <class T>
+T operator+(T,T);
+
+template <class T>
+auto f (T t) -> decltype(operator+(t,t));
+template <class T>
+auto g (T t) -> decltype(operator+<T>(t,t));
+template <class T>
+auto h (T t) -> decltype(t.operator-());
+template <class T>
+auto i (T t) -> decltype(t.T::operator-());
+template <class T>
+auto j (T t) -> decltype(t.operator T*());
+
+int main()
+{
+  f(A());
+  g(A());
+  h(A());
+  i(A());
+  j(A());
+}
diff --git a/libiberty/cp-demangle.c b/libiberty/cp-demangle.c
index 75706b3..b1319cf 100644
--- a/libiberty/cp-demangle.c
+++ b/libiberty/cp-demangle.c
@@ -2722,11 +2722,18 @@ d_expression (struct d_info *di)
 
       return d_make_function_param (di, index);
     }
-  else if (IS_DIGIT (peek))
+  else if (IS_DIGIT (peek)
+	   || (peek == 'o' && d_peek_next_char (di) == 'n'))
     {
       /* We can get an unqualified name as an expression in the case of
-         a dependent member access, i.e. decltype(T().i).  */
-      struct demangle_component *name = d_unqualified_name (di);
+         a dependent function call, i.e. decltype(f(t)).  */
+      struct demangle_component *name;
+
+      if (peek == 'o')
+	/* operator-function-id, i.e. operator+(t).  */
+	d_advance (di, 2);
+
+      name = d_unqualified_name (di);
       if (name == NULL)
 	return NULL;
       if (d_peek_char (di) == 'I')
@@ -2784,10 +2791,18 @@ d_expression (struct d_info *di)
 	  {
 	    struct demangle_component *left;
 	    struct demangle_component *right;
+	    const char *code = op->u.s_operator.op->code;
 
 	    left = d_expression (di);
-	    if (!strcmp (op->u.s_operator.op->code, "cl"))
+	    if (!strcmp (code, "cl"))
 	      right = d_exprlist (di);
+	    else if (!strcmp (code, "dt") || !strcmp (code, "pt"))
+	      {
+		right = d_unqualified_name (di);
+		if (d_peek_char (di) == 'I')
+		  right = d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE,
+				       right, d_template_args (di));
+	      }
 	    else
 	      right = d_expression (di);
 
diff --git a/libiberty/testsuite/demangle-expected b/libiberty/testsuite/demangle-expected
index 3662f16..0f85ddc 100644
--- a/libiberty/testsuite/demangle-expected
+++ b/libiberty/testsuite/demangle-expected
@@ -3932,6 +3932,11 @@ f(float vector[32])
 --format=gnu-v3
 _Z1fIfLi4EEvDv_T0__T_
 void f<float, 4>(float vector[4])
+_Z1fI1AEDTclonplfp_fp_EET_
+decltype ((operator+)({parm#1}, {parm#1})) f<A>(A)
+--format=gnu-v3
+_Z1hI1AEDTcldtfp_miEET_
+decltype (({parm#1}.(operator-))()) h<A>(A)
 #
 # Ada (GNAT) tests.
 #
commit 159370f661add7a9301f8b8441428c945cac81f2
Author: Jason Merrill <jason@redhat.com>
Date:   Tue Nov 10 18:09:57 2009 -0500

    	PR c++/12909
    	* mangle.c (write_type) [VECTOR_TYPE]: Change mangling.

diff --git a/gcc/common.opt b/gcc/common.opt
index 6e369e5..a4358b5 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -266,7 +266,13 @@ Common Separate
 ;
 ; 1: The version of the ABI first used in G++ 3.2.
 ;
-; 2: The version of the ABI first used in G++ 3.4.
+; 2: The version of the ABI first used in G++ 3.4 (and current default).
+;
+; 3: The version of the ABI that fixes the missing underscore
+;    in template non-type arguments of pointer type.
+;
+; 4: The version of the ABI that introduces unambiguous mangling of
+;    vector types.
 ;
 ; Additional positive integers will be assigned as new versions of
 ; the ABI become the default version of the ABI.
diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c
index c14f5b7..37293f1 100644
--- a/gcc/cp/mangle.c
+++ b/gcc/cp/mangle.c
@@ -1850,7 +1850,16 @@ write_type (tree type)
 	      break;
 
 	    case VECTOR_TYPE:
-	      write_string ("U8__vector");
+	      if (abi_version_at_least (4))
+		{
+		  write_string ("Dv");
+		  /* Non-constant vector size would be encoded with
+		     _ expression, but we don't support that yet.  */
+		  write_unsigned_number (TYPE_VECTOR_SUBPARTS (type));
+		  write_char ('_');
+		}
+	      else
+		write_string ("U8__vector");
 	      write_type (TREE_TYPE (type));
 	      break;
 
diff --git a/gcc/testsuite/g++.dg/abi/mangle36.C b/gcc/testsuite/g++.dg/abi/mangle36.C
new file mode 100644
index 0000000..aaace65
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/mangle36.C
@@ -0,0 +1,9 @@
+// PR c++/41959
+// { dg-do compile { target i?86-*-* x86_64-*-* } }
+// { dg-options "-mavx -fabi-version=4" }
+// { dg-final { scan-assembler "_Z1fDv4_f" } }
+// { dg-final { scan-assembler "_Z1fDv8_f" } }
+
+#include <x86intrin.h>
+void f(__m128) { }
+void f(__m256) { }
diff --git a/include/demangle.h b/include/demangle.h
index 2ab2760..8ad073d 100644
--- a/include/demangle.h
+++ b/include/demangle.h
@@ -326,6 +326,9 @@ enum demangle_component_type
   DEMANGLE_COMPONENT_PTRMEM_TYPE,
   /* A fixed-point type.  */
   DEMANGLE_COMPONENT_FIXED_TYPE,
+  /* A vector type.  The left subtree is the number of elements,
+     the right subtree is the element type.  */
+  DEMANGLE_COMPONENT_VECTOR_TYPE,
   /* An argument list.  The left subtree is the current argument, and
      the right subtree is either NULL or another ARGLIST node.  */
   DEMANGLE_COMPONENT_ARGLIST,
@@ -378,6 +381,8 @@ enum demangle_component_type
   DEMANGLE_COMPONENT_COMPOUND_NAME,
   /* A name formed by a single character.  */
   DEMANGLE_COMPONENT_CHARACTER,
+  /* A number.  */
+  DEMANGLE_COMPONENT_NUMBER,
   /* A decltype type.  */
   DEMANGLE_COMPONENT_DECLTYPE,
   /* Global constructors keyed to name.  */
diff --git a/libiberty/cp-demangle.c b/libiberty/cp-demangle.c
index 2f4d0cc..75706b3 100644
--- a/libiberty/cp-demangle.c
+++ b/libiberty/cp-demangle.c
@@ -389,6 +389,8 @@ d_class_enum_type (struct d_info *);
 
 static struct demangle_component *d_array_type (struct d_info *);
 
+static struct demangle_component *d_vector_type (struct d_info *);
+
 static struct demangle_component *
 d_pointer_to_member_type (struct d_info *);
 
@@ -796,6 +798,7 @@ d_make_comp (struct d_info *di, enum demangle_component_type type,
     case DEMANGLE_COMPONENT_LITERAL:
     case DEMANGLE_COMPONENT_LITERAL_NEG:
     case DEMANGLE_COMPONENT_COMPOUND_NAME:
+    case DEMANGLE_COMPONENT_VECTOR_TYPE:
       if (left == NULL || right == NULL)
 	return NULL;
       break;
@@ -1442,6 +1445,20 @@ d_number (struct d_info *di)
     }
 }
 
+/* Like d_number, but returns a demangle_component.  */
+
+static struct demangle_component *
+d_number_component (struct d_info *di)
+{
+  struct demangle_component *ret = d_make_empty (di);
+  if (ret)
+    {
+      ret->type = DEMANGLE_COMPONENT_NUMBER;
+      ret->u.s_number.number = d_number (di);
+    }
+  return ret;
+}
+
 /* identifier ::= <(unqualified source code identifier)>  */
 
 static struct demangle_component *
@@ -2200,6 +2217,10 @@ cplus_demangle_type (struct d_info *di)
 	  ret->u.s_fixed.sat = (peek == 's');
 	  break;
 
+	case 'v':
+	  ret = d_vector_type (di);
+	  break;
+
 	default:
 	  return NULL;
 	}
@@ -2418,6 +2439,34 @@ d_array_type (struct d_info *di)
 		      cplus_demangle_type (di));
 }
 
+/* <vector-type> ::= Dv <number> _ <type>
+                 ::= Dv _ <expression> _ <type> */
+
+static struct demangle_component *
+d_vector_type (struct d_info *di)
+{
+  char peek;
+  struct demangle_component *dim;
+
+  peek = d_peek_char (di);
+  if (peek == '_')
+    {
+      d_advance (di, 1);
+      dim = d_expression (di);
+    }
+  else
+    dim = d_number_component (di);
+
+  if (dim == NULL)
+    return NULL;
+
+  if (! d_check_char (di, '_'))
+    return NULL;
+
+  return d_make_comp (di, DEMANGLE_COMPONENT_VECTOR_TYPE, dim,
+		      cplus_demangle_type (di));
+}
+
 /* <pointer-to-member-type> ::= M <(class) type> <(member) type>  */
 
 static struct demangle_component *
@@ -3930,6 +3979,7 @@ d_print_comp (struct d_print_info *dpi,
       }
 
     case DEMANGLE_COMPONENT_PTRMEM_TYPE:
+    case DEMANGLE_COMPONENT_VECTOR_TYPE:
       {
 	struct d_print_mod dpm;
 
@@ -3944,11 +3994,7 @@ d_print_comp (struct d_print_info *dpi,
 	/* If the modifier didn't get printed by the type, print it
 	   now.  */
 	if (! dpm.printed)
-	  {
-	    d_append_char (dpi, ' ');
-	    d_print_comp (dpi, d_left (dc));
-	    d_append_string (dpi, "::*");
-	  }
+	  d_print_mod (dpi, dc);
 
 	dpi->modifiers = dpm.next;
 
@@ -4168,6 +4214,10 @@ d_print_comp (struct d_print_info *dpi,
       }
       return;
 
+    case DEMANGLE_COMPONENT_NUMBER:
+      d_append_num (dpi, dc->u.s_number.number);
+      return;
+
     case DEMANGLE_COMPONENT_JAVA_RESOURCE:
       d_append_string (dpi, "java resource ");
       d_print_comp (dpi, d_left (dc));
@@ -4440,6 +4490,12 @@ d_print_mod (struct d_print_info *dpi,
     case DEMANGLE_COMPONENT_TYPED_NAME:
       d_print_comp (dpi, d_left (mod));
       return;
+    case DEMANGLE_COMPONENT_VECTOR_TYPE:
+      d_append_string (dpi, " vector[");
+      d_print_comp (dpi, d_left (mod));
+      d_append_char (dpi, ']');
+      return;
+
     default:
       /* Otherwise, we have something that won't go back on the
 	 modifier stack, so we can just print it.  */
diff --git a/libiberty/testsuite/demangle-expected b/libiberty/testsuite/demangle-expected
index eaa7ca9..3662f16 100644
--- a/libiberty/testsuite/demangle-expected
+++ b/libiberty/testsuite/demangle-expected
@@ -3926,6 +3926,12 @@ S<int>::x::{lambda()#3}::operator()() const
 --format=gnu-v3
 _Z1fN1SUt_E
 f(S::{unnamed type#1})
+--format=gnu-v3
+_Z1fDv32_f
+f(float vector[32])
+--format=gnu-v3
+_Z1fIfLi4EEvDv_T0__T_
+void f<float, 4>(float vector[4])
 #
 # Ada (GNAT) tests.
 #

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