This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[RFC] gimplification of types (PR c/21536)


Hi!

PR c/21536 fails because gimplify_type_sizes is only called
on variable sized types of variables, but not e.g. if
a variable has a type pointer to a variable sized type.
This means that the SAVE_EXPR's in those types stay accross
gimplification, and what's worse, in the testcase in the
patch below the SAVE_EXPR (which is shared between the type's
size/unit_size and several ARRAY_REFs) is resolved not in the
place where the type is defined (and mentions the SAVE_EXPR
first), but one place where the ARRAY_REF is used, at which place
x (resp. y) might contain already a different value and/or might
not dominate all the ARRAY_REFs that use the SAVE_EXPR.

The patch below fixes this exact testcase, but unfortunately
other testcases can be created that are still broken, such as:
/* PR c/21536 */
/* { dg-do compile } */
/* { dg-options "-O2 -Wuninitialized" } */

typedef __SIZE_TYPE__ size_t;
extern void *malloc (size_t);

void
foo (int x, int y)
{
  void *d = malloc (10 * 10 * sizeof (double));
  struct S
    {
      double (*e)[x][y];
    } s;
  s.e = 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;
}

int
main ()
{
  foo (10, 10);
  return 0;
}

gimplify_decl_expr contains a comment:
          /* ??? 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);
but the only other places that call gimplify_type_sizes are
gimplify_decl_expr for TYPE_DECLs (which apparently don't appear among the
DECL_EXPRs at least on the testcases I have tried so far) and gimplify_parm_type
(which is only for parameters).
So, I guess gimplify_type_sizes needs to be enhanced (as in the patch below
plus e.g. do the same on aggregate fields etc., wouldn't using walk_tree
be the safest solution here?) plus either we need to simply call gimplify_type_sizes
at least on all DECL_EXPRs types, but maybe even on all types gimplify_expr sees,
or the frontends would need to guarantee that for all types with some variable
TYPE_SIZE reachable from the type there would be a DECL_EXPR with TYPE_DECL
right before the first use of such type.
What's your preference?

	* 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.

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

--- gcc/gimplify.c.jj	2005-05-06 09:58:27.000000000 +0200
+++ gcc/gimplify.c	2005-05-27 19:17:19.000000000 +0200
@@ -1029,6 +1029,18 @@ gimplify_decl_expr (tree *stmt_p)
 	     enclosing BIND_EXPR is exited.  */
 	  gimplify_ctxp->save_stack = true;
 	}
+      else if (POINTER_TYPE_P (TREE_TYPE (decl)))
+	{
+	  tree type;
+	  for (type = TREE_TYPE (TREE_TYPE (decl));
+	       POINTER_TYPE_P (type);
+	       type = TREE_TYPE (type))
+	    ;
+	  if (TYPE_SIZE (type)
+	      && !TREE_CONSTANT (TYPE_SIZE (type))
+	      && !TYPE_SIZES_GIMPLIFIED (type))
+	    gimplify_type_sizes (type, stmt_p);
+	}
 
       if (init && init != error_mark_node)
 	{
@@ -4401,6 +4413,12 @@ gimplify_type_sizes (tree type, tree *li
 	  gimplify_one_sizepos (&DECL_FIELD_OFFSET (field), list_p);
       break;
 
+    case POINTER_TYPE:
+    case REFERENCE_TYPE:
+      if (!TYPE_SIZES_GIMPLIFIED (TREE_TYPE (type)))
+	gimplify_type_sizes (TREE_TYPE (type), list_p);
+      break;
+
     default:
       break;
     }
--- gcc/testsuite/gcc.dg/20050527-1.c.jj	2005-05-27 19:22:32.000000000 +0200
+++ gcc/testsuite/gcc.dg/20050527-1.c	2005-05-27 19:01:31.000000000 +0200
@@ -0,0 +1,26 @@
+/* PR c/21536 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -Wuninitialized" } */
+
+typedef __SIZE_TYPE__ size_t;
+extern void *malloc (size_t);
+
+void
+foo (int x, int y)
+{
+  void *d = malloc (10 * 10 * 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;
+}
+
+int
+main ()
+{
+  foo (10, 10);
+  return 0;
+}

	Jakub


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]