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: Mangling of dependent qualified names


This patch corrects the handling of a number of complex mangling
cases

For most of them, we just crashed; for one, we generated an incorrect
mangling.

Tested on i686-pc-linux-gnu, applied on the mainline.

--
Mark Mitchell                   mark@codesourcery.com
CodeSourcery, LLC               http://www.codesourcery.com

2002-10-15  Mark Mitchell  <mark@codesourcery.com>

	* cp-tree.h (operator_name_info_t): Add arity.
	* lex.c (init_operators): Initialize it.
	* mangle.c (write_conversion_operator_name): New function.
	(write_unqualified_name): Use it.
	(write_template_args): Accept template arguments as a TREE_LIST.
	(write_expression): Adjust handling of qualified names to match
	specification.

Index: cp/cp-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cp-tree.h,v
retrieving revision 1.759
diff -c -5 -p -r1.759 cp-tree.h
*** cp/cp-tree.h	15 Oct 2002 18:06:48 -0000	1.759
--- cp/cp-tree.h	15 Oct 2002 22:54:59 -0000
*************** typedef struct operator_name_info_t
*** 3479,3488 ****
--- 3479,3490 ----
    tree identifier;
    /* The name of the operator.  */
    const char *name;
    /* The mangled name of the operator.  */
    const char *mangled_name;
+   /* The arity of the operator.  */
+   int arity;
  } operator_name_info_t;
  
  /* A mapping from tree codes to operator name information.  */
  extern operator_name_info_t operator_name_info[];
  /* Similar, but for assignment operators.  */
Index: cp/lex.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/lex.c,v
retrieving revision 1.291
diff -c -5 -p -r1.291 lex.c
*** cp/lex.c	21 Sep 2002 12:51:54 -0000	1.291
--- cp/lex.c	15 Oct 2002 22:55:03 -0000
*************** init_operators ()
*** 261,271 ****
    oni = (ASSN_P								    \
  	 ? &assignment_operator_name_info[(int) CODE]			    \
  	 : &operator_name_info[(int) CODE]);				    \
    oni->identifier = identifier;						    \
    oni->name = NAME;							    \
!   oni->mangled_name = MANGLING;
  
  #include "operators.def"
  #undef DEF_OPERATOR
  
    operator_name_info[(int) ERROR_MARK].identifier
--- 261,272 ----
    oni = (ASSN_P								    \
  	 ? &assignment_operator_name_info[(int) CODE]			    \
  	 : &operator_name_info[(int) CODE]);				    \
    oni->identifier = identifier;						    \
    oni->name = NAME;							    \
!   oni->mangled_name = MANGLING;                                             \
!   oni->arity = ARITY;
  
  #include "operators.def"
  #undef DEF_OPERATOR
  
    operator_name_info[(int) ERROR_MARK].identifier
Index: cp/mangle.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/mangle.c,v
retrieving revision 1.60
diff -c -5 -p -r1.60 mangle.c
*** cp/mangle.c	4 Oct 2002 04:59:39 -0000	1.60
--- cp/mangle.c	15 Oct 2002 22:55:04 -0000
*************** static void write_unscoped_name PARAMS (
*** 164,173 ****
--- 164,174 ----
  static void write_unscoped_template_name PARAMS ((tree));
  static void write_nested_name PARAMS ((tree));
  static void write_prefix PARAMS ((tree));
  static void write_template_prefix PARAMS ((tree));
  static void write_unqualified_name PARAMS ((tree));
+ static void write_conversion_operator_name (tree);
  static void write_source_name PARAMS ((tree));
  static int hwint_to_ascii PARAMS ((unsigned HOST_WIDE_INT, unsigned int, char *, unsigned));
  static void write_number PARAMS ((unsigned HOST_WIDE_INT, int,
  				  unsigned int));
  static void write_integer_cst PARAMS ((tree));
*************** write_unqualified_name (decl)
*** 1014,1025 ****
  								NULL);
  	  type = TREE_TYPE (fn_type);
  	}
        else
  	type = TREE_TYPE (DECL_NAME (decl));
!       write_string ("cv");
!       write_type (type);
      }
    else if (DECL_OVERLOADED_OPERATOR_P (decl))
      {
        operator_name_info_t *oni;
        if (DECL_ASSIGNMENT_OPERATOR_P (decl))
--- 1015,1025 ----
  								NULL);
  	  type = TREE_TYPE (fn_type);
  	}
        else
  	type = TREE_TYPE (DECL_NAME (decl));
!       write_conversion_operator_name (type);
      }
    else if (DECL_OVERLOADED_OPERATOR_P (decl))
      {
        operator_name_info_t *oni;
        if (DECL_ASSIGNMENT_OPERATOR_P (decl))
*************** write_unqualified_name (decl)
*** 1031,1040 ****
--- 1031,1049 ----
      }
    else
      write_source_name (DECL_NAME (decl));
  }
  
+ /* Write the unqualified-name for a conversion operator to TYPE.  */
+ 
+ static void
+ write_conversion_operator_name (tree type)
+ {
+   write_string ("cv");
+   write_type (type);
+ }
+ 
  /* Non-termial <source-name>.  IDENTIFIER is an IDENTIFIER_NODE.  
  
       <source-name> ::= </length/ number> <identifier>  */
  
  static void
*************** write_class_enum_type (type)
*** 1778,1815 ****
  
  static void
  write_template_args (args)
       tree args;
  {
-   int i;
-   int length = TREE_VEC_LENGTH (args);
- 
    MANGLE_TRACE_TREE ("template-args", args);
  
!   my_friendly_assert (length > 0, 20000422);
  
!   if (TREE_CODE (TREE_VEC_ELT (args, 0)) == TREE_VEC)
      {
!       /* We have nested template args.  We want the innermost template
! 	 argument list.  */
!       args = TREE_VEC_ELT (args, length - 1);
!       length = TREE_VEC_LENGTH (args);
      }
  
-   write_char ('I');
-   for (i = 0; i < length; ++i)
-     write_template_arg (TREE_VEC_ELT (args, i));
    write_char ('E');
  }
  
  /* <expression> ::= <unary operator-name> <expression>
  		::= <binary operator-name> <expression> <expression>
  		::= <expr-primary>
  
     <expr-primary> ::= <template-param>
  		  ::= L <type> <value number> E  # literal
! 		  ::= L <mangled-name> E         # external name  */
  
  static void
  write_expression (expr)
       tree expr;
  {
--- 1787,1839 ----
  
  static void
  write_template_args (args)
       tree args;
  {
    MANGLE_TRACE_TREE ("template-args", args);
  
!   write_char ('I');
  
!   if (TREE_CODE (args) == TREE_VEC)
      {
!       int i;
!       int length = TREE_VEC_LENGTH (args);
!       my_friendly_assert (length > 0, 20000422);
! 
!       if (TREE_CODE (TREE_VEC_ELT (args, 0)) == TREE_VEC)
! 	{
! 	  /* We have nested template args.  We want the innermost template
! 	     argument list.  */
! 	  args = TREE_VEC_ELT (args, length - 1);
! 	  length = TREE_VEC_LENGTH (args);
! 	}
!       for (i = 0; i < length; ++i)
! 	write_template_arg (TREE_VEC_ELT (args, i));
!     }
!   else 
!     {
!       my_friendly_assert (TREE_CODE (args) == TREE_LIST, 20021014);
! 
!       while (args)
! 	{
! 	  write_template_arg (TREE_VALUE (args));
! 	  args = TREE_CHAIN (args);
! 	}
      }
  
    write_char ('E');
  }
  
  /* <expression> ::= <unary operator-name> <expression>
  		::= <binary operator-name> <expression> <expression>
  		::= <expr-primary>
  
     <expr-primary> ::= <template-param>
  		  ::= L <type> <value number> E  # literal
! 		  ::= L <mangled-name> E         # external name  
!                   ::= sr <type> <unqualified-name>
!                   ::= sr <type> <unqualified-name> <template-args> */
  
  static void
  write_expression (expr)
       tree expr;
  {
*************** write_expression (expr)
*** 1857,1866 ****
--- 1881,1959 ----
  	   && TYPE_P (TREE_OPERAND (expr, 0)))
      {
        write_string ("st");
        write_type (TREE_OPERAND (expr, 0));
      }
+   else if (abi_version_at_least (2) && TREE_CODE (expr) == SCOPE_REF)
+     {
+       tree scope = TREE_OPERAND (expr, 0);
+       tree member = TREE_OPERAND (expr, 1);
+ 
+       /* If the MEMBER is a real declaration, then the qualifying
+ 	 scope was not dependent.  Ideally, we would not have a
+ 	 SCOPE_REF in those cases, but sometimes we do.  If the second
+ 	 argument is a DECL, then the name must not have been
+ 	 dependent.  */
+       if (DECL_P (member))
+ 	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);
+ 	      if (TREE_CODE (member) == LOOKUP_EXPR)
+ 		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 < LAST_CPLUS_TREE_CODE; ++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);
+ 	}
+     }
    else
      {
        int i;
  
        /* When we bind a variable or function to a non-type template
*************** write_expression (expr)
*** 1878,1888 ****
  	      return;
  	    }
  
  	  code = TREE_CODE (expr);
  	}
!       
        /* If it wasn't any of those, recursively expand the expression.  */
        write_string (operator_name_info[(int) code].mangled_name);
  
        switch (code)
  	{
--- 1971,1981 ----
  	      return;
  	    }
  
  	  code = TREE_CODE (expr);
  	}
! 
        /* If it wasn't any of those, recursively expand the expression.  */
        write_string (operator_name_info[(int) code].mangled_name);
  
        switch (code)
  	{
*************** write_expression (expr)
*** 1902,1912 ****
  	case SCOPE_REF:
  	  write_type (TREE_OPERAND (expr, 0));
  	  if (TREE_CODE (TREE_OPERAND (expr, 1)) == IDENTIFIER_NODE)
  	    write_source_name (TREE_OPERAND (expr, 1));
  	  else
! 	    write_encoding (TREE_OPERAND (expr, 1));
  	  break;
  
  	default:
  	  for (i = 0; i < TREE_CODE_LENGTH (code); ++i)
  	    write_expression (TREE_OPERAND (expr, i));
--- 1995,2010 ----
  	case SCOPE_REF:
  	  write_type (TREE_OPERAND (expr, 0));
  	  if (TREE_CODE (TREE_OPERAND (expr, 1)) == IDENTIFIER_NODE)
  	    write_source_name (TREE_OPERAND (expr, 1));
  	  else
! 	    {
! 	      /* G++ 3.2 incorrectly put out both the "sr" code and
! 		 the nested name of the qualified name.  */
! 	      G.need_abi_warning = 1;
! 	      write_encoding (TREE_OPERAND (expr, 1));
! 	    }
  	  break;
  
  	default:
  	  for (i = 0; i < TREE_CODE_LENGTH (code); ++i)
  	    write_expression (TREE_OPERAND (expr, i));
Index: testsuite/ChangeLog
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/ChangeLog,v
retrieving revision 1.2144
diff -c -5 -p -r1.2144 ChangeLog
*** testsuite/ChangeLog	15 Oct 2002 18:07:24 -0000	1.2144
--- testsuite/ChangeLog	15 Oct 2002 22:55:09 -0000
***************
*** 1,9 ****
  2002-10-14  Mark Mitchell  <mark@codesourcery.com>
  
  	* g++.dg/abi/empty8.C: New test.
! 
  2002-10-15  Nathan Sidwell  <nathan@codesourcery.com>
  
  	* g++.dg/init/ctor1.C: New test.
  
  2002-10-15  Ulrich Weigand  <uweigand@de.ibm.com>
--- 1,15 ----
+ 2002-10-15  Mark Mitchell  <mark@codesourcery.com>
+ 
+ 	* g++.dg/abi/mangle13.C: Likewise.
+ 	* g++.dg/abi/mangle14.C: Likewise.
+ 	* g++.dg/abi/mangle15.C: Likewise.
+ 
  2002-10-14  Mark Mitchell  <mark@codesourcery.com>
  
  	* g++.dg/abi/empty8.C: New test.
! 	
  2002-10-15  Nathan Sidwell  <nathan@codesourcery.com>
  
  	* g++.dg/init/ctor1.C: New test.
  
  2002-10-15  Ulrich Weigand  <uweigand@de.ibm.com>
Index: testsuite/g++.dg/abi/mangle13.C
===================================================================
RCS file: testsuite/g++.dg/abi/mangle13.C
diff -N testsuite/g++.dg/abi/mangle13.C
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/abi/mangle13.C	15 Oct 2002 22:55:09 -0000
***************
*** 0 ****
--- 1,28 ----
+ // { dg-options "-fabi-version=0" }
+ 
+ struct A {
+   template <typename T> int f ();
+   int operator+();
+   operator int ();
+   template <typename T> 
+   int operator-();
+ };
+ 
+ typedef int (A::*P)();
+ 
+ template <P> struct S {};
+ 
+ template <typename T> void g (S<&T::template f<int> >) {}
+ template <typename T> void g (S<&T::operator+ >) {}
+ template <typename T> void g (S<&T::operator int>) {}
+ template <typename T> void g (S<&T::template operator- <double> >) {}
+ 
+ template void g<A> (S<&A::f<int> >);
+ template void g<A> (S<&A::operator+>);
+ template void g<A> (S<&A::operator int>);
+ template void g<A> (S<&A::operator-<double> >);
+ 
+ // { dg-final { scan-assembler _Z1gI1AEv1SIXadsrT_1fIiEEE } }
+ // { dg-final { scan-assembler _Z1gI1AEv1SIXadsrT_plEE } }
+ // { dg-final { scan-assembler _Z1gI1AEv1SIXadsrT_cviEE } }
+ // { dg-final { scan-assembler _Z1gI1AEv1SIXadsrT_miIdEEE } }
Index: testsuite/g++.dg/abi/mangle14.C
===================================================================
RCS file: testsuite/g++.dg/abi/mangle14.C
diff -N testsuite/g++.dg/abi/mangle14.C
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/abi/mangle14.C	15 Oct 2002 22:55:09 -0000
***************
*** 0 ****
--- 1,12 ----
+ // { dg-do compile }
+ // { dg-options "-Wabi" }
+ 
+ struct A {
+   template <typename T> int f ();
+ };
+ 
+ typedef int (A::*P)();
+ 
+ template <P> struct S {};
+ 
+ void g (S<&A::f<int> >) {} // { dg-warning "mangle" }
Index: testsuite/g++.dg/abi/mangle15.C
===================================================================
RCS file: testsuite/g++.dg/abi/mangle15.C
diff -N testsuite/g++.dg/abi/mangle15.C
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/abi/mangle15.C	15 Oct 2002 22:55:09 -0000
***************
*** 0 ****
--- 1,14 ----
+ // { dg-do compile }
+ // { dg-options "-fabi-version=0" }
+ 
+ struct A {
+   template <typename T> int f ();
+ };
+ 
+ typedef int (A::*P)();
+ 
+ template <P> struct S {};
+ 
+ void g (S<&A::f<int> >) {}
+ 
+ // { dg-final { scan-assembler _Z1g1SIXadL_ZN1A1fIiEEivEEE } }


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