This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[C++ PATCH] Fix 23118, 22604
- From: Nathan Sidwell <nathan at codesourcery dot com>
- To: GCC Patches <gcc-patches at gcc dot gnu dot org>
- Cc: Volker Reichelt <reichelt at igpm dot rwth-aachen dot de>
- Date: Tue, 18 Oct 2005 13:39:04 +0100
- Subject: [C++ PATCH] Fix 23118, 22604
This patch fixes two ICEs.
22604 was easy, we already mark invalid covariant overriders. All that was
needed was to tell the vtable machinery not to try processing them.
23118 was a little harder. An invalid overload still got added to the *list* of
member function, but wasn't added to the *vector*. We process methods in
declaration order using the list, but search for overrides using the vector.
When a virtual function is only on the list, look_for_overrides_here will fail
to find it. The fix is for add_method to return a flag indicating whether the
function made it to the method vector, and if it doesn't we don't add it to the
method list either.
built & tested on i686-pc-linux-gnu. Mainline & 4.0. Not for 3.4 as these are
both ice-on-illformed-after-error.
nathan
--
Nathan Sidwell :: http://www.codesourcery.com :: CodeSourcery LLC
nathan@codesourcery.com :: http://www.planetfall.pwp.blueyonder.co.uk
2005-10-18 Nathan Sidwell <nathan@codesourcery.com>
PR c++/22604
* class.c (update_vtable_entry_for_fn): Don't process invalid
covariant overriders.
PR c++/23118
* cp-tree.h (add_method): Add return value.
* class.c (add_method): Return success indicator.
* semantics.c (finish_member_declaration): Don't add an invalid
method to the method list.
Index: cp/class.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/class.c,v
retrieving revision 1.737
diff -c -3 -p -r1.737 class.c
*** cp/class.c 15 Oct 2005 18:13:24 -0000 1.737
--- cp/class.c 18 Oct 2005 12:02:15 -0000
*************** modify_vtable_entry (tree t,
*** 879,887 ****
/* Add method METHOD to class TYPE. If USING_DECL is non-null, it is
! the USING_DECL naming METHOD. */
! void
add_method (tree type, tree method, tree using_decl)
{
unsigned slot;
--- 879,888 ----
/* Add method METHOD to class TYPE. If USING_DECL is non-null, it is
! the USING_DECL naming METHOD. Returns true if the method could be
! added to the method vec. */
! bool
add_method (tree type, tree method, tree using_decl)
{
unsigned slot;
*************** add_method (tree type, tree method, tree
*** 894,900 ****
tree current_fns;
if (method == error_mark_node)
! return;
complete_p = COMPLETE_TYPE_P (type);
conv_p = DECL_CONV_FN_P (method);
--- 895,901 ----
tree current_fns;
if (method == error_mark_node)
! return false;
complete_p = COMPLETE_TYPE_P (type);
conv_p = DECL_CONV_FN_P (method);
*************** add_method (tree type, tree method, tree
*** 1027,1033 ****
{
if (DECL_CONTEXT (fn) == type)
/* Defer to the local function. */
! return;
if (DECL_CONTEXT (fn) == DECL_CONTEXT (method))
error ("repeated using declaration %q+D", using_decl);
else
--- 1028,1034 ----
{
if (DECL_CONTEXT (fn) == type)
/* Defer to the local function. */
! return false;
if (DECL_CONTEXT (fn) == DECL_CONTEXT (method))
error ("repeated using declaration %q+D", using_decl);
else
*************** add_method (tree type, tree method, tree
*** 1044,1050 ****
declarations because that will confuse things if the
methods have inline definitions. In particular, we
will crash while processing the definitions. */
! return;
}
}
}
--- 1045,1051 ----
declarations because that will confuse things if the
methods have inline definitions. In particular, we
will crash while processing the definitions. */
! return false;
}
}
}
*************** add_method (tree type, tree method, tree
*** 1069,1074 ****
--- 1070,1076 ----
else
/* Replace the current slot. */
VEC_replace (tree, method_vec, slot, overload);
+ return true;
}
/* Subroutines of finish_struct. */
*************** update_vtable_entry_for_fn (tree t, tree
*** 1980,1986 ****
if (POINTER_TYPE_P (over_return)
&& TREE_CODE (over_return) == TREE_CODE (base_return)
&& CLASS_TYPE_P (TREE_TYPE (over_return))
! && CLASS_TYPE_P (TREE_TYPE (base_return)))
{
/* If FN is a covariant thunk, we must figure out the adjustment
to the final base FN was converting to. As OVERRIDER_TARGET might
--- 1982,1990 ----
if (POINTER_TYPE_P (over_return)
&& TREE_CODE (over_return) == TREE_CODE (base_return)
&& CLASS_TYPE_P (TREE_TYPE (over_return))
! && CLASS_TYPE_P (TREE_TYPE (base_return))
! /* If the overrider is invalid, don't even try. */
! && !DECL_INVALID_OVERRIDER_P (overrider_target))
{
/* If FN is a covariant thunk, we must figure out the adjustment
to the final base FN was converting to. As OVERRIDER_TARGET might
Index: cp/cp-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cp-tree.h,v
retrieving revision 1.1168
diff -c -3 -p -r1.1168 cp-tree.h
*** cp/cp-tree.h 17 Oct 2005 17:25:16 -0000 1.1168
--- cp/cp-tree.h 18 Oct 2005 12:02:18 -0000
*************** extern tree build_vfn_ref (tree, tree)
*** 3709,3715 ****
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, tree);
extern int currently_open_class (tree);
extern tree currently_open_derived_class (tree);
extern tree finish_struct (tree, tree);
--- 3709,3715 ----
extern tree get_vtable_decl (tree, int);
extern void resort_type_method_vec (void *, void *,
gt_pointer_operator, void *);
! extern bool add_method (tree, tree, tree);
extern int currently_open_class (tree);
extern tree currently_open_derived_class (tree);
extern tree finish_struct (tree, tree);
Index: cp/semantics.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/semantics.c,v
retrieving revision 1.493
diff -c -3 -p -r1.493 semantics.c
*** cp/semantics.c 16 Oct 2005 19:38:56 -0000 1.493
--- cp/semantics.c 18 Oct 2005 12:02:20 -0000
*************** finish_member_declaration (tree decl)
*** 2232,2244 ****
{
/* We also need to add this function to the
CLASSTYPE_METHOD_VEC. */
! add_method (current_class_type, decl, NULL_TREE);
!
! TREE_CHAIN (decl) = TYPE_METHODS (current_class_type);
! TYPE_METHODS (current_class_type) = decl;
! maybe_add_class_template_decl_list (current_class_type, decl,
! /*friend_p=*/0);
}
/* Enter the DECL into the scope of the class. */
else if ((TREE_CODE (decl) == USING_DECL && !DECL_DEPENDENT_P (decl))
--- 2232,2245 ----
{
/* We also need to add this function to the
CLASSTYPE_METHOD_VEC. */
! if (add_method (current_class_type, decl, NULL_TREE))
! {
! TREE_CHAIN (decl) = TYPE_METHODS (current_class_type);
! TYPE_METHODS (current_class_type) = decl;
! maybe_add_class_template_decl_list (current_class_type, decl,
! /*friend_p=*/0);
! }
}
/* Enter the DECL into the scope of the class. */
else if ((TREE_CODE (decl) == USING_DECL && !DECL_DEPENDENT_P (decl))
// Copyright (C) 2005 Free Software Foundation, Inc.
// Contributed by Nathan Sidwell 18 Oct 2005 <nathan@codesourcery.com>
// PR 22604
// Origin: Volker Reichelt <reichelt@gcc.gnu.org>
struct A;
struct B
{
virtual A* foo(); // { dg-error "overriding" "" }
};
namespace N
{
struct A : B
{
virtual A* foo(); // { dg-error "invalid covariant" "" }
};
}
// Copyright (C) 2005 Free Software Foundation, Inc.
// Contributed by Nathan Sidwell 18 Oct 2005 <nathan@codesourcery.com>
// PR 22604
// Origin: Volker Reichelt <reichelt@gcc.gnu.org>
struct A
{
void foo(); // { dg-error "with" "" }
virtual void foo(); // { dg-error "cannot be overloaded" "" }
};