diff options
author | Mark Mitchell <mark@codesourcery.com> | 2000-08-04 18:41:00 +0000 |
---|---|---|
committer | Mark Mitchell <mmitchel@gcc.gnu.org> | 2000-08-04 18:41:00 +0000 |
commit | 452a394bc37bc65c043097d18efc8c95a3876615 (patch) | |
tree | dd32bc545603afee2ec2a4f3daf8ad5ab3742f0e /gcc | |
parent | ca2eed217f7de558a5fa3feccfad9ed73e13da1f (diff) | |
download | gcc-452a394bc37bc65c043097d18efc8c95a3876615.zip gcc-452a394bc37bc65c043097d18efc8c95a3876615.tar.gz gcc-452a394bc37bc65c043097d18efc8c95a3876615.tar.bz2 |
cp-tree.h (add_method): Change prototype.
* cp-tree.h (add_method): Change prototype.
* class.c (add_method): Remove FIELDS parameter. Add ERROR_P.
Don't double the size of the method vector in the error case.
(handle_using_decl): Adjust call to add_method.
(add_implicitly_declared_members): Likewise.
(clone_function_decl): Likewise.
* decl2.c (check_classfn): Likewise.
* semantics.c (finish_member_declaration): Likewise.
From-SVN: r35490
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/ChangeLog | 11 | ||||
-rw-r--r-- | gcc/cp/class.c | 333 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 2 | ||||
-rw-r--r-- | gcc/cp/decl2.c | 2 | ||||
-rw-r--r-- | gcc/cp/semantics.c | 2 | ||||
-rw-r--r-- | gcc/testsuite/g++.old-deja/g++.other/crash21.C | 15 |
6 files changed, 200 insertions, 165 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 5f57de9..f6c1683 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,14 @@ +2000-08-04 Mark Mitchell <mark@codesourcery.com> + + * cp-tree.h (add_method): Change prototype. + * class.c (add_method): Remove FIELDS parameter. Add ERROR_P. + Don't double the size of the method vector in the error case. + (handle_using_decl): Adjust call to add_method. + (add_implicitly_declared_members): Likewise. + (clone_function_decl): Likewise. + * decl2.c (check_classfn): Likewise. + * semantics.c (finish_member_declaration): Likewise. + 2000-08-04 Joseph S. Myers <jsm28@cam.ac.uk> * decl.c (flag_isoc94): New variable. diff --git a/gcc/cp/class.c b/gcc/cp/class.c index cf62937..aafecbe 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -1155,190 +1155,199 @@ add_virtual_function (new_virtuals_p, overridden_virtuals_p, extern struct obstack *current_obstack; -/* Add method METHOD to class TYPE. - - If non-NULL, FIELDS is the entry in the METHOD_VEC vector entry of - the class type where the method should be added. */ +/* 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 (type, fields, method) - tree type, *fields, method; +add_method (type, method, error_p) + tree type; + tree method; + int error_p; { int using = (DECL_CONTEXT (method) != type); - - if (fields && *fields) - *fields = build_overload (method, *fields); - else + int len; + int slot; + tree method_vec; + + 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)) + slot = CLASSTYPE_DESTRUCTOR_SLOT; + else { - int len; - int slot; - tree method_vec; - - 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)) - slot = CLASSTYPE_DESTRUCTOR_SLOT; - else - { - /* See if we already have an entry with this name. */ - for (slot = CLASSTYPE_FIRST_CONVERSION_SLOT; slot < len; ++slot) - if (!TREE_VEC_ELT (method_vec, slot) - || (DECL_NAME (OVL_CURRENT (TREE_VEC_ELT (method_vec, - slot))) - == DECL_NAME (method))) - break; + /* See if we already have an entry with this name. */ + for (slot = CLASSTYPE_FIRST_CONVERSION_SLOT; slot < len; ++slot) + if (!TREE_VEC_ELT (method_vec, slot) + || (DECL_NAME (OVL_CURRENT (TREE_VEC_ELT (method_vec, + slot))) + == DECL_NAME (method))) + break; - if (slot == len) - { - /* We need a bigger method vector. */ - tree new_vec = make_tree_vec (2 * len); - bcopy ((PTR) &TREE_VEC_ELT (method_vec, 0), - (PTR) &TREE_VEC_ELT (new_vec, 0), - len * sizeof (tree)); - len = 2 * len; - method_vec = CLASSTYPE_METHOD_VEC (type) = new_vec; - } + 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); + bcopy ((PTR) &TREE_VEC_ELT (method_vec, 0), + (PTR) &TREE_VEC_ELT (new_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)) + 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. */ + for (slot = 2; slot < len; ++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. */ - for (slot = 2; slot < len; ++slot) - { - tree fn = TREE_VEC_ELT (method_vec, 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 (!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 (!DECL_CONV_FN_P (OVL_CURRENT (fn))) + /* We can insert the new function right at the + SLOTth position. */ + break; + } - if (!TREE_VEC_ELT (method_vec, slot)) - /* There is nothing in the Ith slot, so we can avoid - moving anything. */ + 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. */ - bcopy ((PTR) &TREE_VEC_ELT (method_vec, slot), - (PTR) &TREE_VEC_ELT (method_vec, slot + 1), - (len - slot - 1) * sizeof (tree)); - TREE_VEC_ELT (method_vec, slot) = NULL_TREE; - } + 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. */ + bcopy ((PTR) &TREE_VEC_ELT (method_vec, slot), + (PTR) &TREE_VEC_ELT (method_vec, slot + 1), + (len - slot - 1) * sizeof (tree)); + TREE_VEC_ELT (method_vec, slot) = NULL_TREE; } } + } - if (template_class_depth (type)) - /* TYPE is a template class. Don't issue any errors now; wait - until instantiation time to complain. */ - ; - else - { - tree fns; + if (template_class_depth (type)) + /* TYPE is a template class. Don't issue any errors now; wait + until instantiation time to complain. */ + ; + 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); + /* 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); - if (TREE_CODE (fn) != TREE_CODE (method)) - continue; + if (TREE_CODE (fn) != TREE_CODE (method)) + continue; - if (TREE_CODE (method) != TEMPLATE_DECL) + if (TREE_CODE (method) != TEMPLATE_DECL) + { + /* [over.load] Member function declarations with the + same name and the same parameter types cannot be + overloaded if any of them is a static member + function declaration. */ + if ((DECL_STATIC_FUNCTION_P (fn) + != DECL_STATIC_FUNCTION_P (method)) + || using) { - /* [over.load] Member function declarations with the - same name and the same parameter types cannot be - overloaded if any of them is a static member - function declaration. */ - if ((DECL_STATIC_FUNCTION_P (fn) - != DECL_STATIC_FUNCTION_P (method)) - || using) + tree parms1 = TYPE_ARG_TYPES (TREE_TYPE (fn)); + tree parms2 = TYPE_ARG_TYPES (TREE_TYPE (method)); + + if (! DECL_STATIC_FUNCTION_P (fn)) + parms1 = TREE_CHAIN (parms1); + if (! DECL_STATIC_FUNCTION_P (method)) + parms2 = TREE_CHAIN (parms2); + + if (compparms (parms1, parms2)) { - tree parms1 = TYPE_ARG_TYPES (TREE_TYPE (fn)); - tree parms2 = TYPE_ARG_TYPES (TREE_TYPE (method)); - - if (! DECL_STATIC_FUNCTION_P (fn)) - parms1 = TREE_CHAIN (parms1); - if (! DECL_STATIC_FUNCTION_P (method)) - parms2 = TREE_CHAIN (parms2); - - if (compparms (parms1, parms2)) - { - if (using) - /* Defer to the local function. */ - return; - else - cp_error ("`%#D' and `%#D' cannot be overloaded", - fn, method); - } + if (using) + /* Defer to the local function. */ + return; + else + cp_error ("`%#D' and `%#D' cannot be overloaded", + fn, method); } - - /* Since this is an ordinary function in a - non-template class, it's mangled name can be used - as a unique identifier. This technique is only - an optimization; we would get the same results if - we just used decls_match here. */ - if (DECL_ASSEMBLER_NAME (fn) - != DECL_ASSEMBLER_NAME (method)) - continue; } - else if (!decls_match (fn, method)) + + /* Since this is an ordinary function in a + non-template class, it's mangled name can be used + as a unique identifier. This technique is only + an optimization; we would get the same results if + we just used decls_match here. */ + if (DECL_ASSEMBLER_NAME (fn) + != DECL_ASSEMBLER_NAME (method)) continue; + } + else if (!decls_match (fn, method)) + continue; - /* There has already been a declaration of this method - or member template. */ - cp_error_at ("`%D' has already been declared in `%T'", - method, type); + /* There has already been a declaration of this method + or member template. */ + cp_error_at ("`%D' has already been declared in `%T'", + method, type); - /* We don't call duplicate_decls here to merge the - declarations because that will confuse things if the - methods have inline definitions. In particular, we - will crash while processing the definitions. */ - return; - } + /* We don't call duplicate_decls here to merge the + declarations because that will confuse things if the + methods have inline definitions. In particular, we + will crash while processing the definitions. */ + return; } + } - /* Actually insert the new method. */ - TREE_VEC_ELT (method_vec, slot) - = build_overload (method, TREE_VEC_ELT (method_vec, slot)); + /* Actually insert the new method. */ + TREE_VEC_ELT (method_vec, slot) + = build_overload (method, TREE_VEC_ELT (method_vec, slot)); /* Add the new binding. */ - if (!DECL_CONSTRUCTOR_P (method) - && !DECL_DESTRUCTOR_P (method)) - push_class_level_binding (DECL_NAME (method), - TREE_VEC_ELT (method_vec, slot)); - } + if (!DECL_CONSTRUCTOR_P (method) + && !DECL_DESTRUCTOR_P (method)) + push_class_level_binding (DECL_NAME (method), + TREE_VEC_ELT (method_vec, slot)); } /* Subroutines of finish_struct. */ @@ -1567,7 +1576,7 @@ handle_using_decl (using_decl, t) if (flist) for (; flist; flist = OVL_NEXT (flist)) { - add_method (t, 0, OVL_CURRENT (flist)); + add_method (t, OVL_CURRENT (flist), /*error_p=*/0); alter_access (t, OVL_CURRENT (flist), access); } else @@ -3146,7 +3155,7 @@ add_implicitly_declared_members (t, cant_have_default_ctor, /* 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, 0, *f); + add_method (t, *f, /*error_p=*/0); *f = TYPE_METHODS (t); TYPE_METHODS (t) = implicit_fns; @@ -4203,10 +4212,10 @@ clone_function_decl (fn, update_method_vec_p) and a not-in-charge version. */ clone = build_clone (fn, complete_ctor_identifier); if (update_method_vec_p) - add_method (DECL_CONTEXT (clone), NULL, clone); + 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), NULL, clone); + add_method (DECL_CONTEXT (clone), clone, /*error_p=*/0); } else { @@ -4220,13 +4229,13 @@ clone_function_decl (fn, update_method_vec_p) function table. */ clone = build_clone (fn, deleting_dtor_identifier); if (update_method_vec_p) - add_method (DECL_CONTEXT (clone), NULL, clone); + 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), NULL, clone); + 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), NULL, clone); + add_method (DECL_CONTEXT (clone), clone, /*error_p=*/0); } } diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index a945ab4..2c534f3 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -3805,7 +3805,7 @@ extern tree build_vbase_path PARAMS ((enum tree_code, tree, tree, tree, int)); extern tree build_vtbl_ref PARAMS ((tree, tree)); extern tree build_vfn_ref PARAMS ((tree *, tree, tree)); extern tree get_vtable_decl PARAMS ((tree, int)); -extern void add_method PARAMS ((tree, tree *, tree)); +extern void add_method PARAMS ((tree, tree, int)); extern int currently_open_class PARAMS ((tree)); extern tree currently_open_derived_class PARAMS ((tree)); extern tree get_vfield_offset PARAMS ((tree)); diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 690a78d..514b9c6 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -1549,7 +1549,7 @@ check_classfn (ctype, function) case we'll only confuse ourselves when the function is declared properly within the class. */ if (COMPLETE_TYPE_P (ctype)) - add_method (ctype, methods, function); + add_method (ctype, function, /*error_p=*/1); return NULL_TREE; } diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 066f675..9dc6bca 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -1969,7 +1969,7 @@ finish_member_declaration (decl) { /* We also need to add this function to the CLASSTYPE_METHOD_VEC. */ - add_method (current_class_type, 0, decl); + add_method (current_class_type, decl, /*error_p=*/0); TREE_CHAIN (decl) = TYPE_METHODS (current_class_type); TYPE_METHODS (current_class_type) = decl; diff --git a/gcc/testsuite/g++.old-deja/g++.other/crash21.C b/gcc/testsuite/g++.old-deja/g++.other/crash21.C new file mode 100644 index 0000000..e9e642f --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.other/crash21.C @@ -0,0 +1,15 @@ +// Build don't link: +// Origin: Gabriel Dos Reis <gdr@codesourcery.com> + +struct A { + virtual void f(int&) const; +}; + +struct B : public A { + int x; +}; + +void B::f(int& t) +{ + x = t; +} |