OSDN Git Service

PR c++/50089
[pf3gnuchains/gcc-fork.git] / gcc / cp / mangle.c
index 6bab309..1fcd999 100644 (file)
@@ -1,6 +1,6 @@
 /* Name mangling for the 3.0 C++ ABI.
-   Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009
-   Free Software Foundation, Inc.
+   Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010,
+   2011  Free Software Foundation, Inc.
    Written by Alex Samuel <samuel@codesourcery.com>
 
    This file is part of GCC.
@@ -53,7 +53,6 @@ along with GCC; see the file COPYING3.  If not see
 #include "tm_p.h"
 #include "cp-tree.h"
 #include "obstack.h"
-#include "toplev.h"
 #include "flags.h"
 #include "target.h"
 #include "cgraph.h"
@@ -97,6 +96,9 @@ typedef struct GTY(()) globals {
   /* The entity that is being mangled.  */
   tree GTY ((skip)) entity;
 
+  /* How many parameter scopes we are inside.  */
+  int parm_depth;
+
   /* True if the mangling will be different in a future version of the
      ABI.  */
   bool need_abi_warning;
@@ -745,6 +747,11 @@ write_encoding (const tree decl)
 static tree
 decl_mangling_context (tree decl)
 {
+  tree tcontext = targetm.cxx.decl_mangling_context (decl);
+
+  if (tcontext != NULL_TREE)
+    return tcontext;
+
   if (TREE_CODE (decl) == TYPE_DECL
       && LAMBDA_TYPE_P (TREE_TYPE (decl)))
     {
@@ -855,7 +862,7 @@ write_name (tree decl, const int ignore_local_scope)
 static void
 write_unscoped_name (const tree decl)
 {
-  tree context = CP_DECL_CONTEXT (decl);
+  tree context = decl_mangling_context (decl);
 
   MANGLE_TRACE_TREE ("unscoped-name", decl);
 
@@ -941,7 +948,7 @@ write_nested_name (const tree decl)
   else
     {
       /* No, just use <prefix>  */
-      write_prefix (DECL_CONTEXT (decl));
+      write_prefix (CP_DECL_CONTEXT (decl));
       write_unqualified_name (decl);
     }
   write_char ('E');
@@ -950,6 +957,7 @@ write_nested_name (const tree decl)
 /* <prefix> ::= <prefix> <unqualified-name>
            ::= <template-param>
            ::= <template-prefix> <template-args>
+           ::= <decltype>
            ::= # empty
            ::= <substitution>  */
 
@@ -966,6 +974,12 @@ write_prefix (const tree node)
 
   MANGLE_TRACE_TREE ("prefix", node);
 
+  if (TREE_CODE (node) == DECLTYPE_TYPE)
+    {
+      write_type (node);
+      return;
+    }
+
   if (find_substitution (node))
     return;
 
@@ -1878,16 +1892,25 @@ write_type (tree 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');
+             if (TREE_CODE (type) == POINTER_TYPE)
+               write_char ('P');
+             else if (TYPE_REF_IS_RVALUE (type))
+               write_char ('O');
               else
                 write_char ('R');
-             write_type (TREE_TYPE (type));
+             {
+               tree target = TREE_TYPE (type);
+               /* Attribute const/noreturn are not reflected in mangling.
+                  We strip them here rather than at a lower level because
+                  a typedef or template argument can have function type
+                  with function-cv-quals (that use the same representation),
+                  but you can't have a pointer/reference to such a type.  */
+               if (abi_version_at_least (5)
+                   && TREE_CODE (target) == FUNCTION_TYPE)
+                 target = build_qualified_type (target, TYPE_UNQUALIFIED);
+               write_type (target);
+             }
              break;
 
            case TEMPLATE_TYPE_PARM:
@@ -1930,7 +1953,36 @@ write_type (tree type)
             case DECLTYPE_TYPE:
              /* These shouldn't make it into mangling.  */
              gcc_assert (!DECLTYPE_FOR_LAMBDA_CAPTURE (type)
-                         && !DECLTYPE_FOR_LAMBDA_RETURN (type));
+                         && !DECLTYPE_FOR_LAMBDA_PROXY (type));
+
+             /* In ABI <5, we stripped decltype of a plain decl.  */
+             if (!abi_version_at_least (5)
+                 && DECLTYPE_TYPE_ID_EXPR_OR_MEMBER_ACCESS_P (type))
+               {
+                 tree expr = DECLTYPE_TYPE_EXPR (type);
+                 tree etype = NULL_TREE;
+                 switch (TREE_CODE (expr))
+                   {
+                   case VAR_DECL:
+                   case PARM_DECL:
+                   case RESULT_DECL:
+                   case FUNCTION_DECL:
+                   case CONST_DECL:
+                   case TEMPLATE_PARM_INDEX:
+                     etype = TREE_TYPE (expr);
+                     break;
+
+                   default:
+                     break;
+                   }
+
+                 if (etype && !type_uses_auto (etype))
+                   {
+                     G.need_abi_warning = 1;
+                     write_type (etype);
+                     return;
+                   }
+               }
 
               write_char ('D');
               if (DECLTYPE_TYPE_ID_EXPR_OR_MEMBER_ACCESS_P (type))
@@ -1951,6 +2003,10 @@ write_type (tree type)
              sorry ("mangling typeof, use decltype instead");
              break;
 
+           case UNDERLYING_TYPE:
+             sorry ("mangling __underlying_type");
+             break;
+
            case LANG_TYPE:
              /* fall through.  */
 
@@ -1986,12 +2042,6 @@ write_CV_qualifiers_for_type (const tree type)
      array.  */
   cp_cv_quals quals = TYPE_QUALS (type);
 
-  /* Attribute const/noreturn are not reflected in mangling.  */
-  if (abi_version_at_least (5)
-      && (TREE_CODE (type) == FUNCTION_TYPE
-         || TREE_CODE (type) == METHOD_TYPE))
-    return 0;
-
   if (quals & TYPE_QUAL_RESTRICT)
     {
       write_char ('r');
@@ -2209,7 +2259,7 @@ write_function_type (const tree type)
     {
       /* The first parameter must be a POINTER_TYPE pointing to the
         `this' parameter.  */
-      tree this_type = TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (type)));
+      tree this_type = class_of_this_parm (type);
       write_CV_qualifiers_for_type (this_type);
     }
 
@@ -2271,9 +2321,11 @@ write_bare_function_type (const tree type, const int include_return_type_p,
     write_type (TREE_TYPE (type));
 
   /* Now mangle the types of the arguments.  */
+  ++G.parm_depth;
   write_method_parms (TYPE_ARG_TYPES (type),
                      TREE_CODE (type) == METHOD_TYPE,
                      decl);
+  --G.parm_depth;
 }
 
 /* Write the mangled representation of a method parameter list of
@@ -2455,12 +2507,37 @@ write_expression (tree expr)
   else if (TREE_CODE_CLASS (code) == tcc_constant
           || (abi_version_at_least (2) && code == CONST_DECL))
     write_template_arg_literal (expr);
+  else if (code == PARM_DECL && DECL_ARTIFICIAL (expr))
+    {
+      gcc_assert (!strcmp ("this", IDENTIFIER_POINTER (DECL_NAME (expr))));
+      write_string ("fpT");
+    }
   else if (code == PARM_DECL)
     {
       /* A function parameter used in a late-specified return type.  */
       int index = DECL_PARM_INDEX (expr);
+      int level = DECL_PARM_LEVEL (expr);
+      int delta = G.parm_depth - level + 1;
       gcc_assert (index >= 1);
-      write_string ("fp");
+      write_char ('f');
+      if (delta != 0)
+       {
+         if (abi_version_at_least (5))
+           {
+             /* Let L be the number of function prototype scopes from the
+                innermost one (in which the parameter reference occurs) up
+                to (and including) the one containing the declaration of
+                the referenced parameter.  If the parameter declaration
+                clause of the innermost function prototype scope has been
+                completely seen, it is not counted (in that case -- which
+                is perhaps the most common -- L can be zero).  */
+             write_char ('L');
+             write_unsigned_number (delta - 1);
+           }
+         else
+           G.need_abi_warning = true;
+       }
+      write_char ('p');
       write_compact_number (index - 1);
     }
   else if (DECL_P (expr))
@@ -2539,6 +2616,15 @@ write_expression (tree expr)
       write_unqualified_id (fn);
       write_template_args (TREE_OPERAND (expr, 1));
     }
+  else if (TREE_CODE (expr) == MODOP_EXPR)
+    {
+      enum tree_code subop = TREE_CODE (TREE_OPERAND (expr, 1));
+      const char *name = (assignment_operator_name_info[(int) subop]
+                         .mangled_name);
+      write_string (name);
+      write_expression (TREE_OPERAND (expr, 0));
+      write_expression (TREE_OPERAND (expr, 2));
+    }
   else
     {
       int i, len;
@@ -2641,23 +2727,7 @@ write_expression (tree expr)
        default:
          /* In the middle-end, some expressions have more operands than
             they do in templates (and mangling).  */
-         switch (code)
-           {
-           case PREINCREMENT_EXPR:
-           case PREDECREMENT_EXPR:
-           case POSTINCREMENT_EXPR:
-           case POSTDECREMENT_EXPR:
-             len = 1;
-             break;
-
-           case ARRAY_REF:
-             len = 2;
-             break;
-
-           default:
-             len = TREE_OPERAND_LENGTH (expr);
-             break;
-           }
+         len = cp_tree_operand_length (expr);
 
          for (i = 0; i < len; ++i)
            {
@@ -2692,25 +2762,34 @@ write_template_arg_literal (const tree value)
   write_char ('L');
   write_type (TREE_TYPE (value));
 
-  switch (TREE_CODE (value))
-    {
-    case CONST_DECL:
-      write_integer_cst (DECL_INITIAL (value));
-      break;
+  /* Write a null member pointer value as (type)0, regardless of its
+     real representation.  */
+  if (null_member_pointer_value_p (value))
+    write_integer_cst (integer_zero_node);
+  else
+    switch (TREE_CODE (value))
+      {
+      case CONST_DECL:
+       write_integer_cst (DECL_INITIAL (value));
+       break;
 
-    case INTEGER_CST:
-      gcc_assert (!same_type_p (TREE_TYPE (value), boolean_type_node)
-                 || integer_zerop (value) || integer_onep (value));
-      write_integer_cst (value);
-      break;
+      case INTEGER_CST:
+       gcc_assert (!same_type_p (TREE_TYPE (value), boolean_type_node)
+                   || integer_zerop (value) || integer_onep (value));
+       write_integer_cst (value);
+       break;
 
-    case REAL_CST:
-      write_real_cst (value);
-      break;
+      case REAL_CST:
+       write_real_cst (value);
+       break;
 
-    default:
-      gcc_unreachable ();
-    }
+      case STRING_CST:
+       sorry ("string literal in function template signature");
+       break;
+
+      default:
+       gcc_unreachable ();
+      }
 
   write_char ('E');
 }
@@ -2771,7 +2850,8 @@ write_template_arg (tree node)
     /* A template appearing as a template arg is a template template arg.  */
     write_template_template_arg (node);
   else if ((TREE_CODE_CLASS (code) == tcc_constant && code != PTRMEM_CST)
-          || (abi_version_at_least (2) && code == CONST_DECL))
+          || (abi_version_at_least (2) && code == CONST_DECL)
+          || null_member_pointer_value_p (node))
     write_template_arg_literal (node);
   else if (DECL_P (node))
     {
@@ -3038,14 +3118,17 @@ mangle_decl_string (const tree decl)
   tree saved_fn = NULL_TREE;
   bool template_p = false;
 
+  /* We shouldn't be trying to mangle an uninstantiated template.  */
+  gcc_assert (!type_dependent_expression_p (decl));
+
   if (DECL_LANG_SPECIFIC (decl) && DECL_USE_TEMPLATE (decl))
     {
       struct tinst_level *tl = current_instantiation ();
-      if (!tl || tl->decl != decl)
+      if ((!tl || tl->decl != decl)
+         && push_tinst_level (decl))
        {
          template_p = true;
          saved_fn = current_function_decl;
-         push_tinst_level (decl);
          current_function_decl = NULL_TREE;
        }
     }
@@ -3110,7 +3193,7 @@ mangle_decl (const tree decl)
       if (vague_linkage_p (decl))
        DECL_WEAK (alias) = 1;
       if (TREE_CODE (decl) == FUNCTION_DECL)
-       cgraph_same_body_alias (alias, decl);
+       cgraph_same_body_alias (cgraph_get_create_node (decl), alias, decl);
       else
        varpool_extra_name_alias (alias, decl);
 #endif