This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Type safe vector API
- From: Nathan Sidwell <nathan at codesourcery dot com>
- To: gcc-patches at gcc dot gnu dot org
- Cc: Ben Elliston <bje at au dot ibm dot com>, Mark Mitchell <mark at codesourcery dot com>
- Date: Wed, 23 Jun 2004 14:08:57 +0100
- Subject: Type safe vector API
- Organization: CodeSourcery LLC
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);
}