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 11687


This patch fixes another regression introduced by my static_cast
rewrite.  C++ says that there exists a conversion from a derived class
to an ambiguous class, but you aren't allowed to use it.  Who knew?

Tested on i686-pc-linux-gnu, applied on the mainline and the branch.

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

2003-09-06  Mark Mitchell  <mark@codesourcery.com>

	PR c++/11687
	* call.c (standard_conversion): Improve comments.
	(perform_direct_initialization): Make sure we return an expression
	of the correct type.
	* typeck.c (build_static_cast): Check for ambiguity and
	accessibility when performing conversions.

2003-09-06  Mark Mitchell  <mark@codesourcery.com>

	PR c++/11687
	* g++.dg/expr/static_cast5.C: New test.

Index: cp/call.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/call.c,v
retrieving revision 1.431
diff -c -5 -p -r1.431 call.c
*** cp/call.c	5 Sep 2003 18:04:15 -0000	1.431
--- cp/call.c	6 Sep 2003 05:09:42 -0000
*************** standard_conversion (tree to, tree from,
*** 699,718 ****
  					TYPE_PTRMEM_POINTED_TO_TYPE (from));
  	      conv = build_conv (PMEM_CONV, from, conv);
  	    }
  	}
        else if (IS_AGGR_TYPE (TREE_TYPE (from))
! 	       && IS_AGGR_TYPE (TREE_TYPE (to)))
! 	{
! 	  if (DERIVED_FROM_P (TREE_TYPE (to), TREE_TYPE (from)))
! 	    {
! 	      from = 
! 		cp_build_qualified_type (TREE_TYPE (to),
! 					 cp_type_quals (TREE_TYPE (from)));
! 	      from = build_pointer_type (from);
! 	      conv = build_conv (PTR_CONV, from, conv);
! 	    }
  	}
  
        if (tcode == POINTER_TYPE)
  	{
  	  to_pointee = TREE_TYPE (to);
--- 699,727 ----
  					TYPE_PTRMEM_POINTED_TO_TYPE (from));
  	      conv = build_conv (PMEM_CONV, from, conv);
  	    }
  	}
        else if (IS_AGGR_TYPE (TREE_TYPE (from))
! 	       && IS_AGGR_TYPE (TREE_TYPE (to))
! 	       /* [conv.ptr]
! 		  
! 	          An rvalue of type "pointer to cv D," where D is a
! 		  class type, can be converted to an rvalue of type
! 		  "pointer to cv B," where B is a base class (clause
! 		  _class.derived_) of D.  If B is an inaccessible
! 		  (clause _class.access_) or ambiguous
! 		  (_class.member.lookup_) base class of D, a program
! 		  that necessitates this conversion is ill-formed.  */
! 	       /* Therefore, we use DERIVED_FROM_P, and not
! 		  ACESSIBLY_UNIQUELY_DERIVED_FROM_P, in this test.  */
! 	       && DERIVED_FROM_P (TREE_TYPE (to), TREE_TYPE (from)))
! 	{
! 	  from = 
! 	    cp_build_qualified_type (TREE_TYPE (to),
! 				     cp_type_quals (TREE_TYPE (from)));
! 	  from = build_pointer_type (from);
! 	  conv = build_conv (PTR_CONV, from, conv);
  	}
  
        if (tcode == POINTER_TYPE)
  	{
  	  to_pointee = TREE_TYPE (to);
*************** perform_direct_initialization_if_possibl
*** 5968,5981 ****
       -- If the initialization is direct-initialization ...,
       constructors are considered. ... If no constructor applies, or
       the overload resolution is ambiguous, the initialization is
       ill-formed.  */
    if (CLASS_TYPE_P (type))
!     return build_special_member_call (NULL_TREE, complete_ctor_identifier,
! 				      build_tree_list (NULL_TREE, expr),
! 				      TYPE_BINFO (type),
! 				      LOOKUP_NORMAL);
    conv = implicit_conversion (type, TREE_TYPE (expr), expr,
  			      LOOKUP_NORMAL);
    if (!conv || ICS_BAD_FLAG (conv))
      return NULL_TREE;
    return convert_like_real (conv, expr, NULL_TREE, 0, 0, 
--- 5977,5993 ----
       -- If the initialization is direct-initialization ...,
       constructors are considered. ... If no constructor applies, or
       the overload resolution is ambiguous, the initialization is
       ill-formed.  */
    if (CLASS_TYPE_P (type))
!     {
!       expr = build_special_member_call (NULL_TREE, complete_ctor_identifier,
! 					build_tree_list (NULL_TREE, expr),
! 					TYPE_BINFO (type),
! 					LOOKUP_NORMAL);
!       return build_cplus_new (type, expr);
!     }
    conv = implicit_conversion (type, TREE_TYPE (expr), expr,
  			      LOOKUP_NORMAL);
    if (!conv || ICS_BAD_FLAG (conv))
      return NULL_TREE;
    return convert_like_real (conv, expr, NULL_TREE, 0, 0, 
Index: cp/typeck.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/typeck.c,v
retrieving revision 1.500
diff -c -5 -p -r1.500 typeck.c
*** cp/typeck.c	5 Sep 2003 08:24:23 -0000	1.500
--- cp/typeck.c	6 Sep 2003 05:09:45 -0000
*************** build_static_cast (tree type, tree expr)
*** 4425,4440 ****
        && can_convert (build_pointer_type (TYPE_MAIN_VARIANT (intype)),
  		      build_pointer_type (TYPE_MAIN_VARIANT 
  					  (TREE_TYPE (type))))
        && at_least_as_qualified_p (TREE_TYPE (type), intype))
      {
!       /* At this point we have checked all of the conditions except
! 	 that B is not a virtual base class of D.  That will be
! 	 checked by build_base_path.  */
!       tree base = lookup_base (TREE_TYPE (type), intype, ba_any, NULL);
  
!       /* Convert from B* to D*.  */
        expr = build_base_path (MINUS_EXPR, build_address (expr), 
  			      base, /*nonnull=*/false);
        /* Convert the pointer to a reference -- but then remember that
  	 there are no expressions with reference type in C++.  */
        return convert_from_reference (build_nop (type, expr));
--- 4425,4441 ----
        && can_convert (build_pointer_type (TYPE_MAIN_VARIANT (intype)),
  		      build_pointer_type (TYPE_MAIN_VARIANT 
  					  (TREE_TYPE (type))))
        && at_least_as_qualified_p (TREE_TYPE (type), intype))
      {
!       /* There is a standard conversion from "D*" to "B*" even if "B"
! 	 is ambiguous or inaccessible.  Therefore, we ask lookup_base
! 	 to check these conditions.  */
!       tree base = lookup_base (TREE_TYPE (type), intype, ba_check, NULL);
  
!       /* Convert from "B*" to "D*".  This function will check that "B"
! 	 is not a virtual base of "D".  */
        expr = build_base_path (MINUS_EXPR, build_address (expr), 
  			      base, /*nonnull=*/false);
        /* Convert the pointer to a reference -- but then remember that
  	 there are no expressions with reference type in C++.  */
        return convert_from_reference (build_nop (type, expr));
*************** build_static_cast (tree type, tree expr)
*** 4489,4500 ****
  					  (TREE_TYPE (type)))))
      {
        tree base;
  
        check_for_casting_away_constness (intype, type, "static_cast");
!       base = lookup_base (TREE_TYPE (type), TREE_TYPE (intype), 
! 			  ba_check | ba_quiet, NULL);
        return build_base_path (MINUS_EXPR, expr, base, /*nonnull=*/false);
      }
    
    if ((TYPE_PTRMEM_P (type) && TYPE_PTRMEM_P (intype))
        || (TYPE_PTRMEMFUNC_P (type) && TYPE_PTRMEMFUNC_P (intype)))
--- 4490,4501 ----
  					  (TREE_TYPE (type)))))
      {
        tree base;
  
        check_for_casting_away_constness (intype, type, "static_cast");
!       base = lookup_base (TREE_TYPE (type), TREE_TYPE (intype), ba_check, 
! 			  NULL);
        return build_base_path (MINUS_EXPR, expr, base, /*nonnull=*/false);
      }
    
    if ((TYPE_PTRMEM_P (type) && TYPE_PTRMEM_P (intype))
        || (TYPE_PTRMEMFUNC_P (type) && TYPE_PTRMEMFUNC_P (intype)))
Index: testsuite/g++.dg/expr/static_cast5.C
===================================================================
RCS file: testsuite/g++.dg/expr/static_cast5.C
diff -N testsuite/g++.dg/expr/static_cast5.C
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/expr/static_cast5.C	7 Sep 2003 04:07:31 -0000
***************
*** 0 ****
--- 1,17 ----
+ void ambig()
+ {
+   struct A {};
+   struct B : A {};
+   struct C : A {};
+   struct D : B, C {};
+ 
+   D d;
+   A* ap = static_cast<B*> (&d);
+   D* db = static_cast<D*> (ap); // { dg-error "" }
+   
+   D& dr1 = static_cast<D&> (*ap); // { dg-error "" }
+   
+   A& ar = static_cast<C&> (d);
+   D& dr = static_cast<D&> (ar);  // { dg-error "" }
+ }
+ 


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