This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
C++ PATCH: Create assignment operators lazily
- From: Mark Mitchell <mark at codesourcery dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Thu, 15 Jul 2004 18:20:24 -0700
- Subject: C++ PATCH: Create assignment operators lazily
- Reply-to: mark at codesourcery dot com
This patch does two things:
* Causes us to create the declarations of implicitly defined
assignment operators lazily.
* Transitions from TREE_VEC to Nathan's vectors for
CLASSTYPE_METHOD_VEC.
The second point is enabling technlogy for the first.
Creating assignment operators lazily is a big memory win for programs
that don't use many assignment operators, but do have lots of
structures -- like programs that include C header files. For every
assignment operator, we're creating at least:
- FUNCTION_DECL for the operator
- METHOD_TYPE for the operator itself -- and then another METHOD_TYPE
with the right exception-specification.
- PARM_DECL for "this" and the second parameter.
- TREE_LIST for TYPE_METHODs.
We're also creating types for the parameters:
- X*
- X* const
- const X
- const X&
Unfortunately, these still get created for the default constructor
and/or copy constructor. I plan on changing those to be lazy too, but
it's a little trickier because of the cloning of constructors.
(Constructors should be a bigger win than assignment operators
precisely because of the cloning; we'll save the clones as well.)
This is worth about 1.7% of compilation time on one of the bigger Qt
source files. It reduces the number of calls to ggc_alloc_stat by
about 0.8% and the total number of calls to alloc_page by 1.7%.
Tested on i686-pc-linux-gnu, applied on the mainline.
--
Mark Mitchell
CodeSourcery, LLC
mark@codesourcery.com
2004-07-15 Nathan Sidwell <nathan@codesourcery.com>
* vec.h (VEC_address): New function.
2004-07-15 Mark Mitchell <mark@codesourcery.com>
* cp-tree.h (lang_type_class): Remove has_real_assign_ref and
has_abstract_assign_ref. Make methods a VEC(tree) *.
(TYPE_HAS_CONST_ASSIGN_REF): Add documentation.
(CLASSTYPE_CONSTRUCTORS): Adjust for changes to CLASSTYPE_METHOD_VEC.
(CLASSTYPE_DESTRUCTORS): Likewise.
(TYPE_HAS_REAL_ASSIGN_REF): Remove.
(TYPE_HAS_ABSTRACT_ASSIGN_REF): Likewise.
(add_method): Change prototoype.
* class.c (add_method): Remove error_p parameter. Adjust for
changes to CLASSTYPE_METHOD_VEC.
(handle_using_decl): Adjust call to add_method.
(maybe_warn_about_overly_private_class): Adjust for
changes to CLASSTYPE_METHOD_VEC.
(resort_type_method_vec): Likewise.
(finish_struct_methods): Likewise.
(check_for_override): Likewise.
(warn_hidden): Likewise.
(add_implicitly_declared_members): Defer creation of assignment
operators. Adjust call to add_method.
(clone_function_decl): Adjust call to add_method.
(check_bases_and_members): Don't set TYPE_HAS_REAL_ASSIGN_REF.
(finish_struct_1): Use CLASSTYPE_DESTRUCTORS.
* decl.c (grok_special_member_properties): Don't set
TYPE_HAS_ABSTRACT_ASSIGN_REF.
* decl2.c (check_classfn): Adjust for
changes to CLASSTYPE_METHOD_VEC.
* method.c (locate_dtor): Use CLASSTYPE_DESTRUCTORS.
(locate_ctor): Use CLASSTYPE_CONSTRUCTORS.
(locate_copy): Adjust for changes to CLASSTYPE_METHOD_VEC.
(implicitly_declare_fn): Set DECL_SOURCE_LOCATION. Do not call
cp_finish_decl.
* pt.c (check_explicit_specialization): Adjust for
changes to CLASSTYPE_METHOD_VEC.
(instantiate_class_template): Do not set
TYPE_HAS_ABSTRACT_ASSIGN_REF.
* ptree.c (cxx_print_type): Don't try to print
CLASSTYPE_METHOD_VEC.
* rtti.c (emit_support_tinfos): Use CLASSTYPE_DESTRUCTORS.
* search.c (lookup_field_r): Adjust for
changes to CLASSTYPE_METHOD_VEC.
(lookup_fnfields): Likewise.
(lookup_conversion_operator): Likewise.
(lookup_fnfields_1): Likewise. Create assignment operators
lazily.
(look_for_overrides_here): Adjust for
changes to CLASSTYPE_METHOD_VEC.
(add_conversions): Likewise.
* semantics.c (finish_member_declaration): Adjust call to add_method.
Index: vec.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/vec.h,v
retrieving revision 2.10
diff -c -5 -p -r2.10 vec.h
*** vec.h 15 Jul 2004 07:59:27 -0000 2.10
--- vec.h 16 Jul 2004 00:56:32 -0000
*************** Software Foundation, 59 Temple Place - S
*** 242,251 ****
--- 242,258 ----
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))
+ /* Get the address of the array of elements
+ T *VEC_T_address (VEC(T) v)
+
+ If you need to directly manipulate the array (for instance, you
+ want to feed it to qsort), use this accessor. */
+ #define VEC_address(TDEF,V) (VEC_OP(TDEF,address)(V))
+
#if !IN_GENGTYPE
/* Reallocate an array of elements with prefix. */
extern void *vec_p_reserve (void *, int MEM_STAT_DECL);
extern void *vec_o_reserve (void *, int, size_t, size_t MEM_STAT_DECL);
*************** static inline TDEF VEC_OP (TDEF,unordere
*** 447,456 ****
--- 454,469 ----
*slot_ = vec_->vec[--vec_->num]; \
\
return obj_; \
} \
\
+ static inline TDEF *VEC_OP (TDEF,address) \
+ (VEC (TDEF) *vec_) \
+ { \
+ return vec_ ? vec_->vec : 0; \
+ } \
+ \
struct vec_swallow_trailing_semi
#endif
/* Vector of object. */
#if IN_GENGTYPE
*************** static inline void VEC_OP (TDEF,unordere
*** 610,618 ****
--- 623,637 ----
{ \
VEC_ASSERT (ix_ < vec_->num, "remove", TDEF); \
vec_->vec[ix_] = vec_->vec[--vec_->num]; \
} \
\
+ static inline TDEF *VEC_OP (TDEF,address) \
+ (VEC (TDEF) *vec_) \
+ { \
+ return vec_ ? vec_->vec : 0; \
+ } \
+ \
struct vec_swallow_trailing_semi
#endif
#endif /* GCC_VEC_H */
Index: cp/class.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/class.c,v
retrieving revision 1.634
diff -c -5 -p -r1.634 class.c
*** cp/class.c 15 Jul 2004 15:06:26 -0000 1.634
--- cp/class.c 16 Jul 2004 00:56:32 -0000
*************** modify_vtable_entry (tree t,
*** 793,839 ****
BV_FN (v) = fndecl;
}
}
! /* Add method METHOD to class TYPE. If ERROR_P is true, we are adding
! the method after the class has already been defined because a
! declaration for it was seen. (Even though that is erroneous, we
! add the method for improved error recovery.) */
void
! add_method (tree type, tree method, int error_p)
{
int using;
! int len;
! int slot;
! tree method_vec;
tree overload;
int template_conv_p;
if (method == error_mark_node)
return;
!
using = (DECL_CONTEXT (method) != type);
template_conv_p = (TREE_CODE (method) == TEMPLATE_DECL
&& DECL_TEMPLATE_CONV_FN_P (method));
- if (!CLASSTYPE_METHOD_VEC (type))
- /* Make a new method vector. We start with 8 entries. We must
- allocate at least two (for constructors and destructors), and
- we're going to end up with an assignment operator at some point
- as well.
-
- We could use a TREE_LIST for now, and convert it to a TREE_VEC
- in finish_struct, but we would probably waste more memory
- making the links in the list than we would by over-allocating
- the size of the vector here. Furthermore, we would complicate
- all the code that expects this to be a vector. */
- CLASSTYPE_METHOD_VEC (type) = make_tree_vec (8);
-
method_vec = CLASSTYPE_METHOD_VEC (type);
! len = TREE_VEC_LENGTH (method_vec);
/* Constructors and destructors go in special slots. */
if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (method))
slot = CLASSTYPE_CONSTRUCTOR_SLOT;
else if (DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (method))
--- 793,838 ----
BV_FN (v) = fndecl;
}
}
! /* Add method METHOD to class TYPE. */
void
! add_method (tree type, tree method)
{
int using;
! size_t len;
! size_t slot;
tree overload;
int template_conv_p;
+ VEC(tree) *method_vec;
+ bool complete_p;
if (method == error_mark_node)
return;
!
! complete_p = COMPLETE_TYPE_P (type);
using = (DECL_CONTEXT (method) != type);
template_conv_p = (TREE_CODE (method) == TEMPLATE_DECL
&& DECL_TEMPLATE_CONV_FN_P (method));
method_vec = CLASSTYPE_METHOD_VEC (type);
! if (!method_vec)
! {
! /* Make a new method vector. We start with 8 entries. We must
! allocate at least two (for constructors and destructors), and
! we're going to end up with an assignment operator at some
! point as well. */
! method_vec = VEC_alloc (tree, 8);
! /* Create slots for constructors and destructors. */
! VEC_quick_push (tree, method_vec, NULL_TREE);
! VEC_quick_push (tree, method_vec, NULL_TREE);
! CLASSTYPE_METHOD_VEC (type) = method_vec;
! }
!
! len = VEC_length (tree, method_vec);
/* Constructors and destructors go in special slots. */
if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (method))
slot = CLASSTYPE_CONSTRUCTOR_SLOT;
else if (DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (method))
*************** add_method (tree type, tree method, int
*** 847,953 ****
: "Java class '%T' cannot have a destructor",
DECL_CONTEXT (method));
}
else
{
! int have_template_convs_p = 0;
!
/* See if we already have an entry with this name. */
! for (slot = CLASSTYPE_FIRST_CONVERSION_SLOT; slot < len; ++slot)
{
- tree m = TREE_VEC_ELT (method_vec, slot);
-
- if (!m)
- break;
m = OVL_CURRENT (m);
-
if (template_conv_p)
{
! have_template_convs_p = (TREE_CODE (m) == TEMPLATE_DECL
! && DECL_TEMPLATE_CONV_FN_P (m));
!
! /* If we need to move things up, see if there's
! space. */
! if (!have_template_convs_p)
! {
! slot = len - 1;
! if (TREE_VEC_ELT (method_vec, slot))
! slot++;
! }
break;
}
! if (DECL_NAME (m) == DECL_NAME (method))
break;
! }
!
! if (slot == len)
! {
! /* We need a bigger method vector. */
! int new_len;
! tree new_vec;
!
! /* In the non-error case, we are processing a class
! definition. Double the size of the vector to give room
! for new methods. */
! if (!error_p)
! new_len = 2 * len;
! /* In the error case, the vector is already complete. We
! don't expect many errors, and the rest of the front-end
! will get confused if there are empty slots in the vector. */
! else
! new_len = len + 1;
!
! new_vec = make_tree_vec (new_len);
! memcpy (&TREE_VEC_ELT (new_vec, 0), &TREE_VEC_ELT (method_vec, 0),
! len * sizeof (tree));
! len = new_len;
! method_vec = CLASSTYPE_METHOD_VEC (type) = new_vec;
! }
!
! if (DECL_CONV_FN_P (method) && !TREE_VEC_ELT (method_vec, slot))
! {
! /* Type conversion operators have to come before ordinary
! methods; add_conversions depends on this to speed up
! looking for conversion operators. So, if necessary, we
! slide some of the vector elements up. In theory, this
! makes this algorithm O(N^2) but we don't expect many
! conversion operators. */
! if (template_conv_p)
! slot = CLASSTYPE_FIRST_CONVERSION_SLOT;
! else
! for (slot = CLASSTYPE_FIRST_CONVERSION_SLOT; slot < len; ++slot)
! {
! tree fn = TREE_VEC_ELT (method_vec, slot);
!
! if (!fn)
! /* There are no more entries in the vector, so we
! can insert the new conversion operator here. */
! break;
!
! if (!DECL_CONV_FN_P (OVL_CURRENT (fn)))
! /* We can insert the new function right at the
! SLOTth position. */
! break;
! }
!
! if (template_conv_p && have_template_convs_p)
! /*OK*/;
! else if (!TREE_VEC_ELT (method_vec, slot))
! /* There is nothing in the Ith slot, so we can avoid
! moving anything. */
! ;
! else
{
! /* We know the last slot in the vector is empty
! because we know that at this point there's room
! for a new function. */
! memmove (&TREE_VEC_ELT (method_vec, slot + 1),
! &TREE_VEC_ELT (method_vec, slot),
! (len - slot - 1) * sizeof (tree));
! TREE_VEC_ELT (method_vec, slot) = NULL_TREE;
}
}
}
if (processing_template_decl)
/* TYPE is a template class. Don't issue any errors now; wait
until instantiation time to complain. */
--- 846,901 ----
: "Java class '%T' cannot have a destructor",
DECL_CONTEXT (method));
}
else
{
! bool insert_p = true;
! bool conv_p = DECL_CONV_FN_P (method);
! tree m;
!
/* See if we already have an entry with this name. */
! for (slot = CLASSTYPE_FIRST_CONVERSION_SLOT;
! (m = VEC_iterate (tree, method_vec, slot));
! ++slot)
{
m = OVL_CURRENT (m);
if (template_conv_p)
{
! if (TREE_CODE (m) == TEMPLATE_DECL
! && DECL_TEMPLATE_CONV_FN_P (m))
! insert_p = false;
break;
}
! if (conv_p && !DECL_CONV_FN_P (m))
break;
! if (DECL_NAME (m) == DECL_NAME (method))
{
! insert_p = false;
! break;
}
+ if (complete_p
+ && !DECL_CONV_FN_P (m)
+ && DECL_NAME (m) > DECL_NAME (method))
+ break;
}
+
+ /* If we need a new slot, make room. */
+ if (insert_p)
+ {
+ /* We expect to add few methods in the COMPLETE_P case, so
+ just make room for one more method. */
+ if (complete_p)
+ VEC_reserve (tree, method_vec, 1);
+ if (slot == len)
+ VEC_safe_push (tree, method_vec, NULL_TREE);
+ else
+ VEC_safe_insert (tree, method_vec, slot, NULL_TREE);
+ len++;
+ /* Inserting a new slot may have caused the vector to be
+ reallocated. */
+ CLASSTYPE_METHOD_VEC (type) = method_vec;
+ }
}
if (processing_template_decl)
/* TYPE is a template class. Don't issue any errors now; wait
until instantiation time to complain. */
*************** add_method (tree type, tree method, int
*** 955,965 ****
else
{
tree fns;
/* Check to see if we've already got this method. */
! for (fns = TREE_VEC_ELT (method_vec, slot);
fns;
fns = OVL_NEXT (fns))
{
tree fn = OVL_CURRENT (fns);
tree parms1;
--- 903,913 ----
else
{
tree fns;
/* Check to see if we've already got this method. */
! for (fns = VEC_index (tree, method_vec, slot);
fns;
fns = OVL_NEXT (fns))
{
tree fn = OVL_CURRENT (fns);
tree parms1;
*************** add_method (tree type, tree method, int
*** 1025,1041 ****
}
}
}
/* Add the new binding. */
! overload = build_overload (method, TREE_VEC_ELT (method_vec, slot));
if (!DECL_CONSTRUCTOR_P (method)
! && !DECL_DESTRUCTOR_P (method))
push_class_level_binding (DECL_NAME (method), overload);
/* Actually insert the new method. */
! TREE_VEC_ELT (method_vec, slot) = overload;
}
/* Subroutines of finish_struct. */
/* Change the access of FDECL to ACCESS in T. Return 1 if change was
--- 973,990 ----
}
}
}
/* Add the new binding. */
! overload = build_overload (method, VEC_index (tree, method_vec, slot));
if (!DECL_CONSTRUCTOR_P (method)
! && !DECL_DESTRUCTOR_P (method)
! && !complete_p)
push_class_level_binding (DECL_NAME (method), overload);
/* Actually insert the new method. */
! VEC_replace (tree, method_vec, slot, overload);
}
/* Subroutines of finish_struct. */
/* Change the access of FDECL to ACCESS in T. Return 1 if change was
*************** handle_using_decl (tree using_decl, tree
*** 1169,1179 ****
/* Make type T see field decl FDECL with access ACCESS. */
if (flist)
for (; flist; flist = OVL_NEXT (flist))
{
! add_method (t, OVL_CURRENT (flist), /*error_p=*/0);
alter_access (t, OVL_CURRENT (flist), access);
}
else
alter_access (t, fdecl, access);
}
--- 1118,1128 ----
/* Make type T see field decl FDECL with access ACCESS. */
if (flist)
for (; flist; flist = OVL_NEXT (flist))
{
! add_method (t, OVL_CURRENT (flist));
alter_access (t, OVL_CURRENT (flist), access);
}
else
alter_access (t, fdecl, access);
}
*************** maybe_warn_about_overly_private_class (t
*** 1635,1647 ****
complete non-template or fully instantiated classes have this
flag set. */
if (!TYPE_HAS_INIT_REF (t))
nonprivate_ctor = 1;
else
! for (fn = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (t), 0);
! fn;
! fn = OVL_NEXT (fn))
{
tree ctor = OVL_CURRENT (fn);
/* Ideally, we wouldn't count copy constructors (or, in
fact, any constructor that takes an argument of the
class type as a parameter) because such things cannot
--- 1584,1594 ----
complete non-template or fully instantiated classes have this
flag set. */
if (!TYPE_HAS_INIT_REF (t))
nonprivate_ctor = 1;
else
! for (fn = CLASSTYPE_CONSTRUCTORS (t); fn; fn = OVL_NEXT (fn))
{
tree ctor = OVL_CURRENT (fn);
/* Ideally, we wouldn't count copy constructors (or, in
fact, any constructor that takes an argument of the
class type as a parameter) because such things cannot
*************** void
*** 1719,1746 ****
resort_type_method_vec (void* obj,
void* orig_obj ATTRIBUTE_UNUSED ,
gt_pointer_operator new_value,
void* cookie)
{
! tree method_vec = obj;
! int len = TREE_VEC_LENGTH (method_vec);
! int slot;
/* The type conversion ops have to live at the front of the vec, so we
can't sort them. */
! for (slot = 2; slot < len; ++slot)
! {
! tree fn = TREE_VEC_ELT (method_vec, slot);
!
! if (!DECL_CONV_FN_P (OVL_CURRENT (fn)))
! break;
! }
if (len - slot > 1)
{
resort_data.new_value = new_value;
resort_data.cookie = cookie;
! qsort (&TREE_VEC_ELT (method_vec, slot), len - slot, sizeof (tree),
resort_method_name_cmp);
}
}
/* Warn about duplicate methods in fn_fields. Also compact method
--- 1666,1693 ----
resort_type_method_vec (void* obj,
void* orig_obj ATTRIBUTE_UNUSED ,
gt_pointer_operator new_value,
void* cookie)
{
! VEC(tree) *method_vec = (VEC(tree) *) obj;
! int len = VEC_length (tree, method_vec);
! size_t slot;
! tree fn;
/* The type conversion ops have to live at the front of the vec, so we
can't sort them. */
! for (slot = CLASSTYPE_FIRST_CONVERSION_SLOT;
! (fn = VEC_iterate (tree, method_vec, slot));
! ++slot)
! if (!DECL_CONV_FN_P (OVL_CURRENT (fn)))
! break;
!
if (len - slot > 1)
{
resort_data.new_value = new_value;
resort_data.cookie = cookie;
! qsort (VEC_address (tree, method_vec) + slot, len - slot, sizeof (tree),
resort_method_name_cmp);
}
}
/* Warn about duplicate methods in fn_fields. Also compact method
*************** resort_type_method_vec (void* obj,
*** 1761,1786 ****
static void
finish_struct_methods (tree t)
{
tree fn_fields;
! tree method_vec;
int slot, len;
if (!TYPE_METHODS (t))
{
/* Clear these for safety; perhaps some parsing error could set
these incorrectly. */
TYPE_HAS_CONSTRUCTOR (t) = 0;
TYPE_HAS_DESTRUCTOR (t) = 0;
! CLASSTYPE_METHOD_VEC (t) = NULL_TREE;
return;
}
method_vec = CLASSTYPE_METHOD_VEC (t);
! my_friendly_assert (method_vec != NULL_TREE, 19991215);
! len = TREE_VEC_LENGTH (method_vec);
/* First fill in entry 0 with the constructors, entry 1 with destructors,
and the next few with type conversion operators (if any). */
for (fn_fields = TYPE_METHODS (t); fn_fields;
fn_fields = TREE_CHAIN (fn_fields))
--- 1708,1733 ----
static void
finish_struct_methods (tree t)
{
tree fn_fields;
! VEC(tree) *method_vec;
int slot, len;
if (!TYPE_METHODS (t))
{
/* Clear these for safety; perhaps some parsing error could set
these incorrectly. */
TYPE_HAS_CONSTRUCTOR (t) = 0;
TYPE_HAS_DESTRUCTOR (t) = 0;
! CLASSTYPE_METHOD_VEC (t) = NULL;
return;
}
method_vec = CLASSTYPE_METHOD_VEC (t);
! my_friendly_assert (method_vec, 19991215);
! len = VEC_length (tree, method_vec);
/* First fill in entry 0 with the constructors, entry 1 with destructors,
and the next few with type conversion operators (if any). */
for (fn_fields = TYPE_METHODS (t); fn_fields;
fn_fields = TREE_CHAIN (fn_fields))
*************** finish_struct_methods (tree t)
*** 1794,1820 ****
/* Issue warnings about private constructors and such. If there are
no methods, then some public defaults are generated. */
maybe_warn_about_overly_private_class (t);
- /* Now sort the methods. */
- while (len > 2 && TREE_VEC_ELT (method_vec, len-1) == NULL_TREE)
- len--;
- TREE_VEC_LENGTH (method_vec) = len;
-
/* The type conversion ops have to live at the front of the vec, so we
can't sort them. */
! for (slot = 2; slot < len; ++slot)
! {
! tree fn = TREE_VEC_ELT (method_vec, slot);
!
! if (!DECL_CONV_FN_P (OVL_CURRENT (fn)))
! break;
! }
if (len - slot > 1)
! qsort (&TREE_VEC_ELT (method_vec, slot), len-slot, sizeof (tree),
! method_name_cmp);
}
/* Make BINFO's vtable have N entries, including RTTI entries,
vbase and vcall offsets, etc. Set its type and call the backend
to lay it out. */
--- 1741,1760 ----
/* Issue warnings about private constructors and such. If there are
no methods, then some public defaults are generated. */
maybe_warn_about_overly_private_class (t);
/* The type conversion ops have to live at the front of the vec, so we
can't sort them. */
! for (slot = 2;
! (fn_fields = VEC_iterate (tree, method_vec, slot));
! ++slot)
! if (!DECL_CONV_FN_P (OVL_CURRENT (fn_fields)))
! break;
if (len - slot > 1)
! qsort (VEC_address (tree, method_vec) + slot,
! len-slot, sizeof (tree), method_name_cmp);
}
/* Make BINFO's vtable have N entries, including RTTI entries,
vbase and vcall offsets, etc. Set its type and call the backend
to lay it out. */
*************** get_basefndecls (tree name, tree t)
*** 2367,2377 ****
int i;
/* Find virtual functions in T with the indicated NAME. */
i = lookup_fnfields_1 (t, name);
if (i != -1)
! for (methods = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (t), i);
methods;
methods = OVL_NEXT (methods))
{
tree method = OVL_CURRENT (methods);
--- 2307,2317 ----
int i;
/* Find virtual functions in T with the indicated NAME. */
i = lookup_fnfields_1 (t, name);
if (i != -1)
! for (methods = VEC_index (tree, CLASSTYPE_METHOD_VEC (t), i);
methods;
methods = OVL_NEXT (methods))
{
tree method = OVL_CURRENT (methods);
*************** check_for_override (tree decl, tree ctyp
*** 2428,2453 ****
We know that constructors and destructors don't apply. */
void
warn_hidden (tree t)
{
! tree method_vec = CLASSTYPE_METHOD_VEC (t);
! int n_methods = method_vec ? TREE_VEC_LENGTH (method_vec) : 0;
! int i;
/* We go through each separately named virtual function. */
! for (i = 2; i < n_methods && TREE_VEC_ELT (method_vec, i); ++i)
{
! tree fns;
tree name;
tree fndecl;
tree base_fndecls;
int j;
/* All functions in this slot in the CLASSTYPE_METHOD_VEC will
have the same name. Figure out what name that is. */
! name = DECL_NAME (OVL_CURRENT (TREE_VEC_ELT (method_vec, i)));
/* There are no possibly hidden functions yet. */
base_fndecls = NULL_TREE;
/* Iterate through all of the base classes looking for possibly
hidden functions. */
for (j = 0; j < BINFO_N_BASE_BINFOS (TYPE_BINFO (t)); j++)
--- 2368,2395 ----
We know that constructors and destructors don't apply. */
void
warn_hidden (tree t)
{
! VEC(tree) *method_vec = CLASSTYPE_METHOD_VEC (t);
! tree fns;
! size_t i;
/* We go through each separately named virtual function. */
! for (i = CLASSTYPE_FIRST_CONVERSION_SLOT;
! (fns = VEC_iterate (tree, method_vec, i));
! ++i)
{
! tree fn;
tree name;
tree fndecl;
tree base_fndecls;
int j;
/* All functions in this slot in the CLASSTYPE_METHOD_VEC will
have the same name. Figure out what name that is. */
! name = DECL_NAME (OVL_CURRENT (fns));
/* There are no possibly hidden functions yet. */
base_fndecls = NULL_TREE;
/* Iterate through all of the base classes looking for possibly
hidden functions. */
for (j = 0; j < BINFO_N_BASE_BINFOS (TYPE_BINFO (t)); j++)
*************** warn_hidden (tree t)
*** 2460,2472 ****
/* If there are no functions to hide, continue. */
if (!base_fndecls)
continue;
/* Remove any overridden functions. */
! for (fns = TREE_VEC_ELT (method_vec, i); fns; fns = OVL_NEXT (fns))
{
! fndecl = OVL_CURRENT (fns);
if (DECL_VINDEX (fndecl))
{
tree *prev = &base_fndecls;
while (*prev)
--- 2402,2414 ----
/* If there are no functions to hide, continue. */
if (!base_fndecls)
continue;
/* Remove any overridden functions. */
! for (fn = fns; fn; fn = OVL_NEXT (fn))
{
! fndecl = OVL_CURRENT (fn);
if (DECL_VINDEX (fndecl))
{
tree *prev = &base_fndecls;
while (*prev)
*************** warn_hidden (tree t)
*** 2484,2495 ****
as they are hidden. */
while (base_fndecls)
{
/* Here we know it is a hider, and no overrider exists. */
cp_warning_at ("`%D' was hidden", TREE_VALUE (base_fndecls));
! cp_warning_at (" by `%D'",
! OVL_CURRENT (TREE_VEC_ELT (method_vec, i)));
base_fndecls = TREE_CHAIN (base_fndecls);
}
}
}
--- 2426,2436 ----
as they are hidden. */
while (base_fndecls)
{
/* Here we know it is a hider, and no overrider exists. */
cp_warning_at ("`%D' was hidden", TREE_VALUE (base_fndecls));
! cp_warning_at (" by `%D'", fns);
base_fndecls = TREE_CHAIN (base_fndecls);
}
}
}
*************** add_implicitly_declared_members (tree t,
*** 2627,2651 ****
/*const_p=*/!cant_have_const_cctor);
TREE_CHAIN (default_fn) = implicit_fns;
implicit_fns = default_fn;
}
! /* Assignment operator. */
! if (! TYPE_HAS_ASSIGN_REF (t) && ! TYPE_FOR_JAVA (t))
! {
! default_fn
! = implicitly_declare_fn (sfk_assignment_operator, t,
! /*const_p=*/!cant_have_const_assignment);
! TREE_CHAIN (default_fn) = implicit_fns;
! implicit_fns = default_fn;
! }
!
/* Now, hook all of the new functions on to TYPE_METHODS,
and add them to the CLASSTYPE_METHOD_VEC. */
for (f = &implicit_fns; *f; f = &TREE_CHAIN (*f))
{
! add_method (t, *f, /*error_p=*/0);
maybe_add_class_template_decl_list (current_class_type, *f, /*friend_p=*/0);
}
if (abi_version_at_least (2))
/* G++ 3.2 put the implicit destructor at the *beginning* of the
list, which cause the destructor to be emitted in an incorrect
--- 2568,2589 ----
/*const_p=*/!cant_have_const_cctor);
TREE_CHAIN (default_fn) = implicit_fns;
implicit_fns = default_fn;
}
! /* If there is no assignment operator, one will be created if and
! when it is needed. For now, just record whether or not the type
! of the parameter to the assignment operator will be a const or
! non-const reference. */
! if (!TYPE_HAS_ASSIGN_REF (t) && !TYPE_FOR_JAVA (t))
! TYPE_HAS_CONST_ASSIGN_REF (t) = !cant_have_const_assignment;
!
/* Now, hook all of the new functions on to TYPE_METHODS,
and add them to the CLASSTYPE_METHOD_VEC. */
for (f = &implicit_fns; *f; f = &TREE_CHAIN (*f))
{
! add_method (t, *f);
maybe_add_class_template_decl_list (current_class_type, *f, /*friend_p=*/0);
}
if (abi_version_at_least (2))
/* G++ 3.2 put the implicit destructor at the *beginning* of the
list, which cause the destructor to be emitted in an incorrect
*************** clone_function_decl (tree fn, int update
*** 3921,3934 ****
{
/* For each constructor, we need two variants: an in-charge version
and a not-in-charge version. */
clone = build_clone (fn, complete_ctor_identifier);
if (update_method_vec_p)
! add_method (DECL_CONTEXT (clone), clone, /*error_p=*/0);
clone = build_clone (fn, base_ctor_identifier);
if (update_method_vec_p)
! add_method (DECL_CONTEXT (clone), clone, /*error_p=*/0);
}
else
{
my_friendly_assert (DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (fn), 20000411);
--- 3859,3872 ----
{
/* For each constructor, we need two variants: an in-charge version
and a not-in-charge version. */
clone = build_clone (fn, complete_ctor_identifier);
if (update_method_vec_p)
! add_method (DECL_CONTEXT (clone), clone);
clone = build_clone (fn, base_ctor_identifier);
if (update_method_vec_p)
! add_method (DECL_CONTEXT (clone), clone);
}
else
{
my_friendly_assert (DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (fn), 20000411);
*************** clone_function_decl (tree fn, int update
*** 3943,3960 ****
destructor. */
if (DECL_VIRTUAL_P (fn))
{
clone = build_clone (fn, deleting_dtor_identifier);
if (update_method_vec_p)
! add_method (DECL_CONTEXT (clone), clone, /*error_p=*/0);
}
clone = build_clone (fn, complete_dtor_identifier);
if (update_method_vec_p)
! add_method (DECL_CONTEXT (clone), clone, /*error_p=*/0);
clone = build_clone (fn, base_dtor_identifier);
if (update_method_vec_p)
! add_method (DECL_CONTEXT (clone), clone, /*error_p=*/0);
}
/* Note that this is an abstract function that is never emitted. */
DECL_ABSTRACT (fn) = 1;
}
--- 3881,3898 ----
destructor. */
if (DECL_VIRTUAL_P (fn))
{
clone = build_clone (fn, deleting_dtor_identifier);
if (update_method_vec_p)
! add_method (DECL_CONTEXT (clone), clone);
}
clone = build_clone (fn, complete_dtor_identifier);
if (update_method_vec_p)
! add_method (DECL_CONTEXT (clone), clone);
clone = build_clone (fn, base_dtor_identifier);
if (update_method_vec_p)
! add_method (DECL_CONTEXT (clone), clone);
}
/* Note that this is an abstract function that is never emitted. */
DECL_ABSTRACT (fn) = 1;
}
*************** check_bases_and_members (tree t)
*** 4179,4189 ****
CLASSTYPE_NON_AGGREGATE (t) |= (TYPE_HAS_CONSTRUCTOR (t)
|| TYPE_POLYMORPHIC_P (t));
CLASSTYPE_NON_POD_P (t)
|= (CLASSTYPE_NON_AGGREGATE (t) || TYPE_HAS_DESTRUCTOR (t)
|| TYPE_HAS_ASSIGN_REF (t));
- TYPE_HAS_REAL_ASSIGN_REF (t) |= TYPE_HAS_ASSIGN_REF (t);
TYPE_HAS_COMPLEX_ASSIGN_REF (t)
|= TYPE_HAS_ASSIGN_REF (t) || TYPE_CONTAINS_VPTR_P (t);
/* Synthesize any needed methods. */
add_implicitly_declared_members (t, cant_have_default_ctor,
--- 4117,4126 ----
*************** finish_struct_1 (tree t)
*** 5162,5175 ****
/* Build the VTT for T. */
build_vtt (t);
if (warn_nonvdtor && TYPE_POLYMORPHIC_P (t) && TYPE_HAS_DESTRUCTOR (t)
! && DECL_VINDEX (TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (t), 1)) == NULL_TREE)
{
! tree dtor = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (t), 1);
/* Warn only if the dtor is non-private or the class has friends */
if (!TREE_PRIVATE (dtor) ||
(CLASSTYPE_FRIEND_CLASSES (t) ||
DECL_FRIENDLIST (TYPE_MAIN_DECL (t))))
--- 5099,5112 ----
/* Build the VTT for T. */
build_vtt (t);
if (warn_nonvdtor && TYPE_POLYMORPHIC_P (t) && TYPE_HAS_DESTRUCTOR (t)
! && !DECL_VINDEX (CLASSTYPE_DESTRUCTORS (t)))
{
! tree dtor = CLASSTYPE_DESTRUCTORS (t);
/* Warn only if the dtor is non-private or the class has friends */
if (!TREE_PRIVATE (dtor) ||
(CLASSTYPE_FRIEND_CLASSES (t) ||
DECL_FRIENDLIST (TYPE_MAIN_DECL (t))))
Index: cp/cp-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cp-tree.h,v
retrieving revision 1.1006
diff -c -5 -p -r1.1006 cp-tree.h
*** cp/cp-tree.h 14 Jul 2004 15:34:29 -0000 1.1006
--- cp/cp-tree.h 16 Jul 2004 00:56:32 -0000
*************** struct lang_type_class GTY(())
*** 989,1014 ****
unsigned use_template : 2;
unsigned fields_readonly : 1;
unsigned ptrmemfunc_flag : 1;
unsigned was_anonymous : 1;
- unsigned has_real_assign_ref : 1;
unsigned has_const_init_ref : 1;
unsigned has_complex_init_ref : 1;
unsigned has_complex_assign_ref : 1;
- unsigned has_abstract_assign_ref : 1;
unsigned non_aggregate : 1;
unsigned java_interface : 1;
/* When adding a flag here, consider whether or not it ought to
apply to a template instance if it applies to the template. If
so, make sure to copy it in instantiate_class_template! */
/* There are some bits left to fill out a 32-bit word. Keep track
of this by updating the size of this bitfield whenever you add or
remove a flag. */
! unsigned dummy : 9;
tree primary_base;
tree vfields;
tree vcall_indices;
tree vtables;
--- 989,1012 ----
unsigned use_template : 2;
unsigned fields_readonly : 1;
unsigned ptrmemfunc_flag : 1;
unsigned was_anonymous : 1;
unsigned has_const_init_ref : 1;
unsigned has_complex_init_ref : 1;
unsigned has_complex_assign_ref : 1;
unsigned non_aggregate : 1;
unsigned java_interface : 1;
/* When adding a flag here, consider whether or not it ought to
apply to a template instance if it applies to the template. If
so, make sure to copy it in instantiate_class_template! */
/* There are some bits left to fill out a 32-bit word. Keep track
of this by updating the size of this bitfield whenever you add or
remove a flag. */
! unsigned dummy : 11;
tree primary_base;
tree vfields;
tree vcall_indices;
tree vtables;
*************** struct lang_type_class GTY(())
*** 1016,1026 ****
VEC (tree) *vbases;
binding_table nested_udts;
tree as_base;
tree pure_virtuals;
tree friend_classes;
! tree GTY ((reorder ("resort_type_method_vec"))) methods;
tree key_method;
tree decl_list;
tree template_info;
tree befriending_classes;
};
--- 1014,1024 ----
VEC (tree) *vbases;
binding_table nested_udts;
tree as_base;
tree pure_virtuals;
tree friend_classes;
! VEC (tree) * GTY((reorder ("resort_type_method_vec"))) methods;
tree key_method;
tree decl_list;
tree template_info;
tree befriending_classes;
};
*************** struct lang_type GTY(())
*** 1091,1100 ****
--- 1089,1101 ----
#define TYPE_HAS_CONVERSION(NODE) \
(LANG_TYPE_CLASS_CHECK (NODE)->h.has_type_conversion)
/* Nonzero means that this _CLASSTYPE node overloads operator=(X&). */
#define TYPE_HAS_ASSIGN_REF(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->has_assign_ref)
+
+ /* True iff the class type NODE has an "operator =" whose parameter
+ has a parameter of type "const X&". */
#define TYPE_HAS_CONST_ASSIGN_REF(NODE) \
(LANG_TYPE_CLASS_CHECK (NODE)->h.has_const_assign_ref)
/* Nonzero means that this _CLASSTYPE node has an X(X&) constructor. */
#define TYPE_HAS_INIT_REF(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->h.has_init_ref)
*************** struct lang_type GTY(())
*** 1164,1179 ****
#define CLASSTYPE_FIRST_CONVERSION_SLOT 2
/* A FUNCTION_DECL or OVERLOAD for the constructors for NODE. These
are the constructors that take an in-charge parameter. */
#define CLASSTYPE_CONSTRUCTORS(NODE) \
! (TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (NODE), CLASSTYPE_CONSTRUCTOR_SLOT))
/* A FUNCTION_DECL for the destructor for NODE. These are the
destructors that take an in-charge parameter. */
#define CLASSTYPE_DESTRUCTORS(NODE) \
! (TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (NODE), CLASSTYPE_DESTRUCTOR_SLOT))
/* Mark bits for depth-first and breath-first searches. */
/* Get the value of the Nth mark bit. */
#define CLASSTYPE_MARKED_N(NODE, N) \
--- 1165,1180 ----
#define CLASSTYPE_FIRST_CONVERSION_SLOT 2
/* A FUNCTION_DECL or OVERLOAD for the constructors for NODE. These
are the constructors that take an in-charge parameter. */
#define CLASSTYPE_CONSTRUCTORS(NODE) \
! (VEC_index (tree, CLASSTYPE_METHOD_VEC (NODE), CLASSTYPE_CONSTRUCTOR_SLOT))
/* A FUNCTION_DECL for the destructor for NODE. These are the
destructors that take an in-charge parameter. */
#define CLASSTYPE_DESTRUCTORS(NODE) \
! (VEC_index (tree, CLASSTYPE_METHOD_VEC (NODE), CLASSTYPE_DESTRUCTOR_SLOT))
/* Mark bits for depth-first and breath-first searches. */
/* Get the value of the Nth mark bit. */
#define CLASSTYPE_MARKED_N(NODE, N) \
*************** struct lang_decl GTY(())
*** 2365,2377 ****
(LANG_TYPE_CLASS_CHECK (NODE)->non_aggregate)
#define TYPE_NON_AGGREGATE_CLASS(NODE) \
(IS_AGGR_TYPE (NODE) && CLASSTYPE_NON_AGGREGATE (NODE))
/* Nonzero if there is a user-defined X::op=(x&) for this class. */
- #define TYPE_HAS_REAL_ASSIGN_REF(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->has_real_assign_ref)
#define TYPE_HAS_COMPLEX_ASSIGN_REF(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->has_complex_assign_ref)
- #define TYPE_HAS_ABSTRACT_ASSIGN_REF(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->has_abstract_assign_ref)
#define TYPE_HAS_COMPLEX_INIT_REF(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->has_complex_init_ref)
/* Nonzero if TYPE has a trivial destructor. From [class.dtor]:
A destructor is trivial if it is an implicitly declared
--- 2366,2376 ----
*************** extern tree convert_to_base_statically (
*** 3596,3606 ****
extern tree build_vtbl_ref (tree, tree);
extern tree build_vfn_ref (tree, tree);
extern tree get_vtable_decl (tree, int);
extern void resort_type_method_vec
(void *, void *, gt_pointer_operator, void *);
! extern void add_method (tree, tree, int);
extern int currently_open_class (tree);
extern tree currently_open_derived_class (tree);
extern tree finish_struct (tree, tree);
extern void finish_struct_1 (tree);
extern int resolves_to_fixed_type_p (tree, int *);
--- 3595,3605 ----
extern tree build_vtbl_ref (tree, tree);
extern tree build_vfn_ref (tree, tree);
extern tree get_vtable_decl (tree, int);
extern void resort_type_method_vec
(void *, void *, gt_pointer_operator, void *);
! extern void add_method (tree, tree);
extern int currently_open_class (tree);
extern tree currently_open_derived_class (tree);
extern tree finish_struct (tree, tree);
extern void finish_struct_1 (tree);
extern int resolves_to_fixed_type_p (tree, int *);
Index: cp/decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl.c,v
retrieving revision 1.1251
diff -c -5 -p -r1.1251 decl.c
*** cp/decl.c 15 Jul 2004 15:06:23 -0000 1.1251
--- cp/decl.c 16 Jul 2004 00:56:32 -0000
*************** void grok_special_member_properties (tre
*** 8350,8361 ****
if (assop)
{
TYPE_HAS_ASSIGN_REF (DECL_CONTEXT (decl)) = 1;
if (assop != 1)
TYPE_HAS_CONST_ASSIGN_REF (DECL_CONTEXT (decl)) = 1;
- if (DECL_PURE_VIRTUAL_P (decl))
- TYPE_HAS_ABSTRACT_ASSIGN_REF (DECL_CONTEXT (decl)) = 1;
}
}
}
/* Check a constructor DECL has the correct form. Complains
--- 8350,8359 ----
Index: cp/decl2.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl2.c,v
retrieving revision 1.726
diff -c -5 -p -r1.726 decl2.c
*** cp/decl2.c 11 Jul 2004 05:13:12 -0000 1.726
--- cp/decl2.c 16 Jul 2004 00:56:32 -0000
*************** check_classfn (tree ctype, tree function
*** 628,645 ****
DECL_DESTRUCTOR_P (function) ? dtor_identifier :
DECL_NAME (function));
if (ix >= 0)
{
! tree methods = CLASSTYPE_METHOD_VEC (ctype);
tree fndecls, fndecl = 0;
bool is_conv_op;
bool pop_p;
const char *format = NULL;
pop_p = push_scope (ctype);
! for (fndecls = TREE_VEC_ELT (methods, ix);
fndecls; fndecls = OVL_NEXT (fndecls))
{
tree p1, p2;
fndecl = OVL_CURRENT (fndecls);
--- 628,645 ----
DECL_DESTRUCTOR_P (function) ? dtor_identifier :
DECL_NAME (function));
if (ix >= 0)
{
! VEC(tree) *methods = CLASSTYPE_METHOD_VEC (ctype);
tree fndecls, fndecl = 0;
bool is_conv_op;
bool pop_p;
const char *format = NULL;
pop_p = push_scope (ctype);
! for (fndecls = VEC_index (tree, methods, ix);
fndecls; fndecls = OVL_NEXT (fndecls))
{
tree p1, p2;
fndecl = OVL_CURRENT (fndecls);
*************** check_classfn (tree ctype, tree function
*** 683,704 ****
function, ctype);
is_conv_op = DECL_CONV_FN_P (fndecl);
if (is_conv_op)
ix = CLASSTYPE_FIRST_CONVERSION_SLOT;
! fndecls = TREE_VEC_ELT (methods, ix);
while (fndecls)
{
fndecl = OVL_CURRENT (fndecls);
fndecls = OVL_NEXT (fndecls);
if (!fndecls && is_conv_op)
{
! if (TREE_VEC_LENGTH (methods) > ix)
{
ix++;
! fndecls = TREE_VEC_ELT (methods, ix);
if (!DECL_CONV_FN_P (OVL_CURRENT (fndecls)))
{
fndecls = NULL_TREE;
is_conv_op = false;
}
--- 683,704 ----
function, ctype);
is_conv_op = DECL_CONV_FN_P (fndecl);
if (is_conv_op)
ix = CLASSTYPE_FIRST_CONVERSION_SLOT;
! fndecls = VEC_index (tree, methods, ix);
while (fndecls)
{
fndecl = OVL_CURRENT (fndecls);
fndecls = OVL_NEXT (fndecls);
if (!fndecls && is_conv_op)
{
! if (VEC_length (tree, methods) > (size_t) ix)
{
ix++;
! fndecls = VEC_index (tree, methods, ix);
if (!DECL_CONV_FN_P (OVL_CURRENT (fndecls)))
{
fndecls = NULL_TREE;
is_conv_op = false;
}
*************** check_classfn (tree ctype, tree function
*** 724,734 ****
/* If we did not find the method in the class, add it to avoid
spurious errors (unless the CTYPE is not yet defined, in which
case we'll only confuse ourselves when the function is declared
properly within the class. */
if (COMPLETE_TYPE_P (ctype))
! add_method (ctype, function, /*error_p=*/1);
return NULL_TREE;
}
/* We have just processed the DECL, which is a static data member.
Its initializer, if present, is INIT. The ASMSPEC_TREE, if
--- 724,734 ----
/* If we did not find the method in the class, add it to avoid
spurious errors (unless the CTYPE is not yet defined, in which
case we'll only confuse ourselves when the function is declared
properly within the class. */
if (COMPLETE_TYPE_P (ctype))
! add_method (ctype, function);
return NULL_TREE;
}
/* We have just processed the DECL, which is a static data member.
Its initializer, if present, is INIT. The ASMSPEC_TREE, if
Index: cp/method.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/method.c,v
retrieving revision 1.296
diff -c -5 -p -r1.296 method.c
*** cp/method.c 13 Jul 2004 16:22:06 -0000 1.296
--- cp/method.c 16 Jul 2004 00:56:32 -0000
*************** synthesize_exception_spec (tree type, tr
*** 823,839 ****
/* Locate the dtor of TYPE. */
static tree
locate_dtor (tree type, void *client ATTRIBUTE_UNUSED)
{
! tree fns;
!
! if (!TYPE_HAS_DESTRUCTOR (type))
! return NULL_TREE;
! fns = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type),
! CLASSTYPE_DESTRUCTOR_SLOT);
! return fns;
}
/* Locate the default ctor of TYPE. */
static tree
--- 823,833 ----
/* Locate the dtor of TYPE. */
static tree
locate_dtor (tree type, void *client ATTRIBUTE_UNUSED)
{
! return CLASSTYPE_DESTRUCTORS (type);
}
/* Locate the default ctor of TYPE. */
static tree
*************** locate_ctor (tree type, void *client ATT
*** 841,854 ****
{
tree fns;
if (!TYPE_HAS_DEFAULT_CONSTRUCTOR (type))
return NULL_TREE;
!
! fns = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type),
! CLASSTYPE_CONSTRUCTOR_SLOT);
! for (; fns; fns = OVL_NEXT (fns))
{
tree fn = OVL_CURRENT (fns);
tree parms = TYPE_ARG_TYPES (TREE_TYPE (fn));
if (sufficient_parms_p (TREE_CHAIN (parms)))
--- 835,846 ----
{
tree fns;
if (!TYPE_HAS_DEFAULT_CONSTRUCTOR (type))
return NULL_TREE;
!
! for (fns = CLASSTYPE_CONSTRUCTORS (type); fns; fns = OVL_NEXT (fns))
{
tree fn = OVL_CURRENT (fns);
tree parms = TYPE_ARG_TYPES (TREE_TYPE (fn));
if (sufficient_parms_p (TREE_CHAIN (parms)))
*************** locate_copy (tree type, void *client_)
*** 883,893 ****
}
else if (TYPE_HAS_INIT_REF (type))
ix = CLASSTYPE_CONSTRUCTOR_SLOT;
if (ix < 0)
return NULL_TREE;
! fns = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), ix);
for (; fns; fns = OVL_NEXT (fns))
{
tree fn = OVL_CURRENT (fns);
tree parms = TYPE_ARG_TYPES (TREE_TYPE (fn));
--- 875,885 ----
}
else if (TYPE_HAS_INIT_REF (type))
ix = CLASSTYPE_CONSTRUCTOR_SLOT;
if (ix < 0)
return NULL_TREE;
! fns = VEC_index (tree, CLASSTYPE_METHOD_VEC (type), ix);
for (; fns; fns = OVL_NEXT (fns))
{
tree fn = OVL_CURRENT (fns);
tree parms = TYPE_ARG_TYPES (TREE_TYPE (fn));
*************** implicitly_declare_fn (special_function_
*** 987,996 ****
--- 979,989 ----
/* Create the function. */
fn_type = build_method_type_directly (type, return_type, parameter_types);
if (raises)
fn_type = build_exception_variant (fn_type, raises);
fn = build_lang_decl (FUNCTION_DECL, name, fn_type);
+ DECL_SOURCE_LOCATION (fn) = DECL_SOURCE_LOCATION (TYPE_NAME (type));
if (kind == sfk_constructor || kind == sfk_copy_constructor)
DECL_CONSTRUCTOR_P (fn) = 1;
else if (kind == sfk_destructor)
DECL_DESTRUCTOR_P (fn) = 1;
else
*************** implicitly_declare_fn (special_function_
*** 1011,1022 ****
grokclassfn (type, fn, kind == sfk_destructor ? DTOR_FLAG : NO_SPECIAL,
TYPE_UNQUALIFIED);
grok_special_member_properties (fn);
TREE_PUBLIC (fn) = !decl_function_context (TYPE_MAIN_DECL (type));
! cp_finish_decl (fn, /*init=*/NULL_TREE, /*asmspec_tree=*/NULL_TREE,
! /*flags=*/LOOKUP_ONLYCONVERTING);
DECL_IN_AGGR_P (fn) = 1;
DECL_ARTIFICIAL (fn) = 1;
DECL_NOT_REALLY_EXTERN (fn) = 1;
DECL_DECLARED_INLINE_P (fn) = 1;
DECL_INLINE (fn) = 1;
--- 1004,1015 ----
grokclassfn (type, fn, kind == sfk_destructor ? DTOR_FLAG : NO_SPECIAL,
TYPE_UNQUALIFIED);
grok_special_member_properties (fn);
TREE_PUBLIC (fn) = !decl_function_context (TYPE_MAIN_DECL (type));
! rest_of_decl_compilation (fn, /*asmspec=*/NULL,
! toplevel_bindings_p (), at_eof);
DECL_IN_AGGR_P (fn) = 1;
DECL_ARTIFICIAL (fn) = 1;
DECL_NOT_REALLY_EXTERN (fn) = 1;
DECL_DECLARED_INLINE_P (fn) = 1;
DECL_INLINE (fn) = 1;
Index: cp/pt.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/pt.c,v
retrieving revision 1.885
diff -c -5 -p -r1.885 pt.c
*** cp/pt.c 14 Jul 2004 15:34:30 -0000 1.885
--- cp/pt.c 16 Jul 2004 00:56:32 -0000
*************** check_explicit_specialization (tree decl
*** 1819,1833 ****
if (!DECL_CONV_FN_P (decl))
{
idx = lookup_fnfields_1 (ctype, name);
if (idx >= 0)
! fns = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (ctype), idx);
}
else
{
! tree methods;
/* For a type-conversion operator, we cannot do a
name-based lookup. We might be looking for `operator
int' which will be a specialization of `operator T'.
So, we find *all* the conversion operators, and then
--- 1819,1834 ----
if (!DECL_CONV_FN_P (decl))
{
idx = lookup_fnfields_1 (ctype, name);
if (idx >= 0)
! fns = VEC_index (tree, CLASSTYPE_METHOD_VEC (ctype), idx);
}
else
{
! VEC(tree) *methods;
! tree ovl;
/* For a type-conversion operator, we cannot do a
name-based lookup. We might be looking for `operator
int' which will be a specialization of `operator T'.
So, we find *all* the conversion operators, and then
*************** check_explicit_specialization (tree decl
*** 1835,1849 ****
fns = NULL_TREE;
methods = CLASSTYPE_METHOD_VEC (ctype);
if (methods)
for (idx = CLASSTYPE_FIRST_CONVERSION_SLOT;
! idx < TREE_VEC_LENGTH (methods); ++idx)
{
! tree ovl = TREE_VEC_ELT (methods, idx);
!
! if (!ovl || !DECL_CONV_FN_P (OVL_CURRENT (ovl)))
/* There are no more conversion functions. */
break;
/* Glue all these conversion functions together
with those we already have. */
--- 1836,1849 ----
fns = NULL_TREE;
methods = CLASSTYPE_METHOD_VEC (ctype);
if (methods)
for (idx = CLASSTYPE_FIRST_CONVERSION_SLOT;
! (ovl = VEC_iterate (tree, methods, idx));
! ++idx)
{
! if (!DECL_CONV_FN_P (OVL_CURRENT (ovl)))
/* There are no more conversion functions. */
break;
/* Glue all these conversion functions together
with those we already have. */
*************** instantiate_class_template (tree type)
*** 5383,5393 ****
TYPE_HAS_NEW_OPERATOR (type) = TYPE_HAS_NEW_OPERATOR (pattern);
TYPE_HAS_ARRAY_NEW_OPERATOR (type) = TYPE_HAS_ARRAY_NEW_OPERATOR (pattern);
TYPE_GETS_DELETE (type) = TYPE_GETS_DELETE (pattern);
TYPE_HAS_ASSIGN_REF (type) = TYPE_HAS_ASSIGN_REF (pattern);
TYPE_HAS_CONST_ASSIGN_REF (type) = TYPE_HAS_CONST_ASSIGN_REF (pattern);
- TYPE_HAS_ABSTRACT_ASSIGN_REF (type) = TYPE_HAS_ABSTRACT_ASSIGN_REF (pattern);
TYPE_HAS_INIT_REF (type) = TYPE_HAS_INIT_REF (pattern);
TYPE_HAS_CONST_INIT_REF (type) = TYPE_HAS_CONST_INIT_REF (pattern);
TYPE_HAS_DEFAULT_CONSTRUCTOR (type) = TYPE_HAS_DEFAULT_CONSTRUCTOR (pattern);
TYPE_HAS_CONVERSION (type) = TYPE_HAS_CONVERSION (pattern);
TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (type)
--- 5383,5392 ----
Index: cp/ptree.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/ptree.c,v
retrieving revision 1.43
diff -c -5 -p -r1.43 ptree.c
*** cp/ptree.c 13 Jul 2004 16:22:06 -0000 1.43
--- cp/ptree.c 16 Jul 2004 00:56:32 -0000
*************** cxx_print_type (FILE *file, tree node, i
*** 137,148 ****
fprintf (file, " use_template=%d", CLASSTYPE_USE_TEMPLATE (node));
if (CLASSTYPE_INTERFACE_ONLY (node))
fprintf (file, " interface-only");
if (CLASSTYPE_INTERFACE_UNKNOWN (node))
fprintf (file, " interface-unknown");
- print_node (file, "member-functions", CLASSTYPE_METHOD_VEC (node),
- indent + 4);
}
}
static void
--- 137,146 ----
Index: cp/rtti.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/rtti.c,v
retrieving revision 1.188
diff -c -5 -p -r1.188 rtti.c
*** cp/rtti.c 12 Jul 2004 22:28:54 -0000 1.188
--- cp/rtti.c 16 Jul 2004 00:56:32 -0000
*************** emit_support_tinfos (void)
*** 1380,1390 ****
get_identifier ("__fundamental_type_info"),
true, false);
pop_nested_namespace (abi_node);
if (!COMPLETE_TYPE_P (bltn_type))
return;
! dtor = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (bltn_type), 1);
if (DECL_EXTERNAL (dtor))
return;
doing_runtime = 1;
for (ix = 0; fundamentals[ix]; ix++)
{
--- 1380,1390 ----
get_identifier ("__fundamental_type_info"),
true, false);
pop_nested_namespace (abi_node);
if (!COMPLETE_TYPE_P (bltn_type))
return;
! dtor = CLASSTYPE_DESTRUCTORS (bltn_type);
if (DECL_EXTERNAL (dtor))
return;
doing_runtime = 1;
for (ix = 0; fundamentals[ix]; ix++)
{
Index: cp/search.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/search.c,v
retrieving revision 1.300
diff -c -5 -p -r1.300 search.c
*** cp/search.c 14 Jul 2004 15:34:30 -0000 1.300
--- cp/search.c 16 Jul 2004 00:56:32 -0000
*************** lookup_field_r (tree binfo, void *data)
*** 1058,1068 ****
with the same name, the type is hidden by the function. */
if (!lfi->want_type)
{
int idx = lookup_fnfields_1 (type, lfi->name);
if (idx >= 0)
! nval = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), idx);
}
if (!nval)
/* Look for a data member or type. */
nval = lookup_field_1 (type, lfi->name, lfi->want_type);
--- 1058,1068 ----
with the same name, the type is hidden by the function. */
if (!lfi->want_type)
{
int idx = lookup_fnfields_1 (type, lfi->name);
if (idx >= 0)
! nval = VEC_index (tree, CLASSTYPE_METHOD_VEC (type), idx);
}
if (!nval)
/* Look for a data member or type. */
nval = lookup_field_1 (type, lfi->name, lfi->want_type);
*************** lookup_fnfields (tree xbasetype, tree na
*** 1310,1333 ****
static int
lookup_conversion_operator (tree class_type, tree type)
{
int pass;
int i;
! tree methods = CLASSTYPE_METHOD_VEC (class_type);
for (pass = 0; pass < 2; ++pass)
for (i = CLASSTYPE_FIRST_CONVERSION_SLOT;
! i < TREE_VEC_LENGTH (methods);
++i)
{
- tree fn = TREE_VEC_ELT (methods, i);
- /* The size of the vector may have some unused slots at the
- end. */
- if (!fn)
- break;
-
/* All the conversion operators come near the beginning of the
class. Therefore, if FN is not a conversion operator, there
is no matching conversion operator in CLASS_TYPE. */
fn = OVL_CURRENT (fn);
if (!DECL_CONV_FN_P (fn))
--- 1310,1329 ----
static int
lookup_conversion_operator (tree class_type, tree type)
{
int pass;
int i;
+ tree fn;
+ VEC(tree) *methods;
! methods = CLASSTYPE_METHOD_VEC (class_type);
for (pass = 0; pass < 2; ++pass)
for (i = CLASSTYPE_FIRST_CONVERSION_SLOT;
! (fn = VEC_iterate (tree, methods, i));
++i)
{
/* All the conversion operators come near the beginning of the
class. Therefore, if FN is not a conversion operator, there
is no matching conversion operator in CLASS_TYPE. */
fn = OVL_CURRENT (fn);
if (!DECL_CONV_FN_P (fn))
*************** lookup_conversion_operator (tree class_t
*** 1362,1445 ****
the method vector with name NAME, or -1 is no such field exists. */
int
lookup_fnfields_1 (tree type, tree name)
{
! tree method_vec;
! tree *methods;
tree tmp;
! int i;
! int len;
!
if (!CLASS_TYPE_P (type))
return -1;
method_vec = CLASSTYPE_METHOD_VEC (type);
if (!method_vec)
return -1;
- methods = &TREE_VEC_ELT (method_vec, 0);
- len = TREE_VEC_LENGTH (method_vec);
-
#ifdef GATHER_STATISTICS
n_calls_lookup_fnfields_1++;
#endif /* GATHER_STATISTICS */
/* Constructors are first... */
if (name == ctor_identifier)
! return (methods[CLASSTYPE_CONSTRUCTOR_SLOT]
! ? CLASSTYPE_CONSTRUCTOR_SLOT : -1);
/* and destructors are second. */
if (name == dtor_identifier)
! return (methods[CLASSTYPE_DESTRUCTOR_SLOT]
! ? CLASSTYPE_DESTRUCTOR_SLOT : -1);
if (IDENTIFIER_TYPENAME_P (name))
return lookup_conversion_operator (type, TREE_TYPE (name));
/* Skip the conversion operators. */
! i = CLASSTYPE_FIRST_CONVERSION_SLOT;
! while (i < len && methods[i] && DECL_CONV_FN_P (OVL_CURRENT (methods[i])))
! i++;
/* If the type is complete, use binary search. */
if (COMPLETE_TYPE_P (type))
{
! int lo = i;
! int hi = len;
while (lo < hi)
{
i = (lo + hi) / 2;
#ifdef GATHER_STATISTICS
n_outer_fields_searched++;
#endif /* GATHER_STATISTICS */
! tmp = methods[i];
! /* This slot may be empty; we allocate more slots than we
! need. In that case, the entry we're looking for is
! closer to the beginning of the list. */
! if (tmp)
! tmp = DECL_NAME (OVL_CURRENT (tmp));
! if (!tmp || tmp > name)
hi = i;
else if (tmp < name)
lo = i + 1;
else
return i;
}
}
else
! for (; i < len && methods[i]; ++i)
{
#ifdef GATHER_STATISTICS
n_outer_fields_searched++;
#endif /* GATHER_STATISTICS */
!
! tmp = OVL_CURRENT (methods[i]);
! if (DECL_NAME (tmp) == name)
return i;
}
return -1;
}
--- 1358,1459 ----
the method vector with name NAME, or -1 is no such field exists. */
int
lookup_fnfields_1 (tree type, tree name)
{
! VEC(tree) *method_vec;
! tree fn;
tree tmp;
! size_t i;
!
if (!CLASS_TYPE_P (type))
return -1;
method_vec = CLASSTYPE_METHOD_VEC (type);
if (!method_vec)
return -1;
#ifdef GATHER_STATISTICS
n_calls_lookup_fnfields_1++;
#endif /* GATHER_STATISTICS */
/* Constructors are first... */
if (name == ctor_identifier)
! {
! fn = CLASSTYPE_CONSTRUCTORS (type);
! return fn ? CLASSTYPE_CONSTRUCTOR_SLOT : -1;
! }
/* and destructors are second. */
if (name == dtor_identifier)
! {
! fn = CLASSTYPE_DESTRUCTORS (type);
! return fn ? CLASSTYPE_DESTRUCTOR_SLOT : -1;
! }
if (IDENTIFIER_TYPENAME_P (name))
return lookup_conversion_operator (type, TREE_TYPE (name));
/* Skip the conversion operators. */
! for (i = CLASSTYPE_FIRST_CONVERSION_SLOT;
! (fn = VEC_iterate (tree, method_vec, i));
! ++i)
! if (!DECL_CONV_FN_P (OVL_CURRENT (fn)))
! break;
/* If the type is complete, use binary search. */
if (COMPLETE_TYPE_P (type))
{
! int lo;
! int hi;
!
! /* All non-Java classes have "operator=" -- but we do not
! actually create the declaration until it is needed. */
! if (name == ansi_assopname(NOP_EXPR)
! && !TYPE_HAS_ASSIGN_REF (type)
! && !TYPE_FOR_JAVA (type))
! {
! tree fn;
!
! /* Declare the function. */
! fn = implicitly_declare_fn (sfk_assignment_operator, type,
! TYPE_HAS_CONST_ASSIGN_REF (type));
! add_method (type, fn);
! TREE_CHAIN (fn) = TYPE_METHODS (type);
! TYPE_METHODS (type) = fn;
! maybe_add_class_template_decl_list (type, fn, /*friend_p=*/0);
! method_vec = CLASSTYPE_METHOD_VEC (type);
! }
+ lo = i;
+ hi = VEC_length (tree, method_vec);
while (lo < hi)
{
i = (lo + hi) / 2;
#ifdef GATHER_STATISTICS
n_outer_fields_searched++;
#endif /* GATHER_STATISTICS */
! tmp = VEC_index (tree, method_vec, i);
! tmp = DECL_NAME (OVL_CURRENT (tmp));
! if (tmp > name)
hi = i;
else if (tmp < name)
lo = i + 1;
else
return i;
}
}
else
! for (;
! (fn = VEC_iterate (tree, method_vec, i));
! ++i)
{
#ifdef GATHER_STATISTICS
n_outer_fields_searched++;
#endif /* GATHER_STATISTICS */
! if (DECL_NAME (OVL_CURRENT (fn)) == name)
return i;
}
return -1;
}
*************** look_for_overrides_here (tree type, tree
*** 1779,1789 ****
ix = CLASSTYPE_DESTRUCTOR_SLOT;
else
ix = lookup_fnfields_1 (type, DECL_NAME (fndecl));
if (ix >= 0)
{
! tree fns = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), ix);
for (; fns; fns = OVL_NEXT (fns))
{
tree fn = OVL_CURRENT (fns);
--- 1793,1803 ----
ix = CLASSTYPE_DESTRUCTOR_SLOT;
else
ix = lookup_fnfields_1 (type, DECL_NAME (fndecl));
if (ix >= 0)
{
! tree fns = VEC_index (tree, CLASSTYPE_METHOD_VEC (type), ix);
for (; fns; fns = OVL_NEXT (fns))
{
tree fn = OVL_CURRENT (fns);
*************** reinit_search_statistics (void)
*** 2048,2068 ****
}
static tree
add_conversions (tree binfo, void *data)
{
! int i;
! tree method_vec = CLASSTYPE_METHOD_VEC (BINFO_TYPE (binfo));
tree *conversions = (tree *) data;
/* Some builtin types have no method vector, not even an empty one. */
if (!method_vec)
return NULL_TREE;
! for (i = 2; i < TREE_VEC_LENGTH (method_vec); ++i)
{
- tree tmp = TREE_VEC_ELT (method_vec, i);
tree name;
if (!tmp || ! DECL_CONV_FN_P (OVL_CURRENT (tmp)))
break;
--- 2062,2084 ----
}
static tree
add_conversions (tree binfo, void *data)
{
! size_t i;
! VEC(tree) *method_vec = CLASSTYPE_METHOD_VEC (BINFO_TYPE (binfo));
tree *conversions = (tree *) data;
+ tree tmp;
/* Some builtin types have no method vector, not even an empty one. */
if (!method_vec)
return NULL_TREE;
! for (i = CLASSTYPE_FIRST_CONVERSION_SLOT;
! (tmp = VEC_iterate (tree, method_vec, i));
! ++i)
{
tree name;
if (!tmp || ! DECL_CONV_FN_P (OVL_CURRENT (tmp)))
break;
Index: cp/semantics.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/semantics.c,v
retrieving revision 1.416
diff -c -5 -p -r1.416 semantics.c
*** cp/semantics.c 12 Jul 2004 16:06:36 -0000 1.416
--- cp/semantics.c 16 Jul 2004 00:56:32 -0000
*************** finish_member_declaration (tree decl)
*** 2152,2162 ****
if (TREE_CODE (decl) == FUNCTION_DECL
|| DECL_FUNCTION_TEMPLATE_P (decl))
{
/* We also need to add this function to the
CLASSTYPE_METHOD_VEC. */
! add_method (current_class_type, decl, /*error_p=*/0);
TREE_CHAIN (decl) = TYPE_METHODS (current_class_type);
TYPE_METHODS (current_class_type) = decl;
maybe_add_class_template_decl_list (current_class_type, decl,
--- 2152,2162 ----
if (TREE_CODE (decl) == FUNCTION_DECL
|| DECL_FUNCTION_TEMPLATE_P (decl))
{
/* We also need to add this function to the
CLASSTYPE_METHOD_VEC. */
! add_method (current_class_type, decl);
TREE_CHAIN (decl) = TYPE_METHODS (current_class_type);
TYPE_METHODS (current_class_type) = decl;
maybe_add_class_template_decl_list (current_class_type, decl,