merge from gcc
[binutils-gdb.git] / libiberty / cp-demangle.c
index b8255b3a26c9e283c95c3d4fb0de9e9e98689d60..136dc723d2ed15f7075e513c84d8ff4aa1a09c8c 100644 (file)
@@ -938,10 +938,8 @@ static status_t demangle_discriminator
   PARAMS ((demangling_t, int));
 static status_t cp_demangle
   PARAMS ((const char *, dyn_string_t, int));
-#ifdef IN_LIBGCC2
 static status_t cp_demangle_type
   PARAMS ((const char*, dyn_string_t));
-#endif
 
 /* When passed to demangle_bare_function_type, indicates that the
    function's return type is not encoded before its parameter types.  */
@@ -1557,11 +1555,11 @@ demangle_operator_name (dm, short_name, num_args)
   struct operator_code
   {
     /* The mangled code for this operator.  */
-    const char *code;
+    const char *const code;
     /* The source name of this operator.  */
-    const char *name;
+    const char *const name;
     /* The number of arguments this operator takes.  */
-    int num_args;
+    const int num_args;
   };
 
   static const struct operator_code operators[] = 
@@ -1842,11 +1840,27 @@ demangle_special_name (dm)
 
   if (peek == 'G')
     {
-      /* A guard variable name.  Consume the G.  */
+      /* Consume the G.  */
       advance_char (dm);
-      RETURN_IF_ERROR (demangle_char (dm, 'V'));
-      RETURN_IF_ERROR (result_add (dm, "guard variable for "));
-      RETURN_IF_ERROR (demangle_name (dm, &unused));
+      switch (peek_char (dm))
+       {
+       case 'V':
+         /* A guard variable name.  */
+         advance_char (dm);
+         RETURN_IF_ERROR (result_add (dm, "guard variable for "));
+         RETURN_IF_ERROR (demangle_name (dm, &unused));
+         break;
+
+       case 'R':
+         /* A reference temporary.  */
+         advance_char (dm);
+         RETURN_IF_ERROR (result_add (dm, "reference temporary for "));
+         RETURN_IF_ERROR (demangle_name (dm, &unused));
+         break;
+         
+       default:
+         return "Unrecognized <special-name>.";
+       }
     }
   else if (peek == 'T')
     {
@@ -3446,15 +3460,11 @@ demangle_discriminator (dm, suppress_first)
            /* Write the discriminator.  The mangled number is two
               less than the discriminator ordinal, counting from
               zero.  */
-           RETURN_IF_ERROR (int_to_dyn_string (discriminator + 2, 
+           RETURN_IF_ERROR (int_to_dyn_string (discriminator + 1,
                                                (dyn_string_t) dm->result));
        }
       else
-       {
-         if (flag_verbose)
-           /* A missing digit correspond to one.  */
-           RETURN_IF_ERROR (result_add_char (dm, '1'));
-       }
+       return STATUS_ERROR;
       if (flag_verbose)
        RETURN_IF_ERROR (result_add_char (dm, ']'));
     }
@@ -3521,14 +3531,13 @@ cp_demangle (name, result, style)
    dyn_string_t.  On success, returns STATUS_OK.  On failiure, returns
    an error message, and the contents of RESULT are unchanged.  */
 
-#ifdef IN_LIBGCC2
 static status_t
 cp_demangle_type (type_name, result)
      const char* type_name;
      dyn_string_t result;
 {
   status_t status;
-  demangling_t dm = demangling_new (type_name);
+  demangling_t dm = demangling_new (type_name, DMGL_GNU_V3);
   
   if (dm == NULL)
     return STATUS_ALLOCATION_FAILED;
@@ -3559,6 +3568,7 @@ cp_demangle_type (type_name, result)
   return status;
 }
 
+#ifdef IN_LIBGCC2
 extern char *__cxa_demangle PARAMS ((const char *, char *, size_t *, int *));
 
 /* ia64 ABI-mandated entry point in the C++ runtime library for performing
@@ -3675,20 +3685,35 @@ __cxa_demangle (mangled_name, output_buffer, length, status)
    If the demangling failes, returns NULL.  */
 
 char *
-cplus_demangle_v3 (mangled)
+cplus_demangle_v3 (mangled, options)
      const char* mangled;
+     int options;
 {
   dyn_string_t demangled;
   status_t status;
+  int type = !!(options & DMGL_TYPES);
 
-  /* If this isn't a mangled name, don't pretend to demangle it.  */
-  if (strncmp (mangled, "_Z", 2) != 0)
-    return NULL;
+  if (mangled[0] == '_' && mangled[1] == 'Z')
+    /* It is not a type.  */
+    type = 0;
+  else
+    {
+      /* It is a type. Stop if we don't want to demangle types. */
+      if (!type)
+       return NULL;
+    }
+
+  flag_verbose = !!(options & DMGL_VERBOSE);
 
   /* Create a dyn_string to hold the demangled name.  */
   demangled = dyn_string_new (0);
   /* Attempt the demangling.  */
-  status = cp_demangle ((char *) mangled, demangled, 0);
+  if (!type)
+    /* Appears to be a function or variable name.  */
+    status = cp_demangle (mangled, demangled, 0);
+  else
+    /* Try to demangle it as the name of a type.  */
+    status = cp_demangle_type (mangled, demangled);
 
   if (STATUS_NO_ERROR (status))
     /* Demangling succeeded.  */
@@ -3823,7 +3848,8 @@ java_demangle_v3 (mangled)
    zero, indicating that some error occurred, or a demangling_t
    holding the results.  */
 static demangling_t
-demangle_v3_with_details (const char *name)
+demangle_v3_with_details (name)
+     const char *name;
 {
   demangling_t dm;
   status_t status;
@@ -3861,7 +3887,8 @@ demangle_v3_with_details (const char *name)
    - '2' if NAME is a base object constructor, or
    - '3' if NAME is a complete object allocating constructor.  */
 enum gnu_v3_ctor_kinds
-is_gnu_v3_mangled_ctor (const char *name)
+is_gnu_v3_mangled_ctor (name)
+     const char *name;
 {
   demangling_t dm = demangle_v3_with_details (name);
 
@@ -3882,7 +3909,8 @@ is_gnu_v3_mangled_ctor (const char *name)
    - '1' if NAME is a complete object destructor, or
    - '2' if NAME is a base object destructor.  */
 enum gnu_v3_dtor_kinds
-is_gnu_v3_mangled_dtor (const char *name)
+is_gnu_v3_mangled_dtor (name)
+     const char *name;
 {
   demangling_t dm = demangle_v3_with_details (name);
 
@@ -3930,7 +3958,7 @@ print_usage (fp, exit_value)
 }
 
 /* Option specification for getopt_long.  */
-static struct option long_options[] = 
+static const struct option long_options[] = 
 {
   { "help",    no_argument, NULL, 'h' },
   { "strict",  no_argument, NULL, 's' },