This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
C++ PATCH for PR 5857
- From: Jason Merrill <jason at redhat dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Fri, 15 Mar 2002 18:21:32 +0000
- Subject: 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