re PR c/21536 (C99 array of variable length use causes segmentation fault)

PR c/21536
	PR c/20760
	* gimplify.c (gimplify_decl_expr): Call gimplify_type_sizes
	on variable sizes types if a decl is a pointer to a VLA.
	(gimplify_type_sizes): Handle POINTER_TYPE and REFERENCE_TYPE.
	Call gimplify_type_sizes on aggregate fields.  Prevent infinite
	recursion.

	* gcc.dg/20050527-1.c: New test.

From-SVN: r100443
This commit is contained in:
Jakub Jelinek 2005-06-01 12:23:17 +02:00 committed by Jakub Jelinek
parent dcd25113c6
commit 8e0a600bdd
4 changed files with 91 additions and 26 deletions

View File

@ -1,5 +1,13 @@
2005-06-01 Jakub Jelinek <jakub@redhat.com>
PR c/21536
PR c/20760
* gimplify.c (gimplify_decl_expr): Call gimplify_type_sizes
on variable sizes types if a decl is a pointer to a VLA.
(gimplify_type_sizes): Handle POINTER_TYPE and REFERENCE_TYPE.
Call gimplify_type_sizes on aggregate fields. Prevent infinite
recursion.
* fold-const.c (fold_ternary): Optimize BIT_FIELD_REF of VECTOR_CST.
* config/i386/xmmintrin.h (_mm_setzero_ps, _mm_set_ss, _mm_set1_ps,

View File

@ -983,10 +983,12 @@ gimplify_decl_expr (tree *stmt_p)
if (TREE_TYPE (decl) == error_mark_node)
return GS_ERROR;
else if (TREE_CODE (decl) == TYPE_DECL)
if ((TREE_CODE (decl) == TYPE_DECL
|| TREE_CODE (decl) == VAR_DECL)
&& !TYPE_SIZES_GIMPLIFIED (TREE_TYPE (decl)))
gimplify_type_sizes (TREE_TYPE (decl), stmt_p);
else if (TREE_CODE (decl) == VAR_DECL && !DECL_EXTERNAL (decl))
if (TREE_CODE (decl) == VAR_DECL && !DECL_EXTERNAL (decl))
{
tree init = DECL_INITIAL (decl);
@ -997,12 +999,6 @@ gimplify_decl_expr (tree *stmt_p)
of the emitted code: see mx_register_decls(). */
tree t, args, addr, ptr_type;
/* ??? We really shouldn't need to gimplify the type of the variable
since it already should have been done. But leave this here
for now to avoid disrupting too many things at once. */
if (!TYPE_SIZES_GIMPLIFIED (TREE_TYPE (decl)))
gimplify_type_sizes (TREE_TYPE (decl), stmt_p);
gimplify_one_sizepos (&DECL_SIZE (decl), stmt_p);
gimplify_one_sizepos (&DECL_SIZE_UNIT (decl), stmt_p);
@ -4409,21 +4405,21 @@ gimplify_type_sizes (tree type, tree *list_p)
{
tree field, t;
/* Note that we do not check for TYPE_SIZES_GIMPLIFIED already set because
that's not supposed to happen on types where gimplification does anything.
We should assert that it isn't set, but we can indeed be called multiple
times on pointers. Unfortunately, this includes fat pointers which we
can't easily test for. We could pass TYPE down to gimplify_one_sizepos
and test there, but it doesn't seem worth it. */
if (type == NULL)
return;
/* We first do the main variant, then copy into any other variants. */
type = TYPE_MAIN_VARIANT (type);
/* Avoid infinite recursion. */
if (TYPE_SIZES_GIMPLIFIED (type)
|| type == error_mark_node)
return;
TYPE_SIZES_GIMPLIFIED (type) = 1;
switch (TREE_CODE (type))
{
case ERROR_MARK:
return;
case INTEGER_TYPE:
case ENUMERAL_TYPE:
case BOOLEAN_TYPE:
@ -4436,17 +4432,13 @@ gimplify_type_sizes (tree type, tree *list_p)
{
TYPE_MIN_VALUE (t) = TYPE_MIN_VALUE (type);
TYPE_MAX_VALUE (t) = TYPE_MAX_VALUE (type);
TYPE_SIZES_GIMPLIFIED (t) = 1;
}
break;
case ARRAY_TYPE:
/* These types may not have declarations, so handle them here. */
if (!TYPE_SIZES_GIMPLIFIED (TREE_TYPE (type)))
gimplify_type_sizes (TREE_TYPE (type), list_p);
if (!TYPE_SIZES_GIMPLIFIED (TYPE_DOMAIN (type)))
gimplify_type_sizes (TYPE_DOMAIN (type), list_p);
gimplify_type_sizes (TREE_TYPE (type), list_p);
gimplify_type_sizes (TYPE_DOMAIN (type), list_p);
break;
case RECORD_TYPE:
@ -4454,7 +4446,15 @@ gimplify_type_sizes (tree type, tree *list_p)
case QUAL_UNION_TYPE:
for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
if (TREE_CODE (field) == FIELD_DECL)
gimplify_one_sizepos (&DECL_FIELD_OFFSET (field), list_p);
{
gimplify_one_sizepos (&DECL_FIELD_OFFSET (field), list_p);
gimplify_type_sizes (TREE_TYPE (field), list_p);
}
break;
case POINTER_TYPE:
case REFERENCE_TYPE:
gimplify_type_sizes (TREE_TYPE (type), list_p);
break;
default:
@ -4470,8 +4470,6 @@ gimplify_type_sizes (tree type, tree *list_p)
TYPE_SIZE_UNIT (t) = TYPE_SIZE_UNIT (type);
TYPE_SIZES_GIMPLIFIED (t) = 1;
}
TYPE_SIZES_GIMPLIFIED (type) = 1;
}
/* A subroutine of gimplify_type_sizes to make sure that *EXPR_P,

View File

@ -1,5 +1,9 @@
2005-06-01 Jakub Jelinek <jakub@redhat.com>
PR c/21536
PR c/20760
* gcc.dg/20050527-1.c: New test.
* gcc.dg/i386-sse-12.c: New test.
PR fortran/21729

View File

@ -0,0 +1,55 @@
/* PR c/21536 */
/* { dg-do run } */
/* { dg-options "-O2 -Wuninitialized" } */
typedef __SIZE_TYPE__ size_t;
extern void *malloc (size_t);
extern void free (void *);
void *
foo (int x, int y)
{
void *d = malloc (x * y * sizeof (double));
double (*e)[x][y] = d;
x += 10;
y += 10;
if (x > 18)
(*e)[x - 12][y - 12] = 0.0;
else
(*e)[x - 11][y - 11] = 1.0;
return d;
}
void *
bar (int x, int y)
{
void *d = malloc (x * y * sizeof (double));
struct S
{
double (*e)[x][y];
double (*f)[x][y];
} s;
s.e = d;
s.f = d;
x += 10;
y += 10;
if (x > 18)
(*s.e)[x - 12][y - 12] = 0.0;
else
(*s.e)[x - 11][y - 11] = 1.0;
if (x > 16)
(*s.f)[x - 13][y - 13] = 0.0;
else
(*s.f)[x - 14][y - 14] = 1.0;
return d;
}
int
main ()
{
void *d1 = foo (10, 10);
void *d2 = bar (10, 10);
free (d1);
free (d2);
return 0;
}