c-decl.c (finish_decl): Make a decl_stmt for a variable-sized TYPE_DECL.
authorRichard Kenner <kenner@vlsi1.ultra.nyu.edu>
Mon, 12 Apr 2004 21:25:55 +0000 (21:25 +0000)
committerRichard Kenner <kenner@gcc.gnu.org>
Mon, 12 Apr 2004 21:25:55 +0000 (17:25 -0400)
* c-decl.c (finish_decl): Make a decl_stmt for a variable-sized
TYPE_DECL.
* c-semantics.c (genrtl_decl_stmt): Handle TYPE_DECL.
* stmt.c (expand_decl): Remove redundant expansion of TYPE_DOMAIN.
* stor-layout.c (variable_size): Don't check for MINUS_EXPR.
Use skip_simple_arithmetic to find SAVE_EXPR.
(force_type_save_exprs, force_type_save_exprs_1): New functions.
* tree-inline.c (remap_type, case POINTER_TYPE, case REFERENCE_TYPE):
Properly chain multiple pointers.
(copy_tree_r): Copy a TYPE_DECL.
* tree.c (variably_modified_type_p): Add some missing tests and
make some other minor changes.
* tree.h (force_type_save_exprs): New declaration.
* gcc.c-torture/execute/20040411-1.c: New test.

From-SVN: r80629

gcc/ChangeLog
gcc/c-decl.c
gcc/c-semantics.c
gcc/stmt.c
gcc/stor-layout.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/execute/20040411-1.c [new file with mode: 0644]
gcc/tree-inline.c
gcc/tree.c
gcc/tree.h

index ac9f0c9fef2385e3d904eaa1d2658f547575fcc0..72ec5b5eb423baf5b565fce90a0b0ec8d4d6caa3 100644 (file)
@@ -1,3 +1,19 @@
+2004-04-12  Richard Kenner  <kenner@vlsi1.ultra.nyu.edu>
+
+       * c-decl.c (finish_decl): Make a decl_stmt for a variable-sized
+       TYPE_DECL.
+       * c-semantics.c (genrtl_decl_stmt): Handle TYPE_DECL.
+       * stmt.c (expand_decl): Remove redundant expansion of TYPE_DOMAIN.
+       * stor-layout.c (variable_size): Don't check for MINUS_EXPR.
+       Use skip_simple_arithmetic to find SAVE_EXPR.
+       (force_type_save_exprs, force_type_save_exprs_1): New functions.
+       * tree-inline.c (remap_type, case POINTER_TYPE, case REFERENCE_TYPE):
+       Properly chain multiple pointers.
+       (copy_tree_r): Copy a TYPE_DECL.
+       * tree.c (variably_modified_type_p): Add some missing tests and
+       make some other minor changes.
+       * tree.h (force_type_save_exprs): New declaration.
+
 2004-04-12  Roger Sayle  <roger@eyesopen.com>
 
        * simplify-rtx.c (simplify_binary_operation) <UDIV, DIV, UMOD, MOD>:
index de96be380305c5cf363aeebc1abd4541a7180b61..8f1964717dab11d7cc16a8b152338bc014fe3ad9 100644 (file)
@@ -2979,7 +2979,13 @@ finish_decl (tree decl, tree init, tree asmspec_tree)
     mark_referenced (DECL_ASSEMBLER_NAME (decl));
 
   if (TREE_CODE (decl) == TYPE_DECL)
-    rest_of_decl_compilation (decl, NULL, DECL_FILE_SCOPE_P (decl), 0);
+    {
+      if (!DECL_FILE_SCOPE_P (decl)
+         && variably_modified_type_p (TREE_TYPE (decl)))
+       add_decl_stmt (decl);
+
+      rest_of_decl_compilation (decl, NULL, DECL_FILE_SCOPE_P (decl), 0);
+    }
 
   /* At the end of a declaration, throw away any variable type sizes
      of types defined inside that declaration.  There is no use
index 17a301cffffe9b363b0bae3bca37a603bb3d5a86..a8693f9b3f1a62609e3d073d8dced35d60a811c1 100644 (file)
@@ -389,6 +389,8 @@ genrtl_decl_stmt (tree t)
   else if (TREE_CODE (decl) == LABEL_DECL
           && C_DECLARED_LABEL_FLAG (decl))
     declare_nonlocal_label (decl);
+  else if (TREE_CODE (decl) == TYPE_DECL)
+    force_type_save_exprs (TREE_TYPE (decl));
   else if (lang_expand_decl_stmt)
     (*lang_expand_decl_stmt) (t);
 }
index aee574441952ab627d856f8ccf2630892f454eca..422fd054491a0114cacca40bfd9319b25fee572f 100644 (file)
@@ -4013,13 +4013,8 @@ expand_decl (tree decl)
       do_pending_stack_adjust ();
       save_stack_pointer ();
 
-      /* In function-at-a-time mode, variable_size doesn't expand this,
-        so do it now.  */
-      if (TREE_CODE (type) == ARRAY_TYPE && TYPE_DOMAIN (type))
-       expand_expr (TYPE_MAX_VALUE (TYPE_DOMAIN (type)),
-                    const0_rtx, VOIDmode, 0);
-
-      /* Compute the variable's size, in bytes.  */
+      /* Compute the variable's size, in bytes.  This will expand any
+        needed SAVE_EXPRs for the first time.  */
       size = expand_expr (DECL_SIZE_UNIT (decl), NULL_RTX, VOIDmode, 0);
       free_temp_slots ();
 
index 2baa36432a4d878800d6de173c2fb2e448caa0c0..d19fc9fdf3fb63a6700f277b8f04969b878e53b4 100644 (file)
@@ -66,6 +66,7 @@ static void place_union_field (record_layout_info, tree);
 static int excess_unit_span (HOST_WIDE_INT, HOST_WIDE_INT, HOST_WIDE_INT,
                             HOST_WIDE_INT, tree);
 #endif
+static void force_type_save_exprs_1 (tree);
 static unsigned int update_alignment_for_field (record_layout_info, tree,
                                                unsigned int);
 extern void debug_rli (record_layout_info);
@@ -146,12 +147,7 @@ variable_size (tree size)
       || CONTAINS_PLACEHOLDER_P (size))
     return size;
 
-  if (TREE_CODE (size) == MINUS_EXPR && integer_onep (TREE_OPERAND (size, 1)))
-    /* If this is the upper bound of a C array, leave the minus 1 outside
-       the SAVE_EXPR so it can be folded away.  */
-    TREE_OPERAND (size, 0) = save = save_expr (TREE_OPERAND (size, 0));
-  else
-    size = save = save_expr (size);
+  size = save_expr (size);
 
   /* If an array with a variable number of elements is declared, and
      the elements require destruction, we will emit a cleanup for the
@@ -161,6 +157,7 @@ variable_size (tree size)
      `unsaved', i.e., all SAVE_EXPRs are recalculated.  However, we do
      not wish to do that here; the array-size is the same in both
      places.  */
+  save = skip_simple_arithmetic (size);
   if (TREE_CODE (save) == SAVE_EXPR)
     SAVE_EXPR_PERSISTENT_P (save) = 1;
 
@@ -185,6 +182,60 @@ variable_size (tree size)
 
   return size;
 }
+
+/* Given a type T, force elaboration of any SAVE_EXPRs used in the definition
+   of that type.  */
+
+void
+force_type_save_exprs (tree t)
+{
+  tree field;
+
+  switch (TREE_CODE (t))
+    {
+    case ERROR_MARK:
+      return;
+
+    case ARRAY_TYPE:
+    case SET_TYPE:
+    case VECTOR_TYPE:
+      /* It's probably overly-conservative to force elaboration of bounds and
+        also the sizes, but it's better to be safe than sorry.  */
+      force_type_save_exprs_1 (TYPE_MIN_VALUE (TYPE_DOMAIN (t)));
+      force_type_save_exprs_1 (TYPE_MAX_VALUE (TYPE_DOMAIN (t)));
+      break;
+
+    case RECORD_TYPE:
+    case UNION_TYPE:
+    case QUAL_UNION_TYPE:
+      for (field = TYPE_FIELDS (t); field; field = TREE_CHAIN (field))
+       if (TREE_CODE (field) == FIELD_DECL)
+         {
+           force_type_save_exprs (TREE_TYPE (field));
+           force_type_save_exprs_1 (DECL_FIELD_OFFSET (field));
+         }
+      break;
+
+    default:
+      break;
+    }
+
+  force_type_save_exprs_1 (TYPE_SIZE (t));
+  force_type_save_exprs_1 (TYPE_SIZE_UNIT (t));
+}
+
+/* Utility routine of above, to verify that SIZE has been elaborated and
+   do so it it is a SAVE_EXPR and has not been.  */
+
+static void
+force_type_save_exprs_1 (tree size)
+{
+  if (size
+      && (size = skip_simple_arithmetic (size))
+      && TREE_CODE (size) == SAVE_EXPR
+      && !SAVE_EXPR_RTL (size))
+    expand_expr (size, NULL_RTX, VOIDmode, 0);
+}
 \f
 #ifndef MAX_FIXED_MODE_SIZE
 #define MAX_FIXED_MODE_SIZE GET_MODE_BITSIZE (DImode)
index 040aac8a716d28c391d5d162413b7671dbf474b8..df7d2e1448d31d042321fc5ea719a3367283f15c 100644 (file)
@@ -1,3 +1,7 @@
+2004-04-12  Richard Kenner  <kenner@vlsi1.ultra.nyu.edu>
+
+       * gcc.c-torture/execute/20040411-1.c: New test.
+
 2004-04-10  Joseph S. Myers  <jsm@polyomino.org.uk>
 
        * gcc.dg/c90-intprom-1.c, gcc.dg/c99-intprom-1.c: New tests.
diff --git a/gcc/testsuite/gcc.c-torture/execute/20040411-1.c b/gcc/testsuite/gcc.c-torture/execute/20040411-1.c
new file mode 100644 (file)
index 0000000..8db4562
--- /dev/null
@@ -0,0 +1,23 @@
+int
+sub1 (int i, int j)
+{
+  typedef int c[i+2];
+  int x[10], y[10];
+
+  if (j == 2)
+    {
+      memcpy (x, y, 10 * sizeof (int));
+      return sizeof (c);
+    }
+  else
+    return sizeof (c) * 3;
+}
+
+int
+main ()
+{
+  if (sub1 (20, 3) != 66 * sizeof (int))
+    abort ();
+
+  return 0;
+}
index d9aeefe14dbca1c628e633e39b33cadb815de183..622ae18a5487447360ed69c9578a03df1ed19468 100644 (file)
@@ -271,6 +271,7 @@ remap_type (tree type, inline_data *id)
       t = TYPE_MIN_VALUE (new);
       if (t && TREE_CODE (t) != INTEGER_CST)
         walk_tree (&TYPE_MIN_VALUE (new), copy_body_r, id, NULL);
+
       t = TYPE_MAX_VALUE (new);
       if (t && TREE_CODE (t) != INTEGER_CST)
         walk_tree (&TYPE_MAX_VALUE (new), copy_body_r, id, NULL);
@@ -278,14 +279,14 @@ remap_type (tree type, inline_data *id)
     
     case POINTER_TYPE:
       TREE_TYPE (new) = t = remap_type (TREE_TYPE (new), id);
-      if (TYPE_MODE (new) == ptr_mode)
-        TYPE_POINTER_TO (t) = new;
+      TYPE_NEXT_PTR_TO (new) = TYPE_POINTER_TO (t);
+      TYPE_POINTER_TO (t) = new;
       return new;
 
     case REFERENCE_TYPE:
       TREE_TYPE (new) = t = remap_type (TREE_TYPE (new), id);
-      if (TYPE_MODE (new) == ptr_mode)
-        TYPE_REFERENCE_TO (t) = new;
+      TYPE_NEXT_REF_TO (new) = TYPE_REFERENCE_TO (t);
+      TYPE_REFERENCE_TO (t) = new;
       return new;
 
     case METHOD_TYPE:
@@ -2082,6 +2083,7 @@ copy_tree_r (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
       || TREE_CODE_CLASS (code) == 'c'
       || code == TREE_LIST
       || code == TREE_VEC
+      || code == TYPE_DECL
       || lang_hooks.tree_inlining.tree_chain_matters_p (*tp))
     {
       /* Because the chain gets clobbered when we make a copy, we save it
index d4dd3fe1a8a234124ca083fd104cf27655ab7e54..0b301e2bb38f26b03fffd24abebf829b341fdea4 100644 (file)
@@ -4629,38 +4629,62 @@ variably_modified_type_p (tree type)
     case POINTER_TYPE:
     case REFERENCE_TYPE:
     case ARRAY_TYPE:
-      /* If TYPE is a pointer or reference, it is variably modified if
-        the type pointed to is variably modified.  Similarly for arrays;
-        note that VLAs are handled by the TYPE_SIZE check above.  */
-      return variably_modified_type_p (TREE_TYPE (type));
+    case SET_TYPE:
+    case VECTOR_TYPE:
+      if (variably_modified_type_p (TREE_TYPE (type)))
+       return true;
+      break;
 
     case FUNCTION_TYPE:
     case METHOD_TYPE:
       /* If TYPE is a function type, it is variably modified if any of the
          parameters or the return type are variably modified.  */
-      {
-       tree parm;
+      if (variably_modified_type_p (TREE_TYPE (type)))
+         return true;
 
-       if (variably_modified_type_p (TREE_TYPE (type)))
+      for (t = TYPE_ARG_TYPES (type);
+          t && t != void_list_node;
+          t = TREE_CHAIN (t))
+       if (variably_modified_type_p (TREE_VALUE (t)))
          return true;
-       for (parm = TYPE_ARG_TYPES (type);
-            parm && parm != void_list_node;
-            parm = TREE_CHAIN (parm))
-         if (variably_modified_type_p (TREE_VALUE (parm)))
-           return true;
-      }
       break;
 
     case INTEGER_TYPE:
+    case REAL_TYPE:
+    case ENUMERAL_TYPE:
+    case BOOLEAN_TYPE:
+    case CHAR_TYPE:
       /* Scalar types are variably modified if their end points
         aren't constant.  */
       t = TYPE_MIN_VALUE (type);
       if (t && t != error_mark_node && TREE_CODE (t) != INTEGER_CST)
        return true;
+
       t = TYPE_MAX_VALUE (type);
       if (t && t != error_mark_node && TREE_CODE (t) != INTEGER_CST)
        return true;
-      return false;
+      break;
+
+    case RECORD_TYPE:
+    case UNION_TYPE:
+    case QUAL_UNION_TYPE:
+      /* We can't see if any of the field are variably-modified by the
+        definition we normally use, since that would produce infinite
+        recursion via pointers.  */
+      /* This is variably modified if some field's type is.  */
+      for (t = TYPE_FIELDS (type); t; t = TREE_CHAIN (t))
+       if (TREE_CODE (t) == FIELD_DECL)
+         {
+           tree t1 = DECL_FIELD_OFFSET (t);
+
+           if (t1 && t1 != error_mark_node && TREE_CODE (t1) != INTEGER_CST)
+             return true;
+
+           t1 = DECL_SIZE (t);
+           if (t1 && t1 != error_mark_node && TREE_CODE (t1) != INTEGER_CST)
+             return true;
+         }
+       break;
 
     default:
       break;
index 34e6f45f4f2c77ff3b47d4191f4e0cb8a95f4d85..12dec421f671982ba258d5c049b174f947aadeca 100644 (file)
@@ -2768,6 +2768,11 @@ extern tree substitute_placeholder_in_expr (tree, tree);
 
 extern tree variable_size (tree);
 
+/* Given a type T, force elaboration of any SAVE_EXPRs used in the definition
+   of that type.  */
+
+extern void force_type_save_exprs (tree);
+
 /* stabilize_reference (EXP) returns a reference equivalent to EXP
    but it can be used multiple times
    and only evaluate the subexpressions once.  */