/* Support for printing C and C++ types for GDB, the GNU debugger.
- Copyright 1986, 1988, 1989, 1991, 1993, 1994, 1995, 1996, 1998, 1999
+ Copyright 1986, 1988, 1989, 1991, 1993-1996, 1998-2000
Free Software Foundation, Inc.
This file is part of GDB.
/* Flag indicating target was compiled by HP compiler */
extern int hp_som_som_object_present;
-static void cp_type_print_method_args PARAMS ((struct type ** args, char *prefix, char *varstring, int staticp, GDB_FILE * stream));
+static void cp_type_print_method_args (struct type ** args, char *prefix,
+ char *varstring, int staticp,
+ struct ui_file *stream);
-static void
-c_type_print_args PARAMS ((struct type *, GDB_FILE *));
+static void c_type_print_args (struct type *, struct ui_file *);
-static void
-cp_type_print_derivation_info PARAMS ((GDB_FILE *, struct type *));
+static void cp_type_print_derivation_info (struct ui_file *, struct type *);
-void
-c_type_print_varspec_prefix PARAMS ((struct type *, GDB_FILE *, int, int));
+void c_type_print_varspec_prefix (struct type *, struct ui_file *, int,
+ int);
-static void
-c_type_print_cv_qualifier PARAMS ((struct type *, GDB_FILE *, int, int));
+static void c_type_print_cv_qualifier (struct type *, struct ui_file *,
+ int, int);
\f
c_typedef_print (type, new, stream)
struct type *type;
struct symbol *new;
- GDB_FILE *stream;
+ struct ui_file *stream;
{
CHECK_TYPEDEF (type);
switch (current_language->la_language)
c_print_type (type, varstring, stream, show, level)
struct type *type;
char *varstring;
- GDB_FILE *stream;
+ struct ui_file *stream;
int show;
int level;
{
static void
cp_type_print_derivation_info (stream, type)
- GDB_FILE *stream;
+ struct ui_file *stream;
struct type *type;
{
char *name;
char *prefix;
char *varstring;
int staticp;
- GDB_FILE *stream;
+ struct ui_file *stream;
{
int i;
void
c_type_print_varspec_prefix (type, stream, show, passed_a_ptr)
struct type *type;
- GDB_FILE *stream;
+ struct ui_file *stream;
int show;
int passed_a_ptr;
{
case TYPE_CODE_BITSTRING:
case TYPE_CODE_COMPLEX:
case TYPE_CODE_TYPEDEF:
+ case TYPE_CODE_TEMPLATE:
/* These types need no prefix. They are listed here so that
gcc -Wall will reveal any types that haven't been handled. */
break;
+ default:
+ error ("type not handled in c_type_print_varspec_prefix()");
+ break;
}
}
static void
c_type_print_cv_qualifier (type, stream, need_pre_space, need_post_space)
struct type *type;
- GDB_FILE *stream;
+ struct ui_file *stream;
int need_pre_space;
int need_post_space;
{
static void
c_type_print_args (type, stream)
struct type *type;
- GDB_FILE *stream;
+ struct ui_file *stream;
{
int i;
struct type **args;
fprintf_filtered (stream, ")");
}
+
+/* Return true iff the j'th overloading of the i'th method of TYPE
+ is a type conversion operator, like `operator int () { ... }'.
+ When listing a class's methods, we don't print the return type of
+ such operators. */
+static int
+is_type_conversion_operator (struct type *type, int i, int j)
+{
+ /* I think the whole idea of recognizing type conversion operators
+ by their name is pretty terrible. But I don't think our present
+ data structure gives us any other way to tell. If you know of
+ some other way, feel free to rewrite this function. */
+ char *name = TYPE_FN_FIELDLIST_NAME (type, i);
+
+ if (strncmp (name, "operator", 8) != 0)
+ return 0;
+
+ name += 8;
+ if (! strchr (" \t\f\n\r", *name))
+ return 0;
+
+ while (strchr (" \t\f\n\r", *name))
+ name++;
+
+ if (strncmp (name, "new", 3) == 0)
+ name += 3;
+ else if (strncmp (name, "delete", 6) == 0)
+ name += 6;
+ else
+ return 0;
+
+ /* Is that really the end of the name? */
+ if (('a' <= *name && *name <= 'z')
+ || ('A' <= *name && *name <= 'Z')
+ || ('0' <= *name && *name <= '9')
+ || *name == '_')
+ /* No, so the identifier following "operator" must be a type name,
+ and this is a type conversion operator. */
+ return 1;
+
+ /* That was indeed the end of the name, so it was `operator new' or
+ `operator delete', neither of which are type conversion operators. */
+ return 0;
+}
+
+
+/* Given a C++ qualified identifier QID, strip off the qualifiers,
+ yielding the unqualified name. The return value is a pointer into
+ the original string.
+
+ It's a pity we don't have this information in some more structured
+ form. Even the author of this function feels that writing little
+ parsers like this everywhere is stupid. */
+static char *
+remove_qualifiers (char *qid)
+{
+ int quoted = 0; /* zero if we're not in quotes;
+ '"' if we're in a double-quoted string;
+ '\'' if we're in a single-quoted string. */
+ int depth = 0; /* number of unclosed parens we've seen */
+ char *parenstack = (char *) alloca (strlen (qid));
+ char *scan;
+ char *last = 0; /* The character after the rightmost
+ `::' token we've seen so far. */
+
+ for (scan = qid; *scan; scan++)
+ {
+ if (quoted)
+ {
+ if (*scan == quoted)
+ quoted = 0;
+ else if (*scan == '\\' && *(scan + 1))
+ scan++;
+ }
+ else if (scan[0] == ':' && scan[1] == ':')
+ {
+ /* If we're inside parenthesis (i.e., an argument list) or
+ angle brackets (i.e., a list of template arguments), then
+ we don't record the position of this :: token, since it's
+ not relevant to the top-level structure we're trying
+ to operate on. */
+ if (depth == 0)
+ {
+ last = scan + 2;
+ scan++;
+ }
+ }
+ else if (*scan == '"' || *scan == '\'')
+ quoted = *scan;
+ else if (*scan == '(')
+ parenstack[depth++] = ')';
+ else if (*scan == '[')
+ parenstack[depth++] = ']';
+ /* We're going to treat <> as a pair of matching characters,
+ since we're more likely to see those in template id's than
+ real less-than characters. What a crock. */
+ else if (*scan == '<')
+ parenstack[depth++] = '>';
+ else if (*scan == ')' || *scan == ']' || *scan == '>')
+ {
+ if (depth > 0 && parenstack[depth - 1] == *scan)
+ depth--;
+ else
+ {
+ /* We're going to do a little error recovery here. If we
+ don't find a match for *scan on the paren stack, but
+ there is something lower on the stack that does match, we
+ pop the stack to that point. */
+ int i;
+
+ for (i = depth - 1; i >= 0; i--)
+ if (parenstack[i] == *scan)
+ {
+ depth = i;
+ break;
+ }
+ }
+ }
+ }
+
+ if (last)
+ return last;
+ else
+ /* We didn't find any :: tokens at the top level, so declare the
+ whole thing an unqualified identifier. */
+ return qid;
+}
+
+
/* Print any array sizes, function arguments or close parentheses
needed after the variable name (to describe its type).
Args work like c_type_print_varspec_prefix. */
void
c_type_print_varspec_suffix (type, stream, show, passed_a_ptr, demangled_args)
struct type *type;
- GDB_FILE *stream;
+ struct ui_file *stream;
int show;
int passed_a_ptr;
int demangled_args;
case TYPE_CODE_BITSTRING:
case TYPE_CODE_COMPLEX:
case TYPE_CODE_TYPEDEF:
+ case TYPE_CODE_TEMPLATE:
/* These types do not need a suffix. They are listed so that
gcc -Wall will report types that may not have been considered. */
break;
+ default:
+ error ("type not handled in c_type_print_varspec_suffix()");
+ break;
}
}
void
c_type_print_base (type, stream, show, level)
struct type *type;
- GDB_FILE *stream;
+ struct ui_file *stream;
int show;
int level;
{
if (TYPE_HAS_VTABLE (type) && (STREQN (TYPE_FIELD_NAME (type, i), "__vfp", 5)))
continue;
/* Other compilers */
- /* pai:: FIXME : check for has_vtable < 0 */
if (STREQN (TYPE_FIELD_NAME (type, i), "_vptr", 5)
&& is_cplus_marker ((TYPE_FIELD_NAME (type, i))[5]))
continue;
}
else if (!is_constructor && /* constructors don't have declared types */
!is_full_physname_constructor && /* " " */
- !strstr (method_name, "operator ")) /* Not a type conversion operator */
- /* (note space -- other operators don't have it) */
+ !is_type_conversion_operator (type, i, j))
{
type_print (TYPE_TARGET_TYPE (TYPE_FN_FIELD_TYPE (f, j)),
"", stream, -1);
else
{
char *p;
- char *demangled_no_class = demangled_name;
+ char *demangled_no_class
+ = remove_qualifiers (demangled_name);
- while ((p = strchr (demangled_no_class, ':')))
- {
- demangled_no_class = p;
- if (*++demangled_no_class == ':')
- ++demangled_no_class;
- }
- /* get rid of the static word appended by the demangler */
+ /* get rid of the `static' appended by the demangler */
p = strstr (demangled_no_class, " static");
if (p != NULL)
{
}
}
+ fprintfi_filtered (level, stream, "}");
+
if (TYPE_LOCALTYPE_PTR (type) && show >= 0)
fprintfi_filtered (level, stream, " (Local at %s:%d)\n",
TYPE_LOCALTYPE_FILE (type),
TYPE_LOCALTYPE_LINE (type));
-
- fprintfi_filtered (level, stream, "}");
}
if (TYPE_CODE (type) == TYPE_CODE_TEMPLATE)
goto go_back;