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 PR 5857


When a char variable was declared both with and without a typedef,
common_types helpfully promoted it to int.  This illustrates the problem
with using the same code to handle both the usual arithmetic conversions
and redeclaration matching; the two operations really have nothing to do
with one another.  This patch splits the code for each into separate
functions.

Test in g++.dg/other/redecl1.C.

Tested i686-pc-linux-gnu, applied to trunk and 3.1 branch.

2002-03-15  Jason Merrill  <jason@redhat.com>

	PR c++/5857
	* decl.c (duplicate_decls): Use merge_types instead of common_type.
	* typeck.c (common_type): Just hand off to
	type_after_usual_arithmetic_conversions and
	composite_pointer_type.
	(merge_types): New fn.
	(commonparms): Use it instead of common_type.
	(type_after_usual_arithmetic_conversions): Also handle COMPLEX_TYPE.
	(composite_pointer_type): Also handle attributes.

*** cp-tree.h.~1~	Fri Mar 15 10:03:05 2002
--- cp-tree.h	Fri Mar 15 12:57:47 2002
*************** extern tree pfn_from_ptrmemfunc         
*** 4355,4360 ****
--- 4355,4361 ----
  extern tree type_after_usual_arithmetic_conversions PARAMS ((tree, tree));
  extern tree composite_pointer_type              PARAMS ((tree, tree, tree, tree,
  						       const char*));
+ extern tree merge_types				PARAMS ((tree, tree));
  extern tree check_return_expr                   PARAMS ((tree));
  #define cp_build_binary_op(code, arg1, arg2) \
    build_binary_op(code, arg1, arg2, 1)
*** decl.c.~1~	Fri Mar 15 09:42:20 2002
--- decl.c	Fri Mar 15 17:54:49 2002
*************** duplicate_decls (newdecl, olddecl)
*** 3515,3530 ****
        tree newtype;
  
        /* Merge the data types specified in the two decls.  */
!       newtype = common_type (TREE_TYPE (newdecl), TREE_TYPE (olddecl));
  
!       /* If common_type produces a non-typedef type, just use the old type.  */
        if (TREE_CODE (newdecl) == TYPE_DECL
  	  && newtype == DECL_ORIGINAL_TYPE (newdecl))
  	newtype = oldtype;
  
        if (TREE_CODE (newdecl) == VAR_DECL)
  	DECL_THIS_EXTERN (newdecl) |= DECL_THIS_EXTERN (olddecl);
!       /* Do this after calling `common_type' so that default
  	 parameters don't confuse us.  */
        else if (TREE_CODE (newdecl) == FUNCTION_DECL
  	  && (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (newdecl))
--- 3515,3530 ----
        tree newtype;
  
        /* Merge the data types specified in the two decls.  */
!       newtype = merge_types (TREE_TYPE (newdecl), TREE_TYPE (olddecl));
  
!       /* If merge_types produces a non-typedef type, just use the old type.  */
        if (TREE_CODE (newdecl) == TYPE_DECL
  	  && newtype == DECL_ORIGINAL_TYPE (newdecl))
  	newtype = oldtype;
  
        if (TREE_CODE (newdecl) == VAR_DECL)
  	DECL_THIS_EXTERN (newdecl) |= DECL_THIS_EXTERN (olddecl);
!       /* Do this after calling `merge_types' so that default
  	 parameters don't confuse us.  */
        else if (TREE_CODE (newdecl) == FUNCTION_DECL
  	  && (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (newdecl))
*** typeck.c.~1~	Tue Mar 12 01:46:53 2002
--- typeck.c	Fri Mar 15 16:04:08 2002
*************** commonparms (p1, p2)
*** 285,291 ****
        if (TREE_VALUE (p1) != TREE_VALUE (p2))
  	{
  	  any_change = 1;
! 	  TREE_VALUE (n) = common_type (TREE_VALUE (p1), TREE_VALUE (p2));
  	}
        else
  	TREE_VALUE (n) = TREE_VALUE (p1);
--- 285,291 ----
        if (TREE_VALUE (p1) != TREE_VALUE (p2))
  	{
  	  any_change = 1;
! 	  TREE_VALUE (n) = merge_types (TREE_VALUE (p1), TREE_VALUE (p2));
  	}
        else
  	TREE_VALUE (n) = TREE_VALUE (p1);
*************** type_after_usual_arithmetic_conversions 
*** 330,345 ****
  
    /* FIXME: Attributes.  */
    my_friendly_assert (ARITHMETIC_TYPE_P (t1) 
  		      || TREE_CODE (t1) == ENUMERAL_TYPE,
  		      19990725);
    my_friendly_assert (ARITHMETIC_TYPE_P (t2) 
  		      || TREE_CODE (t2) == ENUMERAL_TYPE,
  		      19990725);
  
!   /* In what follows, we slightly generalize the rules given in [expr]
!      so as to deal with `long long'.  First, merge the attributes.  */
    attributes = (*targetm.merge_type_attributes) (t1, t2);
  
    /* If only one is real, use it as the result.  */
    if (code1 == REAL_TYPE && code2 != REAL_TYPE)
      return build_type_attribute_variant (t1, attributes);
--- 330,367 ----
  
    /* FIXME: Attributes.  */
    my_friendly_assert (ARITHMETIC_TYPE_P (t1) 
+ 		      || TREE_CODE (t1) == COMPLEX_TYPE
  		      || TREE_CODE (t1) == ENUMERAL_TYPE,
  		      19990725);
    my_friendly_assert (ARITHMETIC_TYPE_P (t2) 
+ 		      || TREE_CODE (t2) == COMPLEX_TYPE
  		      || TREE_CODE (t2) == ENUMERAL_TYPE,
  		      19990725);
  
!   /* In what follows, we slightly generalize the rules given in [expr] so
!      as to deal with `long long' and `complex'.  First, merge the
!      attributes.  */
    attributes = (*targetm.merge_type_attributes) (t1, t2);
  
+   /* If one type is complex, form the common type of the non-complex
+      components, then make that complex.  Use T1 or T2 if it is the
+      required type.  */
+   if (code1 == COMPLEX_TYPE || code2 == COMPLEX_TYPE)
+     {
+       tree subtype1 = code1 == COMPLEX_TYPE ? TREE_TYPE (t1) : t1;
+       tree subtype2 = code2 == COMPLEX_TYPE ? TREE_TYPE (t2) : t2;
+       tree subtype
+ 	= type_after_usual_arithmetic_conversions (subtype1, subtype2);
+ 
+       if (code1 == COMPLEX_TYPE && TREE_TYPE (t1) == subtype)
+ 	return build_type_attribute_variant (t1, attributes);
+       else if (code2 == COMPLEX_TYPE && TREE_TYPE (t2) == subtype)
+ 	return build_type_attribute_variant (t2, attributes);
+       else
+ 	return build_type_attribute_variant (build_complex_type (subtype),
+ 					     attributes);
+     }
+ 
    /* If only one is real, use it as the result.  */
    if (code1 == REAL_TYPE && code2 != REAL_TYPE)
      return build_type_attribute_variant (t1, attributes);
*************** composite_pointer_type (t1, t2, arg1, ar
*** 439,444 ****
--- 461,467 ----
       const char* location;
  {
    tree result_type;
+   tree attributes;
  
    /* [expr.rel]
  
*************** composite_pointer_type (t1, t2, arg1, ar
*** 456,461 ****
--- 479,487 ----
    if (TYPE_PTRMEMFUNC_P (t2))
      t2 = TYPE_PTRMEMFUNC_FN_TYPE (t2);
    
+   /* Merge the attributes.  */
+   attributes = (*targetm.merge_type_attributes) (t1, t2);
+ 
    /* We have:
  
         [expr.rel]
*************** composite_pointer_type (t1, t2, arg1, ar
*** 504,524 ****
  	}
      }
  
!   return result_type;
  }
  
! /* Return the common type of two types.
     We assume that comptypes has already been done and returned 1;
     if that isn't so, this may crash.
  
!    This is the type for the result of most arithmetic operations
!    if the operands have the given two types.
! 
!    We do not deal with enumeral types here because they have already been
!    converted to integer types.  */
  
  tree
! common_type (t1, t2)
       tree t1, t2;
  {
    register enum tree_code code1;
--- 530,547 ----
  	}
      }
  
!   return build_type_attribute_variant (result_type, attributes);
  }
  
! /* Return the merged type of two types.
     We assume that comptypes has already been done and returned 1;
     if that isn't so, this may crash.
  
!    This just combines attributes and default arguments; any other
!    differences would cause the two types to compare unalike.  */
  
  tree
! merge_types (t1, t2)
       tree t1, t2;
  {
    register enum tree_code code1;
*************** common_type (t1, t2)
*** 528,536 ****
    /* Save time if the two types are the same.  */
    if (t1 == t2)
      return t1;
!   t1 = original_type (t1);
!   t2 = original_type (t2);
!   if (t1 == t2)
      return t1;
  
    /* If one type is nonsense, use the other.  */
--- 551,557 ----
    /* Save time if the two types are the same.  */
    if (t1 == t2)
      return t1;
!   if (original_type (t1) == original_type (t2))
      return t1;
  
    /* If one type is nonsense, use the other.  */
*************** common_type (t1, t2)
*** 539,558 ****
    if (t2 == error_mark_node)
      return t1;
  
-   if ((ARITHMETIC_TYPE_P (t1) || TREE_CODE (t1) == ENUMERAL_TYPE)
-       && (ARITHMETIC_TYPE_P (t2) || TREE_CODE (t2) == ENUMERAL_TYPE))
-     return type_after_usual_arithmetic_conversions (t1, t2);
- 
    /* Merge the attributes.  */
    attributes = (*targetm.merge_type_attributes) (t1, t2);
  
    /* Treat an enum type as the unsigned integer type of the same width.  */
  
-   if (TREE_CODE (t1) == ENUMERAL_TYPE)
-     t1 = type_for_size (TYPE_PRECISION (t1), 1);
-   if (TREE_CODE (t2) == ENUMERAL_TYPE)
-     t2 = type_for_size (TYPE_PRECISION (t2), 1);
- 
    if (TYPE_PTRMEMFUNC_P (t1))
      t1 = TYPE_PTRMEMFUNC_FN_TYPE (t1);
    if (TYPE_PTRMEMFUNC_P (t2))
--- 560,570 ----
*************** common_type (t1, t2)
*** 561,642 ****
    code1 = TREE_CODE (t1);
    code2 = TREE_CODE (t2);
  
-   /* If one type is complex, form the common type of the non-complex
-      components, then make that complex.  Use T1 or T2 if it is the
-      required type.  */
-   if (code1 == COMPLEX_TYPE || code2 == COMPLEX_TYPE)
-     {
-       tree subtype1 = code1 == COMPLEX_TYPE ? TREE_TYPE (t1) : t1;
-       tree subtype2 = code2 == COMPLEX_TYPE ? TREE_TYPE (t2) : t2;
-       tree subtype = common_type (subtype1, subtype2);
- 
-       if (code1 == COMPLEX_TYPE && TREE_TYPE (t1) == subtype)
- 	return build_type_attribute_variant (t1, attributes);
-       else if (code2 == COMPLEX_TYPE && TREE_TYPE (t2) == subtype)
- 	return build_type_attribute_variant (t2, attributes);
-       else
- 	return build_type_attribute_variant (build_complex_type (subtype),
- 					     attributes);
-     }
- 
    switch (code1)
      {
-     case INTEGER_TYPE:
-     case REAL_TYPE:
-       /* We should have called type_after_usual_arithmetic_conversions
- 	 above.  */
-       abort ();
-       break;
- 
      case POINTER_TYPE:
      case REFERENCE_TYPE:
!       /* For two pointers, do this recursively on the target type,
! 	 and combine the qualifiers of the two types' targets.  */
!       /* This code was turned off; I don't know why.
!  	 But ISO C++ specifies doing this with the qualifiers.
!  	 So I turned it on again.  */
        {
! 	tree tt1 = TREE_TYPE (t1);
! 	tree tt2 = TREE_TYPE (t2);
! 	tree b1, b2;
! 	int type_quals;
! 	tree target;
! 
! 	if (TREE_CODE (tt1) == OFFSET_TYPE)
! 	  {
! 	    b1 = TYPE_OFFSET_BASETYPE (tt1);
! 	    b2 = TYPE_OFFSET_BASETYPE (tt2);
! 	    tt1 = TREE_TYPE (tt1);
! 	    tt2 = TREE_TYPE (tt2);
! 	  }
! 	else
! 	  b1 = b2 = NULL_TREE;
! 
! 	type_quals = (cp_type_quals (tt1) | cp_type_quals (tt2));
! 	tt1 = TYPE_MAIN_VARIANT (tt1);
! 	tt2 = TYPE_MAIN_VARIANT (tt2);
! 
! 	if (tt1 == tt2)
! 	  target = tt1;
! 	else if (VOID_TYPE_P (tt1) || VOID_TYPE_P (tt2))
! 	  target = void_type_node;
! 	else if (tt1 == unknown_type_node)
! 	  target = tt2;
! 	else if (tt2 == unknown_type_node)
! 	  target = tt1;
! 	else
! 	  target = common_type (tt1, tt2);
! 
! 	target = cp_build_qualified_type (target, type_quals);
! 
! 	if (b1)
! 	  {
! 	    if (same_type_p (b1, b2)
! 		|| (DERIVED_FROM_P (b1, b2) && binfo_or_else (b1, b2)))
! 	      target = build_offset_type (b2, target);
! 	    else if (binfo_or_else (b2, b1))
! 	      target = build_offset_type (b1, target);
! 	  }
  
  	if (code1 == POINTER_TYPE)
  	  t1 = build_pointer_type (target);
--- 573,585 ----
    code1 = TREE_CODE (t1);
    code2 = TREE_CODE (t2);
  
    switch (code1)
      {
      case POINTER_TYPE:
      case REFERENCE_TYPE:
!       /* For two pointers, do this recursively on the target type.  */
        {
! 	tree target = merge_types (TREE_TYPE (t1), TREE_TYPE (t2));
  
  	if (code1 == POINTER_TYPE)
  	  t1 = build_pointer_type (target);
*************** common_type (t1, t2)
*** 650,658 ****
  	return t1;
        }
  
      case ARRAY_TYPE:
        {
! 	tree elt = common_type (TREE_TYPE (t1), TREE_TYPE (t2));
  	/* Save space: see if the result is identical to one of the args.  */
  	if (elt == TREE_TYPE (t1) && TYPE_DOMAIN (t1))
  	  return build_type_attribute_variant (t1, attributes);
--- 593,609 ----
  	return t1;
        }
  
+     case OFFSET_TYPE:
+       {
+ 	tree base = TYPE_OFFSET_BASETYPE (t1);
+ 	tree target = merge_types (TREE_TYPE (t1), TREE_TYPE (t2));
+ 	t1 = build_offset_type (base, target);
+ 	break;
+       }
+ 
      case ARRAY_TYPE:
        {
! 	tree elt = merge_types (TREE_TYPE (t1), TREE_TYPE (t2));
  	/* Save space: see if the result is identical to one of the args.  */
  	if (elt == TREE_TYPE (t1) && TYPE_DOMAIN (t1))
  	  return build_type_attribute_variant (t1, attributes);
*************** common_type (t1, t2)
*** 661,674 ****
  	/* Merge the element types, and have a size if either arg has one.  */
  	t1 = build_cplus_array_type
  	  (elt, TYPE_DOMAIN (TYPE_DOMAIN (t1) ? t1 : t2));
! 	return build_type_attribute_variant (t1, attributes);
        }
  
      case FUNCTION_TYPE:
        /* Function types: prefer the one that specified arg types.
  	 If both do, merge the arg types.  Also merge the return types.  */
        {
! 	tree valtype = common_type (TREE_TYPE (t1), TREE_TYPE (t2));
  	tree p1 = TYPE_ARG_TYPES (t1);
  	tree p2 = TYPE_ARG_TYPES (t2);
  	tree rval, raises;
--- 612,625 ----
  	/* Merge the element types, and have a size if either arg has one.  */
  	t1 = build_cplus_array_type
  	  (elt, TYPE_DOMAIN (TYPE_DOMAIN (t1) ? t1 : t2));
! 	break;
        }
  
      case FUNCTION_TYPE:
        /* Function types: prefer the one that specified arg types.
  	 If both do, merge the arg types.  Also merge the return types.  */
        {
! 	tree valtype = merge_types (TREE_TYPE (t1), TREE_TYPE (t2));
  	tree p1 = TYPE_ARG_TYPES (t1);
  	tree p2 = TYPE_ARG_TYPES (t2);
  	tree rval, raises;
*************** common_type (t1, t2)
*** 697,769 ****
  	  }
  
  	rval = build_function_type (valtype, commonparms (p1, p2));
! 	rval = build_exception_variant (rval, raises);
! 	return build_type_attribute_variant (rval, attributes);
        }
  
!     case RECORD_TYPE:
!     case UNION_TYPE:
!       t1 = TYPE_MAIN_VARIANT (t1);
!       t2 = TYPE_MAIN_VARIANT (t2);
  
!       if (DERIVED_FROM_P (t1, t2) && binfo_or_else (t1, t2))
! 	return build_type_attribute_variant (t1, attributes);
!       else if (binfo_or_else (t2, t1))
! 	return build_type_attribute_variant (t2, attributes);
!       else
! 	{
! 	  compiler_error ("common_type called with uncommon aggregate types");
! 	  return error_mark_node;
! 	}
  
!     case METHOD_TYPE:
!       if (TREE_CODE (TREE_TYPE (t1)) == TREE_CODE (TREE_TYPE (t2)))
! 	{
! 	  /* Get this value the long way, since TYPE_METHOD_BASETYPE
! 	     is just the main variant of this.  */
! 	  tree basetype;
! 	  tree raises, t3;
! 
! 	  tree b1 = TYPE_OFFSET_BASETYPE (t1);
! 	  tree b2 = TYPE_OFFSET_BASETYPE (t2);
! 
! 	  if (same_type_p (b1, b2)
! 	      || (DERIVED_FROM_P (b1, b2) && binfo_or_else (b1, b2)))
! 	    basetype = TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (t2)));
! 	  else
! 	    {
! 	      if (binfo_or_else (b2, b1) == NULL_TREE)
! 		compiler_error ("common_type called with uncommon method types");
! 	      basetype = TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (t1)));
! 	    }
! 
! 	  raises = TYPE_RAISES_EXCEPTIONS (t1);
! 
! 	  /* If this was a member function type, get back to the
! 	     original type of type member function (i.e., without
! 	     the class instance variable up front.  */
! 	  t1 = build_function_type (TREE_TYPE (t1),
! 				    TREE_CHAIN (TYPE_ARG_TYPES (t1)));
! 	  t2 = build_function_type (TREE_TYPE (t2),
! 				    TREE_CHAIN (TYPE_ARG_TYPES (t2)));
! 	  t3 = common_type (t1, t2);
! 	  t3 = build_cplus_method_type (basetype, TREE_TYPE (t3),
! 					TYPE_ARG_TYPES (t3));
! 	  t1 = build_exception_variant (t3, raises);
! 	}
!       else
!         compiler_error ("common_type called with uncommon method types");
  
!       return build_type_attribute_variant (t1, attributes);
  
!     case OFFSET_TYPE:
!       /* Pointers to members should now be handled by the POINTER_TYPE
! 	 case above.  */
!       abort ();
  
!     default:
!       return build_type_attribute_variant (t1, attributes);
!     }
  }
  
  /* Compare two exception specifier types for exactness or subsetness, if
--- 648,719 ----
  	  }
  
  	rval = build_function_type (valtype, commonparms (p1, p2));
! 	t1 = build_exception_variant (rval, raises);
! 	break;
        }
  
!     case METHOD_TYPE:
!       {
! 	/* Get this value the long way, since TYPE_METHOD_BASETYPE
! 	   is just the main variant of this.  */
! 	tree basetype = TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (t2)));
! 	tree raises = TYPE_RAISES_EXCEPTIONS (t1);
! 	tree t3;
! 
! 	/* If this was a member function type, get back to the
! 	   original type of type member function (i.e., without
! 	   the class instance variable up front.  */
! 	t1 = build_function_type (TREE_TYPE (t1),
! 				  TREE_CHAIN (TYPE_ARG_TYPES (t1)));
! 	t2 = build_function_type (TREE_TYPE (t2),
! 				  TREE_CHAIN (TYPE_ARG_TYPES (t2)));
! 	t3 = merge_types (t1, t2);
! 	t3 = build_cplus_method_type (basetype, TREE_TYPE (t3),
! 				      TYPE_ARG_TYPES (t3));
! 	t1 = build_exception_variant (t3, raises);
! 	break;
!       }
  
!     default:;
!     }
!   return build_type_attribute_variant (t1, attributes);
! }
  
! /* Return the common type of two types.
!    We assume that comptypes has already been done and returned 1;
!    if that isn't so, this may crash.
  
!    This is the type for the result of most arithmetic operations
!    if the operands have the given two types.  */
  
! tree
! common_type (t1, t2)
!      tree t1, t2;
! {
!   enum tree_code code1;
!   enum tree_code code2;
  
!   /* If one type is nonsense, bail.  */
!   if (t1 == error_mark_node || t2 == error_mark_node)
!     return error_mark_node;
! 
!   code1 = TREE_CODE (t1);
!   code2 = TREE_CODE (t2);
! 
!   if ((ARITHMETIC_TYPE_P (t1) || code1 == ENUMERAL_TYPE
!        || code1 == COMPLEX_TYPE)
!       && (ARITHMETIC_TYPE_P (t2) || code2 == ENUMERAL_TYPE
! 	  || code2 == COMPLEX_TYPE))
!     return type_after_usual_arithmetic_conversions (t1, t2);
! 
!   else if ((TYPE_PTR_P (t1) && TYPE_PTR_P (t2))
! 	   || (TYPE_PTRMEM_P (t1) && TYPE_PTRMEM_P (t2))
! 	   || (TYPE_PTRMEMFUNC_P (t1) && TYPE_PTRMEMFUNC_P (t2)))
!     return composite_pointer_type (t1, t2, error_mark_node, error_mark_node,
! 				   "conversion");
! 
!   else
!     abort ();
  }
  
  /* Compare two exception specifier types for exactness or subsetness, if

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