aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2005-06-01 12:23:17 +0200
committerJakub Jelinek <jakub@gcc.gnu.org>2005-06-01 12:23:17 +0200
commit8e0a600bdd9dee1b4eb8f3e5ce840e76fdabf133 (patch)
tree1a35e9a58e4b8b378d4be62b9e9b73130ac4300b
parentdcd25113c6c37534621934617f07776b9212ef33 (diff)
downloadgcc-8e0a600bdd9dee1b4eb8f3e5ce840e76fdabf133.zip
gcc-8e0a600bdd9dee1b4eb8f3e5ce840e76fdabf133.tar.gz
gcc-8e0a600bdd9dee1b4eb8f3e5ce840e76fdabf133.tar.bz2
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
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/gimplify.c50
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.dg/20050527-1.c55
4 files changed, 91 insertions, 26 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 01a685a..2cc5929 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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,
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index 02da99b..853ff9d 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -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,
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index d002a61..716eae7 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
diff --git a/gcc/testsuite/gcc.dg/20050527-1.c b/gcc/testsuite/gcc.dg/20050527-1.c
new file mode 100644
index 0000000..1b32324
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/20050527-1.c
@@ -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;
+}