OSDN Git Service

PR c++/4926
[pf3gnuchains/gcc-fork.git] / gcc / cp / mangle.c
index 37293f1..ca15dab 100644 (file)
@@ -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)