c-common.c (fix_string_type): Just use c_build_qualified_type to build string type.

* 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.

testsuite:
	* 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.

From-SVN: r94411
This commit is contained in:
Joseph Myers 2005-01-29 16:12:45 +00:00 committed by Joseph Myers
parent 24a09741e4
commit 46df282378
9 changed files with 188 additions and 80 deletions

View file

@ -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.

View file

@ -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

View file

@ -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

View file

@ -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)

View file

@ -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

View file

@ -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" } */

View file

@ -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; }

View file

@ -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. */

View file

@ -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'" } */
}