aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorMark Mitchell <mark@codesourcery.com>2000-08-04 18:41:00 +0000
committerMark Mitchell <mmitchel@gcc.gnu.org>2000-08-04 18:41:00 +0000
commit452a394bc37bc65c043097d18efc8c95a3876615 (patch)
treedd32bc545603afee2ec2a4f3daf8ad5ab3742f0e /gcc
parentca2eed217f7de558a5fa3feccfad9ed73e13da1f (diff)
downloadgcc-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/ChangeLog11
-rw-r--r--gcc/cp/class.c333
-rw-r--r--gcc/cp/cp-tree.h2
-rw-r--r--gcc/cp/decl2.c2
-rw-r--r--gcc/cp/semantics.c2
-rw-r--r--gcc/testsuite/g++.old-deja/g++.other/crash21.C15
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;
+}