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: PR 10841 and 18073


My recent conversion fixes caused a regression in the processing of
conversions to VECTOR_TYPEs.  These were previously permitted by
C-style casts, but not reinterpret_casts, which makes no sense.  When
I made C-style casts depend on the reinterpret_cast machinery, I
failed to add support for VECTOR_TYPE.

Also this patch fixes a problem with pointer-to-member conversions.

Tested on i686-pc-linux-gnu, applied on the mainline.  Updating
Bugzilla will have to wait until after I give a talk; I'm due right now.

--
Mark Mitchell
CodeSourcery, LLC
mark@codesourcery.com

2004-10-21  Mark Mitchell  <mark@codesourcery.com>

	PR c++/18073
	PR c++/10841
	* cp-tree.h (convert_to_base): Change prototype.
	(build_ptrmemfunc): Likewise.
	(convert_ptrmem): New function.
	* call.c (struct conversion): Adjust documentation for base_p.
	(standard_conversion): Set base_p for ck_pmem conversions as
	appropriate.
	(convert_like_real): Use convert_to_base for ck_pmem and ck_ptr
	conversions.
	* class.c (convert_to_base): Handle both pointers and objects.
	Add nonnull parameter.
	(build_vfield_ref): Adjust call to convert_to_base.
	* cvt.c (cp_convert_to_pointer): Adjust call to build_ptrmemfunc.
	(convert_force): Likewise.
	* typeck.c (build_unary_op): Likewise.
	(convert_ptrmem): New function.
	(build_static_cast_1): Use it.
	(build_reinterpret_cast): Allow conversions to vector types.
	(get_delta_difference): Add c_cast_p parameter.
	(build_ptrmemfunc): Likewise.  Adjust calls to
	get_delta_difference.

2004-10-21  Mark Mitchell  <mark@codesourcery.com>

	PR c++/10841
	* g++.dg/conversion/cast1.C: New test.
	* g++.dg/overload/pmf1.C: Adjust error marker.

Index: cp/call.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/call.c,v
retrieving revision 1.515
diff -c -5 -p -r1.515 call.c
*** cp/call.c	20 Oct 2004 13:16:41 -0000	1.515
--- cp/call.c	21 Oct 2004 21:20:01 -0000
*************** struct conversion {
*** 90,101 ****
    BOOL_BITFIELD need_temporary_p : 1;
    /* If KIND is ck_identity or ck_base_conv, true to indicate that the
       copy constructor must be accessible, even though it is not being
       used.  */
    BOOL_BITFIELD check_copy_constructor_p : 1;
!   /* If KIND is ck_ptr, true to indicate that a conversion from a
!      pointer-to-derived to pointer-to-base is being performed.  */
    BOOL_BITFIELD base_p : 1;
    /* The type of the expression resulting from the conversion.  */
    tree type;
    union {
      /* The next conversion in the chain.  Since the conversions are
--- 90,101 ----
    BOOL_BITFIELD need_temporary_p : 1;
    /* If KIND is ck_identity or ck_base_conv, true to indicate that the
       copy constructor must be accessible, even though it is not being
       used.  */
    BOOL_BITFIELD check_copy_constructor_p : 1;
!   /* If KIND is ck_ptr or ck_pmem, true to indicate that a conversion
!      from a pointer-to-derived to pointer-to-base is being performed.  */ 
    BOOL_BITFIELD base_p : 1;
    /* The type of the expression resulting from the conversion.  */
    tree type;
    union {
      /* The next conversion in the chain.  Since the conversions are
*************** standard_conversion (tree to, tree from,
*** 777,786 ****
--- 777,787 ----
        from = build_method_type_directly (from, 
  					 TREE_TYPE (fromfn),
  					 TREE_CHAIN (TYPE_ARG_TYPES (fromfn)));
        from = build_ptrmemfunc_type (build_pointer_type (from));
        conv = build_conv (ck_pmem, from, conv);
+       conv->base_p = true;
      }
    else if (tcode == BOOLEAN_TYPE)
      {
        /* [conv.bool]
  
*************** convert_like_real (conversion *convs, tr
*** 4268,4279 ****
  	     subobject of EXPR.  */
  	  if (convs->check_copy_constructor_p)
  	    check_constructor_callable (TREE_TYPE (expr), expr);
  	  /* Build an expression for `*((base*) &expr)'.  */
  	  expr = build_unary_op (ADDR_EXPR, expr, 0);
! 	  expr = perform_implicit_conversion (build_pointer_type (totype), 
! 					      expr);
  	  expr = build_indirect_ref (expr, "implicit conversion");
  	  return expr;
  	}
  
        /* Copy-initialization where the cv-unqualified version of the source
--- 4269,4280 ----
  	     subobject of EXPR.  */
  	  if (convs->check_copy_constructor_p)
  	    check_constructor_callable (TREE_TYPE (expr), expr);
  	  /* Build an expression for `*((base*) &expr)'.  */
  	  expr = build_unary_op (ADDR_EXPR, expr, 0);
! 	  expr = convert_to_base (expr, build_pointer_type (totype),
! 				  !c_cast_p, /*nonnull=*/true);
  	  expr = build_indirect_ref (expr, "implicit conversion");
  	  return expr;
  	}
  
        /* Copy-initialization where the cv-unqualified version of the source
*************** convert_like_real (conversion *convs, tr
*** 4336,4358 ****
        string_conv_p (totype, expr, 1);
        break;
  
      case ck_ptr:
        if (convs->base_p)
! 	{
! 	  tree binfo;
! 
! 	  binfo = lookup_base (TREE_TYPE (TREE_TYPE (expr)),
! 			       TREE_TYPE (totype), 
! 			       c_cast_p ? ba_unique : ba_check,
! 			       NULL);
! 	  if (binfo == error_mark_node)
! 	    return error_mark_node;
! 	  expr = build_base_path (PLUS_EXPR, expr, binfo, /*nonnull=*/0);
! 	}
        return build_nop (totype, expr);
  
      default:
        break;
      }
    return ocp_convert (totype, expr, CONV_IMPLICIT,
  		      LOOKUP_NORMAL|LOOKUP_NO_CONVERSION);
--- 4337,4354 ----
        string_conv_p (totype, expr, 1);
        break;
  
      case ck_ptr:
        if (convs->base_p)
! 	expr = convert_to_base (expr, totype, !c_cast_p,
! 				/*nonnull=*/false);
        return build_nop (totype, expr);
  
+     case ck_pmem:
+       return convert_ptrmem (totype, expr, /*allow_inverse_p=*/false,
+ 			     c_cast_p);
+ 
      default:
        break;
      }
    return ocp_convert (totype, expr, CONV_IMPLICIT,
  		      LOOKUP_NORMAL|LOOKUP_NO_CONVERSION);
Index: cp/class.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/class.c,v
retrieving revision 1.685
diff -c -5 -p -r1.685 class.c
*** cp/class.c	18 Oct 2004 17:21:26 -0000	1.685
--- cp/class.c	21 Oct 2004 21:20:01 -0000
*************** build_simple_base_path (tree expr, tree 
*** 424,449 ****
  
    /* Didn't find the base field?!?  */
    gcc_unreachable ();
  }
  
! /* Convert OBJECT to the base TYPE.  If CHECK_ACCESS is true, an error
!    message is emitted if TYPE is inaccessible.  OBJECT is assumed to
!    be non-NULL.  */
  
  tree
! convert_to_base (tree object, tree type, bool check_access)
  {
    tree binfo;
  
!   binfo = lookup_base (TREE_TYPE (object), type, 
  		       check_access ? ba_check : ba_unique, 
  		       NULL);
    if (!binfo || binfo == error_mark_node)
      return error_mark_node;
  
!   return build_base_path (PLUS_EXPR, object, binfo, /*nonnull=*/1);
  }
  
  /* EXPR is an expression with unqualified class type.  BASE is a base
     binfo of that class type.  Returns EXPR, converted to the BASE
     type.  This function assumes that EXPR is the most derived class;
--- 424,461 ----
  
    /* Didn't find the base field?!?  */
    gcc_unreachable ();
  }
  
! /* Convert OBJECT to the base TYPE.  OBJECT is an expression whose
!    type is a class type or a pointer to a class type.  In the former
!    case, TYPE is also a class type; in the latter it is another
!    pointer type.  If CHECK_ACCESS is true, an error message is emitted
!    if TYPE is inaccessible.  If OBJECT has pointer type, the value is
!    assumed to be non-NULL.  */
  
  tree
! convert_to_base (tree object, tree type, bool check_access, bool nonnull)
  {
    tree binfo;
+   tree object_type;
  
!   if (TYPE_PTR_P (TREE_TYPE (object)))
!     {
!       object_type = TREE_TYPE (TREE_TYPE (object));
!       type = TREE_TYPE (type);
!     }
!   else
!     object_type = TREE_TYPE (object);
! 
!   binfo = lookup_base (object_type, type,
  		       check_access ? ba_check : ba_unique, 
  		       NULL);
    if (!binfo || binfo == error_mark_node)
      return error_mark_node;
  
!   return build_base_path (PLUS_EXPR, object, binfo, nonnull);
  }
  
  /* EXPR is an expression with unqualified class type.  BASE is a base
     binfo of that class type.  Returns EXPR, converted to the BASE
     type.  This function assumes that EXPR is the most derived class;
*************** build_vfield_ref (tree datum, tree type)
*** 483,493 ****
    if (TREE_CODE (TREE_TYPE (datum)) == REFERENCE_TYPE)
      datum = convert_from_reference (datum);
  
    /* First, convert to the requested type.  */
    if (!same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (datum), type))
!     datum = convert_to_base (datum, type, /*check_access=*/false);
  
    /* Second, the requested type may not be the owner of its own vptr.
       If not, convert to the base class that owns it.  We cannot use
       convert_to_base here, because VCONTEXT may appear more than once
       in the inheritance hierarchy of TYPE, and thus direct conversion
--- 495,506 ----
    if (TREE_CODE (TREE_TYPE (datum)) == REFERENCE_TYPE)
      datum = convert_from_reference (datum);
  
    /* First, convert to the requested type.  */
    if (!same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (datum), type))
!     datum = convert_to_base (datum, type, /*check_access=*/false,
! 			     /*nonnull=*/true);
  
    /* Second, the requested type may not be the owner of its own vptr.
       If not, convert to the base class that owns it.  We cannot use
       convert_to_base here, because VCONTEXT may appear more than once
       in the inheritance hierarchy of TYPE, and thus direct conversion
Index: cp/cp-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cp-tree.h,v
retrieving revision 1.1066
diff -c -5 -p -r1.1066 cp-tree.h
*** cp/cp-tree.h	20 Oct 2004 16:20:36 -0000	1.1066
--- cp/cp-tree.h	21 Oct 2004 21:20:01 -0000
*************** extern tree build_cxx_call (tree, tree);
*** 3592,3602 ****
  extern void validate_conversion_obstack (void);
  #endif /* ENABLE_CHECKING */
  
  /* in class.c */
  extern tree build_base_path			(enum tree_code, tree, tree, int);
! extern tree convert_to_base                     (tree, tree, bool);
  extern tree convert_to_base_statically (tree, tree);
  extern tree build_vtbl_ref			(tree, tree);
  extern tree build_vfn_ref			(tree, tree);
  extern tree get_vtable_decl                     (tree, int);
  extern void resort_type_method_vec
--- 3592,3602 ----
  extern void validate_conversion_obstack (void);
  #endif /* ENABLE_CHECKING */
  
  /* in class.c */
  extern tree build_base_path			(enum tree_code, tree, tree, int);
! extern tree convert_to_base                     (tree, tree, bool, bool);
  extern tree convert_to_base_statically (tree, tree);
  extern tree build_vtbl_ref			(tree, tree);
  extern tree build_vfn_ref			(tree, tree);
  extern tree get_vtable_decl                     (tree, int);
  extern void resort_type_method_vec
*************** extern tree build_x_modify_expr			(tree,
*** 4265,4275 ****
  extern tree build_modify_expr			(tree, enum tree_code, tree);
  extern tree dubious_conversion_warnings         (tree, tree, const char *, tree, int);
  extern tree convert_for_initialization		(tree, tree, tree, int, const char *, tree, int);
  extern int comp_ptr_ttypes			(tree, tree);
  extern int ptr_reasonably_similar		(tree, tree);
! extern tree build_ptrmemfunc			(tree, tree, int);
  extern int cp_type_quals                        (tree);
  extern bool cp_has_mutable_p                     (tree);
  extern bool at_least_as_qualified_p              (tree, tree);
  extern bool more_qualified_p                     (tree, tree);
  extern tree build_ptrmemfunc1                   (tree, tree, tree);
--- 4265,4275 ----
  extern tree build_modify_expr			(tree, enum tree_code, tree);
  extern tree dubious_conversion_warnings         (tree, tree, const char *, tree, int);
  extern tree convert_for_initialization		(tree, tree, tree, int, const char *, tree, int);
  extern int comp_ptr_ttypes			(tree, tree);
  extern int ptr_reasonably_similar		(tree, tree);
! extern tree build_ptrmemfunc			(tree, tree, int, bool);
  extern int cp_type_quals                        (tree);
  extern bool cp_has_mutable_p                     (tree);
  extern bool at_least_as_qualified_p              (tree, tree);
  extern bool more_qualified_p                     (tree, tree);
  extern tree build_ptrmemfunc1                   (tree, tree, tree);
*************** extern tree build_address               
*** 4289,4298 ****
--- 4289,4299 ----
  extern tree build_nop                           (tree, tree);
  extern tree non_reference                       (tree);
  extern tree lookup_anon_field                   (tree, tree);
  extern bool invalid_nonstatic_memfn_p           (tree);
  extern tree convert_member_func_to_ptr          (tree, tree);
+ extern tree convert_ptrmem                      (tree, tree, bool, bool);
  
  /* in typeck2.c */
  extern void require_complete_eh_spec_types	(tree, tree);
  extern void cxx_incomplete_type_diagnostic	(tree, tree, int);
  #undef cxx_incomplete_type_error
Index: cp/cvt.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cvt.c,v
retrieving revision 1.169
diff -c -5 -p -r1.169 cvt.c
*** cp/cvt.c	19 Oct 2004 23:24:18 -0000	1.169
--- cp/cvt.c	21 Oct 2004 21:20:01 -0000
*************** cp_convert_to_pointer (tree type, tree e
*** 215,225 ****
  			   build_nop (sizetype, expr),
  			   BINFO_OFFSET (binfo));
        return build_nop (type, expr);
      }
    else if (TYPE_PTRMEMFUNC_P (type) && TYPE_PTRMEMFUNC_P (intype))
!     return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), expr, 0);
    else if (TYPE_PTRMEMFUNC_P (intype))
      {
        if (!warn_pmf2ptr)
  	{
  	  if (TREE_CODE (expr) == PTRMEM_CST)
--- 215,226 ----
  			   build_nop (sizetype, expr),
  			   BINFO_OFFSET (binfo));
        return build_nop (type, expr);
      }
    else if (TYPE_PTRMEMFUNC_P (type) && TYPE_PTRMEMFUNC_P (intype))
!     return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), expr, 0,
! 			     /*c_cast_p=*/false);
    else if (TYPE_PTRMEMFUNC_P (intype))
      {
        if (!warn_pmf2ptr)
  	{
  	  if (TREE_CODE (expr) == PTRMEM_CST)
*************** cp_convert_to_pointer (tree type, tree e
*** 239,249 ****
      }
  
    if (integer_zerop (expr))
      {
        if (TYPE_PTRMEMFUNC_P (type))
! 	return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), expr, 0);
  
        if (TYPE_PTRMEM_P (type))
  	{
  	  /* A NULL pointer-to-member is represented by -1, not by
  	     zero.  */
--- 240,251 ----
      }
  
    if (integer_zerop (expr))
      {
        if (TYPE_PTRMEMFUNC_P (type))
! 	return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), expr, 0,
! 				 /*c_cast_p=*/false);
  
        if (TYPE_PTRMEM_P (type))
  	{
  	  /* A NULL pointer-to-member is represented by -1, not by
  	     zero.  */
*************** convert_force (tree type, tree expr, int
*** 958,971 ****
  	&& TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE
  	&& TREE_CODE (TREE_TYPE (TREE_TYPE (e))) == METHOD_TYPE)
         || integer_zerop (e)
         || TYPE_PTRMEMFUNC_P (TREE_TYPE (e)))
        && TYPE_PTRMEMFUNC_P (type))
!     {
!       /* compatible pointer to member functions.  */
!       return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), e, 1);
!     }
  
    return ocp_convert (type, e, CONV_C_CAST|convtype, LOOKUP_NORMAL);
  }
  
  /* Convert an aggregate EXPR to type XTYPE.  If a conversion
--- 960,972 ----
  	&& TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE
  	&& TREE_CODE (TREE_TYPE (TREE_TYPE (e))) == METHOD_TYPE)
         || integer_zerop (e)
         || TYPE_PTRMEMFUNC_P (TREE_TYPE (e)))
        && TYPE_PTRMEMFUNC_P (type))
!     /* compatible pointer to member functions.  */
!     return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), e, 1,
! 			     /*c_cast_p=*/1);
  
    return ocp_convert (type, e, CONV_C_CAST|convtype, LOOKUP_NORMAL);
  }
  
  /* Convert an aggregate EXPR to type XTYPE.  If a conversion
Index: cp/typeck.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/typeck.c,v
retrieving revision 1.587
diff -c -5 -p -r1.587 typeck.c
*** cp/typeck.c	21 Oct 2004 12:59:00 -0000	1.587
--- cp/typeck.c	21 Oct 2004 21:20:01 -0000
*************** static int comp_ptr_ttypes_real (tree, t
*** 50,60 ****
  static int comp_ptr_ttypes_const (tree, tree);
  static bool comp_except_types (tree, tree, bool);
  static bool comp_array_types (tree, tree, bool);
  static tree common_base_type (tree, tree);
  static tree pointer_diff (tree, tree, tree);
! static tree get_delta_difference (tree, tree, int);
  static void casts_away_constness_r (tree *, tree *);
  static bool casts_away_constness (tree, tree);
  static void maybe_warn_about_returning_address_of_local (tree);
  static tree lookup_destructor (tree, tree, tree);
  
--- 50,60 ----
  static int comp_ptr_ttypes_const (tree, tree);
  static bool comp_except_types (tree, tree, bool);
  static bool comp_array_types (tree, tree, bool);
  static tree common_base_type (tree, tree);
  static tree pointer_diff (tree, tree, tree);
! static tree get_delta_difference (tree, tree, bool, bool);
  static void casts_away_constness_r (tree *, tree *);
  static bool casts_away_constness (tree, tree);
  static void maybe_warn_about_returning_address_of_local (tree);
  static tree lookup_destructor (tree, tree, tree);
  
*************** build_unary_op (enum tree_code code, tre
*** 4144,4154 ****
  
  	if (TREE_CODE (argtype) == POINTER_TYPE
  	    && TREE_CODE (TREE_TYPE (argtype)) == METHOD_TYPE)
  	  {
  	    build_ptrmemfunc_type (argtype);
! 	    addr = build_ptrmemfunc (argtype, addr, 0);
  	  }
  
  	return addr;
        }
  
--- 4144,4155 ----
  
  	if (TREE_CODE (argtype) == POINTER_TYPE
  	    && TREE_CODE (TREE_TYPE (argtype)) == METHOD_TYPE)
  	  {
  	    build_ptrmemfunc_type (argtype);
! 	    addr = build_ptrmemfunc (argtype, addr, 0,
! 				     /*c_cast_p=*/false);
  	  }
  
  	return addr;
        }
  
*************** check_for_casting_away_constness (tree s
*** 4483,4492 ****
--- 4484,4525 ----
    if (diag_fn && casts_away_constness (src_type, dest_type))
      error ("%s from type %qT to type %qT casts away constness",
  	   description, src_type, dest_type);
  }
  
+ /* Convert EXPR (an expression with pointer-to-member type) to TYPE
+    (another pointer-to-member type in the same hierarchy) and return
+    the converted expression.  If ALLOW_INVERSE_P is permitted, a
+    pointer-to-derived may be converted to pointer-to-base; otherwise,
+    only the other direction is permitted.  If C_CAST_P is true, this
+    conversion is taking place as part of a C-style cast.  */
+ 
+ tree 
+ convert_ptrmem (tree type, tree expr, bool allow_inverse_p,
+ 		bool c_cast_p)
+ {
+   if (TYPE_PTRMEM_P (type))
+     {
+       tree delta;
+ 
+       if (TREE_CODE (expr) == PTRMEM_CST)
+ 	expr = cplus_expand_constant (expr);
+       delta = get_delta_difference (TYPE_PTRMEM_CLASS_TYPE (TREE_TYPE (expr)),
+ 				    TYPE_PTRMEM_CLASS_TYPE (type), 
+ 				    allow_inverse_p,
+ 				    c_cast_p);
+       if (!integer_zerop (delta))
+ 	expr = cp_build_binary_op (PLUS_EXPR, 
+ 				   build_nop (ptrdiff_type_node, expr),
+ 				   delta);
+       return build_nop (type, expr);
+     }
+   else
+     return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), expr, 
+ 			     allow_inverse_p, c_cast_p);
+ }
+ 
  /* Perform a static_cast from EXPR to TYPE.  When C_CAST_P is true,
     this static_cast is being attempted as one of the possible casts
     allowed by a C-style cast.  (In that case, accessibility of base
     classes is not considered, and it is OK to cast away
     constness.)  Return the result of the cast.  *VALID_P is set to
*************** build_static_cast_1 (tree type, tree exp
*** 4689,4715 ****
  	  t2 = type;
  	}
        if (can_convert (t1, t2))
  	{
  	  if (!c_cast_p)
! 	    check_for_casting_away_constness (intype, type, diag_fn, desc);
! 	  if (TYPE_PTRMEM_P (type))
! 	    {
! 	      tree delta;
! 
! 	      if (TREE_CODE (expr) == PTRMEM_CST)
! 		expr = cplus_expand_constant (expr);
! 	      delta = get_delta_difference (c1, c2, /*force=*/1);
! 	      if (!integer_zerop (delta))
! 		expr = cp_build_binary_op (PLUS_EXPR, 
! 					   build_nop (ptrdiff_type_node, expr),
! 					   delta);
! 	      return build_nop (type, expr);
! 	    }
! 	  else
! 	    return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), expr, 
! 				     /*force=*/1);
  	}
      }
      
    /* [expr.static.cast]
  
--- 4722,4735 ----
  	  t2 = type;
  	}
        if (can_convert (t1, t2))
  	{
  	  if (!c_cast_p)
! 	    check_for_casting_away_constness (intype, type, diag_fn, 
! 					      desc);
! 	  return convert_ptrmem (type, expr, /*allow_inverse_p=*/1,
! 				 c_cast_p);
  	}
      }
      
    /* [expr.static.cast]
  
*************** build_reinterpret_cast_1 (tree type, tre
*** 4943,4952 ****
--- 4963,4974 ----
  	}
        
        expr = decl_constant_value (expr);
        return fold_if_not_in_template (build_nop (type, expr));
      }
+   else if (TREE_CODE (type) == VECTOR_TYPE)
+     return fold_if_not_in_template (convert_to_vector (type, expr));
    else
      {
        if (valid_p)
  	*valid_p = false;
        error ("invalid cast from type %qT to type %qT", intype, type);
*************** build_x_modify_expr (tree lhs, enum tree
*** 5544,5584 ****
  }
  
  
  /* Get difference in deltas for different pointer to member function
     types.  Returns an integer constant of type PTRDIFF_TYPE_NODE.  If
!    the conversion is invalid, the constant is zero.  If FORCE is true,
!    then allow reverse conversions as well.
  
     Note that the naming of FROM and TO is kind of backwards; the return
     value is what we add to a TO in order to get a FROM.  They are named
     this way because we call this function to find out how to convert from
     a pointer to member of FROM to a pointer to member of TO.  */
  
  static tree
! get_delta_difference (tree from, tree to, int force)
  {
    tree binfo;
    tree virt_binfo;
    base_kind kind;
    tree result;
  
    /* Assume no conversion is required.  */
    result = integer_zero_node;
!   binfo = lookup_base (to, from, ba_check, &kind);
    if (kind == bk_inaccessible || kind == bk_ambig)
      error ("   in pointer to member function conversion");
    else if (!binfo)
      {
!       if (!force)
  	{
  	  error_not_base_type (from, to);
  	  error ("   in pointer to member conversion");
  	}
        else
  	{
! 	  binfo = lookup_base (from, to, ba_check, &kind);
  	  if (binfo)
  	    {
  	      virt_binfo = binfo_from_vbase (binfo);
  	      if (virt_binfo)
  		/* This is a reinterpret cast, we choose to do nothing.  */
--- 5566,5611 ----
  }
  
  
  /* Get difference in deltas for different pointer to member function
     types.  Returns an integer constant of type PTRDIFF_TYPE_NODE.  If
!    the conversion is invalid, the constant is zero.  If
!    ALLOW_INVERSE_P is true, then allow reverse conversions as well.
!    If C_CAST_P is true this conversion is taking place as part of a
!    C-style cast.
  
     Note that the naming of FROM and TO is kind of backwards; the return
     value is what we add to a TO in order to get a FROM.  They are named
     this way because we call this function to find out how to convert from
     a pointer to member of FROM to a pointer to member of TO.  */
  
  static tree
! get_delta_difference (tree from, tree to, 
! 		      bool allow_inverse_p,
! 		      bool c_cast_p)
  {
    tree binfo;
    tree virt_binfo;
    base_kind kind;
    tree result;
  
    /* Assume no conversion is required.  */
    result = integer_zero_node;
!   binfo = lookup_base (to, from, c_cast_p ? ba_unique : ba_check, &kind);
    if (kind == bk_inaccessible || kind == bk_ambig)
      error ("   in pointer to member function conversion");
    else if (!binfo)
      {
!       if (!allow_inverse_p)
  	{
  	  error_not_base_type (from, to);
  	  error ("   in pointer to member conversion");
  	}
        else
  	{
! 	  binfo = lookup_base (from, to, c_cast_p ? ba_unique : ba_check, 
! 			       &kind);
  	  if (binfo)
  	    {
  	      virt_binfo = binfo_from_vbase (binfo);
  	      if (virt_binfo)
  		/* This is a reinterpret cast, we choose to do nothing.  */
*************** get_delta_difference (tree from, tree to
*** 5595,5605 ****
        if (!virt_binfo)
  	result = BINFO_OFFSET (binfo);
        else
  	{
  	  /* This is a reinterpret cast, we choose to do nothing.  */
! 	  if (force)
  	    warning ("pointer to member cast via virtual base %qT",
  		     BINFO_TYPE (virt_binfo));
  	  else
  	    error ("pointer to member conversion via virtual base %qT",
  		   BINFO_TYPE (virt_binfo));
--- 5622,5632 ----
        if (!virt_binfo)
  	result = BINFO_OFFSET (binfo);
        else
  	{
  	  /* This is a reinterpret cast, we choose to do nothing.  */
! 	  if (allow_inverse_p)
  	    warning ("pointer to member cast via virtual base %qT",
  		     BINFO_TYPE (virt_binfo));
  	  else
  	    error ("pointer to member conversion via virtual base %qT",
  		   BINFO_TYPE (virt_binfo));
*************** build_ptrmemfunc1 (tree type, tree delta
*** 5646,5661 ****
     as a value in expressions.  TYPE is the POINTER to METHOD_TYPE we
     want to be.
  
     If FORCE is nonzero, then force this conversion, even if
     we would rather not do it.  Usually set when using an explicit
!    cast.
  
     Return error_mark_node, if something goes wrong.  */
  
  tree
! build_ptrmemfunc (tree type, tree pfn, int force)
  {
    tree fn;
    tree pfn_type;
    tree to_type;
  
--- 5673,5688 ----
     as a value in expressions.  TYPE is the POINTER to METHOD_TYPE we
     want to be.
  
     If FORCE is nonzero, then force this conversion, even if
     we would rather not do it.  Usually set when using an explicit
!    cast.  A C-style cast is being processed iff C_CAST_P is true.
  
     Return error_mark_node, if something goes wrong.  */
  
  tree
! build_ptrmemfunc (tree type, tree pfn, int force, bool c_cast_p)
  {
    tree fn;
    tree pfn_type;
    tree to_type;
  
*************** build_ptrmemfunc (tree type, tree pfn, i
*** 5677,5687 ****
  	error ("invalid conversion to type %qT from type %qT", 
                 to_type, pfn_type);
  
        n = get_delta_difference (TYPE_PTRMEMFUNC_OBJECT_TYPE (pfn_type),
  				TYPE_PTRMEMFUNC_OBJECT_TYPE (to_type),
! 				force);
  
        /* We don't have to do any conversion to convert a
  	 pointer-to-member to its own type.  But, we don't want to
  	 just return a PTRMEM_CST if there's an explicit cast; that
  	 cast should make the expression an invalid template argument.  */
--- 5704,5715 ----
  	error ("invalid conversion to type %qT from type %qT", 
                 to_type, pfn_type);
  
        n = get_delta_difference (TYPE_PTRMEMFUNC_OBJECT_TYPE (pfn_type),
  				TYPE_PTRMEMFUNC_OBJECT_TYPE (to_type),
! 				force,
! 				c_cast_p);
  
        /* We don't have to do any conversion to convert a
  	 pointer-to-member to its own type.  But, we don't want to
  	 just return a PTRMEM_CST if there's an explicit cast; that
  	 cast should make the expression an invalid template argument.  */
*************** expand_ptrmemfunc_cst (tree cst, tree *d
*** 5752,5762 ****
  
    /* The class that we're creating a pointer to member of.  */
    ptr_class = TYPE_PTRMEMFUNC_OBJECT_TYPE (type);
  
    /* First, calculate the adjustment to the function's class.  */
!   *delta = get_delta_difference (fn_class, ptr_class, /*force=*/0);
  
    if (!DECL_VIRTUAL_P (fn))
      *pfn = convert (TYPE_PTRMEMFUNC_FN_TYPE (type), build_addr_func (fn));
    else
      {
--- 5780,5791 ----
  
    /* The class that we're creating a pointer to member of.  */
    ptr_class = TYPE_PTRMEMFUNC_OBJECT_TYPE (type);
  
    /* First, calculate the adjustment to the function's class.  */
!   *delta = get_delta_difference (fn_class, ptr_class, /*force=*/0,
! 				 /*c_cast_p=*/0);
  
    if (!DECL_VIRTUAL_P (fn))
      *pfn = convert (TYPE_PTRMEMFUNC_FN_TYPE (type), build_addr_func (fn));
    else
      {
Index: testsuite/g++.dg/conversion/cast1.C
===================================================================
RCS file: testsuite/g++.dg/conversion/cast1.C
diff -N testsuite/g++.dg/conversion/cast1.C
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/conversion/cast1.C	21 Oct 2004 21:20:20 -0000
***************
*** 0 ****
--- 1,22 ----
+ // PR c++/10841
+ 
+ int main() {
+   class Base { 
+   public: 
+     int i, j, k; 
+     void f(); };
+ 
+   class Derived : private Base { 
+   public: 
+     int m, n, p; 
+     void g(); 
+   };
+ 
+   Derived derived;
+   Base &base = (Base &)derived;
+   (int Base::*)&Derived::n;
+   (int Derived::*)&Base::j;
+   (void (Base::*)(void))&Derived::g;
+   (void (Derived::*)(void))&Base::f;
+ }
+ 
Index: testsuite/g++.dg/overload/pmf1.C
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/g++.dg/overload/pmf1.C,v
retrieving revision 1.2
diff -c -5 -p -r1.2 pmf1.C
*** testsuite/g++.dg/overload/pmf1.C	10 Oct 2004 21:36:41 -0000	1.2
--- testsuite/g++.dg/overload/pmf1.C	21 Oct 2004 21:20:20 -0000
*************** int A::*aip = &A::i;
*** 15,21 ****
  void f (int B::*) {}  // should choose this, even though it's ill-formed
  void f (C) {}         // even though this would be well-formed
  
  int main ()
  {
!   f (aip);  // { dg-error "'A' is an inaccessible base of 'B'" "" }
  }
--- 15,21 ----
  void f (int B::*) {}  // should choose this, even though it's ill-formed
  void f (C) {}         // even though this would be well-formed
  
  int main ()
  {
!   f (aip);  // { dg-error "'A' is an inaccessible base of 'B'|conversion" "" }
  }


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