mangle.c (write_number): Take an unsigned HOST_WIDE_INT as an argument.
authorChip Salzenberg <chip@valinux.com>
Sun, 11 Jun 2000 03:57:18 +0000 (03:57 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Sun, 11 Jun 2000 03:57:18 +0000 (03:57 +0000)
* mangle.c (write_number): Take an unsigned HOST_WIDE_INT as an
argument.
(write_signed_number): New macro.
(write_unsigned_number): Likewise.
(write_source_name): Use them.
(write_number): Handle signed and unsigned values.
(write_integer_cst): Use tree_int_cst_sgn, and use
write_unsigned_number or write_signed_number as appropriate.
(write_discriminator): Use write_unsigned_number or
write_signed_number as appropriate.
(write_template_arg_literal): Likewise.
(write_array_type): Use tree_low_cst.
(write_template_parm):  Use write_unsigned_number or
write_signed_number as appropriate.
(write_substitution): Adjust call to write_number.
(write_type): Get the TYPE_MAIN_VARIANT before mangling it.
(write_expression): Handle non-type template arguments of
reference type correctly.
(mangle_thunk): Use write_signed_number.

* mangle.c (find_substition): Don't mangle objects with typename
substitutions (e.g. "cin" as "Si").

Co-Authored-By: Mark Mitchell <mark@codesourcery.com>
From-SVN: r34488

gcc/cp/ChangeLog
gcc/cp/mangle.c
gcc/testsuite/g++.old-deja/g++.other/crash19.C [new file with mode: 0644]

index 1f570cc9d6e873860f765e43c518ee05013e59cc..f26e03d4c5d16c11ba3111e869048f0b8b3a790a 100644 (file)
@@ -1,3 +1,31 @@
+2000-06-09  Chip Salzenberg  <chip@valinux.com>
+           Mark Mitchell <mark@codesourcery.com>
+
+       * mangle.c (write_number): Take an unsigned HOST_WIDE_INT as an
+       argument.
+       (write_signed_number): New macro.
+       (write_unsigned_number): Likewise.
+       (write_source_name): Use them.
+       (write_number): Handle signed and unsigned values.
+       (write_integer_cst): Use tree_int_cst_sgn, and use
+       write_unsigned_number or write_signed_number as appropriate.
+       (write_discriminator): Use write_unsigned_number or
+       write_signed_number as appropriate.
+       (write_template_arg_literal): Likewise.
+       (write_array_type): Use tree_low_cst.
+       (write_template_parm):  Use write_unsigned_number or
+       write_signed_number as appropriate.
+       (write_substitution): Adjust call to write_number.
+       (write_type): Get the TYPE_MAIN_VARIANT before mangling it.
+       (write_expression): Handle non-type template arguments of
+       reference type correctly.
+       (mangle_thunk): Use write_signed_number.
+
+2000-06-09  Chip Salzenberg  <chip@valinux.com>
+
+       * mangle.c (find_substition): Don't mangle objects with typename
+       substitutions (e.g. "cin" as "Si").
+
 2000-06-09  Zack Weinberg  <zack@wolery.cumb.org>
 
        * call.c (add_candidate): Use ggc_alloc_cleared.
index 2bba09f518b7114877b8d044bd37d504ac1b45de..f4aa12d6ccbeefd4606b55b9aa98eaf2e0dfcbea 100644 (file)
@@ -157,7 +157,8 @@ static void write_template_prefix PARAMS ((tree));
 static void write_component PARAMS ((tree));
 static void write_unqualified_name PARAMS ((tree));
 static void write_source_name PARAMS ((tree));
-static void write_number PARAMS ((int, int));
+static void write_number PARAMS ((unsigned HOST_WIDE_INT, int,
+                                 unsigned int));
 static void write_integer_cst PARAMS ((tree));
 static void write_identifier PARAMS ((char *));
 static void write_special_name_constructor PARAMS ((tree));
@@ -219,6 +220,14 @@ static tree mangle_special_for_type PARAMS ((tree, const char *));
        || TREE_PURPOSE (NODE1) == TREE_PURPOSE (NODE2))             \
    && TREE_VALUE (NODE1) == TREE_VALUE (NODE2))
 
+/* Write out a signed quantity in base 10.  */
+#define write_signed_number(NUMBER) \
+  write_number (NUMBER, /*unsigned_p=*/0, 10)
+
+/* Write out an unsigned quantity in base 10.  */
+#define write_unsigned_number(NUMBER) \
+  write_number (NUMBER, /*unsigned_p=*/1, 10)
+
 /* Produce debugging output of current substitution candidates.  */
 
 static void
@@ -441,7 +450,7 @@ find_substitution (node)
   /* Check for std::basic_string.  */
   if (decl && is_std_substitution (decl, SUBID_BASIC_STRING))
     {
-      if (type)
+      if (TYPE_P (node))
        {
          /* If this is a type (i.e. a fully-qualified template-id), 
             check for 
@@ -473,7 +482,7 @@ find_substitution (node)
     }
 
   /* Check for basic_{i,o,io}stream.  */
-  if (type
+  if (TYPE_P (node)
       && CP_TYPE_QUALS (type) == TYPE_UNQUALIFIED
       && CLASS_TYPE_P (type)
       && CLASSTYPE_USE_TEMPLATE (type)
@@ -510,7 +519,7 @@ find_substitution (node)
     }
 
   /* Check for namespace std.  */
-  if (decl&& DECL_NAMESPACE_STD_P (decl))
+  if (decl && DECL_NAMESPACE_STD_P (decl))
     {
       write_string ("St");
       return 1;
@@ -518,7 +527,6 @@ find_substitution (node)
 
   /* Now check the list of available substitutions for this mangling
      operation.    */
-
   for (i = 0; i < size; ++i)
     {
       tree candidate = VARRAY_TREE (G.substitutions, i);
@@ -604,7 +612,9 @@ static void
 write_name (decl)
      tree decl;
 {
-  tree context = CP_DECL_CONTEXT (decl);
+  tree context;
+
+  context = CP_DECL_CONTEXT (decl);
 
   MANGLE_TRACE_TREE ("name", decl);
 
@@ -913,7 +923,7 @@ write_source_name (identifier)
   if (IDENTIFIER_TEMPLATE (identifier))
     identifier = IDENTIFIER_TEMPLATE (identifier);
 
-  write_number (IDENTIFIER_LENGTH (identifier), 10);
+  write_unsigned_number (IDENTIFIER_LENGTH (identifier));
   write_identifier (IDENTIFIER_POINTER (identifier));
 }
 
@@ -922,20 +932,22 @@ write_source_name (identifier)
      <number> ::= [n] </decimal integer/>  */
 
 static void
-write_number (number, base)
-     int number;
-     int base;
+write_number (number, unsigned_p, base)
+     unsigned HOST_WIDE_INT number;
+     int unsigned_p;
+     unsigned int base;
 {
   static const char digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
-  int n;
-  int m = 1;
+  unsigned HOST_WIDE_INT n;
+  unsigned HOST_WIDE_INT m = 1;
 
-  if (number < 0)
+  if (!unsigned_p && (HOST_WIDE_INT) number < 0)
     {
       write_char ('n');
-      number = -number;
+      number = -((HOST_WIDE_INT) number);
     }
   
+  /* Figure out how many digits there are.  */
   n = number;
   while (n >= base)
     {
@@ -943,6 +955,7 @@ write_number (number, base)
       m *= base;
     }
 
+  /* Write them out.  */
   while (m > 0)
     {
       int digit = number / m;
@@ -960,7 +973,14 @@ static inline void
 write_integer_cst (cst)
      tree cst;
 {
-  write_number (tree_low_cst (cst, TREE_UNSIGNED (TREE_TYPE (cst))), 10);
+  if (tree_int_cst_sgn (cst) >= 0) 
+    {
+      if (TREE_INT_CST_HIGH (cst) != 0)
+       sorry ("mangling very large integers");
+      write_unsigned_number (TREE_INT_CST_LOW (cst));
+    }
+  else
+    write_signed_number (tree_low_cst (cst, 0));
 }
 
 /* Non-terminal <identifier>.
@@ -1086,7 +1106,7 @@ write_discriminator (discriminator)
       /* The number is omitted for discriminator == 1.  Beyond 1, the
         numbering starts at 0.  */
       if (discriminator > 1)
-       write_number (discriminator - 2, 10);
+       write_unsigned_number (discriminator - 2);
     }
 }
 
@@ -1151,7 +1171,7 @@ write_type (type)
 
   if (find_substitution (type))
     return;
-
+  
   if (write_CV_qualifiers_for_type (type) > 0)
     /* If TYPE was CV-qualified, we just wrote the qualifiers; now
        mangle the unqualified type.  The recursive call is needed here
@@ -1159,85 +1179,90 @@ write_type (type)
        candidates.  */
     write_type (TYPE_MAIN_VARIANT (type));
   else
-    switch (TREE_CODE (type))
-      {
-      case VOID_TYPE:
-      case BOOLEAN_TYPE:
-      case INTEGER_TYPE:  /* Includes wchar_t.  */
-      case REAL_TYPE:
-       /* If this is a typedef, TYPE may not be one of
-          the standard builtin type nodes, but an alias of one.  Use
-          TYPE_MAIN_VARIANT to get to the underlying builtin type.  */
-       write_builtin_type (TYPE_MAIN_VARIANT (type));
-       ++is_builtin_type;
-       break;
-
-      case COMPLEX_TYPE:
-       write_char ('C');
-       write_type (TREE_TYPE (type));
-       break;
-
-      case FUNCTION_TYPE:
-      case METHOD_TYPE:
-       write_function_type (type, 1);
-       break;
-
-      case UNION_TYPE:
-      case RECORD_TYPE:
-      case ENUMERAL_TYPE:
-       /* A pointer-to-member function is represented as a special
-          RECORD_TYPE, so check for this first.  */
-       if (TYPE_PTRMEMFUNC_P (type))
-         write_pointer_to_member_type (type);
-       else
-         write_class_enum_type (type);
-       break;
-
-      case TYPENAME_TYPE:
-       /* We handle TYPENAME_TYPEs like ordinary nested names.  */
-       write_nested_name (TYPE_STUB_DECL (type));
-       break;
-
-      case ARRAY_TYPE:
-       write_array_type (type);
-       break;
-
-      case POINTER_TYPE:
-       /* A pointer-to-member variable is represented by a POINTER_TYPE
-          to an OFFSET_TYPE, so check for this first.  */
-       if (TYPE_PTRMEM_P (type))
-         write_pointer_to_member_type (type);
-       else
-         {
-           write_char ('P');
-           write_type (TREE_TYPE (type));
-         }
-       break;
-
-      case REFERENCE_TYPE:
-       write_char ('R');
-       write_type (TREE_TYPE (type));
-       break;
-
-      case TEMPLATE_TYPE_PARM:
-      case TEMPLATE_PARM_INDEX:
-       write_template_param (type);
-       break;
-
-      case TEMPLATE_TEMPLATE_PARM:
-       write_template_template_param (type);
-       if (TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (type))
-         write_template_args 
-           (TI_ARGS (TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (type)));
-       break;
-
-      case OFFSET_TYPE:
-       write_pointer_to_member_type (build_pointer_type (type));
-       break;
-
-      default:
-       my_friendly_abort (20000409);
-      }
+    {
+      /* See through any typedefs.  */
+      type = TYPE_MAIN_VARIANT (type);
+
+      switch (TREE_CODE (type))
+       {
+       case VOID_TYPE:
+       case BOOLEAN_TYPE:
+       case INTEGER_TYPE:  /* Includes wchar_t.  */
+       case REAL_TYPE:
+         /* If this is a typedef, TYPE may not be one of
+            the standard builtin type nodes, but an alias of one.  Use
+            TYPE_MAIN_VARIANT to get to the underlying builtin type.  */
+         write_builtin_type (TYPE_MAIN_VARIANT (type));
+         ++is_builtin_type;
+         break;
+
+       case COMPLEX_TYPE:
+         write_char ('C');
+         write_type (TREE_TYPE (type));
+         break;
+
+       case FUNCTION_TYPE:
+       case METHOD_TYPE:
+         write_function_type (type, 1);
+         break;
+
+       case UNION_TYPE:
+       case RECORD_TYPE:
+       case ENUMERAL_TYPE:
+         /* A pointer-to-member function is represented as a special
+            RECORD_TYPE, so check for this first.  */
+         if (TYPE_PTRMEMFUNC_P (type))
+           write_pointer_to_member_type (type);
+         else
+           write_class_enum_type (type);
+         break;
+
+       case TYPENAME_TYPE:
+         /* We handle TYPENAME_TYPEs like ordinary nested names.  */
+         write_nested_name (TYPE_STUB_DECL (type));
+         break;
+
+       case ARRAY_TYPE:
+         write_array_type (type);
+         break;
+
+       case POINTER_TYPE:
+         /* A pointer-to-member variable is represented by a POINTER_TYPE
+            to an OFFSET_TYPE, so check for this first.  */
+         if (TYPE_PTRMEM_P (type))
+           write_pointer_to_member_type (type);
+         else
+           {
+             write_char ('P');
+             write_type (TREE_TYPE (type));
+           }
+         break;
+
+       case REFERENCE_TYPE:
+         write_char ('R');
+         write_type (TREE_TYPE (type));
+         break;
+
+       case TEMPLATE_TYPE_PARM:
+       case TEMPLATE_PARM_INDEX:
+         write_template_param (type);
+         break;
+
+       case TEMPLATE_TEMPLATE_PARM:
+         write_template_template_param (type);
+         if (TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (type))
+           write_template_args 
+             (TI_ARGS (TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (type)));
+         break;
+
+       case OFFSET_TYPE:
+         write_pointer_to_member_type (build_pointer_type (type));
+         break;
+
+       default:
+         my_friendly_abort (20000409);
+       }
+    }
 
   /* Types other than builtin types are substitution candidates.  */
   if (!is_builtin_type)
@@ -1564,8 +1589,17 @@ write_expression (expr)
       if (TREE_CODE (expr) == ADDR_EXPR
          && TREE_TYPE (expr)
          && TREE_CODE (TREE_TYPE (expr)) == REFERENCE_TYPE)
-       expr = TREE_OPERAND (expr, 0);
+       {
+         expr = TREE_OPERAND (expr, 0);
+         if (DECL_P (expr))
+           {
+             write_expression (expr);
+             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);
 
@@ -1610,9 +1644,9 @@ write_template_arg_literal (value)
       if (same_type_p (type, boolean_type_node))
        {
          if (value == boolean_false_node || integer_zerop (value))
-           write_number (0, 10);
+           write_unsigned_number (0);
          else if (value == boolean_true_node)
-           write_number (1, 10);
+           write_unsigned_number (1);
          else 
            my_friendly_abort (20000412);
        }
@@ -1633,7 +1667,9 @@ write_template_arg_literal (value)
       size_t i;
       for (i = 0; i < sizeof (TREE_REAL_CST (value)); ++i)
        write_number (((unsigned char *) 
-                      &TREE_REAL_CST (value))[i], 16);
+                      &TREE_REAL_CST (value))[i], 
+                     /*unsigned_p=*/1,
+                     16);
 #endif
     }
   else
@@ -1732,7 +1768,7 @@ write_array_type (type)
         array.  */
       max = TYPE_MAX_VALUE (index_type);
       if (TREE_CODE (max) == INTEGER_CST)
-       write_number (TREE_INT_CST_LOW (max) + 1, 10);
+       write_unsigned_number (tree_low_cst (max, 1));
       else
        write_expression (TREE_OPERAND (max, 0));
     }
@@ -1786,7 +1822,7 @@ write_template_param (parm)
   /* NUMBER as it appears in the mangling is (-1)-indexed, with the
      earliest template param denoted by `_'.  */
   if (parm_index > 0)
-    write_number (parm_index - 1, 10);
+    write_unsigned_number (parm_index - 1);
   write_char ('_');
 }
 
@@ -1831,7 +1867,7 @@ write_substitution (seq_id)
 
   write_char ('S');
   if (seq_id > 0)
-    write_number (seq_id - 1, 36);
+    write_number (seq_id - 1, /*unsigned=*/1, 36);
   write_char ('_');
 }
 
@@ -2063,14 +2099,14 @@ mangle_thunk (fn_decl, offset, vcall_offset)
     write_char ('h');
 
   /* For either flavor, write the offset to this.  */
-  write_number (offset, 10);
+  write_signed_number (offset);
   write_char ('_');
 
   /* For a virtual thunk, add the vcall offset.  */
   if (vcall_offset != 0)
     {
       /* Virtual thunk.  Write the vcall offset and base type name.  */
-      write_number (vcall_offset, 10);
+      write_signed_number (vcall_offset);
       write_char ('_');
     }
 
diff --git a/gcc/testsuite/g++.old-deja/g++.other/crash19.C b/gcc/testsuite/g++.old-deja/g++.other/crash19.C
new file mode 100644 (file)
index 0000000..d7ecba8
--- /dev/null
@@ -0,0 +1,12 @@
+// Build don't link:
+// Origin: Mark Mitchell <mark@codesourcery.com>
+
+template <class T>
+struct S {};
+
+struct X {};
+
+void f () {
+  typedef X Y;
+  S<Y> s;
+}