From: Joseph Myers Date: Sun, 6 Jun 2004 15:21:59 +0000 (+0100) Subject: re PR c/13519 (typeof(nonconst+const) is const) X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=10bc1b1bec937131ad05fa18184b985078b99702;p=gcc.git 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 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index cca009ba24f..f3f622e7ba6 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,16 @@ +2004-06-06 Joseph S. Myers + + 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 PR target/14457 diff --git a/gcc/c-decl.c b/gcc/c-decl.c index 3a13664f7b3..ee09afaff0d 100644 --- a/gcc/c-decl.c +++ b/gcc/c-decl.c @@ -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)) diff --git a/gcc/c-tree.h b/gcc/c-tree.h index 9e21b4fc947..e698c871a12 100644 --- a/gcc/c-tree.h +++ b/gcc/c-tree.h @@ -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); diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c index cf01aa5f60f..bdbb58b3f82 100644 --- a/gcc/c-typeck.c +++ b/gcc/c-typeck.c @@ -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; + code1 = TREE_CODE (t1); + code2 = TREE_CODE (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 = 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 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 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 == ENUMERAL_TYPE && code2 == INTEGER_TYPE) + return t1; + if (code2 == ENUMERAL_TYPE && code1 == INTEGER_TYPE) + return 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 (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"); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 197242d2bee..17871dd339e 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2004-06-06 Joseph S. Myers + + PR c/13519 + * gcc.c-torture/enum-3.c, gcc.dg/pr13519-1.c: New tests. + 2004-06-06 Giovanni Bajo PR c++/15503 diff --git a/gcc/testsuite/gcc.c-torture/execute/enum-3.c b/gcc/testsuite/gcc.c-torture/execute/enum-3.c new file mode 100644 index 00000000000..f57bc7f7838 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/enum-3.c @@ -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 */ + +#include + +#include + +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); +} diff --git a/gcc/testsuite/gcc.dg/pr13519-1.c b/gcc/testsuite/gcc.dg/pr13519-1.c new file mode 100644 index 00000000000..907165f5f8e --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr13519-1.c @@ -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 , adapted to a testcase by + Joseph Myers . */ +/* { 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; } +}