This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
C++ PATCH: PR 21614
- From: Mark Mitchell <mark at codesourcery dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Fri, 27 May 2005 19:25:00 -0700
- Subject: C++ PATCH: PR 21614
- Reply-to: mark at codesourcery dot com
This patch fixes PR c++/21614, a wrong-code regression in 4.0.
The problem stems from Nathan's changes to make us not allocate binfos
for incomplete types, which is, of course, a win. But, that means
that lookup_base cannot return a sensible value for an incomplete
type, so we must trying to convert to a base class of an incomplete
type. In most cases, we would never try to do that, because the use
of incomplete type would be an error -- but in this particular case,
it is valid to use a pointer-to-member of incomplete type.
Tested on x86_64-unknown-linux-gnu, applied on the mainline and on the
4.0 branch.
--
Mark Mitchell
CodeSourcery, LLC
mark@codesourcery.com
2005-05-27 Mark Mitchell <mark@codesourcery.com>
PR c++/21614
* typeck.c (get_member_function_from_ptrfunc): Do not attempt
conversions to base classes of incomplete types.
2005-05-27 Mark Mitchell <mark@codesourcery.com>
PR c++/21614
* g++.dg/expr/ptrmem6.C: New test.
* g++.dg/expr/ptrmem6a.C: Likewise.
Index: cp/typeck.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/typeck.c,v
retrieving revision 1.629
diff -c -5 -p -r1.629 typeck.c
*** cp/typeck.c 24 May 2005 22:22:33 -0000 1.629
--- cp/typeck.c 28 May 2005 02:14:46 -0000
*************** get_member_function_from_ptrfunc (tree *
*** 2344,2361 ****
default:
gcc_unreachable ();
}
! /* Convert down to the right base before using the instance. First
! use the type... */
basetype = TYPE_METHOD_BASETYPE (TREE_TYPE (fntype));
! basetype = lookup_base (TREE_TYPE (TREE_TYPE (instance_ptr)),
! basetype, ba_check, NULL);
! instance_ptr = build_base_path (PLUS_EXPR, instance_ptr, basetype, 1);
! if (instance_ptr == error_mark_node)
! return error_mark_node;
/* ...and then the delta in the PMF. */
instance_ptr = build2 (PLUS_EXPR, TREE_TYPE (instance_ptr),
instance_ptr, delta);
/* Hand back the adjusted 'this' argument to our caller. */
--- 2344,2370 ----
default:
gcc_unreachable ();
}
! /* Convert down to the right base before using the instance. A
! special case is that in a pointer to member of class C, C may
! be incomplete. In that case, the function will of course be
! a member of C, and no conversion is required. In fact,
! lookup_base will fail in that case, because incomplete
! classes do not have BINFOs. */
basetype = TYPE_METHOD_BASETYPE (TREE_TYPE (fntype));
! if (!same_type_ignoring_top_level_qualifiers_p
! (basetype, TREE_TYPE (TREE_TYPE (instance_ptr))))
! {
! basetype = lookup_base (TREE_TYPE (TREE_TYPE (instance_ptr)),
! basetype, ba_check, NULL);
! instance_ptr = build_base_path (PLUS_EXPR, instance_ptr, basetype,
! 1);
! if (instance_ptr == error_mark_node)
! return error_mark_node;
! }
/* ...and then the delta in the PMF. */
instance_ptr = build2 (PLUS_EXPR, TREE_TYPE (instance_ptr),
instance_ptr, delta);
/* Hand back the adjusted 'this' argument to our caller. */
Index: testsuite/g++.dg/expr/ptrmem6.C
===================================================================
RCS file: testsuite/g++.dg/expr/ptrmem6.C
diff -N testsuite/g++.dg/expr/ptrmem6.C
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/expr/ptrmem6.C 28 May 2005 02:14:46 -0000
***************
*** 0 ****
--- 1,12 ----
+ // PR C++/21614
+ // { dg-additional-sources "ptrmem6a.C" }
+ // { dg-do run }
+
+ extern struct Z *p;
+ extern int (Z::*m) ();
+
+ int main () {
+ if ((p->*m)() == 7)
+ return 0;
+ return 1;
+ }
Index: testsuite/g++.dg/expr/ptrmem6a.C
===================================================================
RCS file: testsuite/g++.dg/expr/ptrmem6a.C
diff -N testsuite/g++.dg/expr/ptrmem6a.C
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/expr/ptrmem6a.C 28 May 2005 02:14:46 -0000
***************
*** 0 ****
--- 1,9 ----
+ struct Z {
+ int f();
+ };
+
+ int Z::f() { return 7; }
+
+ struct Z z;
+ int (Z::*m)() = &Z::f;
+ struct Z*p = &z;