* external.h (GET_LINENO_LNNO): Use H_GET_32/16.
[deliverable/binutils-gdb.git] / libiberty / cp-demangle.c
index db34b58b1c5b60ed13f99db7be894871400a0296..5ee8a2b457c8e635b0a365f8e21cf468e50b2472 100644 (file)
@@ -172,6 +172,15 @@ struct demangling_def
   
   /* Language style to use for demangled output. */
   int style;
+
+  /* Set to non-zero iff this name is a constructor.  The actual value
+     indicates what sort of constructor this is; see demangle.h.  */
+  enum gnu_v3_ctor_kinds is_constructor;
+
+  /* Set to non-zero iff this name is a destructor.  The actual value
+     indicates what sort of destructor this is; see demangle.h.  */
+  enum gnu_v3_dtor_kinds is_destructor;
+
 };
 
 typedef struct demangling_def *demangling_t;
@@ -415,7 +424,7 @@ string_list_delete (node)
   while (node != NULL)
     {
       string_list_t next = node->next;
-      free (node);
+      dyn_string_delete ((dyn_string_t) node);
       node = next;
     }
 }
@@ -815,6 +824,8 @@ demangling_new (name, style)
       return NULL;
     }
   dm->style = style;
+  dm->is_constructor = 0;
+  dm->is_destructor = 0;
 
   return dm;
 }
@@ -1831,11 +1842,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')
     {
@@ -2018,15 +2045,24 @@ demangle_ctor_dtor_name (dm)
     {
       /* A constructor name.  Consume the C.  */
       advance_char (dm);
-      if (peek_char (dm) < '1' || peek_char (dm) > '3')
+      flavor = next_char (dm);
+      if (flavor < '1' || flavor > '3')
        return "Unrecognized constructor.";
       RETURN_IF_ERROR (result_add_string (dm, dm->last_source_name));
+      switch (flavor)
+       {
+       case '1': dm->is_constructor = gnu_v3_complete_object_ctor;
+         break;
+       case '2': dm->is_constructor = gnu_v3_base_object_ctor;
+         break;
+       case '3': dm->is_constructor = gnu_v3_complete_object_allocating_ctor;
+         break;
+       }
       /* Print the flavor of the constructor if in verbose mode.  */
-      flavor = next_char (dm) - '1';
       if (flag_verbose)
        {
          RETURN_IF_ERROR (result_add (dm, "["));
-         RETURN_IF_ERROR (result_add (dm, ctor_flavors[flavor]));
+         RETURN_IF_ERROR (result_add (dm, ctor_flavors[flavor - '1']));
          RETURN_IF_ERROR (result_add_char (dm, ']'));
        }
     }
@@ -2034,16 +2070,25 @@ demangle_ctor_dtor_name (dm)
     {
       /* A destructor name.  Consume the D.  */
       advance_char (dm);
-      if (peek_char (dm) < '0' || peek_char (dm) > '2')
+      flavor = next_char (dm);
+      if (flavor < '0' || flavor > '2')
        return "Unrecognized destructor.";
       RETURN_IF_ERROR (result_add_char (dm, '~'));
       RETURN_IF_ERROR (result_add_string (dm, dm->last_source_name));
+      switch (flavor)
+       {
+       case '0': dm->is_destructor = gnu_v3_deleting_dtor;
+         break;
+       case '1': dm->is_destructor = gnu_v3_complete_object_dtor;
+         break;
+       case '2': dm->is_destructor = gnu_v3_base_object_dtor;
+         break;
+       }
       /* Print the flavor of the destructor if in verbose mode.  */
-      flavor = next_char (dm) - '0';
       if (flag_verbose)
        {
          RETURN_IF_ERROR (result_add (dm, " ["));
-         RETURN_IF_ERROR (result_add (dm, dtor_flavors[flavor]));
+         RETURN_IF_ERROR (result_add (dm, dtor_flavors[flavor - '0']));
          RETURN_IF_ERROR (result_add_char (dm, ']'));
        }
     }
@@ -3417,15 +3462,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, ']'));
     }
@@ -3789,6 +3830,88 @@ java_demangle_v3 (mangled)
 
 #endif /* IN_LIBGCC2 */
 
+
+/* Demangle NAME in the G++ V3 ABI demangling style, and return either
+   zero, indicating that some error occurred, or a demangling_t
+   holding the results.  */
+static demangling_t
+demangle_v3_with_details (name)
+     const char *name;
+{
+  demangling_t dm;
+  status_t status;
+
+  if (strncmp (name, "_Z", 2))
+    return 0;
+
+  dm = demangling_new (name, DMGL_GNU_V3);
+  if (dm == NULL)
+    {
+      fprintf (stderr, "Memory allocation failed.\n");
+      abort ();
+    }
+
+  status = result_push (dm);
+  if (! STATUS_NO_ERROR (status))
+    {
+      demangling_delete (dm);
+      fprintf (stderr, "%s\n", status);
+      abort ();
+    }
+
+  status = demangle_mangled_name (dm);
+  if (STATUS_NO_ERROR (status))
+    return dm;
+
+  demangling_delete (dm);
+  return 0;
+}
+
+
+/* Return non-zero iff NAME is the mangled form of a constructor name
+   in the G++ V3 ABI demangling style.  Specifically, return:
+   - '1' if NAME is a complete object constructor,
+   - '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 (name)
+     const char *name;
+{
+  demangling_t dm = demangle_v3_with_details (name);
+
+  if (dm)
+    {
+      enum gnu_v3_ctor_kinds result = dm->is_constructor;
+      demangling_delete (dm);
+      return result;
+    }
+  else
+    return 0;
+}
+
+
+/* Return non-zero iff NAME is the mangled form of a destructor name
+   in the G++ V3 ABI demangling style.  Specifically, return:
+   - '0' if NAME is a deleting destructor,
+   - '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 (name)
+     const char *name;
+{
+  demangling_t dm = demangle_v3_with_details (name);
+
+  if (dm)
+    {
+      enum gnu_v3_dtor_kinds result = dm->is_destructor;
+      demangling_delete (dm);
+      return result;
+    }
+  else
+    return 0;
+}
+
+
 #ifdef STANDALONE_DEMANGLER
 
 #include "getopt.h"
This page took 0.025072 seconds and 4 git commands to generate.