[RFA] Extend demangler to recognize destructors/constructors

Jim Blandy
2001-03-15T01:00:00Z

I'd like someone's approval or disapproval for this patch to the V3
demangler.

GDB needs to be able to recognize mangled names for constructors and
destructors.

Because of the complexities of the mangling scheme in the new V3 ABI,
there's no accurate way to do this simpler than having a full parser
for mangled names. So this patch extends the demangler to actually
return to the the caller the information it reliably discovers.

It seems like one would want a more general way to get at the parsed
form of a mangled name, but I didn't see a cleaner interface within
reach; even the demangler itself doesn't keep around any tree-like
form of the name, which would (it seems to me) be ideal. GDB
certainly would like to get at the types, etc. So I'm open to
suggestions.

libiberty/ChangeLog:

2001-03-15 Jim Blandy <jimb@redhat.com>

* cp-demangle.c (struct demangling_def): New fields:
is_constructor and is_destructor.
(demangling_new): Initialize them.
(demangle_ctor_dtor_name): Set them, if we detect a constructor
or destructor.
(demangle_v3_with_details, is_gnu_v3_mangled_constructor,
is_gnu_v3_mangled_destructor): New functions.

include/ChangeLog:

2001-03-15 Jim Blandy <jimb@redhat.com>

* demangle.h (is_gnu_v3_mangled_constructor,
is_gnu_v3_mangled_destructor): New declarations.

Index: libiberty/cp-demangle.c
===================================================================
RCS file: /cvs/src/src/libiberty/cp-demangle.c,v
retrieving revision 1.8
diff -c -c -3 -p -r1.8 cp-demangle.c
*** libiberty/cp-demangle.c 2001/02/02 18:58:39 1.8
--- libiberty/cp-demangle.c 2001/03/15 08:58:11
*************** struct demangling_def
*** 172,177 ****
--- 172,188 ----

/* Language style to use for demangled output. */
int style;
+
+ /* Set to non-zero iff this name is a constructor. The actual value
+ is '1', '2', or '3', indicating a complete object, base object,
+ or complete object allocating constructor. */
+ int is_constructor;
+
+ /* Set to non-zero iff this name is a destructor. The actual value
+ is '0', '1', or '2', indicating a deleting, complete object, or
+ base object destructor. */
+ int is_destructor;
+
};

typedef struct demangling_def *demangling_t;
*************** demangling_new (name, style)
*** 815,820 ****
--- 826,833 ----
return NULL;
}
dm->style = style;
+ dm->is_constructor = 0;
+ dm->is_destructor = 0;

return dm;
}
*************** demangle_ctor_dtor_name (dm)
*** 2021,2026 ****
--- 2034,2040 ----
if (peek_char (dm) < '1' || peek_char (dm) > '3')
return "Unrecognized constructor.";
RETURN_IF_ERROR (result_add_string (dm, dm->last_source_name));
+ dm->is_constructor = peek_char (dm);
/* Print the flavor of the constructor if in verbose mode. */
flavor = next_char (dm) - '1';
if (flag_verbose)
*************** demangle_ctor_dtor_name (dm)
*** 2038,2043 ****
--- 2052,2058 ----
return "Unrecognized destructor.";
RETURN_IF_ERROR (result_add_char (dm, '~'));
RETURN_IF_ERROR (result_add_string (dm, dm->last_source_name));
+ dm->is_destructor = peek_char (dm);
/* Print the flavor of the destructor if in verbose mode. */
flavor = next_char (dm) - '0';
if (flag_verbose)
*************** java_demangle_v3 (mangled)
*** 3788,3793 ****
--- 3803,3887 ----
}

#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 (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. */
+ int
+ is_gnu_v3_mangled_constructor (const char *name)
+ {
+ demangling_t dm = demangle_v3_with_details (name);
+
+ if (dm)
+ {
+ int 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. */
+ int
+ is_gnu_v3_mangled_destructor (const char *name)
+ {
+ demangling_t dm = demangle_v3_with_details (name);
+
+ if (dm)
+ {
+ int result = dm->is_destructor;
+ demangling_delete (dm);
+ return result;
+ }
+ else
+ return 0;
+ }
+

#ifdef STANDALONE_DEMANGLER

Index: include/demangle.h
===================================================================
RCS file: /cvs/src/src/include/demangle.h,v
retrieving revision 1.6
diff -c -c -3 -p -r1.6 demangle.h
*** include/demangle.h 2001/03/14 02:27:43 1.6
--- include/demangle.h 2001/03/15 08:58:13
*************** cplus_demangle_v3 PARAMS ((const char* m
*** 128,131 ****
--- 128,145 ----
extern char*
java_demangle_v3 PARAMS ((const char* mangled));

+ /* 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. */
+ extern int is_gnu_v3_mangled_constructor (const char *name);
+
+ /* 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. */
+ extern int is_gnu_v3_mangled_destructor (const char *name);
+
#endif /* DEMANGLE_H */