This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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);
+ }

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]