OSDN Git Service

* configure: Regenerate.
[pf3gnuchains/gcc-fork.git] / gcc / cp / mangle.c
index b070122..7377a3e 100644 (file)
@@ -1,13 +1,13 @@
 /* Name mangling for the 3.0 C++ ABI.
-   Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005
+   Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2007
    Free Software Foundation, Inc.
-   Written by Alex Samuel <sameul@codesourcery.com>
+   Written by Alex Samuel <samuel@codesourcery.com>
 
    This file is part of GCC.
 
    GCC is free software; you can redistribute it and/or modify it
    under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2, or (at your option)
+   the Free Software Foundation; either version 3, or (at your option)
    any later version.
 
    GCC is distributed in the hope that it will be useful, but
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    General Public License for more details.
 
-   You should have received a copy of the GNU General Public License
-   along with GCC; see the file COPYING.  If not, write to the Free
-   Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
-   02110-1301, USA.  */
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
 
 /* This file implements mangling of C++ names according to the IA64
    C++ ABI specification.  A mangled name encodes a function or
@@ -44,9 +43,7 @@
      mangle_vtbl_for_type:             virtual table data
      mangle_vtt_for_type:              VTT data
      mangle_ctor_vtbl_for_type:                `C-in-B' constructor virtual table data
-     mangle_thunk:                     thunk function or entry
-
-*/
+     mangle_thunk:                     thunk function or entry  */
 
 #include "config.h"
 #include "system.h"
@@ -276,7 +273,7 @@ save_partially_mangled_name (void)
     {
       gcc_assert (!partially_mangled_name);
       partially_mangled_name_len = obstack_object_size (mangle_obstack);
-      partially_mangled_name = xmalloc (partially_mangled_name_len);
+      partially_mangled_name = XNEWVEC (char, partially_mangled_name_len);
       memcpy (partially_mangled_name, obstack_base (mangle_obstack),
              partially_mangled_name_len);
       obstack_free (mangle_obstack, obstack_finish (mangle_obstack));
@@ -690,7 +687,8 @@ write_mangled_name (const tree decl, bool top_level)
        }
     }
   else if (TREE_CODE (decl) == VAR_DECL
-          /* The names of global variables aren't mangled.  */
+          /* The names of non-static global variables aren't mangled.  */
+          && DECL_EXTERNAL_LINKAGE_P (decl)
           && (CP_DECL_CONTEXT (decl) == global_namespace
               /* And neither are `extern "C"' variables.  */
               || DECL_EXTERN_C_P (decl)))
@@ -1088,7 +1086,10 @@ write_template_prefix (const tree node)
 
     <unqualified-name>  ::= <operator-name>
                        ::= <special-name>
-                       ::= <source-name>  */
+                       ::= <source-name>
+                       ::= <local-source-name> 
+
+    <local-source-name>        ::= L <source-name> <discriminator> */
 
 static void
 write_unqualified_name (const tree decl)
@@ -1128,6 +1129,16 @@ write_unqualified_name (const tree decl)
 
       write_string (oni[DECL_OVERLOADED_OPERATOR_P (decl)].mangled_name);
     }
+  else if (VAR_OR_FUNCTION_DECL_P (decl) && ! TREE_PUBLIC (decl)
+          && DECL_NAMESPACE_SCOPE_P (decl)
+          && decl_linkage (decl) == lk_internal)
+    {
+      MANGLE_TRACE_TREE ("local-source-name", decl);
+      write_char ('L');
+      write_source_name (DECL_NAME (decl));
+      /* The default discriminator is 1, and that's all we ever use,
+        so there's no code to output one here.  */
+    }
   else
     write_source_name (DECL_NAME (decl));
 }
@@ -1328,7 +1339,7 @@ write_real_cst (const tree value)
 
       for (; i != limit; i += dir)
        {
-         sprintf (buffer, "%08lx", target_real[i]);
+         sprintf (buffer, "%08lx", (unsigned long) target_real[i]);
          write_chars (buffer, 8);
        }
     }
@@ -1529,6 +1540,13 @@ write_local_name (const tree function, const tree local_entity,
            ::= G <type>    # imaginary (C 2000)     [not supported]
            ::= U <source-name> <type>   # vendor extended type qualifier
 
+   C++0x extensions
+
+     <type> ::= RR <type>   # rvalue reference-to
+     <type> ::= Dt <expression> # decltype of an id-expression or 
+                                # class member access
+     <type> ::= DT <expression> # decltype of an expression
+
    TYPE is a type node.  */
 
 static void
@@ -1559,21 +1577,18 @@ write_type (tree type)
     write_array_type (type);
   else
     {
+      tree type_orig = type;
+
       /* See through any typedefs.  */
       type = TYPE_MAIN_VARIANT (type);
 
       if (TYPE_PTRMEM_P (type))
        write_pointer_to_member_type (type);
-      else switch (TREE_CODE (type))
-       {
-       case VOID_TYPE:
-       case BOOLEAN_TYPE:
-       case INTEGER_TYPE:  /* Includes wchar_t.  */
-       case REAL_TYPE:
-       {
+      else
+        {
          /* Handle any target-specific fundamental types.  */
          const char *target_mangling
-           = targetm.mangle_fundamental_type (type);
+           = targetm.mangle_type (type_orig);
 
          if (target_mangling)
            {
@@ -1581,74 +1596,104 @@ write_type (tree type)
              return;
            }
 
-         /* 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);
-         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:
-       case UNBOUND_CLASS_TEMPLATE:
-         /* We handle TYPENAME_TYPEs and UNBOUND_CLASS_TEMPLATEs like
-            ordinary nested names.  */
-         write_nested_name (TYPE_STUB_DECL (type));
-         break;
-
-       case POINTER_TYPE:
-         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);
-         break;
-
-       case BOUND_TEMPLATE_TEMPLATE_PARM:
-         write_template_template_param (type);
-         write_template_args
-           (TI_ARGS (TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (type)));
-         break;
-
-       case VECTOR_TYPE:
-         write_string ("U8__vector");
-         write_type (TREE_TYPE (type));
-         break;
-
-       default:
-         gcc_unreachable ();
+         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);
+             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:
+           case UNBOUND_CLASS_TEMPLATE:
+             /* We handle TYPENAME_TYPEs and UNBOUND_CLASS_TEMPLATEs like
+                ordinary nested names.  */
+             write_nested_name (TYPE_STUB_DECL (type));
+             break;
+
+           case POINTER_TYPE:
+             write_char ('P');
+             write_type (TREE_TYPE (type));
+             break;
+
+           case REFERENCE_TYPE:
+             if (TYPE_REF_IS_RVALUE (type))
+               write_char('O');
+              else
+                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);
+             break;
+
+           case BOUND_TEMPLATE_TEMPLATE_PARM:
+             write_template_template_param (type);
+             write_template_args
+               (TI_ARGS (TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (type)));
+             break;
+
+           case VECTOR_TYPE:
+             write_string ("U8__vector");
+             write_type (TREE_TYPE (type));
+             break;
+
+            case TYPE_PACK_EXPANSION:
+              write_string ("U10__variadic");
+              write_type (PACK_EXPANSION_PATTERN (type));
+              break;
+
+            case DECLTYPE_TYPE:
+              write_char ('D');
+              if (DECLTYPE_TYPE_ID_EXPR_OR_MEMBER_ACCESS_P (type))
+                write_char ('t');
+              else
+                write_char ('T');
+              write_expression (DECLTYPE_TYPE_EXPR (type));
+              write_char ('E');
+              break;
+
+           case TYPEOF_TYPE:
+             sorry ("mangling typeof, use decltype instead");
+             break;
+
+           default:
+             gcc_unreachable ();
+           }
        }
     }
 
@@ -1734,10 +1779,6 @@ write_builtin_type (tree type)
       break;
 
     case INTEGER_TYPE:
-      /* If this is size_t, get the underlying int type.  */
-      if (TYPE_IS_SIZETYPE (type))
-       type = TYPE_DOMAIN (type);
-
       /* TYPE may still be wchar_t, since that isn't in
         integer_type_nodes.  */
       if (type == wchar_type_node)
@@ -1858,16 +1899,38 @@ write_function_type (const tree type)
    is mangled before the parameter types.  If non-NULL, DECL is
    FUNCTION_DECL for the function whose type is being emitted.
 
-     <bare-function-type> ::= </signature/ type>+  */
+   If DECL is a member of a Java type, then a literal 'J'
+   is output and the return type is mangled as if INCLUDE_RETURN_TYPE
+   were nonzero.
+
+     <bare-function-type> ::= [J]</signature/ type>+  */
 
 static void
 write_bare_function_type (const tree type, const int include_return_type_p,
                          const tree decl)
 {
+  int java_method_p;
+
   MANGLE_TRACE_TREE ("bare-function-type", type);
 
+  /* Detect Java methods and emit special encoding.  */
+  if (decl != NULL
+      && DECL_FUNCTION_MEMBER_P (decl)
+      && TYPE_FOR_JAVA (DECL_CONTEXT (decl))
+      && !DECL_CONSTRUCTOR_P (decl)
+      && !DECL_DESTRUCTOR_P (decl)
+      && !DECL_CONV_FN_P (decl))
+    {
+      java_method_p = 1;
+      write_char ('J');
+    }
+  else
+    {
+      java_method_p = 0;
+    }
+
   /* Mangle the return type, if requested.  */
-  if (include_return_type_p)
+  if (include_return_type_p || java_method_p)
     write_type (TREE_TYPE (type));
 
   /* Now mangle the types of the arguments.  */
@@ -2003,6 +2066,12 @@ write_expression (tree expr)
       code = TREE_CODE (expr);
     }
 
+  if (code == BASELINK)
+    {
+      expr = BASELINK_FUNCTIONS (expr);
+      code = TREE_CODE (expr);
+    }
+
   /* Handle pointers-to-members by making them look like expression
      nodes.  */
   if (code == PTRMEM_CST)
@@ -2184,7 +2253,7 @@ write_expression (tree expr)
          break;
 
        default:
-         for (i = 0; i < TREE_CODE_LENGTH (code); ++i)
+         for (i = 0; i < TREE_OPERAND_LENGTH (expr); ++i)
            {
              tree operand = TREE_OPERAND (expr, i);
              /* As a GNU extension, the middle operand of a
@@ -2280,7 +2349,15 @@ write_template_arg (tree node)
        G.need_abi_warning = 1;
     }
 
-  if (TYPE_P (node))
+  if (ARGUMENT_PACK_P (node))
+    {
+      /* Expand the template argument pack. */
+      tree args = ARGUMENT_PACK_ARGS (node);
+      int i, length = TREE_VEC_LENGTH (args);
+      for (i = 0; i < length; ++i)
+        write_template_arg (TREE_VEC_ELT (args, i));
+    }
+  else if (TYPE_P (node))
     write_type (node);
   else if (code == TEMPLATE_DECL)
     /* A template appearing as a template arg is a template template arg.  */
@@ -2504,7 +2581,7 @@ static inline const char *
 finish_mangling (const bool warn)
 {
   if (warn_abi && warn && G.need_abi_warning)
-    warning (0, "the mangled name of %qD will change in a future "
+    warning (OPT_Wabi, "the mangled name of %qD will change in a future "
             "version of GCC",
             G.entity);
 
@@ -2572,8 +2649,9 @@ get_identifier_nocopy (const char *name)
 void
 mangle_decl (const tree decl)
 {
-  SET_DECL_ASSEMBLER_NAME (decl,
-                          get_identifier_nocopy (mangle_decl_string (decl)));
+  tree id = get_identifier_nocopy (mangle_decl_string (decl));
+  id = targetm.mangle_decl_assembler_name (decl, id);
+  SET_DECL_ASSEMBLER_NAME (decl, id);
 }
 
 /* Generate the mangled representation of TYPE.  */
@@ -2719,8 +2797,7 @@ mangle_call_offset (const tree fixed_offset, const tree virtual_offset)
 
    <special-name> ::= T <call-offset> <base encoding>
                  ::= Tc <this_adjust call-offset> <result_adjust call-offset>
-                                       <base encoding>
-*/
+                                       <base encoding>  */
 
 tree
 mangle_thunk (tree fn_decl, const int this_adjusting, tree fixed_offset,
@@ -2776,7 +2853,7 @@ static GTY ((param_is (union tree_node))) htab_t conv_type_names;
 static hashval_t
 hash_type (const void *val)
 {
-  return (hashval_t) TYPE_UID (TREE_TYPE ((tree) val));
+  return (hashval_t) TYPE_UID (TREE_TYPE ((const_tree) val));
 }
 
 /* Compare VAL1 (a node in the table) with VAL2 (a TYPE).  */
@@ -2784,7 +2861,7 @@ hash_type (const void *val)
 static int
 compare_type (const void *val1, const void *val2)
 {
-  return TREE_TYPE ((tree) val1) == (tree) val2;
+  return TREE_TYPE ((const_tree) val1) == (const_tree) val2;
 }
 
 /* Return an identifier for the mangled unqualified name for a
@@ -2797,6 +2874,9 @@ mangle_conv_op_name_for_type (const tree type)
   void **slot;
   tree identifier;
 
+  if (type == error_mark_node)
+    return error_mark_node;
+
   if (conv_type_names == NULL)
     conv_type_names = htab_create_ggc (31, &hash_type, &compare_type, NULL);