re PR c/21536 (C99 array of variable length use causes segmentation fault)
authorJakub Jelinek <jakub@redhat.com>
Wed, 1 Jun 2005 10:23:17 +0000 (12:23 +0200)
committerJakub Jelinek <jakub@gcc.gnu.org>
Wed, 1 Jun 2005 10:23:17 +0000 (12:23 +0200)
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

gcc/ChangeLog
gcc/gimplify.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/20050527-1.c [new file with mode: 0644]

index 01a685a22a1266e1033b21f6fded939b9f83ccbe..2cc5929837199e2a2b032fee24740640b2efb167 100644 (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,
index 02da99b5672259cb51e17989add217e97f200d48..853ff9db57bc9656521b31aa3bed5e3194d2ea7a 100644 (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,
index d002a6127505c24a5b309b9dfc92b87e47b68d9c..716eae7cfd2554baa958f8b5a95e5bfb5f92aae6 100644 (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
diff --git a/gcc/testsuite/gcc.dg/20050527-1.c b/gcc/testsuite/gcc.dg/20050527-1.c
new file mode 100644 (file)
index 0000000..1b32324
--- /dev/null
@@ -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;
+}