From: jason Date: Fri, 13 Apr 2007 23:43:18 +0000 (+0000) Subject: PR c++/31074 X-Git-Url: http://git.sourceforge.jp/view?p=pf3gnuchains%2Fgcc-fork.git;a=commitdiff_plain;h=0664b4250483d9a279da4d63f157c4a3b2e8b966;hp=9632ba60c73b9f7337e370d7ac2c8f0edc3218f2 PR c++/31074 * call.c (reference_binding): Add c_cast_p parm. If true, add quals to TO as needed to make it reference-compatible. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@123805 138bc75d-0d04-0410-961f-82ee72b054a4 --- diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 663b3e14e50..9d0ac8cc9dc 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,9 @@ +2007-04-13 Jason Merrill + + PR c++/31074 + * call.c (reference_binding): Add c_cast_p parm. If true, + add quals to TO as needed to make it reference-compatible. + 2007-04-11 Jan Hubicka * cp/class.c (convert_to_base_statically): Fold produced tree; verify diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 320e51c09ff..0b0bb646d22 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -173,7 +173,7 @@ static struct z_candidate *add_function_candidate (struct z_candidate **, tree, tree, tree, tree, tree, int); static conversion *implicit_conversion (tree, tree, tree, bool, int); static conversion *standard_conversion (tree, tree, tree, bool, int); -static conversion *reference_binding (tree, tree, tree, int); +static conversion *reference_binding (tree, tree, tree, bool, int); static conversion *build_conv (conversion_kind, tree, conversion *); static bool is_subseq (conversion *, conversion *); static tree maybe_handle_ref_bind (conversion **); @@ -1105,10 +1105,11 @@ direct_reference_binding (tree type, conversion *conv) purposes of reference binding. For lvalue binding, either pass a reference type to FROM or an lvalue expression to EXPR. If the reference will be bound to a temporary, NEED_TEMPORARY_P is set for - the conversion returned. */ + the conversion returned. If C_CAST_P is true, this + conversion is coming from a C-style cast. */ static conversion * -reference_binding (tree rto, tree rfrom, tree expr, int flags) +reference_binding (tree rto, tree rfrom, tree expr, bool c_cast_p, int flags) { conversion *conv = NULL; tree to = TREE_TYPE (rto); @@ -1138,6 +1139,11 @@ reference_binding (tree rto, tree rfrom, tree expr, int flags) reference compatible. We have do do this after stripping references from FROM. */ related_p = reference_related_p (to, from); + /* If this is a C cast, first convert to an appropriately qualified + type, so that we can later do a const_cast to the desired type. */ + if (related_p && c_cast_p + && !at_least_as_qualified_p (to, from)) + to = build_qualified_type (to, cp_type_quals (from)); compatible_p = reference_compatible_p (to, from); if (lvalue_p && compatible_p) @@ -1247,7 +1253,7 @@ reference_binding (tree rto, tree rfrom, tree expr, int flags) if (related_p && !at_least_as_qualified_p (to, from)) return NULL; - conv = implicit_conversion (to, from, expr, /*c_cast_p=*/false, + conv = implicit_conversion (to, from, expr, c_cast_p, flags); if (!conv) return NULL; @@ -1277,7 +1283,7 @@ implicit_conversion (tree to, tree from, tree expr, bool c_cast_p, return NULL; if (TREE_CODE (to) == REFERENCE_TYPE) - conv = reference_binding (to, from, expr, flags); + conv = reference_binding (to, from, expr, c_cast_p, flags); else conv = standard_conversion (to, from, expr, c_cast_p, flags); @@ -6618,7 +6624,8 @@ initialize_reference (tree type, tree expr, tree decl, tree *cleanup) /* Get the high-water mark for the CONVERSION_OBSTACK. */ p = conversion_obstack_alloc (0); - conv = reference_binding (type, TREE_TYPE (expr), expr, LOOKUP_NORMAL); + conv = reference_binding (type, TREE_TYPE (expr), expr, /*c_cast_p=*/false, + LOOKUP_NORMAL); if (!conv || conv->bad_p) { if (!(TYPE_QUALS (TREE_TYPE (type)) & TYPE_QUAL_CONST) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 2b0d8803232..118d9ad3729 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2007-04-13 Jason Merrill + + PR c++/31074 + * conv3.C: New test. + 2007-04-13 Mike Stump * obj-c++.dg/stubify-1.mm: Only run on powerpc. diff --git a/gcc/testsuite/g++.dg/inherit/conv3.C b/gcc/testsuite/g++.dg/inherit/conv3.C new file mode 100644 index 00000000000..73d8c20f143 --- /dev/null +++ b/gcc/testsuite/g++.dg/inherit/conv3.C @@ -0,0 +1,31 @@ +// PR 31074 +// Bug: The reference cast wasn't finding the desired static_cast followed by +// const_cast interpretation. + +struct Shape +{ + Shape() {} + virtual ~Shape() {} +}; + +struct Loop +{ + Loop() {} + virtual ~Loop() {} + virtual void func() {} +}; + +struct Rect : + public Shape, + public Loop +{ + Rect() {} + virtual ~Rect() {} +}; + +int main () +{ + const Rect* rect = new Rect(); + Loop &l = ((Loop&)(*rect)); + return (&l != (const Loop *)rect); +}