OSDN Git Service

2007-02-02 Paul Thomas <pault@gcc.gnu.org>
[pf3gnuchains/gcc-fork.git] / gcc / fortran / trans-array.c
index 7eb56af..529d721 100644 (file)
@@ -1,6 +1,6 @@
 /* Array translation routines
-   Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation,
-   Inc.
+   Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007
+   Free Software Foundation, Inc.
    Contributed by Paul Brook <paul@nowt.org>
    and Steven Bosscher <s.bosscher@student.tudelft.nl>
 
@@ -1467,8 +1467,8 @@ get_array_ctor_strlen (gfc_constructor * c, tree * len)
    elements, and if so returns the number of those elements, otherwise
    return zero.  Note, an empty or NULL array constructor returns zero.  */
 
-static unsigned HOST_WIDE_INT
-constant_array_constructor_p (gfc_constructor * c)
+unsigned HOST_WIDE_INT
+gfc_constant_array_constructor_p (gfc_constructor * c)
 {
   unsigned HOST_WIDE_INT nelem = 0;
 
@@ -1489,7 +1489,7 @@ constant_array_constructor_p (gfc_constructor * c)
    and the tree type of it's elements, TYPE, return a static constant
    variable that is compile-time initialized.  */
 
-static tree
+tree
 gfc_build_constant_array_constructor (gfc_expr * expr, tree type)
 {
   tree tmptype, list, init, tmp;
@@ -1516,7 +1516,7 @@ gfc_build_constant_array_constructor (gfc_expr * expr, tree type)
       nelem++;
     }
 
-  /* Next detemine the tree type for the array.  We use the gfortran
+  /* Next determine the tree type for the array.  We use the gfortran
      front-end's gfc_get_nodesc_array_type in order to create a suitable
      GFC_ARRAY_TYPE_P that may be used by the scalarizer.  */
 
@@ -1633,7 +1633,7 @@ gfc_trans_array_constructor (gfc_loopinfo * loop, gfc_ss * ss)
       && INTEGER_CST_P (loop->from[0])
       && INTEGER_CST_P (loop->to[0]))
     {
-      unsigned HOST_WIDE_INT nelem = constant_array_constructor_p (c);
+      unsigned HOST_WIDE_INT nelem = gfc_constant_array_constructor_p (c);
       if (nelem > 0)
        {
          tree diff = fold_build2 (MINUS_EXPR, gfc_array_index_type,
@@ -4306,7 +4306,6 @@ gfc_conv_expr_descriptor (gfc_se * se, gfc_expr * expr, gfc_ss * ss)
 
   gcc_assert (ss != gfc_ss_terminator);
 
-  /* TODO: Pass constant array constructors without a temporary.  */
   /* Special case things we know we can pass easily.  */
   switch (expr->expr_type)
     {
@@ -4402,6 +4401,24 @@ gfc_conv_expr_descriptor (gfc_se * se, gfc_expr * expr, gfc_ss * ss)
        }
       break;
 
+    case EXPR_ARRAY:
+      /* Constant array constructors don't need a temporary.  */
+      if (ss->type == GFC_SS_CONSTRUCTOR
+         && expr->ts.type != BT_CHARACTER
+         && gfc_constant_array_constructor_p (expr->value.constructor))
+       {
+         need_tmp = 0;
+         info = &ss->data.info;
+         secss = ss;
+       }
+      else
+       {
+         need_tmp = 1;
+         secss = NULL;
+         info = NULL;
+       }
+      break;
+
     default:
       /* Something complicated.  Copy it into a temporary.  */
       need_tmp = 1;
@@ -4553,7 +4570,7 @@ gfc_conv_expr_descriptor (gfc_se * se, gfc_expr * expr, gfc_ss * ss)
         limits will be the limits of the section.
         A function may decide to repack the array to speed up access, but
         we're not bothered about that here.  */
-      int dim;
+      int dim, ndim;
       tree parm;
       tree parmtype;
       tree stride;
@@ -4603,12 +4620,14 @@ gfc_conv_expr_descriptor (gfc_se * se, gfc_expr * expr, gfc_ss * ss)
       else
        base = NULL_TREE;
 
-      for (n = 0; n < info->ref->u.ar.dimen; n++)
+      ndim = info->ref ? info->ref->u.ar.dimen : info->dimen;
+      for (n = 0; n < ndim; n++)
        {
          stride = gfc_conv_array_stride (desc, n);
 
          /* Work out the offset.  */
-         if (info->ref->u.ar.dimen_type[n] == DIMEN_ELEMENT)
+         if (info->ref
+             && info->ref->u.ar.dimen_type[n] == DIMEN_ELEMENT)
            {
              gcc_assert (info->subscript[n]
                      && info->subscript[n]->type == GFC_SS_SCALAR);
@@ -4630,14 +4649,16 @@ gfc_conv_expr_descriptor (gfc_se * se, gfc_expr * expr, gfc_ss * ss)
          tmp = fold_build2 (MULT_EXPR, TREE_TYPE (tmp), tmp, stride);
          offset = fold_build2 (PLUS_EXPR, TREE_TYPE (tmp), offset, tmp);
 
-         if (info->ref->u.ar.dimen_type[n] == DIMEN_ELEMENT)
+         if (info->ref
+             && info->ref->u.ar.dimen_type[n] == DIMEN_ELEMENT)
            {
              /* For elemental dimensions, we only need the offset.  */
              continue;
            }
 
          /* Vector subscripts need copying and are handled elsewhere.  */
-         gcc_assert (info->ref->u.ar.dimen_type[n] == DIMEN_RANGE);
+         if (info->ref)
+           gcc_assert (info->ref->u.ar.dimen_type[n] == DIMEN_RANGE);
 
          /* Set the new lower bound.  */
          from = loop.from[dim];
@@ -4646,7 +4667,9 @@ gfc_conv_expr_descriptor (gfc_se * se, gfc_expr * expr, gfc_ss * ss)
          /* If we have an array section or are assigning to a pointer,
             make sure that the lower bound is 1.  References to the full
             array should otherwise keep the original bounds.  */
-         if ((info->ref->u.ar.type != AR_FULL || se->direct_byref)
+         if ((!info->ref
+              || info->ref->u.ar.type != AR_FULL
+              || se->direct_byref)
              && !integer_onep (from))
            {
              tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type,