Re: RFA: abstract C++ ABI dependencies

Jim Blandy
2001-04-24T17:42:00Z

Here is the same patch, revised (hopefully) to address the problems
David and Anthony pointed out. Test results on both old and new GCC's
are unchanged.

2001-04-24 Jim Blandy <jimb@redhat.com>

(Changes from Daniel Berlin, with revisions by Jim Blandy.)

Abstract out operations specific to particular C++ ABI's, and
invoke them through a function table. This removes the C++ ABI
dependencies scattered throughout the code, and allows us to
cleanly add support for new C++ ABI's.
* cp-abi.h, cp-abi.h, gnu-v2-abi.c, hpacc-abi.c: New files.
* c-typeprint.c, c-valprint.c, dbxread.c, eval.c, gdbtypes.c,
jv-typeprint.c, linespec.c, p-valprint.c, symtab.c, typeprint.c,
valops.c: #include "cp-abi.h". These files all use functions now
declared there.
* symtab.h (OPNAME_PREFIX_P, VTBL_PREFIX_P, DESTRUCTOR_PREFIX_P):
Deleted. These services are now provided by functions declared in
cp-abi.h.
* value.h (value_rtti_type, value_virtual_fn_field): Same.
* values.c (value_virtual_fn_field): Same, for this definition.
* valops.c (value_rtti_type): Same.
* c-typeprint.c (c_type_print_base): Use the functions from
"cp-abi.h", instead of the old macros, or hard-coded ABI-specific
tests.
* dbxread.c (record_minimal_symbol): Same.
* gdbtypes.c (get_destructor_fn_field, virtual_base_index,
virtual_base_index_skip_primaries): Same.
* jv-typeprint.c (java_type_print_base): Same.
* linespec.c (find_methods, decode_line_1): Same.
* symtab.c (gdb_mangle_name): Same.
* Makefile.in (SFILES): Add the new .c files mentioned above.
(cp_abi_h): New variable.
(COMMON_OBS): Add gnu-v2-abi.o, hpacc-abi.o, and cp-abi.o.
(cp-abi.o, gnu-v2-abi.o, hpacc-abi.o): New targets.
(c-typeprint.o, c-valprint.o, dbxread.o, eval.o, gdbtypes.o,
jv-typeprint.o, p-valprint.o, symtab.o, linespec.o, typeprint.o,
valops.o): Add dependency on $(cp_abi_h).

Index: gdb/Makefile.in
===================================================================
RCS file: /cvs/src/src/gdb/Makefile.in,v
retrieving revision 1.79
diff -c -r1.79 Makefile.in
*** gdb/Makefile.in 2001/04/17 21:20:48 1.79
--- gdb/Makefile.in 2001/04/25 00:17:54
***************
*** 539,545 ****
tui/tuiStack.c tui/tuiStack.h tui/tuiWin.c tui/tuiWin.h \
tui/tui-file.h tui/tui-file.c \
ui-file.h ui-file.c \
! frame.c

LINTFILES = $(SFILES) $(YYFILES) $(CONFIG_SRCS) init.c

--- 539,546 ----
tui/tuiStack.c tui/tuiStack.h tui/tuiWin.c tui/tuiWin.h \
tui/tui-file.h tui/tui-file.c \
ui-file.h ui-file.c \
! frame.c \
! gnu-v2-abi.c hpacc-abi.c cp-abi.c

LINTFILES = $(SFILES) $(YYFILES) $(CONFIG_SRCS) init.c

***************
*** 613,618 ****
--- 614,621 ----
cli_setshow_h = $(srcdir)/cli/cli-setshow.h
cli_utils_h = $(srcdir)/cli/cli-utils.h

+ cp_abi_h = cp-abi.h
+
# Header files that need to have srcdir added. Note that in the cases
# where we use a macro like $(gdbcmd_h), things are carefully arranged
# so that each .h file is listed exactly once (M-x tags-search works
***************
*** 686,692 ****
c-valprint.o cp-valprint.o ch-valprint.o f-valprint.o m2-valprint.o \
nlmread.o serial.o mdebugread.o os9kread.o top.o utils.o \
ui-file.o tui-file.o \
! frame.o

OBS = $(COMMON_OBS) $(ANNOTATE_OBS)

--- 689,696 ----
c-valprint.o cp-valprint.o ch-valprint.o f-valprint.o m2-valprint.o \
nlmread.o serial.o mdebugread.o os9kread.o top.o utils.o \
ui-file.o tui-file.o \
! frame.o \
! gnu-v2-abi.o hpacc-abi.o cp-abi.o

OBS = $(COMMON_OBS) $(ANNOTATE_OBS)

***************
*** 1222,1231 ****

c-typeprint.o: c-typeprint.c c-lang.h $(defs_h) $(expression_h) \
$(gdbcmd_h) $(gdbcore_h) $(gdbtypes_h) language.h $(symtab_h) \
! target.h typeprint.h $(value_h) gdb_string.h

c-valprint.o: c-valprint.c $(defs_h) $(expression_h) $(gdbtypes_h) \
! language.h $(symtab_h) valprint.h $(value_h)

f-lang.o: f-lang.c f-lang.h $(defs_h) $(expression_h) $(gdbtypes_h) \
language.h parser-defs.h $(symtab_h) gdb_string.h
--- 1226,1235 ----

c-typeprint.o: c-typeprint.c c-lang.h $(defs_h) $(expression_h) \
$(gdbcmd_h) $(gdbcore_h) $(gdbtypes_h) language.h $(symtab_h) \
! target.h typeprint.h $(value_h) gdb_string.h $(cp_abi_h)

c-valprint.o: c-valprint.c $(defs_h) $(expression_h) $(gdbtypes_h) \
! language.h $(symtab_h) valprint.h $(value_h) $(cp_abi_h)

f-lang.o: f-lang.c f-lang.h $(defs_h) $(expression_h) $(gdbtypes_h) \
language.h parser-defs.h $(symtab_h) gdb_string.h
***************
*** 1278,1283 ****
--- 1282,1289 ----
corelow.o: corelow.c $(command_h) $(defs_h) $(gdbcore_h) $(inferior_h) \
target.h gdbthread.h gdb_string.h $(regcache_h)

+ cp-abi.o: cp-abi.c $(defs_h) $(value_h) $(cp_abi_h)
+
cp-valprint.o: cp-valprint.c $(defs_h) $(expression_h) $(gdbcmd_h) \
$(gdbtypes_h) $(symtab_h) $(value_h) gdb_string.h

***************
*** 1287,1293 ****
dbxread.o: dbxread.c $(breakpoint_h) buildsym.h $(command_h) \
complaints.h $(defs_h) $(expression_h) gdb-stabs.h $(gdbcore_h) \
$(gdbtypes_h) language.h objfiles.h partial-stab.h stabsread.h \
! symfile.h $(symtab_h) target.h gdb_string.h

delta68-nat.o: delta68-nat.c $(defs_h)

--- 1293,1299 ----
dbxread.o: dbxread.c $(breakpoint_h) buildsym.h $(command_h) \
complaints.h $(defs_h) $(expression_h) gdb-stabs.h $(gdbcore_h) \
$(gdbtypes_h) language.h objfiles.h partial-stab.h stabsread.h \
! symfile.h $(symtab_h) target.h gdb_string.h $(cp_abi_h)

delta68-nat.o: delta68-nat.c $(defs_h)

***************
*** 1317,1323 ****

eval.o: eval.c $(bfd_h) $(defs_h) $(expression_h) $(frame_h) \
$(gdbtypes_h) language.h $(symtab_h) target.h $(value_h) \
! gdb_string.h

event-loop.o: event-loop.c $(defs_h) $(top_h) $(event_loop_h) $(event_top_h)

--- 1323,1329 ----

eval.o: eval.c $(bfd_h) $(defs_h) $(expression_h) $(frame_h) \
$(gdbtypes_h) language.h $(symtab_h) target.h $(value_h) \
! gdb_string.h $(cp_abi_h)

event-loop.o: event-loop.c $(defs_h) $(top_h) $(event_loop_h) $(event_top_h)

***************
*** 1446,1452 ****

gdbtypes.o: gdbtypes.c $(bfd_h) complaints.h $(defs_h) $(expression_h) \
$(gdbtypes_h) language.h objfiles.h symfile.h $(symtab_h) target.h \
! $(value_h) gdb_string.h wrapper.h

go32-nat.o: go32-nat.c $(defs_h) $(inferior_h) gdb_wait.h $(gdbcore_h) \
$(command_h) $(floatformat_h) target.h i387-nat.h $(regcache_h)
--- 1452,1458 ----

gdbtypes.o: gdbtypes.c $(bfd_h) complaints.h $(defs_h) $(expression_h) \
$(gdbtypes_h) language.h objfiles.h symfile.h $(symtab_h) target.h \
! $(value_h) gdb_string.h wrapper.h $(cp_abi_h)

go32-nat.o: go32-nat.c $(defs_h) $(inferior_h) gdb_wait.h $(gdbcore_h) \
$(command_h) $(floatformat_h) target.h i387-nat.h $(regcache_h)
***************
*** 1454,1459 ****
--- 1460,1468 ----
gnu-nat.o: process_reply_S.h exc_request_S.h notify_S.h msg_reply_S.h \
exc_request_U.h msg_U.h gnu-nat.h

+ gnu-v2-abi.o: gnu-v2-abi.c $(defs_h) $(cp_abi_h) gdb_string.h $(symtab_h) \
+ $(gdbtypes_h) $(value_h)
+
h8300-tdep.o: h8300-tdep.c $(defs_h) $(frame_h) $(symtab_h) $(regcache_h)

h8500-tdep.o: h8500-tdep.c $(bfd_h) $(dis-asm_h) $(defs_h) \
***************
*** 1462,1467 ****
--- 1471,1479 ----

hp300ux-nat.o: hp300ux-nat.c $(defs_h) $(gdbcore_h) $(inferior_h) $(regcache_h)

+ hpacc-abi.o: hpacc-abi.c $(defs_h) $(cp_abi_h) gdb_string.h $(gdbtypes_h) \
+ $(value_h) $(gdbcore_h)
+
hppa-tdep.o: hppa-tdep.c gdb_wait.h $(defs_h) $(gdbcmd_h) $(gdbcore_h) \
$(inferior_h) objfiles.h symfile.h target.h $(regcache_h)

***************
*** 1551,1557 ****

jv-typeprint.o: jv-typeprint.c $(bfd_h) $(defs_h) $(symtab_h) $(gdbtypes_h) \
$(value_h) $(demangle_h) jv-lang.h gdb_string.h \
! typeprint.h c-lang.h

jv-valprint.o: jv-valprint.c $(bfd_h) $(defs_h) $(symtab_h) $(gdbtypes_h) \
$(expression_h) $(value_h) $(demangle_h) valprint.h \
--- 1563,1569 ----

jv-typeprint.o: jv-typeprint.c $(bfd_h) $(defs_h) $(symtab_h) $(gdbtypes_h) \
$(value_h) $(demangle_h) jv-lang.h gdb_string.h \
! typeprint.h c-lang.h $(cp_abi_h)

jv-valprint.o: jv-valprint.c $(bfd_h) $(defs_h) $(symtab_h) $(gdbtypes_h) \
$(expression_h) $(value_h) $(demangle_h) valprint.h \
***************
*** 1958,1968 ****
symtab.o: symtab.c call-cmds.h $(defs_h) $(expression_h) $(frame_h) \
$(gdbcmd_h) $(gdbcore_h) $(gdbtypes_h) language.h objfiles.h \
gnu-regex.h symfile.h $(symtab_h) target.h $(value_h) \
! gdb_string.h linespec.h

linespec.o: linespec.c linespec.h $(defs_h) $(frame_h) $(value_h) \
objfiles.h symfile.h completer.h $(symtab_h) \
! $(demangle_h) command.h

tic80-tdep.o: tic80-tdep.c $(defs_h) $(regcache_h)

--- 1970,1980 ----
symtab.o: symtab.c call-cmds.h $(defs_h) $(expression_h) $(frame_h) \
$(gdbcmd_h) $(gdbcore_h) $(gdbtypes_h) language.h objfiles.h \
gnu-regex.h symfile.h $(symtab_h) target.h $(value_h) \
! gdb_string.h linespec.h $(cp_abi_h)

linespec.o: linespec.c linespec.h $(defs_h) $(frame_h) $(value_h) \
objfiles.h symfile.h completer.h $(symtab_h) \
! $(demangle_h) command.h $(cp_abi_h)

tic80-tdep.o: tic80-tdep.c $(defs_h) $(regcache_h)

***************
*** 1981,1987 ****

typeprint.o: typeprint.c $(defs_h) $(expression_h) $(gdbcmd_h) \
$(gdbcore_h) $(gdbtypes_h) language.h $(symtab_h) target.h \
! $(value_h) gdb_string.h

# OBSOLETE ultra3-nat.o: ultra3-nat.c $(defs_h) $(gdbcore_h) $(inferior_h) $(regcache_h)

--- 1993,1999 ----

typeprint.o: typeprint.c $(defs_h) $(expression_h) $(gdbcmd_h) \
$(gdbcore_h) $(gdbtypes_h) language.h $(symtab_h) target.h \
! $(value_h) gdb_string.h $(cp_abi.h)

# OBSOLETE ultra3-nat.o: ultra3-nat.c $(defs_h) $(gdbcore_h) $(inferior_h) $(regcache_h)

***************
*** 1998,2004 ****
gdb_string.h

valops.o: valops.c $(defs_h) $(gdbcore_h) $(inferior_h) target.h \
! gdb_string.h $(regcache_h)

valprint.o: valprint.c $(defs_h) $(expression_h) $(gdbcmd_h) \
$(gdbcore_h) $(gdbtypes_h) language.h $(symtab_h) target.h \
--- 2010,2016 ----
gdb_string.h

valops.o: valops.c $(defs_h) $(gdbcore_h) $(inferior_h) target.h \
! gdb_string.h $(regcache_h) $(cp_abi_h)

valprint.o: valprint.c $(defs_h) $(expression_h) $(gdbcmd_h) \
$(gdbcore_h) $(gdbtypes_h) language.h $(symtab_h) target.h \
Index: gdb/c-typeprint.c
===================================================================
RCS file: /cvs/src/src/gdb/c-typeprint.c,v
retrieving revision 1.9
diff -c -r1.9 c-typeprint.c
*** gdb/c-typeprint.c 2001/03/27 20:36:23 1.9
--- gdb/c-typeprint.c 2001/04/25 00:17:56
***************
*** 33,38 ****
--- 33,39 ----
#include "demangle.h"
#include "c-lang.h"
#include "typeprint.h"
+ #include "cp-abi.h"

#include "gdb_string.h"
#include <errno.h>
***************
*** 900,910 ****
{
char *physname = TYPE_FN_FIELD_PHYSNAME (f, j);
int is_full_physname_constructor =
! ((physname[0] == '_' && physname[1] == '_'
! && strchr ("0123456789Qt", physname[2]))
! || STREQN (physname, "__ct__", 6)
! || DESTRUCTOR_PREFIX_P (physname)
! || STREQN (physname, "__dt__", 6));

QUIT;
if (TYPE_FN_FIELD_PROTECTED (f, j))
--- 901,910 ----
{
char *physname = TYPE_FN_FIELD_PHYSNAME (f, j);
int is_full_physname_constructor =
! is_constructor_name (physname)
! || is_destructor_name (physname)
! || method_name[0] == '~';
!

QUIT;
if (TYPE_FN_FIELD_PROTECTED (f, j))
Index: gdb/c-valprint.c
===================================================================
RCS file: /cvs/src/src/gdb/c-valprint.c,v
retrieving revision 1.8
diff -c -r1.8 c-valprint.c
*** gdb/c-valprint.c 2001/03/07 02:57:08 1.8
--- gdb/c-valprint.c 2001/04/25 00:17:56
***************
*** 28,33 ****
--- 28,34 ----
#include "valprint.h"
#include "language.h"
#include "c-lang.h"
+ #include "cp-abi.h"
\f

/* Print function pointer with inferior address ADDRESS onto stdio
***************
*** 303,308 ****
--- 304,310 ----
}
/* Fall through. */
case TYPE_CODE_STRUCT:
+ /*FIXME: Abstract this away */
if (vtblprint && cp_is_vtbl_ptr_type (type))
{
/* Print the unmangled name if desired. */
Index: gdb/cp-abi.c
===================================================================
RCS file: cp-abi.c
diff -N cp-abi.c
*** gdb/cp-abi.c Tue May 5 13:32:27 1998
--- gdb/cp-abi.c Tue Apr 24 17:17:56 2001
***************
*** 0 ****
--- 1,99 ----
+ /* Generic code for supporting multiple C++ ABI's
+ Copyright 2001 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+ #include "defs.h"
+ #include "value.h"
+ #include "cp-abi.h"
+
+ struct cp_abi_ops current_cp_abi;
+
+ struct cp_abi_ops *cp_abis;
+
+ int num_cp_abis = 0;
+
+ enum ctor_kinds
+ is_constructor_name (const char *name)
+ {
+ if ((current_cp_abi.is_constructor_name) == NULL)
+ error ("ABI doesn't define required function is_constructor_name");
+ return (*current_cp_abi.is_constructor_name) (name);
+ }
+
+ enum dtor_kinds
+ is_destructor_name (const char *name)
+ {
+ if ((current_cp_abi.is_destructor_name) == NULL)
+ error ("ABI doesn't define required function is_destructor_name");
+ return (*current_cp_abi.is_destructor_name) (name);
+ }
+
+ int
+ is_vtable_name (const char *name)
+ {
+ if ((current_cp_abi.is_vtable_name) == NULL)
+ error ("ABI doesn't define required function is_vtable_name");
+ return (*current_cp_abi.is_vtable_name) (name);
+ }
+
+ int
+ is_operator_name (const char *name)
+ {
+ if ((current_cp_abi.is_operator_name) == NULL)
+ error ("ABI doesn't define required function is_operator_name");
+ return (*current_cp_abi.is_operator_name) (name);
+ }
+
+ value_ptr
+ value_virtual_fn_field (value_ptr * arg1p, struct fn_field * f, int j,
+ struct type * type, int offset)
+ {
+ if ((current_cp_abi.virtual_fn_field) == NULL)
+ return NULL;
+ return (*current_cp_abi.virtual_fn_field) (arg1p, f, j, type, offset);
+ }
+ struct type *
+ value_rtti_type (value_ptr v, int *full, int *top, int *using_enc)
+ {
+ if ((current_cp_abi.rtti_type) == NULL)
+ return NULL;
+ return (*current_cp_abi.rtti_type) (v, full, top, using_enc);
+ }
+
+ int
+ register_cp_abi (struct cp_abi_ops abi)
+ {
+ cp_abis =
+ xrealloc (cp_abis, (num_cp_abis + 1) * sizeof (struct cp_abi_ops));
+ cp_abis[num_cp_abis++] = abi;
+
+ return 1;
+
+ }
+
+ int
+ switch_to_cp_abi (const char *short_name)
+ {
+ int i;
+ for (i = 0; i < num_cp_abis; i++)
+ if (strcmp (cp_abis[i].shortname, short_name) == 0)
+ current_cp_abi = cp_abis[i];
+ return 1;
+ }
+
Index: gdb/cp-abi.h
===================================================================
RCS file: cp-abi.h
diff -N cp-abi.h
*** gdb/cp-abi.h Tue May 5 13:32:27 1998
--- gdb/cp-abi.h Tue Apr 24 17:17:57 2001
***************
*** 0 ****
--- 1,131 ----
+ /* Abstraction of various C++ ABI's we support, and the info we need
+ to get from them.
+ Contributed by Daniel Berlin <dberlin@redhat.com>
+ Copyright 2001 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or
+ modify
+ it under the terms of the GNU General Public License as published
+ by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+ #ifndef CP_ABI_H_
+ #define CP_ABI_H_ 1
+
+ /* Kinds of constructors. All these values are guaranteed to be
+ non-zero. */
+ enum ctor_kinds {
+
+ /* Initialize a complete object, including virtual bases, using
+ memory provided by caller. */
+ complete_object_ctor = 1,
+
+ /* Initialize a base object of some larger object. */
+ base_object_ctor,
+
+ /* An allocating complete-object constructor. */
+ complete_object_allocating_ctor
+ };
+
+
+ /* Kinds of destructors. All these values are guaranteed to be
+ non-zero. */
+ enum dtor_kinds {
+
+ /* A destructor which finalizes the entire object, and then calls
+ `delete' on its storage. */
+ deleting_dtor = 1,
+
+ /* A destructor which finalizes the entire object, but does not call
+ `delete'. */
+ complete_object_dtor,
+
+ /* A destructor which finalizes a subobject of some larger object. */
+ base_object_dtor
+ };
+
+
+ struct cp_abi_ops
+ {
+ const char *shortname;
+ const char *longname;
+ const char *doc;
+
+ /* The functions here that attempt to determine what sort of thing a
+ mangled name refers to may well be revised in the future. It
+ would certainly be cleaner to carry this information explicitly
+ in GDB's data structures than to derive it from the mangled name. */
+
+ /* Return non-zero iff NAME is the mangled name of a constructor.
+ Actually, return an `enum ctor_kind' value describing what *kind*
+ of constructor it is. */
+ enum ctor_kinds (*is_constructor_name) (const char *name);
+
+ /* Return non-zero iff NAME is the mangled name of a destructor.
+ Actually, return an `enum dtor_kind' value describing what *kind*
+ of destructor it is. */
+ enum dtor_kinds (*is_destructor_name) (const char *name);
+
+ /* Return non-zero iff NAME is the mangled name of a vtable. */
+ int (*is_vtable_name) (const char *name);
+
+ /* Return non-zero iff NAME is the un-mangled name of an operator,
+ perhaps scoped within some class. */
+ int (*is_operator_name) (const char *name);
+
+ value_ptr (*virtual_fn_field) (value_ptr * arg1p, struct fn_field * f,
+ int j, struct type * type, int offset);
+
+ /* Find the real run-time type of a value using RTTI.
+ * V is a pointer to the value.
+ * A pointer to the struct type entry of the run-time type
+ * is returneed.
+ * FULL is a flag that is set only if the value V includes
+ * the entire contents of an object of the RTTI type.
+ * TOP is the offset to the top of the enclosing object of
+ * the real run-time type. This offset may be for the embedded
+ * object, or for the enclosing object of V.
+ * USING_ENC is the flag that distinguishes the two cases.
+ * If it is 1, then the offset is for the enclosing object,
+ * otherwise for the embedded object.
+ *
+ */
+
+ struct type *(*rtti_type) (value_ptr v, int *full, int *top,
+ int *using_enc);
+ };
+
+
+ extern struct cp_abi_ops *cp_abis;
+
+ extern int num_cp_abis;
+
+ extern struct cp_abi_ops current_cp_abi;
+
+ extern enum ctor_kinds is_constructor_name (const char *name);
+ extern enum dtor_kinds is_destructor_name (const char *name);
+ extern int is_vtable_name (const char *name);
+ extern int is_operator_name (const char *name);
+ extern value_ptr value_virtual_fn_field (value_ptr * arg1p,
+ struct fn_field *f, int j,
+ struct type *type, int offset);
+ extern struct type *value_rtti_type (value_ptr v, int *full, int *top,
+ int *using_enc);
+ extern int register_cp_abi (struct cp_abi_ops abi);
+ extern int switch_to_cp_abi (const char *short_name);
+
+ #endif
+
Index: gdb/dbxread.c
===================================================================
RCS file: /cvs/src/src/gdb/dbxread.c,v
retrieving revision 1.17
diff -c -r1.17 dbxread.c
*** gdb/dbxread.c 2001/03/27 20:36:23 1.17
--- gdb/dbxread.c 2001/04/25 00:18:00
***************
*** 57,62 ****
--- 57,63 ----
#include "demangle.h"
#include "language.h" /* Needed inside partial-stab.h */
#include "complaints.h"
+ #include "cp-abi.h"

#include "aout/aout64.h"
#include "aout/stab_gnu.h" /* We always use GNU stabs, not native, now */
***************
*** 514,520 ****
char *tempstring = name;
if (tempstring[0] == bfd_get_symbol_leading_char (objfile->obfd))
++tempstring;
! if (VTBL_PREFIX_P ((tempstring)))
ms_type = mst_data;
}
section = SECT_OFF_DATA (objfile);
--- 515,521 ----
char *tempstring = name;
if (tempstring[0] == bfd_get_symbol_leading_char (objfile->obfd))
++tempstring;
! if (is_vtable_name (tempstring))
ms_type = mst_data;
}
section = SECT_OFF_DATA (objfile);
Index: gdb/eval.c
===================================================================
RCS file: /cvs/src/src/gdb/eval.c,v
retrieving revision 1.12
diff -c -r1.12 eval.c
*** gdb/eval.c 2001/03/19 23:31:41 1.12
--- gdb/eval.c 2001/04/25 00:18:02
***************
*** 30,35 ****
--- 30,36 ----
#include "frame.h"
#include "language.h" /* For CAST_IS_CONVERSION */
#include "f-lang.h" /* for array bound stuff */
+ #include "cp-abi.h"

/* Defined in symtab.c */
extern int hp_som_som_object_present;
Index: gdb/gdbtypes.c
===================================================================
RCS file: /cvs/src/src/gdb/gdbtypes.c,v
retrieving revision 1.19
diff -c -r1.19 gdbtypes.c
*** gdb/gdbtypes.c 2001/03/20 01:37:09 1.19
--- gdb/gdbtypes.c 2001/04/25 00:18:05
***************
*** 35,40 ****
--- 35,41 ----
#include "complaints.h"
#include "gdbcmd.h"
#include "wrapper.h"
+ #include "cp-abi.h"

/* These variables point to the objects
representing the predefined C data types. */
***************
*** 1027,1033 ****

for (j = 0; j < TYPE_FN_FIELDLIST_LENGTH (t, i); j++)
{
! if (DESTRUCTOR_PREFIX_P (TYPE_FN_FIELD_PHYSNAME (f, j)))
{
*method_indexp = i;
*field_indexp = j;
--- 1028,1034 ----

for (j = 0; j < TYPE_FN_FIELDLIST_LENGTH (t, i); j++)
{
! if (is_destructor_name (TYPE_FN_FIELD_PHYSNAME (f, j)) != 0)
{
*method_indexp = i;
*field_indexp = j;
***************
*** 1902,1913 ****
return -1;

i = 0;
! vbase = TYPE_VIRTUAL_BASE_LIST (dclass)[0];
while (vbase)
{
if (vbase == base)
break;
! vbase = TYPE_VIRTUAL_BASE_LIST (dclass)[++i];
}

return vbase ? i : -1;
--- 1903,1914 ----
return -1;

i = 0;
! vbase = virtual_base_list (dclass)[0];
while (vbase)
{
if (vbase == base)
break;
! vbase = virtual_base_list (dclass)[++i];
}

return vbase ? i : -1;
***************
*** 1936,1949 ****

j = -1;
i = 0;
! vbase = TYPE_VIRTUAL_BASE_LIST (dclass)[0];
while (vbase)
{
if (!primary || (virtual_base_index_skip_primaries (vbase, primary) < 0))
j++;
if (vbase == base)
break;
! vbase = TYPE_VIRTUAL_BASE_LIST (dclass)[++i];
}

return vbase ? j : -1;
--- 1937,1950 ----

j = -1;
i = 0;
! vbase = virtual_base_list (dclass)[0];
while (vbase)
{
if (!primary || (virtual_base_index_skip_primaries (vbase, primary) < 0))
j++;
if (vbase == base)
break;
! vbase = virtual_base_list (dclass)[++i];
}

return vbase ? j : -1;
Index: gdb/gnu-v2-abi.c
===================================================================
RCS file: gnu-v2-abi.c
diff -N gnu-v2-abi.c
*** gdb/gnu-v2-abi.c Tue May 5 13:32:27 1998
--- gdb/gnu-v2-abi.c Tue Apr 24 17:18:07 2001
***************
*** 0 ****
--- 1,332 ----
+ /* Abstraction of GNU v2 abi.
+ Contributed by Daniel Berlin <dberlin@redhat.com>
+ Copyright 2001 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or
+ modify
+ it under the terms of the GNU General Public License as published
+ by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+ #include "defs.h"
+ #include "gdb_regex.h"
+ #include "gdb_string.h"
+ #include "symtab.h"
+ #include "gdbtypes.h"
+ #include "value.h"
+ #include "demangle.h"
+ #include "cp-abi.h"
+
+ #include <ctype.h>
+
+ struct cp_abi_ops gnu_v2_abi_ops;
+
+ static int vb_match (struct type *, int, struct type *);
+
+ static enum dtor_kinds
+ gnuv2_is_destructor_name (const char *name)
+ {
+ if ((name[0] == '_' && is_cplus_marker (name[1]) && name[2] == '_')
+ || strncmp (name, "__dt__", 6) == 0)
+ return complete_object_dtor;
+ else
+ return 0;
+ }
+
+ static enum ctor_kinds
+ gnuv2_is_constructor_name (const char *name)
+ {
+ if ((name[0] == '_' && name[1] == '_'
+ && (isdigit (name[2]) || strchr ("Qt", name[2])))
+ || strncmp (name, "__ct__", 6) == 0)
+ return complete_object_ctor;
+ else
+ return 0;
+ }
+
+ static int
+ gnuv2_is_vtable_name (const char *name)
+ {
+ return (((name)[0] == '_'
+ && (((name)[1] == 'V' && (name)[2] == 'T')
+ || ((name)[1] == 'v' && (name)[2] == 't'))
+ && is_cplus_marker ((name)[3])) ||
+ ((name)[0] == '_' && (name)[1] == '_'
+ && (name)[2] == 'v' && (name)[3] == 't' && (name)[4] == '_'));
+ }
+
+ static int
+ gnuv2_is_operator_name (const char *name)
+ {
+ return strncmp (name, "operator", 8) == 0;
+ }
+
+ \f
+ /* Return a virtual function as a value.
+ ARG1 is the object which provides the virtual function
+ table pointer. *ARG1P is side-effected in calling this function.
+ F is the list of member functions which contains the desired virtual
+ function.
+ J is an index into F which provides the desired virtual function.
+
+ TYPE is the type in which F is located. */
+ static value_ptr
+ gnuv2_virtual_fn_field (value_ptr * arg1p, struct fn_field * f, int j,
+ struct type * type, int offset)
+ {
+ value_ptr arg1 = *arg1p;
+ struct type *type1 = check_typedef (VALUE_TYPE (arg1));
+
+
+ struct type *entry_type;
+ /* First, get the virtual function table pointer. That comes
+ with a strange type, so cast it to type `pointer to long' (which
+ should serve just fine as a function type). Then, index into
+ the table, and convert final value to appropriate function type. */
+ value_ptr entry, vfn, vtbl;
+ value_ptr vi = value_from_longest (builtin_type_int,
+ (LONGEST) TYPE_FN_FIELD_VOFFSET (f, j));
+ struct type *fcontext = TYPE_FN_FIELD_FCONTEXT (f, j);
+ struct type *context;
+ if (fcontext == NULL)
+ /* We don't have an fcontext (e.g. the program was compiled with
+ g++ version 1). Try to get the vtbl from the TYPE_VPTR_BASETYPE.
+ This won't work right for multiple inheritance, but at least we
+ should do as well as GDB 3.x did. */
+ fcontext = TYPE_VPTR_BASETYPE (type);
+ context = lookup_pointer_type (fcontext);
+ /* Now context is a pointer to the basetype containing the vtbl. */
+ if (TYPE_TARGET_TYPE (context) != type1)
+ {
+ value_ptr tmp = value_cast (context, value_addr (arg1));
+ VALUE_POINTED_TO_OFFSET (tmp) = 0;
+ arg1 = value_ind (tmp);
+ type1 = check_typedef (VALUE_TYPE (arg1));
+ }
+
+ context = type1;
+ /* Now context is the basetype containing the vtbl. */
+
+ /* This type may have been defined before its virtual function table
+ was. If so, fill in the virtual function table entry for the
+ type now. */
+ if (TYPE_VPTR_FIELDNO (context) < 0)
+ fill_in_vptr_fieldno (context);
+
+ /* The virtual function table is now an array of structures
+ which have the form { int16 offset, delta; void *pfn; }. */
+ vtbl = value_primitive_field (arg1, 0, TYPE_VPTR_FIELDNO (context),
+ TYPE_VPTR_BASETYPE (context));
+
+ /* With older versions of g++, the vtbl field pointed to an array
+ of structures. Nowadays it points directly to the structure. */
+ if (TYPE_CODE (VALUE_TYPE (vtbl)) == TYPE_CODE_PTR
+ && TYPE_CODE (TYPE_TARGET_TYPE (VALUE_TYPE (vtbl))) == TYPE_CODE_ARRAY)
+ {
+ /* Handle the case where the vtbl field points to an
+ array of structures. */
+ vtbl = value_ind (vtbl);
+
+ /* Index into the virtual function table. This is hard-coded because
+ looking up a field is not cheap, and it may be important to save
+ time, e.g. if the user has set a conditional breakpoint calling
+ a virtual function. */
+ entry = value_subscript (vtbl, vi);
+ }
+ else
+ {
+ /* Handle the case where the vtbl field points directly to a structure. */
+ vtbl = value_add (vtbl, vi);
+ entry = value_ind (vtbl);
+ }
+
+ entry_type = check_typedef (VALUE_TYPE (entry));
+
+ if (TYPE_CODE (entry_type) == TYPE_CODE_STRUCT)
+ {
+ /* Move the `this' pointer according to the virtual function table. */
+ VALUE_OFFSET (arg1) += value_as_long (value_field (entry, 0));
+
+ if (!VALUE_LAZY (arg1))
+ {
+ VALUE_LAZY (arg1) = 1;
+ value_fetch_lazy (arg1);
+ }
+
+ vfn = value_field (entry, 2);
+ }
+ else if (TYPE_CODE (entry_type) == TYPE_CODE_PTR)
+ vfn = entry;
+ else
+ error ("I'm confused: virtual function table has bad type");
+ /* Reinstantiate the function pointer with the correct type. */
+ VALUE_TYPE (vfn) = lookup_pointer_type (TYPE_FN_FIELD_TYPE (f, j));
+
+ *arg1p = arg1;
+ return vfn;
+ }
+
+
+ struct type *
+ gnuv2_value_rtti_type (value_ptr v, int *full, int *top, int *using_enc)
+ {
+ struct type *known_type;
+ struct type *rtti_type;
+ CORE_ADDR coreptr;
+ value_ptr vp;
+ int using_enclosing = 0;
+ long top_offset = 0;
+ char rtti_type_name[256];
+ CORE_ADDR vtbl;
+ struct minimal_symbol *minsym;
+ struct symbol *sym;
+ char *demangled_name;
+ struct type *btype;
+
+ if (full)
+ *full = 0;
+ if (top)
+ *top = -1;
+ if (using_enc)
+ *using_enc = 0;
+
+ /* Get declared type */
+ known_type = VALUE_TYPE (v);
+ CHECK_TYPEDEF (known_type);
+ /* RTTI works only or class objects */
+ if (TYPE_CODE (known_type) != TYPE_CODE_CLASS)
+ return NULL;
+
+ /* Plan on this changing in the future as i get around to setting
+ the vtables properly for G++ compiled stuff. Also, I'll be using
+ the type info functions, which are always right. Deal with it
+ until then. */
+
+ /* If the type has no vptr fieldno, try to get it filled in */
+ if (TYPE_VPTR_FIELDNO(known_type) < 0)
+ fill_in_vptr_fieldno(known_type);
+
+ /* If we still can't find one, give up */
+ if (TYPE_VPTR_FIELDNO(known_type) < 0)
+ return NULL;
+
+ /* Make sure our basetype and known type match, otherwise, cast
+ so we can get at the vtable properly.
+ */
+ btype = TYPE_VPTR_BASETYPE (known_type);
+ CHECK_TYPEDEF (btype);
+ if (btype != known_type )
+ {
+ v = value_cast (btype, v);
+ if (using_enc)
+ *using_enc=1;
+ }
+ /*
+ We can't use value_ind here, because it would want to use RTTI, and
+ we'd waste a bunch of time figuring out we already know the type.
+ Besides, we don't care about the type, just the actual pointer
+ */
+ if (VALUE_ADDRESS (value_field (v, TYPE_VPTR_FIELDNO (known_type))) == 0)
+ return NULL;
+
+ /*
+ If we are enclosed by something that isn't us, adjust the
+ address properly and set using_enclosing.
+ */
+ if (VALUE_ENCLOSING_TYPE(v) != VALUE_TYPE(v))
+ {
+ value_ptr tempval;
+ int bitpos = TYPE_BASECLASS_BITPOS (known_type,
+ TYPE_VPTR_FIELDNO (known_type));
+ tempval=value_field (v, TYPE_VPTR_FIELDNO(known_type));
+ VALUE_ADDRESS(tempval) += bitpos / 8;
+ vtbl=value_as_pointer (tempval);
+ using_enclosing=1;
+ }
+ else
+ {
+ vtbl=value_as_pointer(value_field(v,TYPE_VPTR_FIELDNO(known_type)));
+ using_enclosing=0;
+ }
+
+ /* Try to find a symbol that is the vtable */
+ minsym=lookup_minimal_symbol_by_pc(vtbl);
+ if (minsym==NULL
+ || (demangled_name=SYMBOL_NAME(minsym))==NULL
+ || !is_vtable_name (demangled_name))
+ return NULL;
+
+ /* If we just skip the prefix, we get screwed by namespaces */
+ demangled_name=cplus_demangle(demangled_name,DMGL_PARAMS|DMGL_ANSI);
+ *(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)
+ {
+ if (top)
+ *top=TYPE_BASECLASS_BITPOS(rtti_type,TYPE_VPTR_FIELDNO(rtti_type))/8;
+ if (top && ((*top) >0))
+ {
+ if (TYPE_LENGTH(rtti_type) > TYPE_LENGTH(known_type))
+ {
+ if (full)
+ *full=0;
+ }
+ else
+ {
+ if (full)
+ *full=1;
+ }
+ }
+ }
+ else
+ {
+ if (full)
+ *full=1;
+ }
+ if (using_enc)
+ *using_enc=using_enclosing;
+
+ return rtti_type;
+ }
+
+
+ static void
+ init_gnuv2_ops (void)
+ {
+ gnu_v2_abi_ops.shortname = "gnu-v2";
+ gnu_v2_abi_ops.longname = "GNU G++ Version 2 ABI";
+ gnu_v2_abi_ops.doc = "G++ Version 2 ABI";
+ gnu_v2_abi_ops.is_destructor_name = gnuv2_is_destructor_name;
+ gnu_v2_abi_ops.is_constructor_name = gnuv2_is_constructor_name;
+ gnu_v2_abi_ops.is_vtable_name = gnuv2_is_vtable_name;
+ gnu_v2_abi_ops.is_operator_name = gnuv2_is_operator_name;
+ gnu_v2_abi_ops.virtual_fn_field = gnuv2_virtual_fn_field;
+ gnu_v2_abi_ops.rtti_type = gnuv2_value_rtti_type;
+ }
+
+ void
+ _initialize_gnu_v2_abi (void)
+ {
+ init_gnuv2_ops ();
+ register_cp_abi (gnu_v2_abi_ops);
+ switch_to_cp_abi ("gnu-v2");
+ }
Index: gdb/hpacc-abi.c
===================================================================
RCS file: hpacc-abi.c
diff -N hpacc-abi.c
*** gdb/hpacc-abi.c Tue May 5 13:32:27 1998
--- gdb/hpacc-abi.c Tue Apr 24 17:18:07 2001
***************
*** 0 ****
--- 1,321 ----
+ /* Abstraction of HP aCC ABI.
+ Contributed by Daniel Berlin <dberlin@redhat.com>
+ Most of the real code is from HP, i've just fiddled it to fit in
+ the C++ ABI abstraction framework.
+
+ Copyright 2001 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or
+ modify
+ it under the terms of the GNU General Public License as published
+ by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+ #include "defs.h"
+ #include "value.h"
+ #include "gdb_regex.h"
+ #include "gdb_string.h"
+ #include "gdbtypes.h"
+ #include "gdbcore.h"
+ #include "cp-abi.h"
+
+ struct cp_abi_ops hpacc_abi_ops;
+
+ /* It appears the is_*_name stuff is never used when we try the hpACC
+ * ABI. As such, I have no clue what the real answers are. Shouldn't
+ * have any more effect than it does now. */
+ static regex_t constructor_pattern;
+ static regex_t destructor_pattern;
+ static regex_t operator_pattern;
+
+ static enum dtor_kinds
+ hpacc_is_destructor_name (const char *name)
+ {
+ if (regexec (&destructor_pattern, name, 0, 0, 0) == 0)
+ return complete_object_dtor;
+ else
+ return 0;
+ }
+
+ static enum ctor_kinds
+ hpacc_is_constructor_name (const char *name)
+ {
+ if (regexec (&constructor_pattern, name, 0, 0, 0) == 0)
+ return complete_object_ctor;
+ else
+ return 0;
+ }
+
+ static int
+ hpacc_is_operator_name (const char *name)
+ {
+ return regexec (&operator_pattern, name, 0, 0, 0) == 0;
+ }
+
+ static int
+ hpacc_is_vtable_name (const char *name)
+ {
+ return strcmp (name,
+ "This will never match anything, please fill it in") == 0;
+ }
+
+ /* Return a virtual function as a value.
+ ARG1 is the object which provides the virtual function
+ table pointer. *ARG1P is side-effected in calling this function.
+ F is the list of member functions which contains the desired virtual
+ function.
+ J is an index into F which provides the desired virtual function.
+
+ TYPE is the type in which F is located. */
+ static value_ptr
+ hpacc_virtual_fn_field (value_ptr * arg1p, struct fn_field * f, int j,
+ struct type * type, int offset)
+ {
+ value_ptr arg1 = *arg1p;
+ struct type *type1 = check_typedef (VALUE_TYPE (arg1));
+
+ /* Deal with HP/Taligent runtime model for virtual functions */
+ value_ptr vp;
+ value_ptr argp; /* arg1 cast to base */
+ CORE_ADDR coreptr; /* pointer to target address */
+ int class_index; /* which class segment pointer to use */
+ struct type *ftype = TYPE_FN_FIELD_TYPE (f, j); /* method type */
+
+ argp = value_cast (type, *arg1p);
+
+ if (VALUE_ADDRESS (argp) == 0)
+ error ("Address of object is null; object may not have been created.");
+
+ /* pai: FIXME -- 32x64 possible problem? */
+ /* First word (4 bytes) in object layout is the vtable pointer */
+ coreptr = *(CORE_ADDR *) (VALUE_CONTENTS (argp)); /* pai: (temp) */
+ /* + offset + VALUE_EMBEDDED_OFFSET (argp)); */
+
+ if (!coreptr)
+ error
+ ("Virtual table pointer is null for object; object may not have been created.");
+
+ /* pai/1997-05-09
+ * FIXME: The code here currently handles only
+ * the non-RRBC case of the Taligent/HP runtime spec; when RRBC
+ * is introduced, the condition for the "if" below will have to
+ * be changed to be a test for the RRBC case. */
+
+ if (1)
+ {
+ /* Non-RRBC case; the virtual function pointers are stored at fixed
+ * offsets in the virtual table. */
+
+ /* Retrieve the offset in the virtual table from the debug
+ * info. The offset of the vfunc's entry is in words from
+ * the beginning of the vtable; but first we have to adjust
+ * by HP_ACC_VFUNC_START to account for other entries */
+
+ /* pai: FIXME: 32x64 problem here, a word may be 8 bytes in
+ * which case the multiplier should be 8 and values should be long */
+ vp = value_at (builtin_type_int,
+ coreptr + 4 * (TYPE_FN_FIELD_VOFFSET (f, j) +
+ HP_ACC_VFUNC_START), NULL);
+
+ coreptr = *(CORE_ADDR *) (VALUE_CONTENTS (vp));
+ /* coreptr now contains the address of the virtual function */
+ /* (Actually, it contains the pointer to the plabel for the function. */
+ }
+ else
+ {
+ /* RRBC case; the virtual function pointers are found by double
+ * indirection through the class segment tables. */
+
+ /* Choose class segment depending on type we were passed */
+ class_index = class_index_in_primary_list (type);
+
+ /* Find class segment pointer. These are in the vtable slots after
+ * some other entries, so adjust by HP_ACC_VFUNC_START for that. */
+ /* pai: FIXME 32x64 problem here, if words are 8 bytes long
+ * the multiplier below has to be 8 and value should be long. */
+ vp = value_at (builtin_type_int,
+ coreptr + 4 * (HP_ACC_VFUNC_START + class_index), NULL);
+ /* Indirect once more, offset by function index */
+ /* pai: FIXME 32x64 problem here, again multiplier could be 8 and value long */
+ coreptr =
+ *(CORE_ADDR *) (VALUE_CONTENTS (vp) +
+ 4 * TYPE_FN_FIELD_VOFFSET (f, j));
+ vp = value_at (builtin_type_int, coreptr, NULL);
+ coreptr = *(CORE_ADDR *) (VALUE_CONTENTS (vp));
+
+ /* coreptr now contains the address of the virtual function */
+ /* (Actually, it contains the pointer to the plabel for the function.) */
+
+ }
+
+ if (!coreptr)
+ error ("Address of virtual function is null; error in virtual table?");
+
+ /* Wrap this addr in a value and return pointer */
+ vp = allocate_value (ftype);
+ VALUE_TYPE (vp) = ftype;
+ VALUE_ADDRESS (vp) = coreptr;
+
+ /* pai: (temp) do we need the value_ind stuff in value_fn_field? */
+ return vp;
+ }
+
+
+ static struct type *
+ hpacc_value_rtti_type (value_ptr v, int *full, int *top, int *using_enc)
+ {
+ struct type *known_type;
+ struct type *rtti_type;
+ CORE_ADDR coreptr;
+ value_ptr vp;
+ int using_enclosing = 0;
+ long top_offset = 0;
+ char rtti_type_name[256];
+
+ if (full)
+ *full = 0;
+ if (top)
+ *top = -1;
+ if (using_enc)
+ *using_enc = 0;
+
+ /* Get declared type */
+ known_type = VALUE_TYPE (v);
+ CHECK_TYPEDEF (known_type);
+ /* RTTI works only or class objects */
+ if (TYPE_CODE (known_type) != TYPE_CODE_CLASS)
+ return NULL;
+
+ /* If neither the declared type nor the enclosing type of the
+ * value structure has a HP ANSI C++ style virtual table,
+ * we can't do anything. */
+ if (!TYPE_HAS_VTABLE (known_type))
+ {
+ known_type = VALUE_ENCLOSING_TYPE (v);
+ CHECK_TYPEDEF (known_type);
+ if ((TYPE_CODE (known_type) != TYPE_CODE_CLASS) ||
+ !TYPE_HAS_VTABLE (known_type))
+ return NULL; /* No RTTI, or not HP-compiled types */
+ CHECK_TYPEDEF (known_type);
+ using_enclosing = 1;
+ }
+
+ if (using_enclosing && using_enc)
+ *using_enc = 1;
+
+ /* First get the virtual table address */
+ coreptr = *(CORE_ADDR *) ((VALUE_CONTENTS_ALL (v))
+ + VALUE_OFFSET (v)
+ + (using_enclosing
+ ? 0
+ : VALUE_EMBEDDED_OFFSET (v)));
+ if (coreptr == 0)
+ /* return silently -- maybe called on gdb-generated value */
+ return NULL;
+
+ /* Fetch the top offset of the object */
+ /* FIXME possible 32x64 problem with pointer size & arithmetic */
+ vp = value_at (builtin_type_int,
+ coreptr + 4 * HP_ACC_TOP_OFFSET_OFFSET,
+ VALUE_BFD_SECTION (v));
+ top_offset = value_as_long (vp);
+ if (top)
+ *top = top_offset;
+
+ /* Fetch the typeinfo pointer */
+ /* FIXME possible 32x64 problem with pointer size & arithmetic */
+ vp = value_at (builtin_type_int, coreptr + 4 * HP_ACC_TYPEINFO_OFFSET,
+ VALUE_BFD_SECTION (v));
+ /* Indirect through the typeinfo pointer and retrieve the pointer
+ * to the string name */
+ coreptr = *(CORE_ADDR *) (VALUE_CONTENTS (vp));
+ if (!coreptr)
+ error ("Retrieved null typeinfo pointer in trying to determine "
+ "run-time type");
+ /* 4 -> offset of name field */
+ vp = value_at (builtin_type_int, coreptr + 4, VALUE_BFD_SECTION (v));
+ /* FIXME possible 32x64 problem */
+
+ coreptr = *(CORE_ADDR *) (VALUE_CONTENTS (vp));
+
+ read_memory_string (coreptr, rtti_type_name, 256);
+
+ if (strlen (rtti_type_name) == 0)
+ error ("Retrieved null type name from typeinfo");
+
+ /* search for type */
+ rtti_type = lookup_typename (rtti_type_name, (struct block *) 0, 1);
+
+ if (!rtti_type)
+ error ("Could not find run-time type: invalid type name %s in typeinfo??",
+ rtti_type_name);
+ CHECK_TYPEDEF (rtti_type);
+ #if 0
+ printf ("RTTI type name %s, tag %s, full? %d\n", TYPE_NAME (rtti_type),
+ TYPE_TAG_NAME (rtti_type), full ? *full : -1);
+ #endif
+ /* Check whether we have the entire object */
+ if (full /* Non-null pointer passed */
+ &&
+ /* Either we checked on the whole object in hand and found the
+ top offset to be zero */
+ (((top_offset == 0) &&
+ using_enclosing &&
+ TYPE_LENGTH (known_type) == TYPE_LENGTH (rtti_type))
+ ||
+ /* Or we checked on the embedded object and top offset was the
+ same as the embedded offset */
+ ((top_offset == VALUE_EMBEDDED_OFFSET (v)) &&
+ !using_enclosing &&
+ TYPE_LENGTH (VALUE_ENCLOSING_TYPE (v)) == TYPE_LENGTH (rtti_type))))
+
+ *full = 1;
+
+ return rtti_type;
+ }
+
+
+ static void
+ init_hpacc_ops (void)
+ {
+ hpacc_abi_ops.shortname = "hpaCC";
+ hpacc_abi_ops.longname = "HP aCC ABI";
+ hpacc_abi_ops.doc = "HP aCC ABI";
+ hpacc_abi_ops.is_destructor_name = hpacc_is_destructor_name;
+ hpacc_abi_ops.is_constructor_name = hpacc_is_constructor_name;
+ hpacc_abi_ops.is_vtable_name = hpacc_is_vtable_name;
+ hpacc_abi_ops.is_operator_name = hpacc_is_operator_name;
+ hpacc_abi_ops.virtual_fn_field = hpacc_virtual_fn_field;
+ hpacc_abi_ops.rtti_type = hpacc_value_rtti_type;
+ }
+
+
+ void
+ _initialize_hpacc_abi (void)
+ {
+ init_hpacc_ops ();
+
+ regcomp (&constructor_pattern,
+ "^This will never match anything, please fill it in$", REG_NOSUB);
+
+ regcomp (&destructor_pattern,
+ "^This will never match anything, please fill it in$", REG_NOSUB);
+
+ regcomp (&operator_pattern,
+ "^This will never match anything, please fill it in$", REG_NOSUB);
+
+ register_cp_abi (hpacc_abi_ops);
+ }
Index: gdb/jv-typeprint.c
===================================================================
RCS file: /cvs/src/src/gdb/jv-typeprint.c,v
retrieving revision 1.4
diff -c -r1.4 jv-typeprint.c
*** gdb/jv-typeprint.c 2001/03/06 08:21:09 1.4
--- gdb/jv-typeprint.c 2001/04/25 00:18:07
***************
*** 28,33 ****
--- 28,34 ----
#include "gdb_string.h"
#include "typeprint.h"
#include "c-lang.h"
+ #include "cp-abi.h"

/* Local functions */

***************
*** 224,235 ****

physname = TYPE_FN_FIELD_PHYSNAME (f, j);

! is_full_physname_constructor =
! ((physname[0] == '_' && physname[1] == '_'
! && strchr ("0123456789Qt", physname[2]))
! || STREQN (physname, "__ct__", 6)
! || DESTRUCTOR_PREFIX_P (physname)
! || STREQN (physname, "__dt__", 6));

QUIT;

--- 225,233 ----

physname = TYPE_FN_FIELD_PHYSNAME (f, j);

! is_full_physname_constructor
! = (is_constructor_name (physname)
! || is_destructor_name (physname));

QUIT;

Index: gdb/linespec.c
===================================================================
RCS file: /cvs/src/src/gdb/linespec.c,v
retrieving revision 1.10
diff -c -r1.10 linespec.c
*** gdb/linespec.c 2001/03/23 00:41:01 1.10
--- gdb/linespec.c 2001/04/25 00:18:09
***************
*** 29,34 ****
--- 29,35 ----
#include "demangle.h"
#include "value.h"
#include "completer.h"
+ #include "cp-abi.h"

/* Prototype for one function in parser-defs.h,
instead of including that entire file. */
***************
*** 166,172 ****
phys_name = TYPE_FN_FIELD_PHYSNAME (f, field_counter);

/* Destructor is handled by caller, dont add it to the list */
! if (DESTRUCTOR_PREFIX_P (phys_name))
continue;

sym_arr[i1] = lookup_symbol (phys_name,
--- 167,173 ----
phys_name = TYPE_FN_FIELD_PHYSNAME (f, field_counter);

/* Destructor is handled by caller, dont add it to the list */
! if (is_destructor_name (phys_name) != 0)
continue;

sym_arr[i1] = lookup_symbol (phys_name,
***************
*** 801,807 ****
{
char *tmp;

! if (OPNAME_PREFIX_P (copy))
{
tmp = (char *) alloca (strlen (copy + 3) + 9);
strcpy (tmp, "operator ");
--- 802,808 ----
{
char *tmp;

! if (is_operator_name (copy))
{
tmp = (char *) alloca (strlen (copy + 3) + 9);
strcpy (tmp, "operator ");
Index: gdb/symtab.c
===================================================================
RCS file: /cvs/src/src/gdb/symtab.c,v
retrieving revision 1.34
diff -c -r1.34 symtab.c
*** gdb/symtab.c 2001/04/01 19:50:50 1.34
--- gdb/symtab.c 2001/04/25 00:18:13
***************
*** 45,50 ****
--- 45,51 ----
#include "gdb_string.h"
#include "gdb_stat.h"
#include <ctype.h>
+ #include "cp-abi.h"

/* Prototype for one function in parser-defs.h,
instead of including that entire file. */
***************
*** 288,307 ****
int is_full_physname_constructor;

int is_constructor;
! int is_destructor = DESTRUCTOR_PREFIX_P (physname);
/* Need a new type prefix. */
char *const_prefix = method->is_const ? "C" : "";
char *volatile_prefix = method->is_volatile ? "V" : "";
char buf[20];
int len = (newname == NULL ? 0 : strlen (newname));

! if (OPNAME_PREFIX_P (field_name))
return xstrdup (physname);

! is_full_physname_constructor =
! ((physname[0] == '_' && physname[1] == '_' &&
! (isdigit (physname[2]) || physname[2] == 'Q' || physname[2] == 't'))
! || (strncmp (physname, "__ct", 4) == 0));

is_constructor =
is_full_physname_constructor || (newname && STREQ (field_name, newname));
--- 289,305 ----
int is_full_physname_constructor;

int is_constructor;
! int is_destructor = is_destructor_name (physname);
/* Need a new type prefix. */
char *const_prefix = method->is_const ? "C" : "";
char *volatile_prefix = method->is_volatile ? "V" : "";
char buf[20];
int len = (newname == NULL ? 0 : strlen (newname));

! if (is_operator_name (field_name))
return xstrdup (physname);

! is_full_physname_constructor = is_constructor_name (physname);

is_constructor =
is_full_physname_constructor || (newname && STREQ (field_name, newname));
Index: gdb/symtab.h
===================================================================
RCS file: /cvs/src/src/gdb/symtab.h,v
retrieving revision 1.20
diff -c -r1.20 symtab.h
*** gdb/symtab.h 2001/03/07 02:57:08 1.20
--- gdb/symtab.h 2001/04/25 00:18:15
***************
*** 1046,1075 ****

#define VTBL_FNADDR_OFFSET 2

- /* Macro that yields non-zero value iff NAME is the prefix for C++ operator
- names. If you leave out the parenthesis here you will lose! */
- #define OPNAME_PREFIX_P(NAME) \
- (!strncmp (NAME, "operator", 8))
-
- /* Macro that yields non-zero value iff NAME is the prefix for C++ vtbl
- names. Note that this macro is g++ specific (FIXME).
- '_vt$' is the old cfront-style vtables; '_VT$' is the new
- style, using thunks (where '$' is really CPLUS_MARKER). */
-
- #define VTBL_PREFIX_P(NAME) \
- (((NAME)[0] == '_' \
- && (((NAME)[1] == 'V' && (NAME)[2] == 'T') \
- || ((NAME)[1] == 'v' && (NAME)[2] == 't')) \
- && is_cplus_marker ((NAME)[3])) || ((NAME)[0]=='_' && (NAME)[1]=='_' \
- && (NAME)[2]=='v' && (NAME)[3]=='t' && (NAME)[4]=='_'))
-
- /* Macro that yields non-zero value iff NAME is the prefix for C++ destructor
- names. Note that this macro is g++ specific (FIXME). */
-
- #define DESTRUCTOR_PREFIX_P(NAME) \
- ((NAME)[0] == '_' && is_cplus_marker ((NAME)[1]) && (NAME)[2] == '_')
- \f
-
/* External variables and functions for the objects described above. */

/* This symtab variable specifies the current file for printing source lines */
--- 1046,1051 ----
Index: gdb/typeprint.c
===================================================================
RCS file: /cvs/src/src/gdb/typeprint.c,v
retrieving revision 1.8
diff -c -r1.8 typeprint.c
*** gdb/typeprint.c 2001/03/07 02:57:08 1.8
--- gdb/typeprint.c 2001/04/25 00:18:15
***************
*** 31,36 ****
--- 31,37 ----
#include "gdbcmd.h"
#include "target.h"
#include "language.h"
+ #include "cp-abi.h"

#include "gdb_string.h"
#include <errno.h>
Index: gdb/valops.c
===================================================================
RCS file: /cvs/src/src/gdb/valops.c,v
retrieving revision 1.34
diff -c -r1.34 valops.c
*** gdb/valops.c 2001/03/19 20:08:16 1.34
--- gdb/valops.c 2001/04/25 00:18:19
***************
*** 31,36 ****
--- 31,37 ----
#include "language.h"
#include "gdbcmd.h"
#include "regcache.h"
+ #include "cp-abi.h"

#include <errno.h>
#include "gdb_string.h"
***************
*** 3110,3335 ****
return 0;
}

-
- /* Find the real run-time type of a value using RTTI.
- * V is a pointer to the value.
- * A pointer to the struct type entry of the run-time type
- * is returneed.
- * FULL is a flag that is set only if the value V includes
- * the entire contents of an object of the RTTI type.
- * TOP is the offset to the top of the enclosing object of
- * the real run-time type. This offset may be for the embedded
- * object, or for the enclosing object of V.
- * USING_ENC is the flag that distinguishes the two cases.
- * If it is 1, then the offset is for the enclosing object,
- * otherwise for the embedded object.
- *
- */
-
- struct type *
- value_rtti_type (value_ptr v, int *full, int *top, int *using_enc)
- {
- struct type *known_type;
- struct type *rtti_type;
- CORE_ADDR coreptr;
- value_ptr vp;
- int using_enclosing = 0;
- long top_offset = 0;
- char rtti_type_name[256];
-
- if (full)
- *full = 0;
- if (top)
- *top = -1;
- if (using_enc)
- *using_enc = 0;
-
- /* Get declared type */
- known_type = VALUE_TYPE (v);
- CHECK_TYPEDEF (known_type);
- /* RTTI works only or class objects */
- if (TYPE_CODE (known_type) != TYPE_CODE_CLASS)
- return NULL;
- if (TYPE_HAS_VTABLE(known_type))
- {
- /* If neither the declared type nor the enclosing type of the
- * value structure has a HP ANSI C++ style virtual table,
- * we can't do anything. */
- if (!TYPE_HAS_VTABLE (known_type))
- {
- known_type = VALUE_ENCLOSING_TYPE (v);
- CHECK_TYPEDEF (known_type);
- if ((TYPE_CODE (known_type) != TYPE_CODE_CLASS) ||
- !TYPE_HAS_VTABLE (known_type))
- return NULL; /* No RTTI, or not HP-compiled types */
- CHECK_TYPEDEF (known_type);
- using_enclosing = 1;
- }
-
- if (using_enclosing && using_enc)
- *using_enc = 1;
-
- /* First get the virtual table address */
- coreptr = *(CORE_ADDR *) ((VALUE_CONTENTS_ALL (v))
- + VALUE_OFFSET (v)
- + (using_enclosing ? 0 : VALUE_EMBEDDED_OFFSET (v)));
- if (coreptr == 0)
- return NULL; /* return silently -- maybe called on gdb-generated value */
-
- /* Fetch the top offset of the object */
- /* FIXME possible 32x64 problem with pointer size & arithmetic */
- vp = value_at (builtin_type_int,
- coreptr + 4 * HP_ACC_TOP_OFFSET_OFFSET,
- VALUE_BFD_SECTION (v));
- top_offset = value_as_long (vp);
- if (top)
- *top = top_offset;
-
- /* Fetch the typeinfo pointer */
- /* FIXME possible 32x64 problem with pointer size & arithmetic */
- vp = value_at (builtin_type_int, coreptr + 4 * HP_ACC_TYPEINFO_OFFSET, VALUE_BFD_SECTION (v));
- /* Indirect through the typeinfo pointer and retrieve the pointer
- * to the string name */
- coreptr = *(CORE_ADDR *) (VALUE_CONTENTS (vp));
- if (!coreptr)
- error ("Retrieved null typeinfo pointer in trying to determine run-time type");
- vp = value_at (builtin_type_int, coreptr + 4, VALUE_BFD_SECTION (v)); /* 4 -> offset of name field */
- /* FIXME possible 32x64 problem */
-
- coreptr = *(CORE_ADDR *) (VALUE_CONTENTS (vp));
-
- read_memory_string (coreptr, rtti_type_name, 256);
-
- if (strlen (rtti_type_name) == 0)
- error ("Retrieved null type name from typeinfo");
-
- /* search for type */
- rtti_type = lookup_typename (rtti_type_name, (struct block *) 0, 1);
-
- if (!rtti_type)
- error ("Could not find run-time type: invalid type name %s in typeinfo??", rtti_type_name);
- CHECK_TYPEDEF (rtti_type);
- #if 0
- printf ("RTTI type name %s, tag %s, full? %d\n", TYPE_NAME (rtti_type), TYPE_TAG_NAME (rtti_type), full ? *full : -1);
- #endif
- /* Check whether we have the entire object */
- if (full /* Non-null pointer passed */
- &&
- /* Either we checked on the whole object in hand and found the
- top offset to be zero */
- (((top_offset == 0) &&
- using_enclosing &&
- TYPE_LENGTH (known_type) == TYPE_LENGTH (rtti_type))
- ||
- /* Or we checked on the embedded object and top offset was the
- same as the embedded offset */
- ((top_offset == VALUE_EMBEDDED_OFFSET (v)) &&
- !using_enclosing &&
- TYPE_LENGTH (VALUE_ENCLOSING_TYPE (v)) == TYPE_LENGTH (rtti_type))))
-
- *full = 1;
- }
- else
- /*
- Right now this is G++ RTTI. Plan on this changing in the
- future as i get around to setting the vtables properly for G++
- compiled stuff. Also, i'll be using the type info functions,
- which are always right. Deal with it until then.
- */
- {
- CORE_ADDR vtbl;
- struct minimal_symbol *minsym;
- struct symbol *sym;
- char *demangled_name;
- struct type *btype;
- /* If the type has no vptr fieldno, try to get it filled in */
- if (TYPE_VPTR_FIELDNO(known_type) < 0)
- fill_in_vptr_fieldno(known_type);
-
- /* If we still can't find one, give up */
- if (TYPE_VPTR_FIELDNO(known_type) < 0)
- return NULL;
-
- /* Make sure our basetype and known type match, otherwise, cast
- so we can get at the vtable properly.
- */
- btype = TYPE_VPTR_BASETYPE (known_type);
- CHECK_TYPEDEF (btype);
- if (btype != known_type )
- {
- v = value_cast (btype, v);
- if (using_enc)
- *using_enc=1;
- }
- /*
- We can't use value_ind here, because it would want to use RTTI, and
- we'd waste a bunch of time figuring out we already know the type.
- Besides, we don't care about the type, just the actual pointer
- */
- if (VALUE_ADDRESS (value_field (v, TYPE_VPTR_FIELDNO (known_type))) == 0)
- return NULL;
-
- /*
- If we are enclosed by something that isn't us, adjust the
- address properly and set using_enclosing.
- */
- if (VALUE_ENCLOSING_TYPE(v) != VALUE_TYPE(v))
- {
- value_ptr tempval;
- tempval=value_field(v,TYPE_VPTR_FIELDNO(known_type));
- VALUE_ADDRESS(tempval)+=(TYPE_BASECLASS_BITPOS(known_type,TYPE_VPTR_FIELDNO(known_type))/8);
- vtbl=value_as_pointer(tempval);
- using_enclosing=1;
- }
- else
- {
- vtbl=value_as_pointer(value_field(v,TYPE_VPTR_FIELDNO(known_type)));
- using_enclosing=0;
- }
-
- /* Try to find a symbol that is the vtable */
- minsym=lookup_minimal_symbol_by_pc(vtbl);
- if (minsym==NULL || (demangled_name=SYMBOL_NAME(minsym))==NULL || !VTBL_PREFIX_P(demangled_name))
- return NULL;
-
- /* If we just skip the prefix, we get screwed by namespaces */
- demangled_name=cplus_demangle(demangled_name,DMGL_PARAMS|DMGL_ANSI);
- *(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)
- {
- if (top)
- *top=TYPE_BASECLASS_BITPOS(rtti_type,TYPE_VPTR_FIELDNO(rtti_type))/8;
- if (top && ((*top) >0))
- {
- if (TYPE_LENGTH(rtti_type) > TYPE_LENGTH(known_type))
- {
- if (full)
- *full=0;
- }
- else
- {
- if (full)
- *full=1;
- }
- }
- }
- else
- {
- if (full)
- *full=1;
- }
- if (using_enc)
- *using_enc=using_enclosing;
- }
- return rtti_type;
- }

/* Given a pointer value V, find the real (RTTI) type
of the object it points to.
--- 3111,3116 ----
Index: gdb/value.h
===================================================================
RCS file: /cvs/src/src/gdb/value.h,v
retrieving revision 1.17
diff -c -r1.17 value.h
*** gdb/value.h 2001/03/06 08:21:18 1.17
--- gdb/value.h 2001/04/25 00:18:20
***************
*** 367,373 ****
extern value_ptr value_primitive_field (value_ptr arg1, int offset,
int fieldno, struct type *arg_type);

- extern struct type *value_rtti_type (value_ptr, int *, int *, int *);

extern struct type *value_rtti_target_type (value_ptr, int *, int *, int *);

--- 367,372 ----
***************
*** 446,455 ****

extern value_ptr value_fn_field (value_ptr * arg1p, struct fn_field *f,
int j, struct type *type, int offset);
-
- extern value_ptr value_virtual_fn_field (value_ptr * arg1p,
- struct fn_field *f, int j,
- struct type *type, int offset);

extern int binop_user_defined_p (enum exp_opcode op,
value_ptr arg1, value_ptr arg2);
--- 445,450 ----
Index: gdb/values.c
===================================================================
RCS file: /cvs/src/src/gdb/values.c,v
retrieving revision 1.14
diff -c -r1.14 values.c
*** gdb/values.c 2001/03/27 20:36:24 1.14
--- gdb/values.c 2001/04/25 00:18:21
***************
*** 45,51 ****

static void show_convenience (char *, int);

- static int vb_match (struct type *, int, struct type *);

/* The value-history records all the values printed
by print commands during this session. Each chunk
--- 45,50 ----
***************
*** 888,1084 ****
}

return v;
- }
-
- /* Return a virtual function as a value.
- ARG1 is the object which provides the virtual function
- table pointer. *ARG1P is side-effected in calling this function.
- F is the list of member functions which contains the desired virtual
- function.
- J is an index into F which provides the desired virtual function.
-
- TYPE is the type in which F is located. */
- value_ptr
- value_virtual_fn_field (value_ptr *arg1p, struct fn_field *f, int j,
- struct type *type, int offset)
- {
- value_ptr arg1 = *arg1p;
- struct type *type1 = check_typedef (VALUE_TYPE (arg1));
-
- if (TYPE_HAS_VTABLE (type))
- {
- /* Deal with HP/Taligent runtime model for virtual functions */
- value_ptr vp;
- value_ptr argp; /* arg1 cast to base */
- CORE_ADDR coreptr; /* pointer to target address */
- int class_index; /* which class segment pointer to use */
- struct type *ftype = TYPE_FN_FIELD_TYPE (f, j); /* method type */
-
- argp = value_cast (type, *arg1p);
-
- if (VALUE_ADDRESS (argp) == 0)
- error ("Address of object is null; object may not have been created.");
-
- /* pai: FIXME -- 32x64 possible problem? */
- /* First word (4 bytes) in object layout is the vtable pointer */
- coreptr = *(CORE_ADDR *) (VALUE_CONTENTS (argp)); /* pai: (temp) */
- /* + offset + VALUE_EMBEDDED_OFFSET (argp)); */
-
- if (!coreptr)
- error ("Virtual table pointer is null for object; object may not have been created.");
-
- /* pai/1997-05-09
- * FIXME: The code here currently handles only
- * the non-RRBC case of the Taligent/HP runtime spec; when RRBC
- * is introduced, the condition for the "if" below will have to
- * be changed to be a test for the RRBC case. */
-
- if (1)
- {
- /* Non-RRBC case; the virtual function pointers are stored at fixed
- * offsets in the virtual table. */
-
- /* Retrieve the offset in the virtual table from the debug
- * info. The offset of the vfunc's entry is in words from
- * the beginning of the vtable; but first we have to adjust
- * by HP_ACC_VFUNC_START to account for other entries */
-
- /* pai: FIXME: 32x64 problem here, a word may be 8 bytes in
- * which case the multiplier should be 8 and values should be long */
- vp = value_at (builtin_type_int,
- coreptr + 4 * (TYPE_FN_FIELD_VOFFSET (f, j) + HP_ACC_VFUNC_START), NULL);
-
- coreptr = *(CORE_ADDR *) (VALUE_CONTENTS (vp));
- /* coreptr now contains the address of the virtual function */
- /* (Actually, it contains the pointer to the plabel for the function. */
- }
- else
- {
- /* RRBC case; the virtual function pointers are found by double
- * indirection through the class segment tables. */
-
- /* Choose class segment depending on type we were passed */
- class_index = class_index_in_primary_list (type);
-
- /* Find class segment pointer. These are in the vtable slots after
- * some other entries, so adjust by HP_ACC_VFUNC_START for that. */
- /* pai: FIXME 32x64 problem here, if words are 8 bytes long
- * the multiplier below has to be 8 and value should be long. */
- vp = value_at (builtin_type_int,
- coreptr + 4 * (HP_ACC_VFUNC_START + class_index), NULL);
- /* Indirect once more, offset by function index */
- /* pai: FIXME 32x64 problem here, again multiplier could be 8 and value long */
- coreptr = *(CORE_ADDR *) (VALUE_CONTENTS (vp) + 4 * TYPE_FN_FIELD_VOFFSET (f, j));
- vp = value_at (builtin_type_int, coreptr, NULL);
- coreptr = *(CORE_ADDR *) (VALUE_CONTENTS (vp));
-
- /* coreptr now contains the address of the virtual function */
- /* (Actually, it contains the pointer to the plabel for the function.) */
-
- }
-
- if (!coreptr)
- error ("Address of virtual function is null; error in virtual table?");
-
- /* Wrap this addr in a value and return pointer */
- vp = allocate_value (ftype);
- VALUE_TYPE (vp) = ftype;
- VALUE_ADDRESS (vp) = coreptr;
-
- /* pai: (temp) do we need the value_ind stuff in value_fn_field? */
- return vp;
- }
- else
- { /* Not using HP/Taligent runtime conventions; so try to
- * use g++ conventions for virtual table */
-
- struct type *entry_type;
- /* First, get the virtual function table pointer. That comes
- with a strange type, so cast it to type `pointer to long' (which
- should serve just fine as a function type). Then, index into
- the table, and convert final value to appropriate function type. */
- value_ptr entry, vfn, vtbl;
- value_ptr vi = value_from_longest (builtin_type_int,
- (LONGEST) TYPE_FN_FIELD_VOFFSET (f, j));
- struct type *fcontext = TYPE_FN_FIELD_FCONTEXT (f, j);
- struct type *context;
- if (fcontext == NULL)
- /* We don't have an fcontext (e.g. the program was compiled with
- g++ version 1). Try to get the vtbl from the TYPE_VPTR_BASETYPE.
- This won't work right for multiple inheritance, but at least we
- should do as well as GDB 3.x did. */
- fcontext = TYPE_VPTR_BASETYPE (type);
- context = lookup_pointer_type (fcontext);
- /* Now context is a pointer to the basetype containing the vtbl. */
- if (TYPE_TARGET_TYPE (context) != type1)
- {
- value_ptr tmp = value_cast (context, value_addr (arg1));
- VALUE_POINTED_TO_OFFSET (tmp) = 0;
- arg1 = value_ind (tmp);
- type1 = check_typedef (VALUE_TYPE (arg1));
- }
-
- context = type1;
- /* Now context is the basetype containing the vtbl. */
-
- /* This type may have been defined before its virtual function table
- was. If so, fill in the virtual function table entry for the
- type now. */
- if (TYPE_VPTR_FIELDNO (context) < 0)
- fill_in_vptr_fieldno (context);
-
- /* The virtual function table is now an array of structures
- which have the form { int16 offset, delta; void *pfn; }. */
- vtbl = value_primitive_field (arg1, 0, TYPE_VPTR_FIELDNO (context),
- TYPE_VPTR_BASETYPE (context));
-
- /* With older versions of g++, the vtbl field pointed to an array
- of structures. Nowadays it points directly to the structure. */
- if (TYPE_CODE (VALUE_TYPE (vtbl)) == TYPE_CODE_PTR
- && TYPE_CODE (TYPE_TARGET_TYPE (VALUE_TYPE (vtbl))) == TYPE_CODE_ARRAY)
- {
- /* Handle the case where the vtbl field points to an
- array of structures. */
- vtbl = value_ind (vtbl);
-
- /* Index into the virtual function table. This is hard-coded because
- looking up a field is not cheap, and it may be important to save
- time, e.g. if the user has set a conditional breakpoint calling
- a virtual function. */
- entry = value_subscript (vtbl, vi);
- }
- else
- {
- /* Handle the case where the vtbl field points directly to a structure. */
- vtbl = value_add (vtbl, vi);
- entry = value_ind (vtbl);
- }
-
- entry_type = check_typedef (VALUE_TYPE (entry));
-
- if (TYPE_CODE (entry_type) == TYPE_CODE_STRUCT)
- {
- /* Move the `this' pointer according to the virtual function table. */
- VALUE_OFFSET (arg1) += value_as_long (value_field (entry, 0));
-
- if (!VALUE_LAZY (arg1))
- {
- VALUE_LAZY (arg1) = 1;
- value_fetch_lazy (arg1);
- }
-
- vfn = value_field (entry, 2);
- }
- else if (TYPE_CODE (entry_type) == TYPE_CODE_PTR)
- vfn = entry;
- else
- error ("I'm confused: virtual function table has bad type");
- /* Reinstantiate the function pointer with the correct type. */
- VALUE_TYPE (vfn) = lookup_pointer_type (TYPE_FN_FIELD_TYPE (f, j));
-
- *arg1p = arg1;
- return vfn;
- }
}

/* ARG is a pointer to an object we know to be at least
--- 887,892 ----