re PR middle-end/18191 (Struct member is not getting default-initialized)
authorSteven Bosscher <stevenb@suse.de>
Mon, 20 Dec 2004 11:26:47 +0000 (11:26 +0000)
committerSteven Bosscher <steven@gcc.gnu.org>
Mon, 20 Dec 2004 11:26:47 +0000 (11:26 +0000)
gcc/
PR middle-end/18191
PR middle-end/18965
PR middle-end/18999
* expr.c (categorize_ctor_elements_1): Count the total number
of elements in the constructor.
(categorize_ctor_elements): Return it in a new argument.
* tree.h (categorize_ctor_elements): Adjust prototype.
* gimplify.c (gimplify_init_ctor_eval_range): New.
(gimplify_init_ctor_eval): Gimplify RANGE_EXPR.
(gimplify_init_constructor): Block clear the object if the
constructor has fewer elements than the object type.  Only try
to add assignments to individual elements when we have to.

testsuite/
 * gcc.dg/20041219-1.c: New test.

Co-Authored-By: Andrew Pinski <pinskia@physics.uc.edu>
From-SVN: r92415

gcc/ChangeLog
gcc/expr.c
gcc/gimplify.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/20041219-1.c [new file with mode: 0644]
gcc/tree.h

index c3ff588777bed9bd19f7d6c69d5614e4803efb45..b8876afdfab252c7e787acd4c5dead9249316ab3 100644 (file)
@@ -1,3 +1,19 @@
+2004-12-20  Steven Bosscher  <stevenb@suse.de>
+           Andrew Pinski  <pinskia@physics.uc.edu>
+
+       PR middle-end/18191
+       PR middle-end/18965
+       PR middle-end/18999
+       * expr.c (categorize_ctor_elements_1): Count the total number
+       of elements in the constructor.
+       (categorize_ctor_elements): Return it in a new argument.
+       * tree.h (categorize_ctor_elements): Adjust prototype.
+       * gimplify.c (gimplify_init_ctor_eval_range): New.
+       (gimplify_init_ctor_eval): Gimplify RANGE_EXPR.
+       (gimplify_init_constructor): Block clear the object if the
+       constructor has fewer elements than the object type.  Only try
+       to add assignments to individual elements when we have to.
+
 2004-12-20  Richard Henderson  <rth@redhat.com>
 
        * config/i386/i386.c (ix86_init_mmx_sse_builtins): Use 
index 2581c150dba95a76c6f30012e25e5ff2250da4e3..de11afffe3f06e0d489d90cb63d681dc5ad293ca 100644 (file)
@@ -4220,19 +4220,25 @@ store_expr (tree exp, rtx target, int call_param_p)
   return NULL_RTX;
 }
 \f
-/* Examine CTOR.  Discover how many scalar fields are set to nonzero
-   values and place it in *P_NZ_ELTS.  Discover how many scalar fields
-   are set to non-constant values and place it in  *P_NC_ELTS.  */
+/* Examine CTOR to discover:
+   * how many scalar fields are set to nonzero values,
+     and place it in *P_NZ_ELTS;
+   * how many scalar fields are set to non-constant values,
+     and place it in  *P_NC_ELTS; and
+   * how many scalar fields in total are in CTOR,
+     and place it in *P_ELT_COUNT.  */
 
 static void
 categorize_ctor_elements_1 (tree ctor, HOST_WIDE_INT *p_nz_elts,
-                           HOST_WIDE_INT *p_nc_elts)
+                           HOST_WIDE_INT *p_nc_elts,
+                           HOST_WIDE_INT *p_elt_count)
 {
-  HOST_WIDE_INT nz_elts, nc_elts;
+  HOST_WIDE_INT nz_elts, nc_elts, elt_count;
   tree list;
 
   nz_elts = 0;
   nc_elts = 0;
+  elt_count = 0;
 
   for (list = CONSTRUCTOR_ELTS (ctor); list; list = TREE_CHAIN (list))
     {
@@ -4255,10 +4261,11 @@ categorize_ctor_elements_1 (tree ctor, HOST_WIDE_INT *p_nz_elts,
        {
        case CONSTRUCTOR:
          {
-           HOST_WIDE_INT nz = 0, nc = 0;
-           categorize_ctor_elements_1 (value, &nz, &nc);
+           HOST_WIDE_INT nz = 0, nc = 0, count = 0;
+           categorize_ctor_elements_1 (value, &nz, &nc, &count);
            nz_elts += mult * nz;
            nc_elts += mult * nc;
+           elt_count += mult * count;
          }
          break;
 
@@ -4266,10 +4273,12 @@ categorize_ctor_elements_1 (tree ctor, HOST_WIDE_INT *p_nz_elts,
        case REAL_CST:
          if (!initializer_zerop (value))
            nz_elts += mult;
+         elt_count += mult;
          break;
 
        case STRING_CST:
          nz_elts += mult * TREE_STRING_LENGTH (value);
+         elt_count += mult * TREE_STRING_LENGTH (value);
          break;
 
        case COMPLEX_CST:
@@ -4277,19 +4286,24 @@ categorize_ctor_elements_1 (tree ctor, HOST_WIDE_INT *p_nz_elts,
            nz_elts += mult;
          if (!initializer_zerop (TREE_IMAGPART (value)))
            nz_elts += mult;
+         elt_count += mult;
          break;
 
        case VECTOR_CST:
          {
            tree v;
            for (v = TREE_VECTOR_CST_ELTS (value); v; v = TREE_CHAIN (v))
-             if (!initializer_zerop (TREE_VALUE (v)))
-               nz_elts += mult;
+             {
+               if (!initializer_zerop (TREE_VALUE (v)))
+                 nz_elts += mult;
+               elt_count += mult;
+             }
          }
          break;
 
        default:
          nz_elts += mult;
+         elt_count += mult;
          if (!initializer_constant_valid_p (value, TREE_TYPE (value)))
            nc_elts += mult;
          break;
@@ -4298,15 +4312,18 @@ categorize_ctor_elements_1 (tree ctor, HOST_WIDE_INT *p_nz_elts,
 
   *p_nz_elts += nz_elts;
   *p_nc_elts += nc_elts;
+  *p_elt_count += elt_count;
 }
 
 void
 categorize_ctor_elements (tree ctor, HOST_WIDE_INT *p_nz_elts,
-                         HOST_WIDE_INT *p_nc_elts)
+                         HOST_WIDE_INT *p_nc_elts,
+                         HOST_WIDE_INT *p_elt_count)
 {
   *p_nz_elts = 0;
   *p_nc_elts = 0;
-  categorize_ctor_elements_1 (ctor, p_nz_elts, p_nc_elts);
+  *p_elt_count = 0;
+  categorize_ctor_elements_1 (ctor, p_nz_elts, p_nc_elts, p_elt_count);
 }
 
 /* Count the number of scalars in TYPE.  Return -1 on overflow or
@@ -4395,9 +4412,9 @@ mostly_zeros_p (tree exp)
   if (TREE_CODE (exp) == CONSTRUCTOR)
 
     {
-      HOST_WIDE_INT nz_elts, nc_elts, elts;
+      HOST_WIDE_INT nz_elts, nc_elts, count, elts;
 
-      categorize_ctor_elements (exp, &nz_elts, &nc_elts);
+      categorize_ctor_elements (exp, &nz_elts, &nc_elts, &count);
       elts = count_type_elements (TREE_TYPE (exp));
 
       return nz_elts < elts / 4;
index 55889ea9dcceb0bc0fa5373bfb027362980c7cba..34b22cc678175b70d83980868993afc1e20ab03a 100644 (file)
@@ -2367,6 +2367,95 @@ gimplify_init_ctor_preeval (tree *expr_p, tree *pre_p, tree *post_p,
   *expr_p = get_formal_tmp_var (*expr_p, pre_p);
 }
 
+/* A subroutine of gimplify_init_ctor_eval.  Create a loop for
+   a RANGE_EXPR in a CONSTRUCTOR for an array.
+
+      var = lower;
+    loop_entry:
+      object[var] = value;
+      if (var == upper)
+       goto loop_exit;
+      var = var + 1;
+      goto loop_entry;
+    loop_exit:
+
+   We increment var _after_ the loop exit check because we might otherwise
+   fail if upper == TYPE_MAX_VALUE (type for upper).
+
+   Note that we never have to deal with SAVE_EXPRs here, because this has
+   already been taken care of for us, in gimplify_init_ctor_preeval().  */
+
+static void gimplify_init_ctor_eval (tree, tree, tree *, bool);
+
+static void
+gimplify_init_ctor_eval_range (tree object, tree lower, tree upper,
+                              tree value, tree array_elt_type,
+                              tree *pre_p, bool cleared)
+{
+  tree loop_entry_label, loop_exit_label;
+  tree var, var_type, cref;
+
+  loop_entry_label = create_artificial_label ();
+  loop_exit_label = create_artificial_label ();
+
+  /* Create and initialize the index variable.  */
+  var_type = TREE_TYPE (upper);
+  var = create_tmp_var (var_type, NULL);
+  append_to_statement_list (build2 (MODIFY_EXPR, var_type, var, lower), pre_p);
+
+  /* Add the loop entry label.  */
+  append_to_statement_list (build1 (LABEL_EXPR,
+                                   void_type_node,
+                                   loop_entry_label),
+                           pre_p);
+
+  /* Build the reference.  */
+  cref = build4 (ARRAY_REF, array_elt_type, unshare_expr (object),
+                var, NULL_TREE, NULL_TREE);
+
+  /* If we are a constructor, just call gimplify_init_ctor_eval to do
+     the store.  Otherwise just assign value to the reference.  */
+
+  if (TREE_CODE (value) == CONSTRUCTOR)
+    /* NB we might have to call ourself recursively through
+       gimplify_init_ctor_eval if the value is a constructor.  */
+    gimplify_init_ctor_eval (cref, CONSTRUCTOR_ELTS (value),
+                            pre_p, cleared);
+  else
+    append_to_statement_list (build2 (MODIFY_EXPR, TREE_TYPE (cref),
+                                     cref, value),
+                             pre_p);
+
+  /* We exit the loop when the index var is equal to the upper bound.  */
+  gimplify_and_add (build3 (COND_EXPR, void_type_node,
+                           build2 (EQ_EXPR, boolean_type_node,
+                                   var, upper),
+                           build1 (GOTO_EXPR,
+                                   void_type_node,
+                                   loop_exit_label),
+                           NULL_TREE),
+                   pre_p);
+
+  /* Otherwise, increment the index var...  */
+  append_to_statement_list (build2 (MODIFY_EXPR, var_type, var,
+                                   build2 (PLUS_EXPR, var_type, var,
+                                           fold_convert (var_type,
+                                                         integer_one_node))),
+                           pre_p);
+
+  /* ...and jump back to the loop entry.  */
+  append_to_statement_list (build1 (GOTO_EXPR,
+                                   void_type_node,
+                                   loop_entry_label),
+                           pre_p);
+
+  /* Add the loop exit label.  */
+  append_to_statement_list (build1 (LABEL_EXPR,
+                                   void_type_node,
+                                   loop_exit_label),
+                           pre_p);
+}
+
 /* A subroutine of gimplify_init_constructor.  Generate individual
    MODIFY_EXPRs for a CONSTRUCTOR.  OBJECT is the LHS against which the
    assignments should happen.  LIST is the CONSTRUCTOR_ELTS of the
@@ -2395,14 +2484,31 @@ gimplify_init_ctor_eval (tree object, tree list, tree *pre_p, bool cleared)
       if (cleared && initializer_zerop (value))
        continue;
 
-      if (array_elt_type)
+      /* ??? Here's to hoping the front end fills in all of the indices,
+        so we don't have to figure out what's missing ourselves.  */
+      gcc_assert (purpose);
+
+      /* If we have a RANGE_EXPR, we have to build a loop to assign the
+        whole range.  */
+      if (TREE_CODE (purpose) == RANGE_EXPR)
        {
-         /* ??? Here's to hoping the front end fills in all of the indicies,
-            so we don't have to figure out what's missing ourselves.  */
-         gcc_assert (purpose);
-         /* ??? Need to handle this.  */
-         gcc_assert (TREE_CODE (purpose) != RANGE_EXPR);
+         tree lower = TREE_OPERAND (purpose, 0);
+         tree upper = TREE_OPERAND (purpose, 1);
+
+         /* If the lower bound is equal to upper, just treat it as if
+            upper was the index.  */
+         if (simple_cst_equal (lower, upper))
+           purpose = upper;
+         else
+           {
+             gimplify_init_ctor_eval_range (object, lower, upper, value,
+                                            array_elt_type, pre_p, cleared);
+             continue;
+           }
+       }
 
+      if (array_elt_type)
+       {
          cref = build (ARRAY_REF, array_elt_type, unshare_expr (object),
                        purpose, NULL_TREE, NULL_TREE);
        }
@@ -2458,8 +2564,8 @@ gimplify_init_constructor (tree *expr_p, tree *pre_p,
     case ARRAY_TYPE:
       {
        struct gimplify_init_ctor_preeval_data preeval_data;
-       HOST_WIDE_INT num_elements, num_nonzero_elements;
-       HOST_WIDE_INT num_nonconstant_elements;
+       HOST_WIDE_INT num_type_elements, num_ctor_elements;
+       HOST_WIDE_INT num_nonzero_elements, num_nonconstant_elements;
        bool cleared;
 
        /* Aggregate types must lower constructors to initialization of
@@ -2469,7 +2575,8 @@ gimplify_init_constructor (tree *expr_p, tree *pre_p,
          break;
 
        categorize_ctor_elements (ctor, &num_nonzero_elements,
-                                 &num_nonconstant_elements);
+                                 &num_nonconstant_elements,
+                                 &num_ctor_elements);
 
        /* If a const aggregate variable is being initialized, then it
           should never be a lose to promote the variable to be static.  */
@@ -2552,12 +2659,12 @@ gimplify_init_constructor (tree *expr_p, tree *pre_p,
           parts in, then generate code for the non-constant parts.  */
        /* TODO.  There's code in cp/typeck.c to do this.  */
 
-       num_elements = count_type_elements (TREE_TYPE (ctor));
+       num_type_elements = count_type_elements (TREE_TYPE (ctor));
 
        /* If there are "lots" of zeros, then block clear the object first.  */
        cleared = false;
-       if (num_elements - num_nonzero_elements > CLEAR_RATIO
-           && num_nonzero_elements < num_elements/4)
+       if (num_type_elements - num_nonzero_elements > CLEAR_RATIO
+           && num_nonzero_elements < num_type_elements/4)
          cleared = true;
 
        /* ??? This bit ought not be needed.  For any element not present
@@ -2565,19 +2672,8 @@ gimplify_init_constructor (tree *expr_p, tree *pre_p,
           we'd need to *find* the elements that are not present, and that
           requires trickery to avoid quadratic compile-time behavior in
           large cases or excessive memory use in small cases.  */
-       else
-         {
-           HOST_WIDE_INT len = list_length (elt_list);
-           if (TREE_CODE (type) == ARRAY_TYPE)
-             {
-               tree nelts = array_type_nelts (type);
-               if (!host_integerp (nelts, 1)
-                   || tree_low_cst (nelts, 1) + 1 != len)
-                 cleared = true;
-             }
-           else if (len != fields_length (type))
-             cleared = true;
-         }
+       else if (num_ctor_elements < num_type_elements)
+         cleared = true;
 
        if (cleared)
          {
@@ -2590,14 +2686,20 @@ gimplify_init_constructor (tree *expr_p, tree *pre_p,
            append_to_statement_list (*expr_p, pre_p);
          }
 
-       preeval_data.lhs_base_decl = get_base_address (object);
-       if (!DECL_P (preeval_data.lhs_base_decl))
-         preeval_data.lhs_base_decl = NULL;
-       preeval_data.lhs_alias_set = get_alias_set (object);
-
-       gimplify_init_ctor_preeval (&TREE_OPERAND (*expr_p, 1),
-                                   pre_p, post_p, &preeval_data);
-       gimplify_init_ctor_eval (object, elt_list, pre_p, cleared);
+       /* If we have not block cleared the object, or if there are nonzero
+          elements in the constructor, add assignments to the individual
+          scalar fields of the object.  */
+       if (!cleared || num_nonzero_elements > 0)
+         {
+           preeval_data.lhs_base_decl = get_base_address (object);
+           if (!DECL_P (preeval_data.lhs_base_decl))
+             preeval_data.lhs_base_decl = NULL;
+           preeval_data.lhs_alias_set = get_alias_set (object);
+
+           gimplify_init_ctor_preeval (&TREE_OPERAND (*expr_p, 1),
+                                       pre_p, post_p, &preeval_data);
+           gimplify_init_ctor_eval (object, elt_list, pre_p, cleared);
+         }
 
        *expr_p = NULL_TREE;
       }
index 2de4305e81778cf64aebb39f193f055f93473f23..c1c21c400ab9ab487a4e01a08582d225aa41e163 100644 (file)
@@ -1,3 +1,7 @@
+2004-12-20  Steven Bosscher  <stevenb@suse.de>
+
+       * gcc.dg/20041219-1.c: New test.
+
 2004-12-19  Roger Sayle  <roger@eyesopen.com>
 
        PR middle-end/19068
diff --git a/gcc/testsuite/gcc.dg/20041219-1.c b/gcc/testsuite/gcc.dg/20041219-1.c
new file mode 100644 (file)
index 0000000..4fdc954
--- /dev/null
@@ -0,0 +1,47 @@
+/* PR18191 Struct member is not getting default-initialized.
+   Origin: Grigory Zagorodnev  <grigory.zagorodnev@intel.com>  */
+
+/* { dg-do run } */
+
+extern int printf (__const char *__restrict __format, ...);
+
+typedef struct S {
+  const char* s;
+  int         i;
+} S;
+
+void
+foo (void)
+{
+  S dummy[2];
+  unsigned i;
+
+  /* Put some garbage on the stack.  */
+  for (i = 0; i < sizeof(dummy); i++)
+    ((char *)&dummy)[i] = -1;
+}
+
+int
+bar (void)
+{
+  /* Allocate object on the stack.  */
+  S obj[2] = { {"m0"}, {"m1"} };
+
+  /* Assume fields those not explicitly initialized
+     are default initialized to 0 [8.5.1/7 and 8.5/5].  */
+  if (obj[0].i == 0)
+    return 0;
+  else
+    {
+      printf("Failed: obj[0].i == '%d', expecting '0'\n", obj[0].i);
+      return 1;
+    }
+}
+
+int
+main (void)
+{
+  foo();
+  return bar();
+}
+
index fa328bedad2ce68fd3ef4fbd3e5ce1310fa730c1..90d17e5cc41ce992d3064a37588534ddf74fda9d 100644 (file)
@@ -3226,7 +3226,8 @@ extern int fields_length (tree);
 
 extern bool initializer_zerop (tree);
 
-extern void categorize_ctor_elements (tree, HOST_WIDE_INT *, HOST_WIDE_INT *);
+extern void categorize_ctor_elements (tree, HOST_WIDE_INT *,
+                                     HOST_WIDE_INT *, HOST_WIDE_INT *);
 extern HOST_WIDE_INT count_type_elements (tree);
 
 /* add_var_to_bind_expr (bind_expr, var) binds var to bind_expr.  */