re PR c/13519 (typeof(nonconst+const) is const)

PR c/13519
	* c-typeck.c (composite_type, common_pointer_type): New functions.
	(common_type): Split parts into composite_type and
	common_pointer_type.  Ensure that arithmetic operations return
	unqualified types without attributes.  Don't make composite type
	of signed enum and compatible integer be unsigned.
	(build_conditional_expr, build_binary_op): Use
	common_pointer_type.
	* c-decl.c (merge_decls): Use composite_type.
	* c-tree.h (composite_type): Declare.

testsuite:
	* gcc.c-torture/enum-3.c, gcc.dg/pr13519-1.c: New tests.

From-SVN: r82671
This commit is contained in:
Joseph Myers 2004-06-06 16:21:59 +01:00 committed by Joseph Myers
parent ff24b82044
commit 10bc1b1bec
7 changed files with 296 additions and 140 deletions

View file

@ -1,3 +1,16 @@
2004-06-06 Joseph S. Myers <jsm@polyomino.org.uk>
PR c/13519
* c-typeck.c (composite_type, common_pointer_type): New functions.
(common_type): Split parts into composite_type and
common_pointer_type. Ensure that arithmetic operations return
unqualified types without attributes. Don't make composite type
of signed enum and compatible integer be unsigned.
(build_conditional_expr, build_binary_op): Use
common_pointer_type.
* c-decl.c (merge_decls): Use composite_type.
* c-tree.h (composite_type): Declare.
2004-06-06 Stephane Carrez <stcarrez@nerim.fr>
PR target/14457

View file

@ -1452,7 +1452,7 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype)
/* Merge the data types specified in the two decls. */
TREE_TYPE (newdecl)
= TREE_TYPE (olddecl)
= common_type (newtype, oldtype);
= composite_type (newtype, oldtype);
/* Lay the type out, unless already done. */
if (oldtype != TREE_TYPE (newdecl))

View file

@ -226,6 +226,7 @@ extern tree c_size_in_bytes (tree);
extern bool c_mark_addressable (tree);
extern void c_incomplete_type_error (tree, tree);
extern tree c_type_promotes_to (tree);
extern tree composite_type (tree, tree);
extern tree build_component_ref (tree, tree);
extern tree build_indirect_ref (tree, const char *);
extern tree build_array_ref (tree, tree);

View file

@ -199,19 +199,14 @@ qualify_type (tree type, tree like)
TYPE_QUALS (type) | TYPE_QUALS (like));
}
/* Return the composite type of two compatible types, or the common
type for two arithmetic types under the usual arithmetic
conversions.
/* Return the composite type of two compatible types.
Unless both types are arithmetic types, we assume that comptypes
has already been done and returned 1; if that isn't so, this may
crash. In particular, we assume that qualifiers match.
This is the type for the result of most arithmetic operations
if the operands have the given two types. */
We assume that comptypes has already been done and returned
nonzero; if that isn't so, this may crash. In particular, we
assume that qualifiers match. */
tree
common_type (tree t1, tree t2)
composite_type (tree t1, tree t2)
{
enum tree_code code1;
enum tree_code code2;
@ -227,145 +222,40 @@ common_type (tree t1, tree t2)
if (t2 == error_mark_node)
return t1;
/* 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 = c_common_type_for_size (TYPE_PRECISION (t1), 1);
if (TREE_CODE (t2) == ENUMERAL_TYPE)
t2 = c_common_type_for_size (TYPE_PRECISION (t2), 1);
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);
/* Merge the attributes. */
attributes = targetm.merge_type_attributes (t1, t2);
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 one is an enumerated type and the other is the compatible
integer type, the composite type might be either of the two
(DR#013 question 3). For consistency, use the enumerated type as
the composite type. */
if (code1 == ENUMERAL_TYPE && code2 == INTEGER_TYPE)
return t1;
if (code2 == ENUMERAL_TYPE && code1 == INTEGER_TYPE)
return t2;
if (code1 != code2)
abort ();
switch (code1)
{
case INTEGER_TYPE:
case REAL_TYPE:
/* If only one is real, use it as the result. */
if (code1 == REAL_TYPE && code2 != REAL_TYPE)
return build_type_attribute_variant (t1, attributes);
if (code2 == REAL_TYPE && code1 != REAL_TYPE)
return build_type_attribute_variant (t2, attributes);
/* Both real or both integers; use the one with greater precision. */
if (TYPE_PRECISION (t1) > TYPE_PRECISION (t2))
return build_type_attribute_variant (t1, attributes);
else if (TYPE_PRECISION (t2) > TYPE_PRECISION (t1))
return build_type_attribute_variant (t2, attributes);
/* Same precision. Prefer long longs to longs to ints when the
same precision, following the C99 rules on integer type rank
(which are equivalent to the C90 rules for C90 types).
Make sure that we don't lose the type qualifications when
creating the new variant. */
if (TYPE_MAIN_VARIANT (t1) == long_long_unsigned_type_node
|| TYPE_MAIN_VARIANT (t2) == long_long_unsigned_type_node)
{
t1 = build_qualified_type (long_long_unsigned_type_node,
TYPE_QUALS (t1));
return build_type_attribute_variant (t1, attributes);
}
if (TYPE_MAIN_VARIANT (t1) == long_long_integer_type_node
|| TYPE_MAIN_VARIANT (t2) == long_long_integer_type_node)
{
tree ntype;
if (TYPE_UNSIGNED (t1) || TYPE_UNSIGNED (t2))
ntype = long_long_unsigned_type_node;
else
ntype = long_long_integer_type_node;
ntype = build_qualified_type (ntype, TYPE_QUALS (t1));
return build_type_attribute_variant (ntype, attributes);
}
if (TYPE_MAIN_VARIANT (t1) == long_unsigned_type_node
|| TYPE_MAIN_VARIANT (t2) == long_unsigned_type_node)
{
t1 = build_qualified_type (long_unsigned_type_node,
TYPE_QUALS (t1));
return build_type_attribute_variant (t1, attributes);
}
if (TYPE_MAIN_VARIANT (t1) == long_integer_type_node
|| TYPE_MAIN_VARIANT (t2) == long_integer_type_node)
{
tree ntype;
/* But preserve unsignedness from the other type,
since long cannot hold all the values of an unsigned int. */
if (TYPE_UNSIGNED (t1) || TYPE_UNSIGNED (t2))
ntype = long_unsigned_type_node;
else
ntype = long_integer_type_node;
ntype = build_qualified_type (ntype, TYPE_QUALS (t1));
return build_type_attribute_variant (ntype, attributes);
}
/* Likewise, prefer long double to double even if same size. */
if (TYPE_MAIN_VARIANT (t1) == long_double_type_node
|| TYPE_MAIN_VARIANT (t2) == long_double_type_node)
{
t1 = build_qualified_type (long_double_type_node,
TYPE_QUALS (t1));
return build_type_attribute_variant (t1, attributes);
}
/* Otherwise prefer the unsigned one. */
if (TYPE_UNSIGNED (t1))
return build_type_attribute_variant (t1, attributes);
else
return build_type_attribute_variant (t2, attributes);
case POINTER_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 ANSI C specifies doing this with the qualifiers.
So I turned it on again. */
/* For two pointers, do this recursively on the target type. */
{
tree pointed_to_1 = TREE_TYPE (t1);
tree pointed_to_2 = TREE_TYPE (t2);
tree target = common_type (TYPE_MAIN_VARIANT (pointed_to_1),
TYPE_MAIN_VARIANT (pointed_to_2));
t1 = build_pointer_type (c_build_qualified_type
(target,
TYPE_QUALS (pointed_to_1) |
TYPE_QUALS (pointed_to_2)));
tree target = composite_type (pointed_to_1, pointed_to_2);
t1 = build_pointer_type (target);
return build_type_attribute_variant (t1, attributes);
}
case ARRAY_TYPE:
{
tree elt = common_type (TREE_TYPE (t1), TREE_TYPE (t2));
tree elt = composite_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);
@ -380,7 +270,7 @@ common_type (tree t1, tree t2)
/* 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 valtype = composite_type (TREE_TYPE (t1), TREE_TYPE (t2));
tree p1 = TYPE_ARG_TYPES (t1);
tree p2 = TYPE_ARG_TYPES (t2);
int len;
@ -468,7 +358,7 @@ common_type (tree t1, tree t2)
goto parm_done;
}
}
TREE_VALUE (n) = common_type (TREE_VALUE (p1), TREE_VALUE (p2));
TREE_VALUE (n) = composite_type (TREE_VALUE (p1), TREE_VALUE (p2));
parm_done: ;
}
@ -482,6 +372,182 @@ common_type (tree t1, tree t2)
}
}
/* Return the type of a conditional expression between pointers to
possibly differently qualified versions of compatible types.
We assume that comp_target_types has already been done and returned
nonzero; if that isn't so, this may crash. */
static tree
common_pointer_type (tree t1, tree t2)
{
tree attributes;
tree pointed_to_1;
tree pointed_to_2;
tree target;
/* Save time if the two types are the same. */
if (t1 == t2) return t1;
/* If one type is nonsense, use the other. */
if (t1 == error_mark_node)
return t2;
if (t2 == error_mark_node)
return t1;
if (TREE_CODE (t1) != POINTER_TYPE || TREE_CODE (t2) != POINTER_TYPE)
abort ();
/* Merge the attributes. */
attributes = targetm.merge_type_attributes (t1, t2);
/* Find the composite type of the target types, and combine the
qualifiers of the two types' targets. */
pointed_to_1 = TREE_TYPE (t1);
pointed_to_2 = TREE_TYPE (t2);
target = composite_type (TYPE_MAIN_VARIANT (pointed_to_1),
TYPE_MAIN_VARIANT (pointed_to_2));
t1 = build_pointer_type (c_build_qualified_type
(target,
TYPE_QUALS (pointed_to_1) |
TYPE_QUALS (pointed_to_2)));
return build_type_attribute_variant (t1, attributes);
}
/* Return the common type for two arithmetic types under the usual
arithmetic conversions. The default conversions have already been
applied, and enumerated types converted to their compatible integer
types. The resulting type is unqualified and has no attributes.
This is the type for the result of most arithmetic operations
if the operands have the given two types. */
tree
common_type (tree t1, tree t2)
{
enum tree_code code1;
enum tree_code code2;
/* If one type is nonsense, use the other. */
if (t1 == error_mark_node)
return t2;
if (t2 == error_mark_node)
return t1;
if (TYPE_QUALS (t1) != TYPE_UNQUALIFIED)
t1 = TYPE_MAIN_VARIANT (t1);
if (TYPE_QUALS (t2) != TYPE_UNQUALIFIED)
t2 = TYPE_MAIN_VARIANT (t2);
if (TYPE_ATTRIBUTES (t1) != NULL_TREE)
t1 = build_type_attribute_variant (t1, NULL_TREE);
if (TYPE_ATTRIBUTES (t2) != NULL_TREE)
t2 = build_type_attribute_variant (t2, NULL_TREE);
/* Save time if the two types are the same. */
if (t1 == t2) return t1;
code1 = TREE_CODE (t1);
code2 = TREE_CODE (t2);
if (code1 != VECTOR_TYPE && code1 != COMPLEX_TYPE
&& code1 != REAL_TYPE && code1 != INTEGER_TYPE)
abort ();
if (code2 != VECTOR_TYPE && code2 != COMPLEX_TYPE
&& code2 != REAL_TYPE && code2 != INTEGER_TYPE)
abort ();
/* If one type is a vector type, return that type. (How the usual
arithmetic conversions apply to the vector types extension is not
precisely specified.) */
if (code1 == VECTOR_TYPE)
return t1;
if (code2 == VECTOR_TYPE)
return 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 t1;
else if (code2 == COMPLEX_TYPE && TREE_TYPE (t2) == subtype)
return t2;
else
return build_complex_type (subtype);
}
/* If only one is real, use it as the result. */
if (code1 == REAL_TYPE && code2 != REAL_TYPE)
return t1;
if (code2 == REAL_TYPE && code1 != REAL_TYPE)
return t2;
/* Both real or both integers; use the one with greater precision. */
if (TYPE_PRECISION (t1) > TYPE_PRECISION (t2))
return t1;
else if (TYPE_PRECISION (t2) > TYPE_PRECISION (t1))
return t2;
/* Same precision. Prefer long longs to longs to ints when the
same precision, following the C99 rules on integer type rank
(which are equivalent to the C90 rules for C90 types). */
if (TYPE_MAIN_VARIANT (t1) == long_long_unsigned_type_node
|| TYPE_MAIN_VARIANT (t2) == long_long_unsigned_type_node)
return long_long_unsigned_type_node;
if (TYPE_MAIN_VARIANT (t1) == long_long_integer_type_node
|| TYPE_MAIN_VARIANT (t2) == long_long_integer_type_node)
{
if (TYPE_UNSIGNED (t1) || TYPE_UNSIGNED (t2))
return long_long_unsigned_type_node;
else
return long_long_integer_type_node;
}
if (TYPE_MAIN_VARIANT (t1) == long_unsigned_type_node
|| TYPE_MAIN_VARIANT (t2) == long_unsigned_type_node)
return long_unsigned_type_node;
if (TYPE_MAIN_VARIANT (t1) == long_integer_type_node
|| TYPE_MAIN_VARIANT (t2) == long_integer_type_node)
{
/* But preserve unsignedness from the other type,
since long cannot hold all the values of an unsigned int. */
if (TYPE_UNSIGNED (t1) || TYPE_UNSIGNED (t2))
return long_unsigned_type_node;
else
return long_integer_type_node;
}
/* Likewise, prefer long double to double even if same size. */
if (TYPE_MAIN_VARIANT (t1) == long_double_type_node
|| TYPE_MAIN_VARIANT (t2) == long_double_type_node)
return long_double_type_node;
/* Otherwise prefer the unsigned one. */
if (TYPE_UNSIGNED (t1))
return t1;
else
return t2;
}
/* Return 1 if TYPE1 and TYPE2 are compatible types for assignment
or various other operations. Return 2 if they are compatible
@ -2760,7 +2826,7 @@ build_conditional_expr (tree ifexp, tree op1, tree op2)
else if (code1 == POINTER_TYPE && code2 == POINTER_TYPE)
{
if (comp_target_types (type1, type2, 1))
result_type = common_type (type1, type2);
result_type = common_pointer_type (type1, type2);
else if (integer_zerop (op1) && TREE_TYPE (type1) == void_type_node
&& TREE_CODE (orig_op1) != NOP_EXPR)
result_type = qualify_type (type2, type1);
@ -6704,7 +6770,7 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
Otherwise, the targets must be compatible
and both must be object or both incomplete. */
if (comp_target_types (type0, type1, 1))
result_type = common_type (type0, type1);
result_type = common_pointer_type (type0, type1);
else if (VOID_TYPE_P (tt0))
{
/* op0 != orig_op0 detects the case of something
@ -6752,7 +6818,7 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
{
if (comp_target_types (type0, type1, 1))
{
result_type = common_type (type0, type1);
result_type = common_pointer_type (type0, type1);
if (pedantic
&& TREE_CODE (TREE_TYPE (type0)) == FUNCTION_TYPE)
pedwarn ("ISO C forbids ordered comparisons of pointers to functions");
@ -6777,7 +6843,7 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
{
if (comp_target_types (type0, type1, 1))
{
result_type = common_type (type0, type1);
result_type = common_pointer_type (type0, type1);
if (!COMPLETE_TYPE_P (TREE_TYPE (type0))
!= !COMPLETE_TYPE_P (TREE_TYPE (type1)))
pedwarn ("comparison of complete and incomplete pointers");

View file

@ -1,3 +1,8 @@
2004-06-06 Joseph S. Myers <jsm@polyomino.org.uk>
PR c/13519
* gcc.c-torture/enum-3.c, gcc.dg/pr13519-1.c: New tests.
2004-06-06 Giovanni Bajo <giovannibajo@gcc.gnu.org>
PR c++/15503

View file

@ -0,0 +1,24 @@
/* The composite type of int and an enum compatible with int might be
either of the two types, but it isn't an unsigned type. */
/* Origin: Joseph Myers <jsm@polyomino.org.uk> */
#include <limits.h>
#include <stdio.h>
extern void abort (void);
extern void exit (int);
enum e { a = INT_MIN };
int *p;
enum e *q;
int
main (void)
{
enum e x = a;
q = &x;
if (*(1 ? q : p) > 0)
abort ();
exit (0);
}

View file

@ -0,0 +1,47 @@
/* typeof applied to const+nonconst should be nonconst, as should
typeof applied to other arithmetic expressions. Bug 13519. */
/* Origin: Debian bug report 208981
from Kalle Olavi Niemitalo <kon@iki.fi>, adapted to a testcase by
Joseph Myers <jsm@polyomino.org.uk>. */
/* { dg-do compile } */
/* { dg-options "" } */
void fn(void)
{
int n;
const int c;
{ __typeof__(n) a1; a1=0; }
{ __typeof__(c) a2; a2=0; } /* { dg-error "read-only" "correct error" } */
{ __typeof__((int)n) a3; a3=0; }
{ __typeof__((int)c) a4; a4=0; } /* { dg-bogus "read-only" "bogus error" { xfail *-*-* } } */
{ __typeof__((const int)n) a5; a5=0; } /* { dg-error "read-only" "correct error" { xfail *-*-* } } */
{ __typeof__((const int)c) a6; a6=0; } /* { dg-error "read-only" "correct error" } */
{ __typeof__(0) a7; a7=0; }
{ __typeof__(1) a8; a8=0; }
{ __typeof__(n+n) b0; b0=0; }
{ __typeof__(n+c) b1; b1=0; }
{ __typeof__(c+n) b2; b2=0; }
{ __typeof__(c+c) b3; b3=0; }
{ __typeof__(0+n) c0; c0=0; }
{ __typeof__(0+c) c1; c1=0; }
{ __typeof__(n+0) c2; c2=0; }
{ __typeof__(c+0) c3; c3=0; }
{ __typeof__(1+n) d0; d0=0; }
{ __typeof__(1+c) d1; d1=0; }
{ __typeof__(n+1) d2; d2=0; }
{ __typeof__(c+1) d3; d3=0; }
{ __typeof__(((int)n)+((int)n)) e0; e0=0; }
{ __typeof__(((int)n)+((int)c)) e1; e1=0; }
{ __typeof__(((int)c)+((int)n)) e2; e2=0; }
{ __typeof__(((int)c)+((int)c)) e3; e3=0; }
{ __typeof__(((const int)n)+((const int)n)) f0; f0=0; }
{ __typeof__(((const int)n)+((const int)c)) f1; f1=0; }
{ __typeof__(((const int)c)+((const int)n)) f2; f2=0; }
{ __typeof__(((const int)c)+((const int)c)) f3; f3=0; }
}