Commit 10bc1b1b by Joseph Myers Committed by Joseph Myers

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
parent ff24b820
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> 2004-06-06 Stephane Carrez <stcarrez@nerim.fr>
PR target/14457 PR target/14457
......
...@@ -1452,7 +1452,7 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype) ...@@ -1452,7 +1452,7 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype)
/* Merge the data types specified in the two decls. */ /* Merge the data types specified in the two decls. */
TREE_TYPE (newdecl) TREE_TYPE (newdecl)
= TREE_TYPE (olddecl) = TREE_TYPE (olddecl)
= common_type (newtype, oldtype); = composite_type (newtype, oldtype);
/* Lay the type out, unless already done. */ /* Lay the type out, unless already done. */
if (oldtype != TREE_TYPE (newdecl)) if (oldtype != TREE_TYPE (newdecl))
......
...@@ -226,6 +226,7 @@ extern tree c_size_in_bytes (tree); ...@@ -226,6 +226,7 @@ extern tree c_size_in_bytes (tree);
extern bool c_mark_addressable (tree); extern bool c_mark_addressable (tree);
extern void c_incomplete_type_error (tree, tree); extern void c_incomplete_type_error (tree, tree);
extern tree c_type_promotes_to (tree); extern tree c_type_promotes_to (tree);
extern tree composite_type (tree, tree);
extern tree build_component_ref (tree, tree); extern tree build_component_ref (tree, tree);
extern tree build_indirect_ref (tree, const char *); extern tree build_indirect_ref (tree, const char *);
extern tree build_array_ref (tree, tree); extern tree build_array_ref (tree, tree);
......
...@@ -199,19 +199,14 @@ qualify_type (tree type, tree like) ...@@ -199,19 +199,14 @@ qualify_type (tree type, tree like)
TYPE_QUALS (type) | TYPE_QUALS (like)); TYPE_QUALS (type) | TYPE_QUALS (like));
} }
/* Return the composite type of two compatible types, or the common /* Return the composite type of two compatible types.
type for two arithmetic types under the usual arithmetic
conversions.
Unless both types are arithmetic types, we assume that comptypes We assume that comptypes has already been done and returned
has already been done and returned 1; if that isn't so, this may nonzero; if that isn't so, this may crash. In particular, we
crash. In particular, we assume that qualifiers match. assume that qualifiers match. */
This is the type for the result of most arithmetic operations
if the operands have the given two types. */
tree tree
common_type (tree t1, tree t2) composite_type (tree t1, tree t2)
{ {
enum tree_code code1; enum tree_code code1;
enum tree_code code2; enum tree_code code2;
...@@ -227,145 +222,40 @@ common_type (tree t1, tree t2) ...@@ -227,145 +222,40 @@ common_type (tree t1, tree t2)
if (t2 == error_mark_node) if (t2 == error_mark_node)
return t1; return t1;
code1 = TREE_CODE (t1);
code2 = TREE_CODE (t2);
/* Merge the attributes. */ /* Merge the attributes. */
attributes = targetm.merge_type_attributes (t1, t2); attributes = targetm.merge_type_attributes (t1, t2);
/* Treat an enum type as the unsigned integer type of the same width. */ /* If one is an enumerated type and the other is the compatible
integer type, the composite type might be either of the two
if (TREE_CODE (t1) == ENUMERAL_TYPE) (DR#013 question 3). For consistency, use the enumerated type as
t1 = c_common_type_for_size (TYPE_PRECISION (t1), 1); the composite type. */
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 if (code1 == ENUMERAL_TYPE && code2 == INTEGER_TYPE)
components, then make that complex. Use T1 or T2 if it is the return t1;
required type. */ if (code2 == ENUMERAL_TYPE && code1 == INTEGER_TYPE)
if (code1 == COMPLEX_TYPE || code2 == COMPLEX_TYPE) return t2;
{
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) if (code1 != code2)
return build_type_attribute_variant (t1, attributes); abort ();
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) 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: case POINTER_TYPE:
/* For two pointers, do this recursively on the target 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. */
{ {
tree pointed_to_1 = TREE_TYPE (t1); tree pointed_to_1 = TREE_TYPE (t1);
tree pointed_to_2 = TREE_TYPE (t2); tree pointed_to_2 = TREE_TYPE (t2);
tree target = common_type (TYPE_MAIN_VARIANT (pointed_to_1), tree target = composite_type (pointed_to_1, pointed_to_2);
TYPE_MAIN_VARIANT (pointed_to_2)); t1 = build_pointer_type (target);
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 build_type_attribute_variant (t1, attributes);
} }
case ARRAY_TYPE: 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. */ /* Save space: see if the result is identical to one of the args. */
if (elt == TREE_TYPE (t1) && TYPE_DOMAIN (t1)) if (elt == TREE_TYPE (t1) && TYPE_DOMAIN (t1))
return build_type_attribute_variant (t1, attributes); return build_type_attribute_variant (t1, attributes);
...@@ -380,7 +270,7 @@ common_type (tree t1, tree t2) ...@@ -380,7 +270,7 @@ common_type (tree t1, tree t2)
/* Function types: prefer the one that specified arg types. /* Function types: prefer the one that specified arg types.
If both do, merge the arg types. Also merge the return 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 p1 = TYPE_ARG_TYPES (t1);
tree p2 = TYPE_ARG_TYPES (t2); tree p2 = TYPE_ARG_TYPES (t2);
int len; int len;
...@@ -468,7 +358,7 @@ common_type (tree t1, tree t2) ...@@ -468,7 +358,7 @@ common_type (tree t1, tree t2)
goto parm_done; 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: ; parm_done: ;
} }
...@@ -482,6 +372,182 @@ common_type (tree t1, tree t2) ...@@ -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 /* Return 1 if TYPE1 and TYPE2 are compatible types for assignment
or various other operations. Return 2 if they are compatible or various other operations. Return 2 if they are compatible
...@@ -2760,7 +2826,7 @@ build_conditional_expr (tree ifexp, tree op1, tree op2) ...@@ -2760,7 +2826,7 @@ build_conditional_expr (tree ifexp, tree op1, tree op2)
else if (code1 == POINTER_TYPE && code2 == POINTER_TYPE) else if (code1 == POINTER_TYPE && code2 == POINTER_TYPE)
{ {
if (comp_target_types (type1, type2, 1)) 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 else if (integer_zerop (op1) && TREE_TYPE (type1) == void_type_node
&& TREE_CODE (orig_op1) != NOP_EXPR) && TREE_CODE (orig_op1) != NOP_EXPR)
result_type = qualify_type (type2, type1); result_type = qualify_type (type2, type1);
...@@ -6704,7 +6770,7 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, ...@@ -6704,7 +6770,7 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
Otherwise, the targets must be compatible Otherwise, the targets must be compatible
and both must be object or both incomplete. */ and both must be object or both incomplete. */
if (comp_target_types (type0, type1, 1)) 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)) else if (VOID_TYPE_P (tt0))
{ {
/* op0 != orig_op0 detects the case of something /* 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, ...@@ -6752,7 +6818,7 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
{ {
if (comp_target_types (type0, type1, 1)) if (comp_target_types (type0, type1, 1))
{ {
result_type = common_type (type0, type1); result_type = common_pointer_type (type0, type1);
if (pedantic if (pedantic
&& TREE_CODE (TREE_TYPE (type0)) == FUNCTION_TYPE) && TREE_CODE (TREE_TYPE (type0)) == FUNCTION_TYPE)
pedwarn ("ISO C forbids ordered comparisons of pointers to functions"); 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, ...@@ -6777,7 +6843,7 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
{ {
if (comp_target_types (type0, type1, 1)) 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)) if (!COMPLETE_TYPE_P (TREE_TYPE (type0))
!= !COMPLETE_TYPE_P (TREE_TYPE (type1))) != !COMPLETE_TYPE_P (TREE_TYPE (type1)))
pedwarn ("comparison of complete and incomplete pointers"); pedwarn ("comparison of complete and incomplete pointers");
......
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> 2004-06-06 Giovanni Bajo <giovannibajo@gcc.gnu.org>
PR c++/15503 PR c++/15503
......
/* 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);
}
/* 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; }
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment