re PR c/37303 (const compound initializers in structs are written to .data instead...
[platform/upstream/gcc.git] / gcc / gimplify.c
index 43e3518..9c58a38 100644 (file)
@@ -1003,7 +1003,7 @@ unshare_body (tree fndecl)
 
   if (cgn)
     for (cgn = cgn->nested; cgn; cgn = cgn->next_nested)
-      unshare_body (cgn->decl);
+      unshare_body (cgn->symbol.decl);
 }
 
 /* Callback for walk_tree to unmark the visited trees rooted at *TP.
@@ -1046,7 +1046,7 @@ unvisit_body (tree fndecl)
 
   if (cgn)
     for (cgn = cgn->nested; cgn; cgn = cgn->next_nested)
-      unvisit_body (cgn->decl);
+      unvisit_body (cgn->symbol.decl);
 }
 
 /* Unconditionally make an unshared copy of EXPR.  This is used when using
@@ -1575,6 +1575,9 @@ gimplify_switch_expr (tree *expr_p, gimple_seq *pre_p)
   tree switch_expr = *expr_p;
   gimple_seq switch_body_seq = NULL;
   enum gimplify_status ret;
+  tree index_type = TREE_TYPE (switch_expr);
+  if (index_type == NULL_TREE)
+    index_type = TREE_TYPE (SWITCH_COND (switch_expr));
 
   ret = gimplify_expr (&SWITCH_COND (switch_expr), pre_p, NULL, is_gimple_val,
                        fb_rvalue);
@@ -1585,6 +1588,7 @@ gimplify_switch_expr (tree *expr_p, gimple_seq *pre_p)
     {
       VEC (tree,heap) *labels;
       VEC (tree,heap) *saved_labels;
+      tree min_value, max_value;
       tree default_case = NULL_TREE;
       size_t i, len;
       gimple gimple_switch;
@@ -1593,7 +1597,7 @@ gimplify_switch_expr (tree *expr_p, gimple_seq *pre_p)
         be bothered to null out the body too.  */
       gcc_assert (!SWITCH_LABELS (switch_expr));
 
-      /* save old labels, get new ones from body, then restore the old
+      /* Save old labels, get new ones from body, then restore the old
          labels.  Save all the things from the switch body to append after.  */
       saved_labels = gimplify_ctxp->case_labels;
       gimplify_ctxp->case_labels = VEC_alloc (tree, heap, 8);
@@ -1603,18 +1607,82 @@ gimplify_switch_expr (tree *expr_p, gimple_seq *pre_p)
       gimplify_ctxp->case_labels = saved_labels;
 
       i = 0;
+      min_value = TYPE_MIN_VALUE (index_type);
+      max_value = TYPE_MAX_VALUE (index_type);
       while (i < VEC_length (tree, labels))
        {
          tree elt = VEC_index (tree, labels, i);
          tree low = CASE_LOW (elt);
+         tree high = CASE_HIGH (elt);
          bool remove_element = FALSE;
 
+
          if (low)
            {
-             /* Discard empty ranges.  */
-             tree high = CASE_HIGH (elt);
-             if (high && tree_int_cst_lt (high, low))
-               remove_element = TRUE;
+             gcc_checking_assert (TREE_CODE (low) == INTEGER_CST);
+             gcc_checking_assert (!high || TREE_CODE (high) == INTEGER_CST);
+
+             /* This is a non-default case label, i.e. it has a value.
+
+                See if the case label is reachable within the range of
+                the index type.  Remove out-of-range case values.  Turn
+                case ranges into a canonical form (high > low strictly)
+                and convert the case label values to the index type.
+
+                NB: The type of gimple_switch_index() may be the promoted
+                type, but the case labels retain the original type.  */
+
+             if (high)
+               {
+                 /* This is a case range.  Discard empty ranges.
+                    If the bounds or the range are equal, turn this
+                    into a simple (one-value) case.  */
+                 int cmp = tree_int_cst_compare (high, low);
+                 if (cmp < 0)
+                   remove_element = TRUE;
+                 else if (cmp == 0)
+                   high = NULL_TREE;
+               }
+
+             if (! high)
+               {
+                 /* If the simple case value is unreachable, ignore it.  */
+                 if ((TREE_CODE (min_value) == INTEGER_CST
+                      && tree_int_cst_compare (low, min_value) < 0)
+                     || (TREE_CODE (max_value) == INTEGER_CST
+                         && tree_int_cst_compare (low, max_value) > 0))
+                   remove_element = TRUE;
+                 else
+                   low = fold_convert (index_type, low);
+               }
+             else
+               {
+                 /* If the entire case range is unreachable, ignore it.  */
+                 if ((TREE_CODE (min_value) == INTEGER_CST
+                      && tree_int_cst_compare (high, min_value) < 0)
+                     || (TREE_CODE (max_value) == INTEGER_CST
+                         && tree_int_cst_compare (low, max_value) > 0))
+                   remove_element = TRUE;
+                 else
+                   {
+                     /* If the lower bound is less than the index type's
+                        minimum value, truncate the range bounds.  */
+                     if (TREE_CODE (min_value) == INTEGER_CST
+                         && tree_int_cst_compare (low, min_value) < 0)
+                       low = min_value;
+                     low = fold_convert (index_type, low);
+
+                     /* If the upper bound is greater than the index type's
+                        maximum value, truncate the range bounds.  */
+                     if (TREE_CODE (max_value) == INTEGER_CST
+                         && tree_int_cst_compare (high, max_value) > 0)
+                       high = max_value;
+                     high = fold_convert (index_type, high);
+                   }
+               }
+
+             CASE_LOW (elt) = low;
+             CASE_HIGH (elt) = high;
            }
          else
            {
@@ -1636,25 +1704,20 @@ gimplify_switch_expr (tree *expr_p, gimple_seq *pre_p)
 
       if (!default_case)
        {
-         tree type = TREE_TYPE (switch_expr);
-
          /* If the switch has no default label, add one, so that we jump
             around the switch body.  If the labels already cover the whole
-            range of type, add the default label pointing to one of the
-            existing labels.  */
-         if (type == void_type_node)
-           type = TREE_TYPE (SWITCH_COND (switch_expr));
+            range of the switch index_type, add the default label pointing
+            to one of the existing labels.  */
          if (len
-             && INTEGRAL_TYPE_P (type)
-             && TYPE_MIN_VALUE (type)
-             && TYPE_MAX_VALUE (type)
+             && TYPE_MIN_VALUE (index_type)
+             && TYPE_MAX_VALUE (index_type)
              && tree_int_cst_equal (CASE_LOW (VEC_index (tree, labels, 0)),
-                                    TYPE_MIN_VALUE (type)))
+                                    TYPE_MIN_VALUE (index_type)))
            {
              tree low, high = CASE_HIGH (VEC_index (tree, labels, len - 1));
              if (!high)
                high = CASE_LOW (VEC_index (tree, labels, len - 1));
-             if (tree_int_cst_equal (high, TYPE_MAX_VALUE (type)))
+             if (tree_int_cst_equal (high, TYPE_MAX_VALUE (index_type)))
                {
                  for (i = 1; i < len; i++)
                    {
@@ -3693,7 +3756,8 @@ rhs_predicate_for (tree lhs)
    decl instead.  */
 
 static enum gimplify_status
-gimplify_compound_literal_expr (tree *expr_p, gimple_seq *pre_p)
+gimplify_compound_literal_expr (tree *expr_p, gimple_seq *pre_p,
+                               fallback_t fallback)
 {
   tree decl_s = COMPOUND_LITERAL_EXPR_DECL_EXPR (*expr_p);
   tree decl = DECL_EXPR_DECL (decl_s);
@@ -3712,6 +3776,12 @@ gimplify_compound_literal_expr (tree *expr_p, gimple_seq *pre_p)
       && !needs_to_live_in_memory (decl))
     DECL_GIMPLE_REG_P (decl) = 1;
 
+  /* If the decl is not addressable, then it is being used in some
+     expression or on the right hand side of a statement, and it can
+     be put into a readonly data section.  */
+  if (!TREE_ADDRESSABLE (decl) && (fallback & fb_lvalue) == 0)
+    TREE_READONLY (decl) = 1;
+
   /* This decl isn't mentioned in the enclosing block, so add it to the
      list of temps.  FIXME it seems a bit of a kludge to say that
      anonymous artificial vars aren't pushed, but everything else is.  */
@@ -7008,7 +7078,7 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
          break;
 
        case COMPOUND_LITERAL_EXPR:
-         ret = gimplify_compound_literal_expr (expr_p, pre_p);
+         ret = gimplify_compound_literal_expr (expr_p, pre_p, fallback);
          break;
 
        case MODIFY_EXPR: