Commit 8e0a600b by Jakub Jelinek Committed by Jakub Jelinek

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
parent dcd25113
2005-06-01 Jakub Jelinek <jakub@redhat.com> 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. * 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, * config/i386/xmmintrin.h (_mm_setzero_ps, _mm_set_ss, _mm_set1_ps,
......
...@@ -983,10 +983,12 @@ gimplify_decl_expr (tree *stmt_p) ...@@ -983,10 +983,12 @@ gimplify_decl_expr (tree *stmt_p)
if (TREE_TYPE (decl) == error_mark_node) if (TREE_TYPE (decl) == error_mark_node)
return GS_ERROR; 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); 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); tree init = DECL_INITIAL (decl);
...@@ -997,12 +999,6 @@ gimplify_decl_expr (tree *stmt_p) ...@@ -997,12 +999,6 @@ gimplify_decl_expr (tree *stmt_p)
of the emitted code: see mx_register_decls(). */ of the emitted code: see mx_register_decls(). */
tree t, args, addr, ptr_type; 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 (decl), stmt_p);
gimplify_one_sizepos (&DECL_SIZE_UNIT (decl), stmt_p); gimplify_one_sizepos (&DECL_SIZE_UNIT (decl), stmt_p);
...@@ -4409,21 +4405,21 @@ gimplify_type_sizes (tree type, tree *list_p) ...@@ -4409,21 +4405,21 @@ gimplify_type_sizes (tree type, tree *list_p)
{ {
tree field, t; tree field, t;
/* Note that we do not check for TYPE_SIZES_GIMPLIFIED already set because if (type == NULL)
that's not supposed to happen on types where gimplification does anything. return;
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. */
/* We first do the main variant, then copy into any other variants. */ /* We first do the main variant, then copy into any other variants. */
type = TYPE_MAIN_VARIANT (type); 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)) switch (TREE_CODE (type))
{ {
case ERROR_MARK:
return;
case INTEGER_TYPE: case INTEGER_TYPE:
case ENUMERAL_TYPE: case ENUMERAL_TYPE:
case BOOLEAN_TYPE: case BOOLEAN_TYPE:
...@@ -4436,17 +4432,13 @@ gimplify_type_sizes (tree type, tree *list_p) ...@@ -4436,17 +4432,13 @@ gimplify_type_sizes (tree type, tree *list_p)
{ {
TYPE_MIN_VALUE (t) = TYPE_MIN_VALUE (type); TYPE_MIN_VALUE (t) = TYPE_MIN_VALUE (type);
TYPE_MAX_VALUE (t) = TYPE_MAX_VALUE (type); TYPE_MAX_VALUE (t) = TYPE_MAX_VALUE (type);
TYPE_SIZES_GIMPLIFIED (t) = 1;
} }
break; break;
case ARRAY_TYPE: case ARRAY_TYPE:
/* These types may not have declarations, so handle them here. */ /* 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);
gimplify_type_sizes (TREE_TYPE (type), list_p); gimplify_type_sizes (TYPE_DOMAIN (type), list_p);
if (!TYPE_SIZES_GIMPLIFIED (TYPE_DOMAIN (type)))
gimplify_type_sizes (TYPE_DOMAIN (type), list_p);
break; break;
case RECORD_TYPE: case RECORD_TYPE:
...@@ -4454,7 +4446,15 @@ gimplify_type_sizes (tree type, tree *list_p) ...@@ -4454,7 +4446,15 @@ gimplify_type_sizes (tree type, tree *list_p)
case QUAL_UNION_TYPE: case QUAL_UNION_TYPE:
for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field)) for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
if (TREE_CODE (field) == FIELD_DECL) 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; break;
default: default:
...@@ -4470,8 +4470,6 @@ gimplify_type_sizes (tree type, tree *list_p) ...@@ -4470,8 +4470,6 @@ gimplify_type_sizes (tree type, tree *list_p)
TYPE_SIZE_UNIT (t) = TYPE_SIZE_UNIT (type); TYPE_SIZE_UNIT (t) = TYPE_SIZE_UNIT (type);
TYPE_SIZES_GIMPLIFIED (t) = 1; TYPE_SIZES_GIMPLIFIED (t) = 1;
} }
TYPE_SIZES_GIMPLIFIED (type) = 1;
} }
/* A subroutine of gimplify_type_sizes to make sure that *EXPR_P, /* A subroutine of gimplify_type_sizes to make sure that *EXPR_P,
......
2005-06-01 Jakub Jelinek <jakub@redhat.com> 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. * gcc.dg/i386-sse-12.c: New test.
PR fortran/21729 PR fortran/21729
......
/* 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;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment