diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 23 | ||||
-rw-r--r-- | gcc/c-common.c | 32 | ||||
-rw-r--r-- | gcc/c-decl.c | 43 | ||||
-rw-r--r-- | gcc/c-typeck.c | 124 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/Wwrite-strings-1.c | 8 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/array-quals-2.c | 14 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/concat.c | 4 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/lvalue-3.c | 14 |
9 files changed, 188 insertions, 80 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index d0f51a0..3edb615 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,26 @@ +2005-01-29 Joseph S. Myers <joseph@codesourcery.com> + + * c-common.c (fix_string_type): Just use c_build_qualified_type to + build string type. + (c_build_qualified_type): Build qualified array types with + TYPE_MAIN_VARIANT pointing to corresponding unqualified type. + * c-decl.c (c_make_fname_decl): Build unqualified array type + before qualified type. + (grokdeclarator): Use TYPE_MAIN_VARIANT of typedef type if element + type is qualified, not just if type itself is. Don't apply + qualifiers to array type when declarator is processed. Apply + qualifiers to field type whether or not it is an array type. + Don't handle array types specially for applying qualifiers to + variables. + * c-typeck.c (composite_type): Build unqualified element type and + array type when forming composite of array types. + (common_pointer_type, comptypes, comp_target_types, + type_lists_compatible_p, build_indirect_ref, build_array_ref, + convert_for_assignment): Don't apply TYPE_MAIN_VARIANT to array + types. + (type_lists_compatible_p): Cache TREE_VALUE (args1) and TREE_VALUE + (args2) in variables a1 and a2. + 2005-01-29 Kazu Hirata <kazu@cs.umass.edu> * cse.c (n_elements_made, max_elements_made): Remove. diff --git a/gcc/c-common.c b/gcc/c-common.c index 1df71ad..72fd846 100644 --- a/gcc/c-common.c +++ b/gcc/c-common.c @@ -862,12 +862,7 @@ fix_string_type (tree value) i_type = build_index_type (build_int_cst (NULL_TREE, nchars - 1)); a_type = build_array_type (e_type, i_type); if (flag_const_strings) - { - /* bleah, c_build_qualified_type should set TYPE_MAIN_VARIANT. */ - tree qa_type = c_build_qualified_type (a_type, TYPE_QUAL_CONST); - TYPE_MAIN_VARIANT (qa_type) = a_type; - a_type = qa_type; - } + a_type = c_build_qualified_type (a_type, TYPE_QUAL_CONST); TREE_TYPE (value) = a_type; TREE_CONSTANT (value) = 1; @@ -2483,9 +2478,28 @@ c_build_qualified_type (tree type, int type_quals) return type; if (TREE_CODE (type) == ARRAY_TYPE) - return build_array_type (c_build_qualified_type (TREE_TYPE (type), - type_quals), - TYPE_DOMAIN (type)); + { + tree t; + tree element_type = c_build_qualified_type (TREE_TYPE (type), + type_quals); + + /* See if we already have an identically qualified type. */ + for (t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t)) + { + if (TYPE_QUALS (strip_array_types (t)) == type_quals + && TYPE_NAME (t) == TYPE_NAME (type) + && TYPE_CONTEXT (t) == TYPE_CONTEXT (type) + && attribute_list_equal (TYPE_ATTRIBUTES (t), + TYPE_ATTRIBUTES (type))) + break; + } + if (!t) + { + t = build_variant_type_copy (type); + TREE_TYPE (t) = element_type; + } + return t; + } /* A restrict-qualified pointer type must be a pointer to object or incomplete type. Note that the use of POINTER_TYPE_P also allows diff --git a/gcc/c-decl.c b/gcc/c-decl.c index 6e8c742..efb17e8 100644 --- a/gcc/c-decl.c +++ b/gcc/c-decl.c @@ -2632,9 +2632,9 @@ c_make_fname_decl (tree id, int type_dep) tree decl, type, init; size_t length = strlen (name); - type = build_array_type - (build_qualified_type (char_type_node, TYPE_QUAL_CONST), - build_index_type (size_int (length))); + type = build_array_type (char_type_node, + build_index_type (size_int (length))); + type = c_build_qualified_type (type, TYPE_QUAL_CONST); decl = build_decl (VAR_DECL, id, type); @@ -3861,7 +3861,7 @@ grokdeclarator (const struct c_declarator *declarator, if (volatilep > 1) pedwarn ("duplicate %<volatile%>"); } - if (!flag_gen_aux_info && (TYPE_QUALS (type))) + if (!flag_gen_aux_info && (TYPE_QUALS (element_type))) type = TYPE_MAIN_VARIANT (type); type_quals = ((constp ? TYPE_QUAL_CONST : 0) | (restrictp ? TYPE_QUAL_RESTRICT : 0) @@ -3946,7 +3946,13 @@ grokdeclarator (const struct c_declarator *declarator, /* Now figure out the structure of the declarator proper. Descend through it, creating more complex types, until we reach - the declared identifier (or NULL_TREE, in an absolute declarator). */ + the declared identifier (or NULL_TREE, in an absolute declarator). + At each stage we maintain an unqualified version of the type + together with any qualifiers that should be applied to it with + c_build_qualified_type; this way, array types including + multidimensional array types are first built up in unqualified + form and then the qualified form is created with + TYPE_MAIN_VARIANT pointing to the unqualified form. */ while (declarator && declarator->kind != cdk_id) { @@ -4146,13 +4152,7 @@ grokdeclarator (const struct c_declarator *declarator, if (pedantic && !COMPLETE_TYPE_P (type)) pedwarn ("array type has incomplete element type"); - /* Build the array type itself, then merge any constancy - or volatility into the target type. We must do it in - this order to ensure that the TYPE_MAIN_VARIANT field - of the array type is set correctly. */ type = build_array_type (type, itype); - if (type_quals) - type = c_build_qualified_type (type, type_quals); if (size_varies) C_TYPE_VARIABLE_SIZE (type) = 1; @@ -4278,7 +4278,8 @@ grokdeclarator (const struct c_declarator *declarator, } } - /* Now TYPE has the actual type. */ + /* Now TYPE has the actual type, apart from any qualifiers in + TYPE_QUALS. */ /* Check the type and width of a bit-field. */ if (bitfield) @@ -4447,11 +4448,7 @@ grokdeclarator (const struct c_declarator *declarator, error ("field %qs has incomplete type", name); type = error_mark_node; } - /* Move type qualifiers down to element of an array. */ - if (TREE_CODE (type) == ARRAY_TYPE && type_quals) - type = build_array_type (c_build_qualified_type (TREE_TYPE (type), - type_quals), - TYPE_DOMAIN (type)); + type = c_build_qualified_type (type, type_quals); decl = build_decl (FIELD_DECL, declarator->u.id, type); DECL_NONADDRESSABLE_P (decl) = bitfield; @@ -4556,17 +4553,7 @@ grokdeclarator (const struct c_declarator *declarator, /* An uninitialized decl with `extern' is a reference. */ int extern_ref = !initialized && storage_class == csc_extern; - /* Move type qualifiers down to element of an array. */ - if (TREE_CODE (type) == ARRAY_TYPE && type_quals) - { - int saved_align = TYPE_ALIGN(type); - type = build_array_type (c_build_qualified_type (TREE_TYPE (type), - type_quals), - TYPE_DOMAIN (type)); - TYPE_ALIGN (type) = saved_align; - } - else if (type_quals) - type = c_build_qualified_type (type, type_quals); + type = c_build_qualified_type (type, type_quals); /* C99 6.2.2p7: It is invalid (compile-time undefined behavior) to create an 'extern' declaration for a diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c index cb657df..fed17f2 100644 --- a/gcc/c-typeck.c +++ b/gcc/c-typeck.c @@ -277,7 +277,9 @@ composite_type (tree t1, tree t2) case ARRAY_TYPE: { tree elt = composite_type (TREE_TYPE (t1), TREE_TYPE (t2)); - + int quals; + tree unqual_elt; + /* We should not have any type quals on arrays at all. */ gcc_assert (!TYPE_QUALS (t1) && !TYPE_QUALS (t2)); @@ -292,8 +294,16 @@ composite_type (tree t1, tree t2) if (elt == TREE_TYPE (t2) && !TYPE_DOMAIN (t2) && !TYPE_DOMAIN (t1)) return build_type_attribute_variant (t2, attributes); - /* Merge the element types, and have a size if either arg has one. */ - t1 = build_array_type (elt, TYPE_DOMAIN (TYPE_DOMAIN (t1) ? t1 : t2)); + /* Merge the element types, and have a size if either arg has + one. We may have qualifiers on the element types. To set + up TYPE_MAIN_VARIANT correctly, we need to form the + composite of the unqualified types and add the qualifiers + back at the end. */ + quals = TYPE_QUALS (strip_array_types (elt)); + unqual_elt = c_build_qualified_type (elt, TYPE_UNQUALIFIED); + t1 = build_array_type (unqual_elt, + TYPE_DOMAIN (TYPE_DOMAIN (t1) ? t1 : t2)); + t1 = c_build_qualified_type (t1, quals); return build_type_attribute_variant (t1, attributes); } @@ -415,8 +425,8 @@ static tree common_pointer_type (tree t1, tree t2) { tree attributes; - tree pointed_to_1; - tree pointed_to_2; + tree pointed_to_1, mv1; + tree pointed_to_2, mv2; tree target; /* Save time if the two types are the same. */ @@ -436,11 +446,15 @@ common_pointer_type (tree t1, tree t2) 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)); + qualifiers of the two types' targets. Do not lose qualifiers on + array element types by taking the TYPE_MAIN_VARIANT. */ + mv1 = pointed_to_1 = TREE_TYPE (t1); + mv2 = pointed_to_2 = TREE_TYPE (t2); + if (TREE_CODE (mv1) != ARRAY_TYPE) + mv1 = TYPE_MAIN_VARIANT (pointed_to_1); + if (TREE_CODE (mv2) != ARRAY_TYPE) + mv2 = TYPE_MAIN_VARIANT (pointed_to_2); + target = composite_type (mv1, mv2); t1 = build_pointer_type (c_build_qualified_type (target, TYPE_QUALS (pointed_to_1) | @@ -632,7 +646,8 @@ comptypes (tree type1, tree type2) definition. Note that we already checked for equality of the type qualifiers (just above). */ - if (TYPE_MAIN_VARIANT (t1) == TYPE_MAIN_VARIANT (t2)) + if (TREE_CODE (t1) != ARRAY_TYPE + && TYPE_MAIN_VARIANT (t1) == TYPE_MAIN_VARIANT (t2)) return 1; /* 1 if no need for warning yet, 2 if warning cause has been seen. */ @@ -734,13 +749,21 @@ static int comp_target_types (tree ttl, tree ttr, int reflexive) { int val; + tree mvl, mvr; /* Give objc_comptypes a crack at letting these types through. */ if ((val = objc_comptypes (ttl, ttr, reflexive)) >= 0) return val; - val = comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (ttl)), - TYPE_MAIN_VARIANT (TREE_TYPE (ttr))); + /* Do not lose qualifiers on element types of array types that are + pointer targets by taking their TYPE_MAIN_VARIANT. */ + mvl = TREE_TYPE (ttl); + mvr = TREE_TYPE (ttr); + if (TREE_CODE (mvl) != ARRAY_TYPE) + mvl = TYPE_MAIN_VARIANT (mvl); + if (TREE_CODE (mvr) != ARRAY_TYPE) + mvr = TYPE_MAIN_VARIANT (mvr); + val = comptypes (mvl, mvr); if (val == 2 && pedantic) pedwarn ("types are not quite compatible"); @@ -1042,61 +1065,67 @@ type_lists_compatible_p (tree args1, tree args2) while (1) { + tree a1, mv1, a2, mv2; if (args1 == 0 && args2 == 0) return val; /* If one list is shorter than the other, they fail to match. */ if (args1 == 0 || args2 == 0) return 0; + mv1 = a1 = TREE_VALUE (args1); + mv2 = a2 = TREE_VALUE (args2); + if (mv1 && mv1 != error_mark_node && TREE_CODE (mv1) != ARRAY_TYPE) + mv1 = TYPE_MAIN_VARIANT (mv1); + if (mv2 && mv2 != error_mark_node && TREE_CODE (mv2) != ARRAY_TYPE) + mv2 = TYPE_MAIN_VARIANT (mv2); /* A null pointer instead of a type means there is supposed to be an argument but nothing is specified about what type it has. So match anything that self-promotes. */ - if (TREE_VALUE (args1) == 0) + if (a1 == 0) { - if (c_type_promotes_to (TREE_VALUE (args2)) != TREE_VALUE (args2)) + if (c_type_promotes_to (a2) != a2) return 0; } - else if (TREE_VALUE (args2) == 0) + else if (a2 == 0) { - if (c_type_promotes_to (TREE_VALUE (args1)) != TREE_VALUE (args1)) + if (c_type_promotes_to (a1) != a1) return 0; } /* If one of the lists has an error marker, ignore this arg. */ - else if (TREE_CODE (TREE_VALUE (args1)) == ERROR_MARK - || TREE_CODE (TREE_VALUE (args2)) == ERROR_MARK) + else if (TREE_CODE (a1) == ERROR_MARK + || TREE_CODE (a2) == ERROR_MARK) ; - else if (!(newval = comptypes (TYPE_MAIN_VARIANT (TREE_VALUE (args1)), - TYPE_MAIN_VARIANT (TREE_VALUE (args2))))) + else if (!(newval = comptypes (mv1, mv2))) { /* Allow wait (union {union wait *u; int *i} *) and wait (union wait *) to be compatible. */ - if (TREE_CODE (TREE_VALUE (args1)) == UNION_TYPE - && (TYPE_NAME (TREE_VALUE (args1)) == 0 - || TYPE_TRANSPARENT_UNION (TREE_VALUE (args1))) - && TREE_CODE (TYPE_SIZE (TREE_VALUE (args1))) == INTEGER_CST - && tree_int_cst_equal (TYPE_SIZE (TREE_VALUE (args1)), - TYPE_SIZE (TREE_VALUE (args2)))) + if (TREE_CODE (a1) == UNION_TYPE + && (TYPE_NAME (a1) == 0 + || TYPE_TRANSPARENT_UNION (a1)) + && TREE_CODE (TYPE_SIZE (a1)) == INTEGER_CST + && tree_int_cst_equal (TYPE_SIZE (a1), + TYPE_SIZE (a2))) { tree memb; - for (memb = TYPE_FIELDS (TREE_VALUE (args1)); + for (memb = TYPE_FIELDS (a1); memb; memb = TREE_CHAIN (memb)) - if (comptypes (TREE_TYPE (memb), TREE_VALUE (args2))) + if (comptypes (TREE_TYPE (memb), a2)) break; if (memb == 0) return 0; } - else if (TREE_CODE (TREE_VALUE (args2)) == UNION_TYPE - && (TYPE_NAME (TREE_VALUE (args2)) == 0 - || TYPE_TRANSPARENT_UNION (TREE_VALUE (args2))) - && TREE_CODE (TYPE_SIZE (TREE_VALUE (args2))) == INTEGER_CST - && tree_int_cst_equal (TYPE_SIZE (TREE_VALUE (args2)), - TYPE_SIZE (TREE_VALUE (args1)))) + else if (TREE_CODE (a2) == UNION_TYPE + && (TYPE_NAME (a2) == 0 + || TYPE_TRANSPARENT_UNION (a2)) + && TREE_CODE (TYPE_SIZE (a2)) == INTEGER_CST + && tree_int_cst_equal (TYPE_SIZE (a2), + TYPE_SIZE (a1))) { tree memb; - for (memb = TYPE_FIELDS (TREE_VALUE (args2)); + for (memb = TYPE_FIELDS (a2); memb; memb = TREE_CHAIN (memb)) - if (comptypes (TREE_TYPE (memb), TREE_VALUE (args1))) + if (comptypes (TREE_TYPE (memb), a1)) break; if (memb == 0) return 0; @@ -1542,7 +1571,12 @@ build_indirect_ref (tree ptr, const char *errorstring) else { tree t = TREE_TYPE (type); - tree ref = build1 (INDIRECT_REF, TYPE_MAIN_VARIANT (t), pointer); + tree mvt = t; + tree ref; + + if (TREE_CODE (mvt) != ARRAY_TYPE) + mvt = TYPE_MAIN_VARIANT (mvt); + ref = build1 (INDIRECT_REF, mvt, pointer); if (!COMPLETE_OR_VOID_TYPE_P (t) && TREE_CODE (t) != ARRAY_TYPE) { @@ -1670,7 +1704,9 @@ build_array_ref (tree array, tree index) pedwarn ("ISO C90 forbids subscripting non-lvalue array"); } - type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (array))); + type = TREE_TYPE (TREE_TYPE (array)); + if (TREE_CODE (type) != ARRAY_TYPE) + type = TYPE_MAIN_VARIANT (type); rval = build4 (ARRAY_REF, type, array, index, NULL_TREE, NULL_TREE); /* Array ref is const/volatile if the array elements are or if the array is. */ @@ -3597,9 +3633,15 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype, { tree ttl = TREE_TYPE (type); tree ttr = TREE_TYPE (rhstype); + tree mvl = ttl; + tree mvr = ttr; bool is_opaque_pointer; int target_cmp = 0; /* Cache comp_target_types () result. */ + if (TREE_CODE (mvl) != ARRAY_TYPE) + mvl = TYPE_MAIN_VARIANT (mvl); + if (TREE_CODE (mvr) != ARRAY_TYPE) + mvr = TYPE_MAIN_VARIANT (mvr); /* Opaque pointers are treated like void pointers. */ is_opaque_pointer = (targetm.vector_opaque_p (type) || targetm.vector_opaque_p (rhstype)) @@ -3612,8 +3654,8 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype, if (VOID_TYPE_P (ttl) || VOID_TYPE_P (ttr) || (target_cmp = comp_target_types (type, rhstype, 0)) || is_opaque_pointer - || (c_common_unsigned_type (TYPE_MAIN_VARIANT (ttl)) - == c_common_unsigned_type (TYPE_MAIN_VARIANT (ttr)))) + || (c_common_unsigned_type (mvl) + == c_common_unsigned_type (mvr))) { if (pedantic && ((VOID_TYPE_P (ttl) && TREE_CODE (ttr) == FUNCTION_TYPE) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 2fc135f..e7ff37e 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2005-01-29 Joseph S. Myers <joseph@codesourcery.com> + + * gcc.dg/Wwrite-strings-1.c, gcc.dg/array-quals-2.c, + gcc.dg/lvalue-3.c: New tests. + * gcc.dg/concat.c: Update expected messages. + 2005-01-29 Thomas Koenig <Thomas.Koenig@online.de> PR libfortran/19595 diff --git a/gcc/testsuite/gcc.dg/Wwrite-strings-1.c b/gcc/testsuite/gcc.dg/Wwrite-strings-1.c new file mode 100644 index 0000000..9270e8f --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wwrite-strings-1.c @@ -0,0 +1,8 @@ +/* Test pointer initialization and dereference don't lose qualifiers + on array types. This test wrongly failed to diagnose the loss of + const. */ +/* Origin: Joseph Myers <joseph@codesourcery.com> */ +/* { dg-do compile } */ +/* { dg-options "-Wwrite-strings" } */ +typedef char T[1]; +T *p = &""; /* { dg-warning "warning: initialization from incompatible pointer type" } */ diff --git a/gcc/testsuite/gcc.dg/array-quals-2.c b/gcc/testsuite/gcc.dg/array-quals-2.c new file mode 100644 index 0000000..5d20244 --- /dev/null +++ b/gcc/testsuite/gcc.dg/array-quals-2.c @@ -0,0 +1,14 @@ +/* Test that pointers to arrays of differently qualified types aren't + permitted in conditional expressions, and that qualifiers aren't + lost in forming composite types. */ +/* Origin: Joseph Myers <joseph@codesourcery.com> */ +/* { dg-do compile } */ +/* { dg-options "" } */ +typedef const char T[1]; +typedef const char T2[1]; +typedef volatile char U[1]; +T *p; +T2 *p2; +U *q; +void *f(void) { return 1 ? p : q; } /* { dg-warning "warning: pointer type mismatch in conditional expression" } */ +T *g(void) { return 1 ? p : p2; } diff --git a/gcc/testsuite/gcc.dg/concat.c b/gcc/testsuite/gcc.dg/concat.c index 9503368..0b9d6f6 100644 --- a/gcc/testsuite/gcc.dg/concat.c +++ b/gcc/testsuite/gcc.dg/concat.c @@ -8,8 +8,8 @@ void foo () { - char s1[] = __FUNCTION__"."; /* { dg-error "(parse|syntax|expected|invalid)" } */ - char s2[] = __PRETTY_FUNCTION__".";/* { dg-error "(parse|syntax|expected|invalid)" } */ + char s1[] = __FUNCTION__"."; /* { dg-error "(parse|syntax|expected|invalid|array)" } */ + char s2[] = __PRETTY_FUNCTION__".";/* { dg-error "(parse|syntax|expected|invalid|array)" } */ char s3[] = "."__FUNCTION__; /* { dg-error "(parse|syntax|expected|invalid)" } */ char s4[] = "."__PRETTY_FUNCTION__;/* { dg-error "(parse|syntax|expected|invalid)" } */ char s5[] = ".""."; /* No error. */ diff --git a/gcc/testsuite/gcc.dg/lvalue-3.c b/gcc/testsuite/gcc.dg/lvalue-3.c new file mode 100644 index 0000000..0745c7e --- /dev/null +++ b/gcc/testsuite/gcc.dg/lvalue-3.c @@ -0,0 +1,14 @@ +/* Test that assignment of a read-only variable that gets const-ness + from a read-only field is diagnosed. */ +/* Origin: Joseph Myers <joseph@codesourcery.com> */ +/* { dg-do compile } */ +/* { dg-options "" } */ + +struct s { const int a; } x; +typeof (x.a) b; +void +f (void) +{ + x.a = 1; /* { dg-error "error: assignment of read-only member 'a'" } */ + b = 1; /* { dg-error "error: assignment of read-only variable 'b'" } */ +} |