This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Type safe vector API


Hi,
Here's a patch which implements a type safe vector API, and a separate patch
which applies it to the CLASSTYPE_VBASECLASSES.

The basic idea is that you define a vector of pointers with
	DEF_VEC_P(typedef)
and a vector of objects with
	DEF_VEC_O(typedef)
these produce a structure declaration and a set of inline functions to
manipulate the vector.

You define a pointer to vector object with
	VEC(typedef) *v;
and away you go. You have to deal with pointers to vectors, as
the implementation uses the trailing array hack.  There is an API
call to allow you to have a structure ending with a vector member
(something that would be useful for a BINFO or TEMPLATE_ARG_VEC).

I couldn't measure time or size difference with this patch, as I
didn't have a testcase with significant virtual bases.

ok?

nathan

--
Nathan Sidwell    ::   http://www.codesourcery.com   ::     CodeSourcery LLC
nathan@codesourcery.com    ::     http://www.planetfall.pwp.blueyonder.co.uk

2004-06-23  Nathan Sidwell  <nathan@codesourcery.com>

	* vec.h, vec.c: New, type safe vector API.
	* Makefile.in (OBJS-common): Add vec.o.
	(vec.o): New target.
	(gengtype-lex.o): Depend on vec.h.

Index: Makefile.in
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Makefile.in,v
retrieving revision 1.1305
diff -c -3 -p -r1.1305 Makefile.in
*** Makefile.in	22 Jun 2004 22:27:16 -0000	1.1305
--- Makefile.in	23 Jun 2004 12:56:13 -0000
*************** OBJS-common = \
*** 914,920 ****
   sbitmap.o sched-deps.o sched-ebb.o sched-rgn.o sched-vis.o sdbout.o	   \
   simplify-rtx.o sreal.o stmt.o stor-layout.o stringpool.o 	 	  \
   targhooks.o timevar.o toplev.o tracer.o tree.o tree-dump.o unroll.o	   \
!  varasm.o varray.o version.o vmsdbgout.o xcoffout.o alloc-pool.o	   \
   et-forest.o cfghooks.o bt-load.o pretty-print.o $(GGC) web.o passes.o	   \
   rtl-profile.o tree-profile.o rtlhooks.o cfgexpand.o
  
--- 914,920 ----
   sbitmap.o sched-deps.o sched-ebb.o sched-rgn.o sched-vis.o sdbout.o	   \
   simplify-rtx.o sreal.o stmt.o stor-layout.o stringpool.o 	 	  \
   targhooks.o timevar.o toplev.o tracer.o tree.o tree-dump.o unroll.o	   \
!  varasm.o varray.o vec.o version.o vmsdbgout.o xcoffout.o alloc-pool.o	   \
   et-forest.o cfghooks.o bt-load.o pretty-print.o $(GGC) web.o passes.o	   \
   rtl-profile.o tree-profile.o rtlhooks.o cfgexpand.o
  
*************** global.o : global.c $(CONFIG_H) $(SYSTEM
*** 1987,1992 ****
--- 1987,1993 ----
     toplev.h $(TM_P_H)
  varray.o : varray.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) varray.h $(GGC_H) errors.h \
     $(HASHTAB_H)
+ vec.o : vec.c $(CONFIG_H) coretypes.h vec.h ggc.h errors.h
  ra.o : ra.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(TM_P_H) insn-config.h \
     $(RECOG_H) $(INTEGRATE_H) function.h $(REGS_H) $(OBSTACK_H) hard-reg-set.h \
     $(BASIC_BLOCK_H) $(DF_H) $(EXPR_H) output.h toplev.h $(FLAGS_H) reload.h $(RA_H)
*************** gengtype.o : gengtype.c gengtype.h $(BCO
*** 2512,2518 ****
    real.h $(RTL_BASE_H) gtyp-gen.h
  
  gengtype-lex.o : gengtype-lex.c gengtype.h gengtype-yacc.h \
!   $(BCONFIG_H) coretypes.h $(GTM_H) $(SYSTEM_H)
  	$(CC_FOR_BUILD) -c $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) $(INCLUDES) \
  	 $< $(OUTPUT_OPTION)
  
--- 2513,2519 ----
    real.h $(RTL_BASE_H) gtyp-gen.h
  
  gengtype-lex.o : gengtype-lex.c gengtype.h gengtype-yacc.h \
!   $(BCONFIG_H) coretypes.h $(GTM_H) $(SYSTEM_H) vec.h
  	$(CC_FOR_BUILD) -c $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) $(INCLUDES) \
  	 $< $(OUTPUT_OPTION)
  
Index: gcc.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/gcc.c,v
retrieving revision 1.425
diff -c -3 -p -r1.425 gcc.c
*** gcc.c	22 Jun 2004 06:51:51 -0000	1.425
--- gcc.c	23 Jun 2004 12:56:27 -0000
*************** static const struct option_map option_ma
*** 1125,1130 ****
--- 1125,1131 ----
     {"--warn-", "-W", "*j"},
     {"--write-dependencies", "-MD", 0},
     {"--write-user-dependencies", "-MMD", 0},
+    {"--m", "-m", "*j"},
     {"--", "-f", "*j"}
   };
  
Index: gengtype-lex.l
===================================================================
RCS file: /cvs/gcc/gcc/gcc/gengtype-lex.l,v
retrieving revision 1.21
diff -c -3 -p -r1.21 gengtype-lex.l
*** gengtype-lex.l	31 May 2004 19:49:50 -0000	1.21
--- gengtype-lex.l	23 Jun 2004 12:56:28 -0000
*************** Software Foundation, 59 Temple Place - S
*** 30,35 ****
--- 30,40 ----
  #include "gengtype.h"
  #include "gengtype-yacc.h"
  
+ #define YY_INPUT(BUF,RESULT,SIZE) ((RESULT) = macro_input (BUF,SIZE))
+ 
+ static unsigned macro_input (char *buffer, unsigned);
+ static void push_macro_expansion (const char *, unsigned,
+ 				  const char *, unsigned);
  static void update_lineno (const char *l, size_t len);
  
  struct fileloc lexer_line;
*************** ITYPE	{IWORD}({WS}{IWORD})*
*** 218,223 ****
--- 223,257 ----
    return ENT_YACCUNION;
  }
  
+ ^"DEF_VEC_"[[:alnum:]_]*{WS}?"("{WS}?{ID}{WS}?")" {
+   char *macro, *arg;
+   unsigned macro_len, arg_len;
+   char *ptr = yytext;
+   type_p t;
+ 
+   /* Locate the macro and argument strings.  */
+   macro = ptr;
+   while (*ptr != '(' && !ISSPACE (*ptr))
+     ptr++;
+   macro_len = ptr - macro;
+   while (*ptr == '(' || ISSPACE (*ptr))
+     ptr++;
+   arg = ptr;
+   while (*ptr != ')' && !ISSPACE (*ptr))
+     ptr++;
+   arg_len = ptr - arg;
+ 
+   /* Push the macro for later expansion.  */
+   push_macro_expansion (macro, macro_len, arg, arg_len);
+ 
+   /* Create the struct and typedef.  */
+   ptr = xmemdup ("VEC_", 4, 4 + arg_len + 1);
+   memcpy (&ptr[4], arg, arg_len);
+   ptr[4 + arg_len] = 0;
+   t = find_structure (ptr, 0);
+   do_typedef (ptr, t, &lexer_line);
+ }
+ 
  <in_struct>{
  
  "/*"				{ BEGIN(in_struct_comment); }
*************** ITYPE	{IWORD}({WS}{IWORD})*
*** 229,235 ****
  {WS}				{ update_lineno (yytext, yyleng); }
  
  "const"/[^[:alnum:]_]		/* don't care */
- 
  "GTY"/[^[:alnum:]_]		{ return GTY_TOKEN; }
  "union"/[^[:alnum:]_]		{ return UNION; }
  "struct"/[^[:alnum:]_]		{ return STRUCT; }
--- 263,268 ----
*************** ITYPE	{IWORD}({WS}{IWORD})*
*** 254,259 ****
--- 287,314 ----
    return SCALAR;
  }
  
+ "VEC"{WS}?"("{WS}?{ID}{WS}?")" {
+   char *macro, *arg;
+   unsigned macro_len, arg_len;
+   char *ptr = yytext;
+ 
+   macro = ptr;
+   while (*ptr != '(' && !ISSPACE (*ptr))
+     ptr++;
+   macro_len = ptr - macro;
+   while (*ptr == '(' || ISSPACE (*ptr))
+     ptr++;
+   arg = ptr;
+   while (*ptr != ')' && !ISSPACE (*ptr))
+     ptr++;
+   arg_len = ptr - arg;
+   ptr = xmemdup (macro, macro_len, macro_len + arg_len + 2);
+   ptr[macro_len] = '_';
+   memcpy (&ptr[macro_len+1], arg, arg_len);
+   yylval.s = ptr;
+   return ID;
+ }
+ 
  {ID}/[^[:alnum:]_]		{
    yylval.s = xmemdup (yytext, yyleng, yyleng+1);
    return ID;
*************** ITYPE	{IWORD}({WS}{IWORD})*
*** 340,345 ****
--- 395,479 ----
  
  %%
  
+ /* Deal with the expansion caused by the DEF_VEC_x macros.  */
+ 
+ typedef struct macro
+ {
+   const char *name;
+   const char *expansion;
+   struct macro *next;
+ } macro_t;
+ 
+ static const macro_t macro_defs[] = 
+ {
+ #define IN_GENGTYPE 1
+ #include "vec.h"
+   {NULL, NULL, NULL}
+ };
+ 
+ static macro_t *macro_expns;
+ 
+ static void
+ push_macro_expansion (const char *name, unsigned name_len,
+ 		      const char *arg, unsigned arg_len)
+ {
+   unsigned ix;
+ 
+   for (ix = 0; macro_defs[ix].name; ix++)
+     if (strlen (macro_defs[ix].name) == name_len
+         && !memcmp (name, macro_defs[ix].name, name_len))
+       {
+         macro_t *expansion = xmalloc (sizeof (*expansion));
+ 
+ 	expansion->next = macro_expns;
+ 	expansion->name = xmemdup (arg, arg_len, arg_len+1);
+ 	expansion->expansion = macro_defs[ix].expansion;
+ 	macro_expns = expansion;
+ 	return;
+       }
+   error_at_line (&lexer_line, "unrecognized macro `%.*s(%.*s)'",
+ 		 name_len, name, arg_len, arg);
+ }
+ 
+ static unsigned
+ macro_input (char *buffer, unsigned size)
+ {
+   unsigned result;
+ 
+   result = fread (buffer, 1, size, yyin);
+   if (result)
+     /*NOP*/;
+   else if (ferror (yyin))
+     YY_FATAL_ERROR ("read of source file failed");
+   else if (macro_expns)
+     {
+       const char *expn;
+       unsigned len;
+ 
+       for (expn = macro_expns->expansion; *expn; expn++)
+         {
+ 	  if (*expn == '#')
+ 	    {
+ 	      if (buffer[result-1] == ' ' && buffer[result-2] == '_')
+ 	        result--;
+ 	      len = strlen (macro_expns->name);
+ 	      memcpy (&buffer[result], macro_expns->name, len);
+ 	      result += len;
+ 	    }
+ 	  else
+ 	    {
+ 	      buffer[result++] = *expn;
+ 	      if (*expn == ';' || *expn == '{')
+ 	        buffer[result++] = '\n';
+ 	    }
+         }
+       if (result > size)
+         YY_FATAL_ERROR ("buffer too small to expand macro");
+       macro_expns = macro_expns->next;
+     }
+   return result;
+ }
+ 
  void
  yyerror (const char *s)
  {
Index: vec.c
===================================================================
RCS file: vec.c
diff -N vec.c
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- vec.c	23 Jun 2004 12:56:29 -0000
***************
*** 0 ****
--- 1,104 ----
+ /* Vector API for GNU compiler.
+    Copyright (C) 2004 Free Software Foundation, Inc.
+    Contributed by Nathan Sidwell <nathan@codesourcery.com>
+ 
+ This file is part of GCC.
+ 
+ GCC 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, or (at your option) any later
+ version.
+ 
+ GCC 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 GCC; see the file COPYING.  If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA.  */
+ 
+ #include "config.h"
+ #include "system.h"
+ #include "ggc.h"
+ #include "vec.h"
+ #include "errors.h"
+ #include "coretypes.h"
+ #include "tree.h"
+ 
+ struct vec_prefix 
+ {
+   size_t num;
+   size_t alloc;
+   void *vec[1];
+ };
+ 
+ /* Ensure there are at least RESERVE free slots in VEC, if RESERVE !=
+    ~0u. If RESERVE == ~0u increase the current allocation
+    exponentially.  VEC can be NULL, to create a new vector.  */
+ 
+ void *
+ vec_p_reserve (void *vec, size_t reserve)
+ {
+   return vec_o_reserve (vec, reserve,
+ 			offsetof (struct vec_prefix, vec), sizeof (void *));
+ }
+ 
+ /* Ensure there are at least RESERVE free slots in VEC, if RESERVE !=
+    ~0u.  If RESERVE == ~0u, increase the current allocation
+    exponentially.  VEC can be NULL, in which case a new vector is
+    created.  The vector's trailing array is at VEC_OFFSET offset and
+    consistes of ELT_SIZE sized elements.  */
+ 
+ void *
+ vec_o_reserve (void *vec, size_t reserve, size_t vec_offset, size_t elt_size)
+ {
+   struct vec_prefix *pfx = vec;
+   size_t alloc;
+ 
+   if (reserve + 1)
+     alloc = (pfx ? pfx->num : 0) + reserve;
+   else
+     alloc = pfx ? pfx->alloc * 2 : 4;
+   
+   if (!pfx || pfx->alloc < alloc)
+     {
+       vec = ggc_realloc (vec, vec_offset + alloc * elt_size);
+       ((struct vec_prefix *)vec)->alloc = alloc;
+       if (!pfx)
+ 	((struct vec_prefix *)vec)->num = 0;
+     }
+   
+   return vec;
+ }
+ 
+ /* Allocate a structure which contains a vector as a trailing element.
+    The vector is at STRUCT_OFFSET offset within the struct and the
+    vector's array is at VEC_OFFSET offset within the vector.  */
+ 
+ void *
+ vec_embedded_alloc (size_t struct_offset, size_t vec_offset,
+ 		    size_t elt_size, size_t reserve)
+ {
+   void *ptr = ggc_alloc (struct_offset + vec_offset + elt_size * reserve);
+   struct vec_prefix *pfx = (struct vec_prefix *)((char *)ptr + struct_offset);
+ 
+   pfx->num = 0;
+   pfx->alloc = reserve;
+ 
+   return ptr;
+ }
+ 
+ #if ENABLE_CHECKING
+ /* Issue a vector domain error, and then fall over.  */
+ 
+ void
+ vec_assert_fail (const char *op, const char *struct_name,
+ 		 const char *file, size_t line, const char *function)
+ {
+   internal_error ("vector %s %s domain error, in %s at %s:%u",
+ 		  struct_name, op, function, function,
+ 		  trim_filename (file), line);
+ }
+ #endif
Index: vec.h
===================================================================
RCS file: vec.h
diff -N vec.h
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- vec.h	23 Jun 2004 12:56:30 -0000
***************
*** 0 ****
--- 1,516 ----
+ /* Vector API for GNU compiler.
+    Copyright (C) 2004 Free Software Foundation, Inc.
+    Contributed by Nathan Sidwell <nathan@codesourcery.com>
+ 
+ This file is part of GCC.
+ 
+ GCC 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, or (at your option) any later
+ version.
+ 
+ GCC 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 GCC; see the file COPYING.  If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA.  */
+ 
+ #ifndef GCC_VEC_H
+ #define GCC_VEC_H
+ 
+ /* The macros here implement a set of templated vector types and
+    associated interfaces.  These templates are implemented with
+    macros, as we're not in C++ land.  The interface functions are
+    typesafe and use static inline functions, sometimes backed by
+    out-of-line generic functions.  The vectors are designed to
+    interoperate with the GTY machinery.
+ 
+    Because of the different behaviour of objects and of pointers to
+    objects, there are two flavours.  One to deal with a vector of
+    pointers to objects, and one to deal with a vector of objects
+    themselves.  Both of these pass pointers to objects around -- in
+    the former case the pointers are stored into the vector and in the
+    latter case the pointers are dereferenced and the objects copied
+    into the vector.  Therefore, when using a vector of pointers, the
+    objects pointed to must be long lived, but when dealing with a
+    vector of objects, the source objects need not be.
+ 
+    The vectors are implemented using the trailing array idiom, thus
+    they are not resizeable without changing the address of the vector
+    object itself.  Each operation that increases the number of active
+    elements is available in 'quick' and 'safe' variants.  The former
+    presumes that there is sufficient allocated space for the operation
+    to succeed (it aborts if there is not).  The latter will reallocate
+    the vector, if needed.  Reallocation causes an exponential increase
+    in vector size.  If you know you will be adding N elements, it
+    would be more efficient to use the reserve operation before adding
+    the elements with the 'quick' operation.
+ 
+    You should prefer the push and pop operations, as they append and
+    remove from the end of the vector.  The insert and remove
+    operations allow you to change elements in the middle of the
+    vector.  There are two remove operations, one which preserves the
+    element ordering 'ordered_remove', and one which does not
+    'unordered_remove'.  The latter function copies the end element
+    into the removed slot, rather than invoke a memmove operation.
+    
+    Vector types are defined using a DEF_VEC_x(TYPEDEF) macro, and
+    variables of vector type are declared using a VEC(TYPEDEF)
+    macro. The 'x' letter indicates whether TYPEDEF is a pointer (P) or
+    object (O) type.  */
+ 
+ /* Macros to invoke API calls.  A single macro works for both pointer
+    and object vectors, but the argument and return types might well be
+    different.  In each macro, TDEF is the typedef of the vector
+    elements.  Some of these macros pass the vector, V, by reference
+    (by taking its address), this is noted in the descriptions.  */
+ 
+ /* Length of vector
+    size_t VEC_T_length(const VEC(T) *v);
+ 
+    Return the number of active elements in V.  V can be NULL, in which
+    case zero is returned.  */
+ #define VEC_length(TDEF,V)		(VEC_OP(TDEF,length)(V))
+ 
+ /* Index into vector
+    T VEC_T_index(VEC(T) *v, size_t ix); // Pointer
+    T *VEC_T_index(VEC(T) *v, size_t ix); // Object
+ 
+    Return the IX'th element.  If IX is outside the domain of V,
+    abort.  */
+ #define VEC_index(TDEF,V,I)		(VEC_OP(TDEF,index)(V,I))
+ 
+ /* Iterate over vector
+    T VEC_T_index(VEC(T) *v, size_t ix); // Pointer
+    T *VEC_T_index(VEC(T) *v, size_t ix); // Object
+ 
+    Return the IX'th element or NULL. Use this to iterate over the
+    elements of a vector as follows,
+ 
+      for (ix = 0; (ptr = VEC_iterate(T,v,ix)); ix++)
+        continue;  */
+ #define VEC_iterate(TDEF,V,I)		(VEC_OP(TDEF,iterate)(V,I))
+ 
+ /* Allocate new vector.
+    VEC(T) *VEC_T_alloc(size_t reserve);
+ 
+    Allocate a new vector with space for RESERVE objects.  */
+ #define VEC_alloc(TDEF,A)		(VEC_OP(TDEF,alloc)(A))
+ 
+ /* Allocate new vector offset within a structure
+    void *VEC_T_embedded_alloc(size_t offset, size_t reserve);
+ 
+    Allocate a new vector which is at offset OFFSET within a structure,
+    and with space for RESERVE objects.  Return a pointer to the start
+    of the structure containing the vector.  Naturally, the vector must
+    be the last member of the structure.  */
+ #define VEC_embedded_alloc(TDEF,O,A)	(VEC_OP(TDEF,embedded_alloc)(O,A))
+ 
+ /* Reserve space.
+    void VEC_T_reserve(VEC(T) *&v, size_t reserve);
+ 
+    Ensure that V has at least RESERVE slots available.  Note this can
+    cause V to be reallocated.  */
+ #define VEC_reserve(TDEF,V,R)		(VEC_OP(TDEF,reserve)(&(V),R))
+ 
+ /* Push object with no reallocation
+    T *VEC_T_quick_push (VEC(T) *v, T obj); // Pointer
+    T *VEC_T_quick_push (VEC(T) *v, T *obj); // Object
+    
+    Push a new element onto the end, returns a pointer to the slot
+    filled in. For object vectors, the new value can be NULL, in which
+    case NO initialization is performed.  Aborts if there is
+    insufficient space in the vector. */
+ #define VEC_quick_push(TDEF,V,O)	(VEC_OP(TDEF,quick_push)(V,O))
+ 
+ /* Push object with reallocation
+    T *VEC_T_safe_push (VEC(T) *&v, T obj); // Pointer
+    T *VEC_T_safe_push (VEC(T) *&v, T *obj); // Object
+    
+    Push a new element onto the end, returns a pointer to the slot
+    filled in. For object vectors, the new value can be NULL, in which
+    case NO initialization is performed.  Reallocates V, if needed.  */
+ #define VEC_safe_push(TDEF,V,O)		(VEC_OP(TDEF,safe_push)(&(V),O))
+ 
+ /* Pop element off end
+    T VEC_T_pop (VEC(T) *v);		// Pointer
+    void VEC_T_pop (VEC(T) *v);		// Object
+ 
+    Pop the last element off the end. Returns the element popped, for
+    pointer vectors.  */
+ #define VEC_pop(TDEF,V)			(VEC_OP(TDEF,pop)(V))
+ 
+ /* Replace element
+    T VEC_T_replace (VEC(T) *v, size_t ix, T val); // Pointer
+    T *VEC_T_replace (VEC(T) *v, size_t ix, T *val);  // Object
+    
+    Replace the IXth element of V with a new value, VAL.  For pointer
+    vectors returns the original value. For object vectors returns a
+    pointer to the new value.  For object vectors the new value can be
+    NULL, in which case no overwriting of the slot is actually
+    performed.  */
+ #define VEC_replace(TDEF,V,I,O)		(VEC_OP(TDEF,replace)(V,I,O))
+ 
+ /* Insert object with no reallocation
+    T *VEC_T_quick_insert (VEC(T) *v, size_t ix, T val); // Pointer
+    T *VEC_T_quick_insert (VEC(T) *v, size_t ix, T *val); // Object
+    
+    Insert an element, VAL, at the IXth position of V. Return a pointer
+    to the slot created.  For vectors of object, the new value can be
+    NULL, in which case no initialization of the inserted slot takes
+    place. Aborts if there is insufficient space.  */
+ #define VEC_quick_insert(TDEF,V,I,O)	(VEC_OP(TDEF,quick_insert)(V,I,O))
+ 
+ /* Insert object with reallocation
+    T *VEC_T_safe_insert (VEC(T) *&v, size_t ix, T val); // Pointer
+    T *VEC_T_safe_insert (VEC(T) *&v, size_t ix, T *val); // Object
+    
+    Insert an element, VAL, at the IXth position of V. Return a pointer
+    to the slot created.  For vectors of object, the new value can be
+    NULL, in which case no initialization of the inserted slot takes
+    place. Reallocate V, if necessary.  */
+ #define VEC_safe_insert(TDEF,V,I,O)	(VEC_OP(TDEF,safe_insert)(&(V),I,O))
+      
+ /* Remove element retaining order
+    T VEC_T_ordered_remove (VEC(T) *v, size_t ix); // Pointer
+    void VEC_T_ordered_remove (VEC(T) *v, size_t ix); // Object
+    
+    Remove an element from the IXth position of V. Ordering of
+    remaining elements is preserverd.  For pointer vectors returns the
+    removed object.  This is an O(N) operation due to a memmove.  */
+ #define VEC_ordered_remove(TDEF,V,I)	(VEC_OP(TDEF,ordered_remove)(V,I))
+ 
+ /* Remove element destroying order
+    T VEC_T_unordered_remove (VEC(T) *v, size_t ix); // Pointer
+    void VEC_T_unordered_remove (VEC(T) *v, size_t ix); // Object
+    
+    Remove an element from the IXth position of V. Ordering of
+    remaining elements is destroyed.  For pointer vectors returns the
+    removed object.  This is an O(1) operation.  */
+ #define VEC_unordered_remove(TDEF,V,I)	(VEC_OP(TDEF,unordered_remove)(V,I))
+ 
+ #if !IN_GENGTYPE
+ #include "auto-host.h"
+ 
+ /* Reallocate an array of elements with prefix.  */
+ extern void *vec_p_reserve (void *, size_t);
+ extern void *vec_o_reserve (void *, size_t, size_t, size_t);
+ extern void *vec_embedded_alloc (size_t, size_t, size_t, size_t);
+ 
+ #if ENABLE_CHECKING
+ extern void vec_assert_fail (const char *, const char *,
+ 			    const char *, size_t, const char *)
+      ATTRIBUTE_NORETURN;
+ #define VEC_ASSERT_FAIL(OP,VEC) \
+   vec_assert_fail (OP,#VEC,__FILE__,__LINE__,__FUNCTION__)
+      
+ #define VEC_ASSERT(EXPR,OP,TDEF) \
+   (void)((EXPR) ? 0 : (VEC_ASSERT_FAIL(OP,VEC(TDEF)), 0))
+ #else
+ #define VEC_ASSERT(EXPR,OP,TYPE) (void)(EXPR)
+ #endif
+ 
+ #define VEC(TDEF) VEC_##TDEF
+ #define VEC_OP(TDEF,OP) VEC_OP_(VEC(TDEF),OP)
+ #define VEC_OP_(VEC,OP) VEC_OP__(VEC,OP)
+ #define VEC_OP__(VEC,OP) VEC ## _ ## OP
+ #else  /* IN_GENGTYPE */
+ #define VEC(TDEF) VEC_ TDEF
+ #define VEC_STRINGIFY(X) VEC_STRINGIFY_(X)
+ #define VEC_STRINGIFY_(X) #X
+ #undef GTY
+ #endif /* IN_GENGTYPE */
+ 
+ #define VEC_TDEF(TDEF)							  \
+ typedef struct VEC (TDEF) GTY(())					  \
+ {									  \
+   size_t num;								  \
+   size_t alloc;								  \
+   TDEF GTY ((length ("%h.num"))) vec[1];				  \
+ } VEC (TDEF)
+ 
+ /* Vector of pointer to object.  */
+ #if IN_GENGTYPE
+ {"DEF_VEC_P", VEC_STRINGIFY (VEC_TDEF (#)) ";", NULL},
+ #else
+   
+ #define DEF_VEC_P(TDEF)							  \
+ VEC_TDEF (TDEF);							  \
+ 									  \
+ static inline size_t VEC_OP (TDEF,length)				  \
+      (const VEC (TDEF) *vec_) 						  \
+ {									  \
+   return vec_ ? vec_->num : 0;						  \
+ }									  \
+ 									  \
+ static inline TDEF VEC_OP (TDEF,index)					  \
+      (const VEC (TDEF) *vec_, size_t ix_)				  \
+ {									  \
+   VEC_ASSERT (ix_ < vec_->num, "index", TDEF);				  \
+   									  \
+   return vec_->vec[ix_];						  \
+ }									  \
+ 									  \
+ static inline TDEF VEC_OP (TDEF,iterate)		  	     	  \
+      (const VEC (TDEF) *vec_, size_t ix_)				  \
+ {									  \
+   return vec_ && ix_ < vec_->num ? vec_->vec[ix_] : NULL;		  \
+ }									  \
+ 									  \
+ static inline VEC (TDEF) *VEC_OP (TDEF,alloc)		       		  \
+      (size_t alloc_)							  \
+ {									  \
+   return vec_p_reserve (NULL, alloc_ - !alloc_);			  \
+ }									  \
+ 									  \
+ static inline void *VEC_OP (TDEF,embedded_alloc)			  \
+      (size_t offset_, size_t alloc_)					  \
+ {									  \
+   return vec_embedded_alloc (offset_, offsetof (VEC(TDEF),vec),		  \
+ 			     sizeof (TDEF), alloc_);			  \
+ }									  \
+ 									  \
+ static inline void VEC_OP (TDEF,reserve)	       			  \
+      (VEC (TDEF) **vec_, size_t alloc_)					  \
+ {									  \
+   *vec_ = vec_p_reserve (*vec_, alloc_);				  \
+ }									  \
+ 									  \
+ static inline TDEF *VEC_OP (TDEF,quick_push)				  \
+      (VEC (TDEF) *vec_, TDEF obj_)					  \
+ {									  \
+   TDEF *slot_;								  \
+   									  \
+   VEC_ASSERT (vec_->num < vec_->alloc, "push", TDEF);			  \
+   slot_ = &vec_->vec[vec_->num++];					  \
+   *slot_ = obj_;							  \
+   									  \
+   return slot_;								  \
+ }									  \
+ 									  \
+ static inline TDEF *VEC_OP (TDEF,safe_push)				  \
+      (VEC (TDEF) **vec_, TDEF obj_)					  \
+ {									  \
+   if (!*vec_ || (*vec_)->num == (*vec_)->alloc)				  \
+     VEC_OP (TDEF,reserve) (vec_, ~0u);					  \
+ 									  \
+   return VEC_OP (TDEF,quick_push) (*vec_, obj_);			  \
+ }									  \
+ 									  \
+ static inline TDEF VEC_OP (TDEF,pop)					  \
+      (VEC (TDEF) *vec_)			       				  \
+ {									  \
+   TDEF obj_;								  \
+ 									  \
+   VEC_ASSERT (vec_->num, "pop", TDEF);					  \
+   obj_ = vec_->vec[--vec_->num];					  \
+ 									  \
+   return obj_;								  \
+ }									  \
+ 									  \
+ static inline TDEF VEC_OP (TDEF,replace)		  	     	  \
+      (VEC (TDEF) *vec_, size_t ix_, TDEF obj_)				  \
+ {									  \
+   TDEF old_obj_;							  \
+ 									  \
+   VEC_ASSERT (ix_ < vec_->num, "replace", TDEF);			  \
+   old_obj_ = vec_->vec[ix_];						  \
+   vec_->vec[ix_] = obj_;						  \
+ 									  \
+   return old_obj_;							  \
+ }									  \
+ 									  \
+ static inline TDEF *VEC_OP (TDEF,quick_insert)		     	  	  \
+      (VEC (TDEF) *vec_, size_t ix_, TDEF obj_)				  \
+ {									  \
+   TDEF *slot_;								  \
+ 									  \
+   VEC_ASSERT (vec_->num < vec_->alloc, "insert", TDEF);			  \
+   VEC_ASSERT (ix_ <= vec_->num, "insert", TDEF);			  \
+   slot_ = &vec_->vec[ix_];						  \
+   memmove (slot_ + 1, slot_, vec_->num++ - ix_);			  \
+   *slot_ = obj_;							  \
+   									  \
+   return slot_;								  \
+ }									  \
+ 									  \
+ static inline TDEF *VEC_OP (TDEF,safe_insert)		     	  	  \
+      (VEC (TDEF) **vec_, size_t ix_, TDEF obj_)       			  \
+ {									  \
+   if (!*vec_ || (*vec_)->num == (*vec_)->alloc)				  \
+     VEC_OP (TDEF,reserve) (vec_, ~0u);					  \
+ 									  \
+   return VEC_OP (TDEF,quick_insert) (*vec_, ix_, obj_);			  \
+ }									  \
+ 									  \
+ static inline TDEF VEC_OP (TDEF,ordered_remove)				  \
+      (VEC (TDEF) *vec_, size_t ix_)					  \
+ {									  \
+   TDEF *slot_;								  \
+   TDEF obj_;								  \
+ 									  \
+   VEC_ASSERT (ix_ < vec_->num, "remove", TDEF);				  \
+   slot_ = &vec_->vec[ix_];						  \
+   obj_ = *slot_;							  \
+   memmove (slot_, slot_ + 1, --vec_->num - ix_);       			  \
+ 									  \
+   return obj_;								  \
+ }									  \
+ 									  \
+ static inline TDEF VEC_OP (TDEF,unordered_remove)			  \
+      (VEC (TDEF) *vec_, size_t ix_)					  \
+ {									  \
+   TDEF *slot_;								  \
+   TDEF obj_;								  \
+ 									  \
+   VEC_ASSERT (ix_ < vec_->num, "remove", TDEF);				  \
+   slot_ = &vec_->vec[ix_];						  \
+   obj_ = *slot_;							  \
+   *slot_ = vec_->vec[--vec_->num];					  \
+ 									  \
+   return obj_;								  \
+ }									  \
+ 									  \
+ struct vec_swallow_trailing_semi
+ #endif
+ 
+ /* Vector of object.  */
+ #if IN_GENGTYPE
+ {"DEF_VEC_O", VEC_STRINGIFY (VEC_TDEF (#)) ";", NULL},
+ #else
+   
+ #define DEF_VEC_O(TDEF)							  \
+ VEC_TDEF (TDEF);							  \
+ 									  \
+ static inline size_t VEC_OP (TDEF,length)				  \
+      (const VEC (TDEF) *vec_) 						  \
+ {									  \
+   return vec_ ? vec_->num : 0;						  \
+ }									  \
+ 									  \
+ static inline TDEF *VEC_OP (TDEF,index)					  \
+      (VEC (TDEF) *vec_, size_t ix_)					  \
+ {									  \
+   VEC_ASSERT (ix_ < vec_->num, "index", TDEF);				  \
+   									  \
+   return &vec_->vec[ix_];						  \
+ }									  \
+ 									  \
+ static inline TDEF *VEC_OP (TDEF,iterate)				  \
+      (VEC (TDEF) *vec_, size_t ix_)					  \
+ {									  \
+   return vec_ && ix_ < vec_->num ? &vec_->vec[ix_] : NULL;		  \
+ }									  \
+ 									  \
+ static inline VEC (TDEF) *VEC_OP (TDEF,alloc)      			  \
+      (size_t alloc_)							  \
+ {									  \
+   return vec_o_reserve (NULL, alloc_ - !alloc_,				  \
+ 			offsetof (VEC(TDEF),vec), sizeof (TDEF));	  \
+ }									  \
+ 									  \
+ static inline void *VEC_OP (TDEF,embedded_alloc)			  \
+      (size_t offset_, size_t alloc_)					  \
+ {									  \
+   return vec_embedded_alloc (offset_, offsetof (VEC(TDEF),vec),		  \
+ 			     sizeof (TDEF), alloc_);			  \
+ }									  \
+ 									  \
+ static inline void VEC_OP (TDEF,reserve)	       			  \
+      (VEC (TDEF) **vec_, size_t alloc_)					  \
+ {									  \
+   *vec_ = vec_o_reserve (*vec_, alloc_,					  \
+ 			 offsetof (VEC(TDEF),vec), sizeof (TDEF));	  \
+ }									  \
+ 									  \
+ static inline TDEF *VEC_OP (TDEF,quick_push)				  \
+      (VEC (TDEF) *vec_, const TDEF *obj_)				  \
+ {									  \
+   TDEF *slot_;								  \
+   									  \
+   VEC_ASSERT (vec_->num < vec_->alloc, "push", TDEF);			  \
+   slot_ = &vec_->vec[vec_->num++];					  \
+   if (obj_)								  \
+     *slot_ = *obj_;							  \
+   									  \
+   return slot_;								  \
+ }									  \
+ 									  \
+ static inline TDEF *VEC_OP (TDEF,safe_push)				  \
+      (VEC (TDEF) **vec_, const TDEF *obj_)				  \
+ {									  \
+   if (!*vec_ || (*vec_)->num == (*vec_)->alloc)				  \
+     VEC_OP (TDEF,reserve) (vec_, ~0u);					  \
+ 									  \
+   return VEC_OP (TDEF,quick_push) (*vec_, obj_);			  \
+ }									  \
+ 									  \
+ static inline void VEC_OP (TDEF,pop)					  \
+      (VEC (TDEF) *vec_)							  \
+ {									  \
+   VEC_ASSERT (vec_->num, "pop", TDEF);					  \
+   vec_->vec[--vec_->num];						  \
+ }									  \
+ 									  \
+ static inline TDEF *VEC_OP (TDEF,replace)				  \
+      (VEC (TDEF) *vec_, size_t ix_, const TDEF *obj_)			  \
+ {									  \
+   TDEF *slot_;								  \
+ 									  \
+   VEC_ASSERT (ix_ < vec_->num, "replace", TDEF);			  \
+   slot_ = &vec_->vec[ix_];						  \
+   if (obj_)								  \
+     *slot_ = *obj_;							  \
+ 									  \
+   return slot_;								  \
+ }									  \
+ 									  \
+ static inline TDEF *VEC_OP (TDEF,quick_insert)				  \
+      (VEC (TDEF) *vec_, size_t ix_, const TDEF *obj_)			  \
+ {									  \
+   TDEF *slot_;								  \
+ 									  \
+   VEC_ASSERT (vec_->num < vec_->alloc, "insert", TDEF);			  \
+   VEC_ASSERT (ix_ <= vec_->num, "insert", TDEF);			  \
+   slot_ = &vec_->vec[ix_];						  \
+   memmove (slot_ + 1, slot_, vec_->num++ - ix_);			  \
+   if (obj_)								  \
+     *slot_ = *obj_;							  \
+   									  \
+   return slot_;								  \
+ }									  \
+ 									  \
+ static inline TDEF *VEC_OP (TDEF,safe_insert)		     	  	  \
+      (VEC (TDEF) **vec_, size_t ix_, const TDEF *obj_)			  \
+ {									  \
+   if (!*vec_ || (*vec_)->num == (*vec_)->alloc)				  \
+     VEC_OP (TDEF,reserve) (vec_, ~0u);					  \
+ 									  \
+   return VEC_OP (TDEF,quick_insert) (*vec_, ix_, obj_);			  \
+ }									  \
+ 									  \
+ static inline void VEC_OP (TDEF,ordered_remove)				  \
+      (VEC (TDEF) *vec_, size_t ix_)					  \
+ {									  \
+   TDEF *slot_;								  \
+ 									  \
+   VEC_ASSERT (ix_ < vec_->num, "remove", TDEF);				  \
+   slot_ = &vec_->vec[ix_];						  \
+   memmove (slot_, slot_ + 1, --vec_->num - ix_);       			  \
+ }									  \
+ 									  \
+ static inline void VEC_OP (TDEF,unordered_remove)			  \
+      (VEC (TDEF) *vec_, size_t ix_)					  \
+ {									  \
+   VEC_ASSERT (ix_ < vec_->num, "remove", TDEF);				  \
+   vec_->vec[ix_] = vec_->vec[--vec_->num];				  \
+ }									  \
+ 									  \
+ struct vec_swallow_trailing_semi
+ #endif
+ 
+ #endif /* GCC_VEC_H */
2004-06-23  Nathan Sidwell  <nathan@codesourcery.com>

	Use vector API for vbase list.
	* cp-tree.h: Include vec.h
	(DEF_VEC_P (tree)): New type.
	(struct lang_type_class): Change vbase's member type.
	(binfo_for_vbase): Declare.
	* class.c (determine_primary_base, base_derived_from,
	update_vtable_entry_for_fn, walk_subobject_offsets, end_of_class,
	warn_about_ambiguous_bases, dfs_accumulate_vtbl_inits,
	build_vtbl_initializer): Adjust.
	* decl.c (xref_basetypes): Adjust, accumulate upper bound of
	vbases.
	* init.c (sort_mem_initializers, expand_member_init,
	push_base_cleanups): Adjust.
	* method.c (do_build_copy_constructor): Adjust.
	* search.c (get_pure_virtuals, copied_binfo, original_binfo): Adjust.
	(binfo_for_vbase): New.
	* tree.c (copy_base_binfos): Adjust.

Index: cp/class.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/class.c,v
retrieving revision 1.618
diff -c -3 -p -r1.618 class.c
*** cp/class.c	23 Jun 2004 00:25:59 -0000	1.618
--- cp/class.c	23 Jun 2004 12:57:00 -0000
*************** set_primary_base (tree t, tree binfo)
*** 1345,1353 ****
  static void
  determine_primary_base (tree t)
  {
!   int i, n_baseclasses = CLASSTYPE_N_BASECLASSES (t);
!   tree vbases;
    tree type_binfo;
  
    /* If there are no baseclasses, there is certainly no primary base.  */
    if (n_baseclasses == 0)
--- 1345,1353 ----
  static void
  determine_primary_base (tree t)
  {
!   unsigned i, n_baseclasses = CLASSTYPE_N_BASECLASSES (t);
    tree type_binfo;
+   tree vbase_binfo;
  
    /* If there are no baseclasses, there is certainly no primary base.  */
    if (n_baseclasses == 0)
*************** determine_primary_base (tree t)
*** 1395,1423 ****
  
    /* Find the indirect primary bases - those virtual bases which are primary
       bases of something else in this hierarchy.  */
!   for (vbases = CLASSTYPE_VBASECLASSES (t);
!        vbases;
!        vbases = TREE_CHAIN (vbases)) 
!     {
!       tree vbase_binfo = TREE_VALUE (vbases);
! 
!       /* See if this virtual base is an indirect primary base.  To be so,
!          it must be a primary base within the hierarchy of one of our
!          direct bases.  */
!       for (i = 0; i < n_baseclasses; ++i) 
! 	{
! 	  tree basetype = TYPE_BINFO_BASETYPE (t, i);
! 	  tree v;
! 
! 	  for (v = CLASSTYPE_VBASECLASSES (basetype); 
! 	       v; 
! 	       v = TREE_CHAIN (v))
  	    {
! 	      tree base_vbase = TREE_VALUE (v);
! 	      
! 	      if (BINFO_PRIMARY_P (base_vbase)
! 		  && same_type_p (BINFO_TYPE (base_vbase),
! 	                          BINFO_TYPE (vbase_binfo)))
  		{
  		  BINFO_INDIRECT_PRIMARY_P (vbase_binfo) = 1;
  		  break;
--- 1395,1420 ----
  
    /* Find the indirect primary bases - those virtual bases which are primary
       bases of something else in this hierarchy.  */
!   for (i = 0; (vbase_binfo = VEC_iterate
! 	       (tree, CLASSTYPE_VBASECLASSES (t), i)); i++)
!     {
!       unsigned j;
! 
!       /* See if this virtual base is an indirect primary base.  To be
!          so, it must be a primary base within the hierarchy of one of
!          our direct bases.  */
!       for (j = 0; j != n_baseclasses; ++j) 
! 	{
! 	  unsigned k;
! 	  tree base_vbase_binfo;
! 	  tree basetype = TYPE_BINFO_BASETYPE (t, j);
! 	  
! 	  for (k = 0; (base_vbase_binfo = VEC_iterate
! 		       (tree, CLASSTYPE_VBASECLASSES (basetype), k)); k++)
  	    {
! 	      if (BINFO_PRIMARY_P (base_vbase_binfo)
! 		  && same_type_p (BINFO_TYPE (base_vbase_binfo),
! 				  BINFO_TYPE (vbase_binfo)))
  		{
  		  BINFO_INDIRECT_PRIMARY_P (vbase_binfo) = 1;
  		  break;
*************** base_derived_from (tree derived, tree ba
*** 1924,1932 ****
  	/* If we meet a virtual base, we can't follow the inheritance
  	   any more.  See if the complete type of DERIVED contains
  	   such a virtual base.  */
! 	return purpose_member (BINFO_TYPE (probe),
! 			       CLASSTYPE_VBASECLASSES (BINFO_TYPE (derived)))
! 	  != NULL_TREE;
      }
    return false;
  }
--- 1921,1928 ----
  	/* If we meet a virtual base, we can't follow the inheritance
  	   any more.  See if the complete type of DERIVED contains
  	   such a virtual base.  */
! 	return (binfo_for_vbase (BINFO_TYPE (probe), BINFO_TYPE (derived))
! 		!= NULL_TREE);
      }
    return false;
  }
*************** update_vtable_entry_for_fn (tree t, tree
*** 2170,2179 ****
  	/* Find the equivalent binfo within the return type of the
  	   overriding function. We will want the vbase offset from
  	   there.  */
! 	virtual_offset =
! 	  TREE_VALUE (purpose_member
! 		      (BINFO_TYPE (virtual_offset),
! 		       CLASSTYPE_VBASECLASSES (TREE_TYPE (over_return))));
        else if (!same_type_p (TREE_TYPE (over_return),
  			     TREE_TYPE (base_return)))
  	{
--- 2166,2173 ----
  	/* Find the equivalent binfo within the return type of the
  	   overriding function. We will want the vbase offset from
  	   there.  */
! 	virtual_offset = binfo_for_vbase (BINFO_TYPE (virtual_offset),
! 					  TREE_TYPE (over_return));
        else if (!same_type_p (TREE_TYPE (over_return),
  			     TREE_TYPE (base_return)))
  	{
*************** walk_subobject_offsets (tree type, 
*** 3319,3327 ****
  	    return r;
  	}
  
!       if (abi_version_at_least (2))
  	{
! 	  tree vbase;
  
  	  /* Iterate through the virtual base classes of TYPE.  In G++
  	     3.2, we included virtual bases in the direct base class
--- 3313,3321 ----
  	    return r;
  	}
  
!       if (abi_version_at_least (2) && CLASSTYPE_VBASECLASSES (type))
  	{
! 	  unsigned ix;
  
  	  /* Iterate through the virtual base classes of TYPE.  In G++
  	     3.2, we included virtual bases in the direct base class
*************** walk_subobject_offsets (tree type, 
*** 3329,3339 ****
  	     correct offsets for virtual bases are only known when
  	     working with the most derived type.  */
  	  if (vbases_p)
! 	    for (vbase = CLASSTYPE_VBASECLASSES (type);
! 		 vbase;
! 		 vbase = TREE_CHAIN (vbase))
  	      {
- 		binfo = TREE_VALUE (vbase);
  		r = walk_subobject_offsets (binfo,
  					    f,
  					    size_binop (PLUS_EXPR,
--- 3323,3331 ----
  	     correct offsets for virtual bases are only known when
  	     working with the most derived type.  */
  	  if (vbases_p)
! 	    for (ix = 0; (binfo = VEC_iterate
! 			  (tree, CLASSTYPE_VBASECLASSES (type), ix)); ix++)
  	      {
  		r = walk_subobject_offsets (binfo,
  					    f,
  					    size_binop (PLUS_EXPR,
*************** walk_subobject_offsets (tree type, 
*** 3350,3356 ****
  	      /* We still have to walk the primary base, if it is
  		 virtual.  (If it is non-virtual, then it was walked
  		 above.)  */
! 	      vbase = get_primary_binfo (type_binfo);
  	      if (vbase && TREE_VIA_VIRTUAL (vbase)
  		  && BINFO_PRIMARY_BASE_OF (vbase) == type_binfo)
  		{
--- 3342,3349 ----
  	      /* We still have to walk the primary base, if it is
  		 virtual.  (If it is non-virtual, then it was walked
  		 above.)  */
! 	      tree vbase = get_primary_binfo (type_binfo);
! 	      
  	      if (vbase && TREE_VIA_VIRTUAL (vbase)
  		  && BINFO_PRIMARY_BASE_OF (vbase) == type_binfo)
  		{
*************** end_of_class (tree t, int include_virtua
*** 4531,4541 ****
  
    /* G++ 3.2 did not check indirect virtual bases.  */
    if (abi_version_at_least (2) && include_virtuals_p)
!     for (binfo = CLASSTYPE_VBASECLASSES (t); 
! 	 binfo; 
! 	 binfo = TREE_CHAIN (binfo))
        {
! 	offset = end_of_base (TREE_VALUE (binfo));
  	if (INT_CST_LT_UNSIGNED (result, offset))
  	  result = offset;
        }
--- 4524,4533 ----
  
    /* G++ 3.2 did not check indirect virtual bases.  */
    if (abi_version_at_least (2) && include_virtuals_p)
!     for (i = 0; (binfo = VEC_iterate
! 		 (tree, CLASSTYPE_VBASECLASSES (t), i)); i++)
        {
! 	offset = end_of_base (binfo);
  	if (INT_CST_LT_UNSIGNED (result, offset))
  	  result = offset;
        }
*************** static void
*** 4557,4564 ****
  warn_about_ambiguous_bases (tree t)
  {
    int i;
-   tree vbases;
    tree basetype;
  
    /* Check direct bases.  */
    for (i = 0; i < CLASSTYPE_N_BASECLASSES (t); ++i)
--- 4549,4556 ----
  warn_about_ambiguous_bases (tree t)
  {
    int i;
    tree basetype;
+   tree binfo;
  
    /* Check direct bases.  */
    for (i = 0; i < CLASSTYPE_N_BASECLASSES (t); ++i)
*************** warn_about_ambiguous_bases (tree t)
*** 4572,4582 ****
  
    /* Check for ambiguous virtual bases.  */
    if (extra_warnings)
!     for (vbases = CLASSTYPE_VBASECLASSES (t); 
! 	 vbases; 
! 	 vbases = TREE_CHAIN (vbases))
        {
! 	basetype = BINFO_TYPE (TREE_VALUE (vbases));
  	
  	if (!lookup_base (t, basetype, ba_ignore | ba_quiet, NULL))
  	  warning ("virtual base `%T' inaccessible in `%T' due to ambiguity",
--- 4564,4573 ----
  
    /* Check for ambiguous virtual bases.  */
    if (extra_warnings)
!     for (i = 0; (binfo = VEC_iterate
! 		 (tree, CLASSTYPE_VBASECLASSES (t), i)); i++)
        {
! 	basetype = BINFO_TYPE (binfo);
  	
  	if (!lookup_base (t, basetype, ba_ignore | ba_quiet, NULL))
  	  warning ("virtual base `%T' inaccessible in `%T' due to ambiguity",
*************** dfs_accumulate_vtbl_inits (tree binfo,
*** 7278,7285 ****
  	 either case, we share our vtable with LAST, i.e. the
  	 derived-most base within B of which we are a primary.  */
        if (b == rtti_binfo
! 	  || (b && purpose_member (BINFO_TYPE (b),
! 				   CLASSTYPE_VBASECLASSES (BINFO_TYPE (rtti_binfo)))))
  	/* Just set our BINFO_VTABLE to point to LAST, as we may not have
  	   set LAST's BINFO_VTABLE yet.  We'll extract the actual vptr in
  	   binfo_ctor_vtable after everything's been set up.  */
--- 7269,7275 ----
  	 either case, we share our vtable with LAST, i.e. the
  	 derived-most base within B of which we are a primary.  */
        if (b == rtti_binfo
! 	  || (b && binfo_for_vbase (BINFO_TYPE (b), BINFO_TYPE (rtti_binfo))))
  	/* Just set our BINFO_VTABLE to point to LAST, as we may not have
  	   set LAST's BINFO_VTABLE yet.  We'll extract the actual vptr in
  	   binfo_ctor_vtable after everything's been set up.  */
*************** build_vtbl_initializer (tree binfo,
*** 7357,7364 ****
  {
    tree v, b;
    tree vfun_inits;
-   tree vbase;
    vtbl_init_data vid;
  
    /* Initialize VID.  */
    memset (&vid, 0, sizeof (vid));
--- 7347,7355 ----
  {
    tree v, b;
    tree vfun_inits;
    vtbl_init_data vid;
+   unsigned ix;
+   tree vbinfo;
  
    /* Initialize VID.  */
    memset (&vid, 0, sizeof (vid));
*************** build_vtbl_initializer (tree binfo,
*** 7381,7392 ****
    VARRAY_TREE_INIT (vid.fns, 32, "fns");
    /* Add the vcall and vbase offset entries.  */
    build_vcall_and_vbase_vtbl_entries (binfo, &vid);
    /* Clear BINFO_VTABLE_PATH_MARKED; it's set by
       build_vbase_offset_vtbl_entries.  */
!   for (vbase = CLASSTYPE_VBASECLASSES (t); 
!        vbase; 
!        vbase = TREE_CHAIN (vbase))
!     BINFO_VTABLE_PATH_MARKED (TREE_VALUE (vbase)) = 0;
  
    /* If the target requires padding between data entries, add that now.  */
    if (TARGET_VTABLE_DATA_ENTRY_DISTANCE > 1)
--- 7372,7383 ----
    VARRAY_TREE_INIT (vid.fns, 32, "fns");
    /* Add the vcall and vbase offset entries.  */
    build_vcall_and_vbase_vtbl_entries (binfo, &vid);
+   
    /* Clear BINFO_VTABLE_PATH_MARKED; it's set by
       build_vbase_offset_vtbl_entries.  */
!   for (ix = 0; (vbinfo = VEC_iterate
! 		(tree, CLASSTYPE_VBASECLASSES (t), ix)); ix++)
!     BINFO_VTABLE_PATH_MARKED (vbinfo) = 0;
  
    /* If the target requires padding between data entries, add that now.  */
    if (TARGET_VTABLE_DATA_ENTRY_DISTANCE > 1)
Index: cp/cp-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cp-tree.h,v
retrieving revision 1.985
diff -c -3 -p -r1.985 cp-tree.h
*** cp/cp-tree.h	23 Jun 2004 00:26:00 -0000	1.985
--- cp/cp-tree.h	23 Jun 2004 12:57:13 -0000
*************** Boston, MA 02111-1307, USA.  */
*** 27,34 ****
  #include "function.h"
  #include "hashtab.h"
  #include "splay-tree.h"
  #include "varray.h"
- 
  #include "c-common.h"
  #include "name-lookup.h"
  
--- 27,34 ----
  #include "function.h"
  #include "hashtab.h"
  #include "splay-tree.h"
+ #include "vec.h"
  #include "varray.h"
  #include "c-common.h"
  #include "name-lookup.h"
  
*************** struct lang_type_header GTY(())
*** 1017,1022 ****
--- 1017,1024 ----
    BOOL_BITFIELD has_const_assign_ref : 1;
  };
  
+ DEF_VEC_P (tree);
+ 
  /* This structure provides additional information above and beyond
     what is provide in the ordinary tree_type.  In the past, we used it
     for the types of class types, template parameters types, typename
*************** struct lang_type_class GTY(())
*** 1087,1093 ****
    tree vcall_indices;
    tree vtables;
    tree typeinfo_var;
!   tree vbases;
    binding_table nested_udts;
    tree as_base;
    tree pure_virtuals;
--- 1089,1095 ----
    tree vcall_indices;
    tree vtables;
    tree typeinfo_var;
!   VEC (tree) *vbases;
    binding_table nested_udts;
    tree as_base;
    tree pure_virtuals;
*************** struct lang_type GTY(())
*** 1305,1311 ****
  #define CLASSTYPE_PRIMARY_BINFO(NODE) \
    (LANG_TYPE_CLASS_CHECK (NODE)->primary_base)
  
! /* A chain of BINFOs for the direct and indirect virtual base classes
     that this type uses in a post-order depth-first left-to-right
     order.  (In other words, these bases appear in the order that they
     should be initialized.)  */
--- 1307,1313 ----
  #define CLASSTYPE_PRIMARY_BINFO(NODE) \
    (LANG_TYPE_CLASS_CHECK (NODE)->primary_base)
  
! /* A vector of BINFOs for the direct and indirect virtual base classes
     that this type uses in a post-order depth-first left-to-right
     order.  (In other words, these bases appear in the order that they
     should be initialized.)  */
*************** extern tree context_for_name_lookup		(tr
*** 4054,4059 ****
--- 4056,4062 ----
  extern tree lookup_conversions			(tree);
  extern tree binfo_for_vtable			(tree);
  extern tree binfo_from_vbase			(tree);
+ extern tree binfo_for_vbase			(tree, tree);
  extern tree look_for_overrides_here		(tree, tree);
  extern int check_final_overrider		(tree, tree);
  extern tree dfs_walk                            (tree,
Index: cp/decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl.c,v
retrieving revision 1.1224
diff -c -3 -p -r1.1224 decl.c
*** cp/decl.c	22 Jun 2004 07:18:28 -0000	1.1224
--- cp/decl.c	23 Jun 2004 12:57:36 -0000
*************** xref_basetypes (tree ref, tree base_list
*** 9216,9222 ****
    /* In the declaration `A : X, Y, ... Z' we mark all the types
       (A, X, Y, ..., Z) so we can check for duplicates.  */
    tree *basep;
! 
    int i;
    enum tag_types tag_code;
  
--- 9216,9222 ----
    /* In the declaration `A : X, Y, ... Z' we mark all the types
       (A, X, Y, ..., Z) so we can check for duplicates.  */
    tree *basep;
!   unsigned max_vbases = 0;
    int i;
    enum tag_types tag_code;
  
*************** xref_basetypes (tree ref, tree base_list
*** 9265,9270 ****
--- 9265,9272 ----
  	  tree basetype = TREE_VALUE (base_list);
  	  tree base_binfo;
  	  
+ 	  if (via_virtual)
+ 	    max_vbases++;
  	  if (access == access_default_node)
  	    /* The base of a derived struct is public by default.  */
  	    access = (tag_code == class_type
*************** xref_basetypes (tree ref, tree base_list
*** 9341,9346 ****
--- 9343,9350 ----
  	     	 base as well.  */
  	      TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (ref)
  		|= TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (basetype);
+ 	      max_vbases += VEC_length
+ 		(tree, CLASSTYPE_VBASECLASSES (basetype));
  	    }
  	  i++;
  	}
*************** xref_basetypes (tree ref, tree base_list
*** 9348,9353 ****
--- 9352,9359 ----
  	TREE_VEC_LENGTH (accesses) = TREE_VEC_LENGTH (binfos) = i;
        else
  	BINFO_BASEACCESSES (binfo) = BINFO_BASETYPES (binfo) = NULL_TREE;
+       if (max_vbases)
+ 	CLASSTYPE_VBASECLASSES (ref) = VEC_alloc (tree, max_vbases);
        
        if (i > 1)
  	{
*************** xref_basetypes (tree ref, tree base_list
*** 9361,9367 ****
    /* Copy the base binfos, collect the virtual bases and set the
       inheritance order chain.  */
    copy_base_binfos (TYPE_BINFO (ref), ref, NULL_TREE);
-   CLASSTYPE_VBASECLASSES (ref) = nreverse (CLASSTYPE_VBASECLASSES (ref));
  
    if (TYPE_FOR_JAVA (ref))
      {
--- 9367,9372 ----
Index: cp/init.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/init.c,v
retrieving revision 1.376
diff -c -3 -p -r1.376 init.c
*** cp/init.c	22 Jun 2004 07:18:36 -0000	1.376
--- cp/init.c	23 Jun 2004 12:57:42 -0000
*************** sort_mem_initializers (tree t, tree mem_
*** 468,476 ****
       TREE_VALUE will be the constructor arguments, or NULL if no
       explicit initialization was provided.  */
    sorted_inits = NULL_TREE;
    /* Process the virtual bases.  */
!   for (base = CLASSTYPE_VBASECLASSES (t); base; base = TREE_CHAIN (base))
!     sorted_inits = tree_cons (TREE_VALUE (base), NULL_TREE, sorted_inits);
    /* Process the direct bases.  */
    for (i = 0; i < CLASSTYPE_N_BASECLASSES (t); ++i)
      {
--- 468,479 ----
       TREE_VALUE will be the constructor arguments, or NULL if no
       explicit initialization was provided.  */
    sorted_inits = NULL_TREE;
+   
    /* Process the virtual bases.  */
!   for (i = 0; (base = VEC_iterate
! 	       (tree, CLASSTYPE_VBASECLASSES (t), i)); i++)
!     sorted_inits = tree_cons (base, NULL_TREE, sorted_inits);
!   
    /* Process the direct bases.  */
    for (i = 0; i < CLASSTYPE_N_BASECLASSES (t); ++i)
      {
*************** expand_member_init (tree name)
*** 988,1000 ****
        /* Look for a virtual base -- unless the direct base is itself
  	 virtual.  */
        if (!direct_binfo || !TREE_VIA_VIRTUAL (direct_binfo))
! 	{
! 	  virtual_binfo 
! 	    = purpose_member (basetype,
! 			      CLASSTYPE_VBASECLASSES (current_class_type));
! 	  if (virtual_binfo)
! 	    virtual_binfo = TREE_VALUE (virtual_binfo);
! 	}
  
        /* [class.base.init]
  	 
--- 991,997 ----
        /* Look for a virtual base -- unless the direct base is itself
  	 virtual.  */
        if (!direct_binfo || !TREE_VIA_VIRTUAL (direct_binfo))
! 	virtual_binfo = binfo_for_vbase (basetype, current_class_type);
  
        /* [class.base.init]
  	 
*************** push_base_cleanups (void)
*** 2874,2900 ****
    /* Run destructors for all virtual baseclasses.  */
    if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type))
      {
-       tree vbases;
        tree cond = (condition_conversion
  		   (build (BIT_AND_EXPR, integer_type_node,
  			   current_in_charge_parm,
  			   integer_two_node)));
  
!       vbases = CLASSTYPE_VBASECLASSES (current_class_type);
!       /* The CLASSTYPE_VBASECLASSES list is in initialization
  	 order, which is also the right order for pushing cleanups.  */
!       for (; vbases;
! 	   vbases = TREE_CHAIN (vbases))
  	{
! 	  tree vbase = TREE_VALUE (vbases);
! 	  tree base_type = BINFO_TYPE (vbase);
! 
! 	  if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (base_type))
  	    {
  	      expr = build_special_member_call (current_class_ref, 
  						base_dtor_identifier,
  						NULL_TREE,
! 						vbase,
  						(LOOKUP_NORMAL 
  						 | LOOKUP_NONVIRTUAL));
  	      expr = build (COND_EXPR, void_type_node, cond,
--- 2871,2893 ----
    /* Run destructors for all virtual baseclasses.  */
    if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type))
      {
        tree cond = (condition_conversion
  		   (build (BIT_AND_EXPR, integer_type_node,
  			   current_in_charge_parm,
  			   integer_two_node)));
  
!       /* The CLASSTYPE_VBASECLASSES vector is in initialization
  	 order, which is also the right order for pushing cleanups.  */
!       for (i = 0; (binfos = VEC_iterate
! 		   (tree, CLASSTYPE_VBASECLASSES (current_class_type), i));
! 	   i++)
  	{
! 	  if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (BINFO_TYPE (binfos)))
  	    {
  	      expr = build_special_member_call (current_class_ref, 
  						base_dtor_identifier,
  						NULL_TREE,
! 						binfos,
  						(LOOKUP_NORMAL 
  						 | LOOKUP_NONVIRTUAL));
  	      expr = build (COND_EXPR, void_type_node, cond,
*************** push_base_cleanups (void)
*** 2948,2964 ****
  tree
  build_vbase_delete (tree type, tree decl)
  {
!   tree vbases = CLASSTYPE_VBASECLASSES (type);
    tree result;
    tree addr = build_unary_op (ADDR_EXPR, decl, 0);
  
    my_friendly_assert (addr != error_mark_node, 222);
  
!   for (result = convert_to_void (integer_zero_node, NULL);
!        vbases; vbases = TREE_CHAIN (vbases))
      {
        tree base_addr = convert_force
! 	(build_pointer_type (BINFO_TYPE (TREE_VALUE (vbases))), addr, 0);
        tree base_delete = build_delete
  	(TREE_TYPE (base_addr), base_addr, sfk_base_destructor,
  	 LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 0);
--- 2941,2959 ----
  tree
  build_vbase_delete (tree type, tree decl)
  {
!   unsigned ix;
!   tree binfo;
    tree result;
    tree addr = build_unary_op (ADDR_EXPR, decl, 0);
  
    my_friendly_assert (addr != error_mark_node, 222);
  
!   result = convert_to_void (integer_zero_node, NULL);
!   for (ix = 0; (binfo = VEC_iterate
! 		(tree, CLASSTYPE_VBASECLASSES (type), ix)); ix++)
      {
        tree base_addr = convert_force
! 	(build_pointer_type (BINFO_TYPE (binfo)), addr, 0);
        tree base_delete = build_delete
  	(TREE_TYPE (base_addr), base_addr, sfk_base_destructor,
  	 LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 0);
Index: cp/method.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/method.c,v
retrieving revision 1.288
diff -c -3 -p -r1.288 method.c
*** cp/method.c	22 Jun 2004 07:18:36 -0000	1.288
--- cp/method.c	23 Jun 2004 12:57:44 -0000
*************** do_build_copy_constructor (tree fndecl)
*** 523,539 ****
        tree member_init_list = NULL_TREE;
        int cvquals = cp_type_quals (TREE_TYPE (parm));
        int i;
  
        /* Initialize all the base-classes with the parameter converted
  	 to their type so that we get their copy constructor and not
  	 another constructor that takes current_class_type.  We must
  	 deal with the binfo's directly as a direct base might be
  	 inaccessible due to ambiguity.  */
!       for (t = CLASSTYPE_VBASECLASSES (current_class_type); t;
! 	   t = TREE_CHAIN (t))
  	{
- 	  tree binfo = TREE_VALUE (t);
- 	  
  	  member_init_list 
  	    = tree_cons (binfo,
  			 build_tree_list (NULL_TREE,
--- 523,539 ----
        tree member_init_list = NULL_TREE;
        int cvquals = cp_type_quals (TREE_TYPE (parm));
        int i;
+       tree binfo;
  
        /* Initialize all the base-classes with the parameter converted
  	 to their type so that we get their copy constructor and not
  	 another constructor that takes current_class_type.  We must
  	 deal with the binfo's directly as a direct base might be
  	 inaccessible due to ambiguity.  */
!       for (i = 0; (binfo = VEC_iterate
! 		   (tree, CLASSTYPE_VBASECLASSES (current_class_type), i));
! 	   i++)
  	{
  	  member_init_list 
  	    = tree_cons (binfo,
  			 build_tree_list (NULL_TREE,
Index: cp/pt.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/pt.c,v
retrieving revision 1.873
diff -c -3 -p -r1.873 pt.c
*** cp/pt.c	22 Jun 2004 07:18:37 -0000	1.873
--- cp/pt.c	23 Jun 2004 12:58:09 -0000
*************** check_cv_quals_for_unify (int strict, tr
*** 9484,9498 ****
    int arg_quals = cp_type_quals (arg);
    int parm_quals = cp_type_quals (parm);
  
!   if (TREE_CODE (parm) == TEMPLATE_TYPE_PARM
!       && !(strict & UNIFY_ALLOW_OUTER_MORE_CV_QUAL))
      {
        /*  Although a CVR qualifier is ignored when being applied to a
            substituted template parameter ([8.3.2]/1 for example), that
            does not apply during deduction [14.8.2.4]/1, (even though
            that is not explicitly mentioned, [14.8.2.4]/9 indicates
!           this).  Except when we're allowing additional CV qualifiers
!           at the outer level [14.8.2.1]/3,1st bullet.  */
        if ((TREE_CODE (arg) == REFERENCE_TYPE
  	   || TREE_CODE (arg) == FUNCTION_TYPE
  	   || TREE_CODE (arg) == METHOD_TYPE)
--- 9484,9496 ----
    int arg_quals = cp_type_quals (arg);
    int parm_quals = cp_type_quals (parm);
  
!   if (TREE_CODE (parm) == TEMPLATE_TYPE_PARM)
      {
        /*  Although a CVR qualifier is ignored when being applied to a
            substituted template parameter ([8.3.2]/1 for example), that
            does not apply during deduction [14.8.2.4]/1, (even though
            that is not explicitly mentioned, [14.8.2.4]/9 indicates
!           this, apparently).   */
        if ((TREE_CODE (arg) == REFERENCE_TYPE
  	   || TREE_CODE (arg) == FUNCTION_TYPE
  	   || TREE_CODE (arg) == METHOD_TYPE)
Index: cp/search.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/search.c,v
retrieving revision 1.292
diff -c -3 -p -r1.292 search.c
*** cp/search.c	15 Jun 2004 01:46:20 -0000	1.292
--- cp/search.c	23 Jun 2004 12:58:14 -0000
*************** dfs_get_pure_virtuals (tree binfo, void 
*** 1921,1927 ****
  void
  get_pure_virtuals (tree type)
  {
!   tree vbases;
  
    /* Clear the CLASSTYPE_PURE_VIRTUALS list; whatever is already there
       is going to be overridden.  */
--- 1921,1928 ----
  void
  get_pure_virtuals (tree type)
  {
!   unsigned ix;
!   tree binfo;
  
    /* Clear the CLASSTYPE_PURE_VIRTUALS list; whatever is already there
       is going to be overridden.  */
*************** get_pure_virtuals (tree type)
*** 1938,1951 ****
    /* Put the pure virtuals in dfs order.  */
    CLASSTYPE_PURE_VIRTUALS (type) = nreverse (CLASSTYPE_PURE_VIRTUALS (type));
  
!   for (vbases = CLASSTYPE_VBASECLASSES (type); 
!        vbases; 
!        vbases = TREE_CHAIN (vbases))
      {
        tree virtuals;
! 
!       for (virtuals = BINFO_VIRTUALS (TREE_VALUE (vbases));
! 	   virtuals;
  	   virtuals = TREE_CHAIN (virtuals))
  	{
  	  tree base_fndecl = BV_FN (virtuals);
--- 1939,1950 ----
    /* Put the pure virtuals in dfs order.  */
    CLASSTYPE_PURE_VIRTUALS (type) = nreverse (CLASSTYPE_PURE_VIRTUALS (type));
  
!   for (ix = 0; (binfo = VEC_iterate
! 		(tree, CLASSTYPE_VBASECLASSES (type), ix)); ix++)
      {
        tree virtuals;
!       
!       for (virtuals = BINFO_VIRTUALS (binfo); virtuals;
  	   virtuals = TREE_CHAIN (virtuals))
  	{
  	  tree base_fndecl = BV_FN (virtuals);
*************** copied_binfo (tree binfo, tree here)
*** 2532,2541 ****
        for (t = here; BINFO_INHERITANCE_CHAIN (t);
  	   t = BINFO_INHERITANCE_CHAIN (t))
  	continue;
!       
!       result = purpose_member (BINFO_TYPE (binfo),
! 			       CLASSTYPE_VBASECLASSES (BINFO_TYPE (t)));
!       result = TREE_VALUE (result);
      }
    else if (BINFO_INHERITANCE_CHAIN (binfo))
      {
--- 2531,2538 ----
        for (t = here; BINFO_INHERITANCE_CHAIN (t);
  	   t = BINFO_INHERITANCE_CHAIN (t))
  	continue;
! 
!       result = binfo_for_vbase (BINFO_TYPE (binfo), BINFO_TYPE (t));
      }
    else if (BINFO_INHERITANCE_CHAIN (binfo))
      {
*************** copied_binfo (tree binfo, tree here)
*** 2566,2571 ****
--- 2563,2581 ----
    return result;
  }
  
+ tree
+ binfo_for_vbase (tree base, tree t)
+ {
+   unsigned ix;
+   tree binfo;
+   
+   for (ix = 0; (binfo = VEC_iterate
+ 		(tree, CLASSTYPE_VBASECLASSES (t), ix)); ix++)
+     if (BINFO_TYPE (binfo) == base)
+       return binfo;
+   return NULL;
+ }
+ 
  /* BINFO is some base binfo of HERE, within some other
     hierarchy. Return the equivalent binfo, but in the hierarchy
     dominated by HERE.  This is the inverse of copied_binfo.  If BINFO
*************** original_binfo (tree binfo, tree here)
*** 2579,2590 ****
    if (BINFO_TYPE (binfo) == BINFO_TYPE (here))
      result = here;
    else if (TREE_VIA_VIRTUAL (binfo))
!     {
!       result = purpose_member (BINFO_TYPE (binfo),
! 			       CLASSTYPE_VBASECLASSES (BINFO_TYPE (here)));
!       if (result)
! 	result = TREE_VALUE (result);
!     }
    else if (BINFO_INHERITANCE_CHAIN (binfo))
      {
        tree base_binfos;
--- 2589,2597 ----
    if (BINFO_TYPE (binfo) == BINFO_TYPE (here))
      result = here;
    else if (TREE_VIA_VIRTUAL (binfo))
!     result = (CLASSTYPE_VBASECLASSES (BINFO_TYPE (here))
! 	      ? binfo_for_vbase (BINFO_TYPE (binfo), BINFO_TYPE (here))
! 	      : NULL_TREE);
    else if (BINFO_INHERITANCE_CHAIN (binfo))
      {
        tree base_binfos;
Index: cp/tree.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/tree.c,v
retrieving revision 1.381
diff -c -3 -p -r1.381 tree.c
*** cp/tree.c	22 Jun 2004 03:07:00 -0000	1.381
--- cp/tree.c	23 Jun 2004 12:58:19 -0000
*************** canonical_type_variant (tree t)
*** 571,578 ****
     derived TYPE. PREV is the previous binfo, whose TREE_CHAIN we make
     point to this binfo. We return the last BINFO created.
  
!    The CLASSTYPE_VBASECLASSES list of T is constructed in reverse
!    order (pre-order, depth-first, right-to-left). You must nreverse it.
  
     The BINFO_INHERITANCE of a virtual base class points to the binfo
     og the most derived type.
--- 571,578 ----
     derived TYPE. PREV is the previous binfo, whose TREE_CHAIN we make
     point to this binfo. We return the last BINFO created.
  
!    The CLASSTYPE_VBASECLASSES vector of T is constructed in the correct
!    order.
  
     The BINFO_INHERITANCE of a virtual base class points to the binfo
     og the most derived type.
*************** copy_base_binfos (tree binfo, tree t, tr
*** 613,624 ****
  	  BINFO_DEPENDENT_BASE_P (new_binfo) = 1;
  	}
        else if (TREE_VIA_VIRTUAL (base_binfo))
! 	{
! 	  new_binfo = purpose_member (BINFO_TYPE (base_binfo),
! 				      CLASSTYPE_VBASECLASSES (t));
! 	  if (new_binfo)
! 	    new_binfo = TREE_VALUE (new_binfo);
! 	}
        
        if (!new_binfo)
  	{
--- 613,619 ----
  	  BINFO_DEPENDENT_BASE_P (new_binfo) = 1;
  	}
        else if (TREE_VIA_VIRTUAL (base_binfo))
! 	new_binfo = binfo_for_vbase (BINFO_TYPE (base_binfo), t);
        
        if (!new_binfo)
  	{
*************** copy_base_binfos (tree binfo, tree t, tr
*** 628,636 ****
  	  prev = copy_base_binfos (new_binfo, t, prev);
  	  if (TREE_VIA_VIRTUAL (base_binfo))
  	    {
! 	      CLASSTYPE_VBASECLASSES (t)
! 		= tree_cons (BINFO_TYPE (new_binfo), new_binfo,
! 			     CLASSTYPE_VBASECLASSES (t));
  	      TREE_VIA_VIRTUAL (new_binfo) = 1;
  	      BINFO_INHERITANCE_CHAIN (new_binfo) = TYPE_BINFO (t);
  	    }
--- 623,629 ----
  	  prev = copy_base_binfos (new_binfo, t, prev);
  	  if (TREE_VIA_VIRTUAL (base_binfo))
  	    {
! 	      VEC_quick_push (tree, CLASSTYPE_VBASECLASSES (t), new_binfo);
  	      TREE_VIA_VIRTUAL (new_binfo) = 1;
  	      BINFO_INHERITANCE_CHAIN (new_binfo) = TYPE_BINFO (t);
  	    }

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]