This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
PR c/27184: bad alias sets for incomplete array types
- From: Alexandre Oliva <aoliva at redhat dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Tue, 30 May 2006 02:46:28 -0300
- Subject: PR c/27184: bad alias sets for incomplete array types
The testcase included in the patch below fails at -O2 because the
pointers to arrays with unknown bounds are regarded as unrelated
types. That's because incomplete array types were not unified by
build_array_type, presumably to avoid modifying shared types if/when
such incomplete array types get completed, even though there was only
one case that set TYPE_DOMAIN without avoiding modifying shared array
types. Other languages didn't seem to be affected, and the testsuite
results supported this impression.
Bootstrapped and tested on amd64-linux-gnu. Ok to install?
for gcc/ChangeLog
from Alexandre Oliva <aoliva@redhat.com>
PR c/27184
* tree.c (build_array_type): Unify array types with
unspecified index_type.
* c-decl.c (grokdeclarator): Make sure we do not modify a
unified incomplete array type.
* c-typeck.c (store_init_value): Create distinct type before
filling in the index type in an initializer from a compound
literal.
for gcc/testsuite/ChangeLog
from Alexandre Oliva <aoliva@redhat.com>
PR c/27184
* gcc.dg/torture/pr27184.c: New test.
Index: gcc/c-decl.c
===================================================================
--- gcc/c-decl.c.orig 2006-05-29 05:57:01.000000000 -0300
+++ gcc/c-decl.c 2006-05-29 15:48:19.000000000 -0300
@@ -4291,6 +4291,18 @@ grokdeclarator (const struct c_declarato
size_varies = 1;
}
}
+ else if (decl_context == TYPENAME)
+ {
+ if (array_parm_vla_unspec_p)
+ {
+ /* The error is printed elsewhere. We use this to
+ avoid messing up with incomplete array types of
+ the same type, that would otherwise be modified
+ below. */
+ itype = build_range_type (sizetype, size_zero_node,
+ NULL_TREE);
+ }
+ }
/* Complain about arrays of incomplete types. */
if (!COMPLETE_TYPE_P (type))
@@ -4299,11 +4311,22 @@ grokdeclarator (const struct c_declarato
type = error_mark_node;
}
else
+ /* When itype is NULL, a shared incomplete array type is
+ returned for all array of a given type. Elsewhere we
+ make sure we don't complete that type before copying
+ it, but here we want to make sure we don't ever
+ modify the shared type, so we gcc_assert (itype)
+ below. */
type = build_array_type (type, itype);
if (type != error_mark_node)
{
if (size_varies)
+ /* It is ok to modify type here even if itype is
+ NULL: if size_varies, we're in a
+ multi-dimentional array and the inner type has
+ variable size, so the enclosing shared array type
+ must too. */
C_TYPE_VARIABLE_SIZE (type) = 1;
/* The GCC extension for zero-length arrays differs from
@@ -4311,11 +4334,13 @@ grokdeclarator (const struct c_declarato
zero. */
if (size && integer_zerop (size))
{
+ gcc_assert (itype);
TYPE_SIZE (type) = bitsize_zero_node;
TYPE_SIZE_UNIT (type) = size_zero_node;
}
if (array_parm_vla_unspec_p)
{
+ gcc_assert (itype);
/* The type is complete. C99 6.7.5.2p4 */
TYPE_SIZE (type) = bitsize_zero_node;
TYPE_SIZE_UNIT (type) = size_zero_node;
Index: gcc/c-typeck.c
===================================================================
--- gcc/c-typeck.c.orig 2006-05-29 05:57:01.000000000 -0300
+++ gcc/c-typeck.c 2006-05-29 06:03:46.000000000 -0300
@@ -4301,16 +4301,18 @@ store_init_value (tree decl, tree init)
if (TREE_CODE (inside_init) == COMPOUND_LITERAL_EXPR)
{
- tree decl = COMPOUND_LITERAL_EXPR_DECL (inside_init);
+ tree cldecl = COMPOUND_LITERAL_EXPR_DECL (inside_init);
- if (TYPE_DOMAIN (TREE_TYPE (decl)))
+ if (TYPE_DOMAIN (TREE_TYPE (cldecl)))
{
/* For int foo[] = (int [3]){1}; we need to set array size
now since later on array initializer will be just the
brace enclosed list of the compound literal. */
- TYPE_DOMAIN (type) = TYPE_DOMAIN (TREE_TYPE (decl));
+ type = build_distinct_type_copy (TYPE_MAIN_VARIANT (type));
+ TREE_TYPE (decl) = type;
+ TYPE_DOMAIN (type) = TYPE_DOMAIN (TREE_TYPE (cldecl));
layout_type (type);
- layout_decl (decl, 0);
+ layout_decl (cldecl, 0);
}
}
}
Index: gcc/tree.c
===================================================================
--- gcc/tree.c.orig 2006-05-29 05:57:01.000000000 -0300
+++ gcc/tree.c 2006-05-29 06:03:46.000000000 -0300
@@ -5060,7 +5060,11 @@ build_array_type (tree elt_type, tree in
if (index_type == 0)
{
- layout_type (t);
+ tree save = t;
+ hashcode = iterative_hash_object (TYPE_HASH (elt_type), hashcode);
+ t = type_hash_canon (hashcode, t);
+ if (save == t)
+ layout_type (t);
return t;
}
Index: gcc/testsuite/gcc.dg/torture/pr27184.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ gcc/testsuite/gcc.dg/torture/pr27184.c 2006-05-29 06:03:36.000000000 -0300
@@ -0,0 +1,22 @@
+/* Copyright 2006 Free Software Foundation */
+
+/* Make sure a and a1 alias each other.
+ Incomplete array types used to not be unified, which broke aliasing. */
+
+/* { dg-do run } */
+
+typedef long atype[];
+typedef long atype1[];
+int NumSift (atype *a, atype1 *a1)
+{
+ (*a)[0] = 0;
+ (*a1)[0] = 1;
+ return (*a)[0];
+}
+int main(void)
+{
+ long a[2];
+ if (!NumSift(&a, &a))
+ __builtin_abort ();
+ return 0;
+}
--
Alexandre Oliva http://www.lsd.ic.unicamp.br/~oliva/
Secretary for FSF Latin America http://www.fsfla.org/
Red Hat Compiler Engineer aoliva@{redhat.com, gcc.gnu.org}
Free Software Evangelist oliva@{lsd.ic.unicamp.br, gnu.org}