This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
C++ PATCH for c++/31074
- From: Jason Merrill <jason at redhat dot com>
- To: gcc-patches List <gcc-patches at gcc dot gnu dot org>
- Date: Fri, 13 Apr 2007 19:42:44 -0400
- Subject: C++ PATCH for c++/31074
The reference case of 22132 which Mark fixed back in August. Fixed by
extending his c_cast_p parameter into reference_binding.
Tested x86_64-pc-linux-gnu, applied to trunk. I'll test and apply to
4.1 and 4.2 soon.
2007-04-13 Jason Merrill <jason@redhat.com>
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.
Index: cp/call.c
===================================================================
*** cp/call.c (revision 123804)
--- cp/call.c (working copy)
*************** static struct z_candidate *add_function_
*** 173,179 ****
(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 *build_conv (conversion_kind, tree, conversion *);
static bool is_subseq (conversion *, conversion *);
static tree maybe_handle_ref_bind (conversion **);
--- 173,179 ----
(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, bool, int);
static conversion *build_conv (conversion_kind, tree, conversion *);
static bool is_subseq (conversion *, conversion *);
static tree maybe_handle_ref_bind (conversion **);
*************** direct_reference_binding (tree type, con
*** 1105,1114 ****
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. */
static conversion *
! reference_binding (tree rto, tree rfrom, tree expr, int flags)
{
conversion *conv = NULL;
tree to = TREE_TYPE (rto);
--- 1105,1115 ----
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. 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, bool c_cast_p, int flags)
{
conversion *conv = NULL;
tree to = TREE_TYPE (rto);
*************** reference_binding (tree rto, tree rfrom,
*** 1138,1143 ****
--- 1139,1149 ----
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)
*************** reference_binding (tree rto, tree rfrom,
*** 1247,1253 ****
if (related_p && !at_least_as_qualified_p (to, from))
return NULL;
! conv = implicit_conversion (to, from, expr, /*c_cast_p=*/false,
flags);
if (!conv)
return NULL;
--- 1253,1259 ----
if (related_p && !at_least_as_qualified_p (to, from))
return NULL;
! conv = implicit_conversion (to, from, expr, c_cast_p,
flags);
if (!conv)
return NULL;
*************** implicit_conversion (tree to, tree from,
*** 1277,1283 ****
return NULL;
if (TREE_CODE (to) == REFERENCE_TYPE)
! conv = reference_binding (to, from, expr, flags);
else
conv = standard_conversion (to, from, expr, c_cast_p, flags);
--- 1283,1289 ----
return NULL;
if (TREE_CODE (to) == REFERENCE_TYPE)
! conv = reference_binding (to, from, expr, c_cast_p, flags);
else
conv = standard_conversion (to, from, expr, c_cast_p, flags);
*************** initialize_reference (tree type, tree ex
*** 6618,6624 ****
/* Get the high-water mark for the CONVERSION_OBSTACK. */
p = conversion_obstack_alloc (0);
! conv = reference_binding (type, TREE_TYPE (expr), expr, LOOKUP_NORMAL);
if (!conv || conv->bad_p)
{
if (!(TYPE_QUALS (TREE_TYPE (type)) & TYPE_QUAL_CONST)
--- 6624,6631 ----
/* Get the high-water mark for the CONVERSION_OBSTACK. */
p = conversion_obstack_alloc (0);
! 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)
Index: testsuite/g++.dg/inherit/conv3.C
===================================================================
*** testsuite/g++.dg/inherit/conv3.C (revision 0)
--- testsuite/g++.dg/inherit/conv3.C (revision 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);
+ }