[rfa/symtab/c++] fix c++ rtti type lookup

Michael Elizabeth Chastain
2003-11-27T07:09:10Z

This patch is a partial fix for PR c++/1465, which is the bug where RTTI
lookup gets the "namespace" symbol instead of the class symbol. It also
fixes PR c++/1377, which was another manifestation of the same bug.

http://sources.redhat.com/gdb/bugs/1465
http://sources.redhat.com/gdb/bugs/1377

These bugs are regressions versus gdb 6.0 so they are high priority.

First, lookup_rtti_type is a new function which takes a name and a block
and returns the class type of that name. It's basically a block of code
extracted from gnuv3_rtti_type. gnuv3_rtti_type calls lookup_rtti_type
now.

Then I changed gnuv2_rtti_type to call lookup_rtti_type. This
changes the symbol lookup from VAR_DOMAIN to STRUCT_DOMAIN.

lookup_rtti_type is full of checks and warnings so that it doesn't
return crap to its caller.

This fixes the simple cases of the bug.

More work is needed:

. The calls to lookup_rtti_type need a proper "block" parameter.
The old code needed this too; I haven't regressed anything.
I put FIXME notes in for this.

. hpacc_value_rtti_type has the same buggy code.
I can't change the code because I can't test it,
but I can put it a big FIXME into it.
(I wonder if anyone still uses HP aCC with gdb).

. Nested types give a warning and don't work.
It would be nice to make them work.

. Types with virtual bases appear to work with v3, but give a warning
and don't work with v2. "don't work" probably means that they fall back
to the static type rather than the dynamic type.

Testing: I tested with gcc v2 and v3, dwarf-2 and stabs+.
Nothing got worse. gdb.cp/class2.exp has a specific test for this,
which now passes.

Some tests in virtfunc.exp that broke after the 2003-09-11 namespace
commit started working again. That was pr gdb/1377.

I think I need approval from a symtab maintainer to add the
new utility function "lookup_rtti_type", and then approval
from a C++ maintainer to change gnuv2_rtti_type and gnuv3_rtti_type
to call lookup_rtti_type.

Okay to commit?

Michael C

2003-11-26 Michael Chastain <mec.gnu@mindspring.com>

Partial fix for PR c++/1465.
Fix for PR c++/1377.
* symtab.h (lookup_rtti_type): New function.
* gdbtypes.c (lookup_rtti_type): New function.
* gnu-v2-abi.c: Update copyright years.
(gnuv2_rtti_type): Call lookup_rtti_type.
* gnu-v3-abi.c: Update copyright years.
(gnuv3_rtti_type): Call lookup_rtti_type.

Index: symtab.h
===================================================================
RCS file: /cvs/src/src/gdb/symtab.h,v
retrieving revision 1.83
diff -c -3 -p -r1.83 symtab.h
*** symtab.h 11 Nov 2003 20:04:52 -0000 1.83
--- symtab.h 27 Nov 2003 01:20:19 -0000
*************** extern struct type *lookup_union (char *
*** 1050,1055 ****
--- 1050,1059 ----

extern struct type *lookup_enum (char *, struct block *);

+ /* Lookup an rtti type by name, within a specified block */
+
+ extern struct type *lookup_rtti_type (const char *, struct block *);
+
/* from blockframe.c: */

/* lookup the function symbol corresponding to the address */
Index: gdbtypes.c
===================================================================
RCS file: /cvs/src/src/gdb/gdbtypes.c,v
retrieving revision 1.78
diff -c -3 -p -r1.78 gdbtypes.c
*** gdbtypes.c 6 Oct 2003 19:27:12 -0000 1.78
--- gdbtypes.c 27 Nov 2003 01:20:22 -0000
*************** lookup_struct_elt_type (struct type *typ
*** 1287,1292 ****
--- 1287,1335 ----
return (struct type *) -1; /* For lint */
}

+ /* Lookup the rtti type for a class name. */
+
+ struct type *
+ lookup_rtti_type (const char *name, struct block *block)
+ {
+ struct symbol * rtti_sym;
+ struct type * rtti_type;
+
+ rtti_sym = lookup_symbol (name, block, STRUCT_DOMAIN, NULL, NULL);
+
+ if (rtti_sym == NULL)
+ {
+ warning ("RTTI symbol not found for class '%s'", name);
+ return NULL;
+ }
+
+ if (SYMBOL_CLASS (rtti_sym) != LOC_TYPEDEF)
+ {
+ warning ("RTTI symbol for class '%s' is not a typedef", name);
+ return NULL;
+ }
+
+ rtti_type = SYMBOL_TYPE (rtti_sym);
+
+ switch (TYPE_CODE (rtti_type))
+ {
+ case TYPE_CODE_CLASS:
+ break;
+ case TYPE_CODE_NAMESPACE:
+ /* chastain/2003-11-26: the symbol tables often contain fake
+ symbols for namespaces with the same name as the struct.
+ This warning is an indication of a bug in the lookup order
+ or a bug in the way that the symbol tables are populated. */
+ warning ("RTTI symbol for class '%s' is a namespace", name);
+ return NULL;
+ default:
+ warning ("RTTI symbol for class '%s' has bad type", name);
+ return NULL;
+ }
+
+ return rtti_type;
+ }
+
/* If possible, make the vptr_fieldno and vptr_basetype fields of TYPE
valid. Callers should be aware that in some cases (for example,
the type or one of its baseclasses is a stub type and we are
Index: gnu-v2-abi.c
===================================================================
RCS file: /cvs/src/src/gdb/gnu-v2-abi.c,v
retrieving revision 1.13
diff -c -3 -p -r1.13 gnu-v2-abi.c
*** gnu-v2-abi.c 16 Sep 2003 18:56:35 -0000 1.13
--- gnu-v2-abi.c 27 Nov 2003 01:20:23 -0000
***************
*** 1,6 ****
/* Abstraction of GNU v2 abi.

! Copyright 2001, 2003 Free Software Foundation, Inc.

Contributed by Daniel Berlin <dberlin@redhat.com>

--- 1,6 ----
/* Abstraction of GNU v2 abi.

! Copyright 2001, 2002, 2003 Free Software Foundation, Inc.

Contributed by Daniel Berlin <dberlin@redhat.com>

*************** gnuv2_value_rtti_type (struct value *v,
*** 259,267 ****
*(strchr(demangled_name,' '))=0;

/* Lookup the type for the name */
! rtti_type=lookup_typename(demangled_name, (struct block *)0,1);
!
! if (rtti_type==NULL)
return NULL;

if (TYPE_N_BASECLASSES(rtti_type) > 1 && full && (*full) != 1)
--- 259,267 ----
*(strchr(demangled_name,' '))=0;

/* Lookup the type for the name */
! /* FIXME: chastain/2003-11-26: block=NULL is bogus. See pr gdb/1465. */
! rtti_type = lookup_rtti_type (demangled_name, NULL);
! if (rtti_type == NULL)
return NULL;

if (TYPE_N_BASECLASSES(rtti_type) > 1 && full && (*full) != 1)
Index: gnu-v3-abi.c
===================================================================
RCS file: /cvs/src/src/gdb/gnu-v3-abi.c,v
retrieving revision 1.19
diff -c -3 -p -r1.19 gnu-v3-abi.c
*** gnu-v3-abi.c 22 Aug 2003 20:45:55 -0000 1.19
--- gnu-v3-abi.c 27 Nov 2003 01:20:23 -0000
***************
*** 1,7 ****
/* Abstraction of GNU v3 abi.
Contributed by Jim Blandy <jimb@redhat.com>

! Copyright 2001, 2002 Free Software Foundation, Inc.

This file is part of GDB.

--- 1,7 ----
/* Abstraction of GNU v3 abi.
Contributed by Jim Blandy <jimb@redhat.com>

! Copyright 2001, 2002, 2003 Free Software Foundation, Inc.

This file is part of GDB.

*************** gnuv3_rtti_type (struct value *value,
*** 196,202 ****
struct minimal_symbol *vtable_symbol;
const char *vtable_symbol_name;
const char *class_name;
- struct symbol *class_symbol;
struct type *run_time_type;
struct type *base_type;
LONGEST offset_to_top;
--- 196,201 ----
*************** gnuv3_rtti_type (struct value *value,
*** 255,280 ****
class_name = vtable_symbol_name + 11;

/* Try to look up the class name as a type name. */
! class_symbol = lookup_symbol (class_name, 0, STRUCT_DOMAIN, 0, 0);
! if (! class_symbol)
! {
! warning ("can't find class named `%s', as given by C++ RTTI", class_name);
! return NULL;
! }
!
! /* Make sure the type symbol is sane. (An earlier version of this
! code would find constructor functions, who have the same name as
! the class.) */
! if (SYMBOL_CLASS (class_symbol) != LOC_TYPEDEF
! || TYPE_CODE (SYMBOL_TYPE (class_symbol)) != TYPE_CODE_CLASS)
! {
! warning ("C++ RTTI gives a class name of `%s', but that isn't a type name",
! class_name);
! return NULL;
! }
!
! /* This is the object's run-time type! */
! run_time_type = SYMBOL_TYPE (class_symbol);

/* Get the offset from VALUE to the top of the complete object.
NOTE: this is the reverse of the meaning of *TOP_P. */
--- 254,263 ----
class_name = vtable_symbol_name + 11;

/* Try to look up the class name as a type name. */
! /* FIXME: chastain/2003-11-26: block=NULL is bogus. See pr gdb/1465. */
! run_time_type = lookup_rtti_type (class_name, NULL);
! if (run_time_type == NULL)
! return NULL;

/* Get the offset from VALUE to the top of the complete object.
NOTE: this is the reverse of the meaning of *TOP_P. */