PR fortran/PR53876 PR fortran/PR54990 PR fortran/PR54992
authorPaul Thomas <pault@gcc.gnu.org>
Sun, 6 Jan 2013 21:32:48 +0000 (21:32 +0000)
committerPaul Thomas <pault@gcc.gnu.org>
Sun, 6 Jan 2013 21:32:48 +0000 (21:32 +0000)
2013-01-06  Paul Thomas  <pault@gcc.gnu.org>

PR fortran/PR53876
PR fortran/PR54990
PR fortran/PR54992
* trans-array.c (build_array_ref): Check the TYPE_CANONICAL
to see if it is GFC_CLASS_TYPE_P.
* trans-expr.c (gfc_get_vptr_from_expr): The same.
(gfc_conv_class_to_class): If the types are not the same,
cast parmese->expr to the type of ctree.
* trans-types.c (gfc_get_derived_type): GFC_CLASS_TYPE_P of
CLASS components must be set.

2013-01-06  Paul Thomas  <pault@gcc.gnu.org>

PR fortran/PR53876
PR fortran/PR54990
PR fortran/PR54992
* gfortran.dg/class_array_15.f03: New test.

From-SVN: r194953

gcc/fortran/ChangeLog
gcc/fortran/trans-array.c
gcc/fortran/trans-expr.c
gcc/fortran/trans-types.c
gcc/testsuite/ChangeLog
gcc/testsuite/gfortran.dg/class_array_15.f03 [new file with mode: 0644]

index f08f9b4..8c2cb3c 100644 (file)
@@ -1,3 +1,16 @@
+2013-01-06  Paul Thomas  <pault@gcc.gnu.org>
+
+       PR fortran/PR53876
+       PR fortran/PR54990
+       PR fortran/PR54992
+       * trans-array.c (build_array_ref): Check the TYPE_CANONICAL
+       to see if it is GFC_CLASS_TYPE_P.
+       * trans-expr.c (gfc_get_vptr_from_expr): The same.
+       (gfc_conv_class_to_class): If the types are not the same,
+       cast parmese->expr to the type of ctree.
+       * trans-types.c (gfc_get_derived_type): GFC_CLASS_TYPE_P of
+       CLASS components must be set.
+
 2013-01-06  Mikael Morin  <mikael@gcc.gnu.org>
 
        PR fortran/42769
index 0689892..794322a 100644 (file)
@@ -1,6 +1,6 @@
 /* Array translation routines
    Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
-   2011, 2012
+   2011, 2012, 2013
    Free Software Foundation, Inc.
    Contributed by Paul Brook <paul@nowt.org>
    and Steven Bosscher <s.bosscher@student.tudelft.nl>
@@ -159,7 +159,7 @@ gfc_conv_descriptor_data_get (tree desc)
 /* This provides WRITE access to the data field.
 
    TUPLES_P is true if we are generating tuples.
-   
+
    This function gets called through the following macros:
      gfc_conv_descriptor_data_set
      gfc_conv_descriptor_data_set.  */
@@ -593,7 +593,7 @@ gfc_get_temp_ss (tree type, tree string_length, int dimen)
 
   return ss;
 }
-               
+
 
 /* Creates and initializes a scalar type gfc_ss struct.  */
 
@@ -1363,7 +1363,7 @@ gfc_put_offset_into_var (stmtblock_t * pblock, tree * poffset,
 
 /* Variables needed for bounds-checking.  */
 static bool first_len;
-static tree first_len_val; 
+static tree first_len_val;
 static bool typespec_chararray_ctor;
 
 static void
@@ -2206,7 +2206,7 @@ trans_array_constructor (gfc_ss * ss, locus * where)
 
   if ((gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
       && expr->ts.type == BT_CHARACTER && !typespec_chararray_ctor)
-    {  
+    {
       first_len_val = gfc_create_var (gfc_charlen_type_node, "len");
       first_len = true;
     }
@@ -2217,7 +2217,7 @@ trans_array_constructor (gfc_ss * ss, locus * where)
   if (expr->ts.type == BT_CHARACTER)
     {
       bool const_string;
-      
+
       /* get_array_ctor_strlen walks the elements of the constructor, if a
         typespec was given, we already know the string length and want the one
         specified there.  */
@@ -2924,9 +2924,9 @@ conv_array_index_offset (gfc_se * se, gfc_ss * ss, int dim, int i,
       gcc_assert (se->loop);
       index = se->loop->loopvar[se->loop->order[i]];
 
-      /* Pointer functions can have stride[0] different from unity. 
+      /* Pointer functions can have stride[0] different from unity.
         Use the stride returned by the function call and stored in
-        the descriptor for the temporary.  */ 
+        the descriptor for the temporary.  */
       if (se->ss && se->ss->info->type == GFC_SS_FUNCTION
          && se->ss->info->expr
          && se->ss->info->expr->symtree
@@ -2986,7 +2986,7 @@ build_class_array_ref (gfc_se *se, tree base, tree index)
          ts = &ref->u.c.component->ts;
          class_ref = ref;
          break;
-       }          
+       }
     }
 
   if (ts == NULL)
@@ -3099,31 +3099,40 @@ static tree
 build_array_ref (tree desc, tree offset, tree decl)
 {
   tree tmp;
+  tree type;
 
-  /* Class array references need special treatment because the assigned
-     type size needs to be used to point to the element.  */ 
+  /* Class container types do not always have the GFC_CLASS_TYPE_P
+     but the canonical type does.  */
   if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc))
-       && TREE_CODE (desc) == COMPONENT_REF
-       && GFC_CLASS_TYPE_P (TREE_TYPE (TREE_OPERAND (desc, 0))))
+      && TREE_CODE (desc) == COMPONENT_REF)
     {
-      tree type = gfc_get_element_type (TREE_TYPE (desc));
-      tmp = TREE_OPERAND (desc, 0);
-      tmp = gfc_get_class_array_ref (offset, tmp);
-      tmp = fold_convert (build_pointer_type (type), tmp);
-      tmp = build_fold_indirect_ref_loc (input_location, tmp);
+      type = TREE_TYPE (TREE_OPERAND (desc, 0));
+      if (TYPE_CANONICAL (type)
+         && GFC_CLASS_TYPE_P (TYPE_CANONICAL (type)))
+       type = TYPE_CANONICAL (type);
     }
   else
+    type = NULL;
+
+  /* Class array references need special treatment because the assigned
+     type size needs to be used to point to the element.  */
+  if (type && GFC_CLASS_TYPE_P (type))
     {
-      tmp = gfc_conv_array_data (desc);
+      type = gfc_get_element_type (TREE_TYPE (desc));
+      tmp = TREE_OPERAND (desc, 0);
+      tmp = gfc_get_class_array_ref (offset, tmp);
+      tmp = fold_convert (build_pointer_type (type), tmp);
       tmp = build_fold_indirect_ref_loc (input_location, tmp);
-      tmp = gfc_build_array_ref (tmp, offset, decl);
+      return tmp;
     }
 
+  tmp = gfc_conv_array_data (desc);
+  tmp = build_fold_indirect_ref_loc (input_location, tmp);
+  tmp = gfc_build_array_ref (tmp, offset, decl);
   return tmp;
 }
 
 
-
 /* Build an array reference.  se->expr already holds the array descriptor.
    This should be either a variable, indirect variable reference or component
    reference.  For arrays which do not have a descriptor, se->expr will be
@@ -3202,7 +3211,7 @@ gfc_conv_array_ref (gfc_se * se, gfc_array_ref * ar, gfc_symbol * sym,
              tmp = tmpse.expr;
            }
 
-         cond = fold_build2_loc (input_location, LT_EXPR, boolean_type_node, 
+         cond = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
                                  indexse.expr, tmp);
          asprintf (&msg, "Index '%%ld' of dimension %d of array '%s' "
                    "below lower bound of %%ld", n+1, sym->name);
@@ -3964,8 +3973,8 @@ done:
                                               stride_pos, stride_neg);
 
              /* Check the start of the range against the lower and upper
-                bounds of the array, if the range is not empty. 
-                If upper bound is present, include both bounds in the 
+                bounds of the array, if the range is not empty.
+                If upper bound is present, include both bounds in the
                 error message.  */
              if (check_upper)
                {
@@ -4012,7 +4021,7 @@ done:
                     fold_convert (long_integer_type_node, lbound));
                  free (msg);
                }
-             
+
              /* Compute the last element of the range, which is not
                 necessarily "end" (think 0:5:3, which doesn't contain 5)
                 and check it against both lower and upper bounds.  */
@@ -4041,12 +4050,12 @@ done:
                  gfc_trans_runtime_check (true, false, tmp2, &inner,
                                           expr_loc, msg,
                     fold_convert (long_integer_type_node, tmp),
-                    fold_convert (long_integer_type_node, ubound), 
+                    fold_convert (long_integer_type_node, ubound),
                     fold_convert (long_integer_type_node, lbound));
                  gfc_trans_runtime_check (true, false, tmp3, &inner,
                                           expr_loc, msg,
                     fold_convert (long_integer_type_node, tmp),
-                    fold_convert (long_integer_type_node, ubound), 
+                    fold_convert (long_integer_type_node, ubound),
                     fold_convert (long_integer_type_node, lbound));
                  free (msg);
                }
@@ -4885,7 +4894,7 @@ gfc_array_init_size (tree descriptor, int rank, int corank, tree * poffset,
              ubound = lower[n];
            }
        }
-      gfc_conv_descriptor_lbound_set (descriptor_block, descriptor, 
+      gfc_conv_descriptor_lbound_set (descriptor_block, descriptor,
                                      gfc_rank_cst[n], se.expr);
       conv_lbound = se.expr;
 
@@ -4916,11 +4925,11 @@ gfc_array_init_size (tree descriptor, int rank, int corank, tree * poffset,
       /* Check whether multiplying the stride by the number of
         elements in this dimension would overflow. We must also check
         whether the current dimension has zero size in order to avoid
-        division by zero. 
+        division by zero.
       */
-      tmp = fold_build2_loc (input_location, TRUNC_DIV_EXPR, 
-                            gfc_array_index_type, 
-                            fold_convert (gfc_array_index_type, 
+      tmp = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
+                            gfc_array_index_type,
+                            fold_convert (gfc_array_index_type,
                                           TYPE_MAX_VALUE (gfc_array_index_type)),
                                           size);
       cond = gfc_unlikely (fold_build2_loc (input_location, LT_EXPR,
@@ -4935,7 +4944,7 @@ gfc_array_init_size (tree descriptor, int rank, int corank, tree * poffset,
       tmp = fold_build2_loc (input_location, PLUS_EXPR, integer_type_node,
                             *overflow, tmp);
       *overflow = gfc_evaluate_now (tmp, pblock);
-      
+
       /* Multiply the stride by the number of elements in this dimension.  */
       stride = fold_build2_loc (input_location, MULT_EXPR,
                                gfc_array_index_type, stride, size);
@@ -4966,7 +4975,7 @@ gfc_array_init_size (tree descriptor, int rank, int corank, tree * poffset,
              ubound = lower[n];
            }
        }
-      gfc_conv_descriptor_lbound_set (descriptor_block, descriptor, 
+      gfc_conv_descriptor_lbound_set (descriptor_block, descriptor,
                                      gfc_rank_cst[n], se.expr);
 
       if (n < rank + corank - 1)
@@ -5019,7 +5028,7 @@ gfc_array_init_size (tree descriptor, int rank, int corank, tree * poffset,
   /* First check for overflow. Since an array of type character can
      have zero element_size, we must check for that before
      dividing.  */
-  tmp = fold_build2_loc (input_location, TRUNC_DIV_EXPR, 
+  tmp = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
                         size_type_node,
                         TYPE_MAX_VALUE (size_type_node), element_size);
   cond = gfc_unlikely (fold_build2_loc (input_location, LT_EXPR,
@@ -5210,7 +5219,7 @@ gfc_array_allocate (gfc_se * se, gfc_expr * expr, tree status, tree errmsg,
     {
       cond = gfc_unlikely (fold_build2_loc (input_location, NE_EXPR,
                           boolean_type_node, var_overflow, integer_zero_node));
-      tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond, 
+      tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond,
                             error, gfc_finish_block (&elseblock));
     }
   else
@@ -5221,7 +5230,7 @@ gfc_array_allocate (gfc_se * se, gfc_expr * expr, tree status, tree errmsg,
   if (expr->ts.type == BT_CLASS)
     {
       tmp = build_int_cst (unsigned_char_type_node, 0);
-      /* With class objects, it is best to play safe and null the 
+      /* With class objects, it is best to play safe and null the
         memory because we cannot know if dynamic types have allocatable
         components or not.  */
       tmp = build_call_expr_loc (input_location,
@@ -5233,7 +5242,7 @@ gfc_array_allocate (gfc_se * se, gfc_expr * expr, tree status, tree errmsg,
   /* Update the array descriptors. */
   if (dimension)
     gfc_conv_descriptor_offset_set (&set_descriptor_block, se->expr, offset);
-  
+
   set_descriptor = gfc_finish_block (&set_descriptor_block);
   if (status != NULL_TREE)
     {
@@ -5243,7 +5252,7 @@ gfc_array_allocate (gfc_se * se, gfc_expr * expr, tree status, tree errmsg,
       gfc_add_expr_to_block (&se->pre,
                 fold_build3_loc (input_location, COND_EXPR, void_type_node,
                                  gfc_likely (cond), set_descriptor,
-                                 build_empty_stmt (input_location))); 
+                                 build_empty_stmt (input_location)));
     }
   else
       gfc_add_expr_to_block (&se->pre, set_descriptor);
@@ -5331,7 +5340,7 @@ gfc_conv_array_initializer (tree type, gfc_expr * expr)
       /* A single scalar or derived type value.  Create an array with all
          elements equal to that value.  */
       gfc_init_se (&se, NULL);
-      
+
       if (expr->expr_type == EXPR_CONSTANT)
        gfc_conv_constant (&se, expr);
       else
@@ -5743,7 +5752,7 @@ gfc_trans_g77_array (gfc_symbol * sym, gfc_wrapped_block * block)
       tmp = gfc_conv_expr_present (sym);
       stmt = build3_v (COND_EXPR, tmp, stmt, build_empty_stmt (input_location));
     }
-  
+
   gfc_add_init_cleanup (block, stmt, NULL_TREE);
 }
 
@@ -5945,7 +5954,7 @@ gfc_trans_dummy_array_bias (gfc_symbol * sym, tree tmpdesc,
              asprintf (&msg, "Dimension %d of array '%s' has extent "
                        "%%ld instead of %%ld", n+1, sym->name);
 
-             gfc_trans_runtime_check (true, false, tmp, &init, &loc, msg, 
+             gfc_trans_runtime_check (true, false, tmp, &init, &loc, msg,
                        fold_convert (long_integer_type_node, temp),
                        fold_convert (long_integer_type_node, stride2));
 
@@ -6069,7 +6078,7 @@ gfc_trans_dummy_array_bias (gfc_symbol * sym, tree tmpdesc,
       gfc_add_expr_to_block (&cleanup, tmp);
 
       stmtCleanup = gfc_finish_block (&cleanup);
-       
+
       /* Only do the cleanup if the array was repacked.  */
       tmp = build_fold_indirect_ref_loc (input_location, dumdesc);
       tmp = gfc_conv_descriptor_data_get (tmp);
@@ -6381,7 +6390,7 @@ walk_coarray (gfc_expr *e)
         EXPR is the right-hand side of a pointer assignment and
         se->expr is the descriptor for the previously-evaluated
         left-hand side.  The function creates an assignment from
-        EXPR to se->expr.  
+        EXPR to se->expr.
 
 
    The se->force_tmp flag disables the non-copying descriptor optimization
@@ -6495,7 +6504,7 @@ gfc_conv_expr_descriptor (gfc_se *se, gfc_expr *expr)
          return;
        }
       break;
-      
+
     case EXPR_FUNCTION:
       /* A transformational function return value will be a temporary
         array descriptor.  We still need to go through the scalarizer
@@ -6785,7 +6794,7 @@ gfc_conv_expr_descriptor (gfc_se *se, gfc_expr *expr)
          /* Vector subscripts need copying and are handled elsewhere.  */
          if (info->ref)
            gcc_assert (info->ref->u.ar.dimen_type[n] == DIMEN_RANGE);
+
          /* look for the corresponding scalarizer dimension: dim.  */
          for (dim = 0; dim < ndim; dim++)
            if (ss->dim[dim] == n)
@@ -7011,9 +7020,9 @@ gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, bool g77,
 
       if (!sym->attr.pointer
          && sym->as
-         && sym->as->type != AS_ASSUMED_SHAPE 
+         && sym->as->type != AS_ASSUMED_SHAPE
          && sym->as->type != AS_DEFERRED
-         && sym->as->type != AS_ASSUMED_RANK 
+         && sym->as->type != AS_ASSUMED_RANK
          && !sym->attr.allocatable)
         {
          /* Some variables are declared directly, others are declared as
@@ -7071,7 +7080,7 @@ gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, bool g77,
                       && expr->symtree->n.sym->attr.allocatable;
 
   /* Or ultimate allocatable components.  */
-  ultimate_alloc_comp = contiguous && ultimate_alloc_comp; 
+  ultimate_alloc_comp = contiguous && ultimate_alloc_comp;
 
   if (no_pack || array_constructor || good_allocatable || ultimate_alloc_comp)
     {
@@ -7254,7 +7263,7 @@ gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, bool g77,
 
 tree
 gfc_trans_dealloc_allocated (tree descriptor, bool coarray)
-{ 
+{
   tree tmp;
   tree var;
   stmtblock_t block;
@@ -7454,7 +7463,7 @@ structure_alloc_comps (gfc_symbol * der_type, tree decl,
       tmp = gfc_conv_array_data (decl);
       var = build_fold_indirect_ref_loc (input_location,
                                     tmp);
-       
+
       /* Get the number of elements - 1 and set the counter.  */
       if (GFC_DESCRIPTOR_TYPE_P (decl_type))
        {
@@ -7578,7 +7587,7 @@ structure_alloc_comps (gfc_symbol * der_type, tree decl,
              /* Allocatable CLASS components.  */
              comp = fold_build3_loc (input_location, COMPONENT_REF, ctype,
                                      decl, cdecl, NULL_TREE);
-             
+
              /* Add reference to '_data' component.  */
              tmp = CLASS_DATA (c)->backend_decl;
              comp = fold_build3_loc (input_location, COMPONENT_REF,
@@ -7725,7 +7734,7 @@ structure_alloc_comps (gfc_symbol * der_type, tree decl,
 
              null_cond = fold_build2_loc (input_location, NE_EXPR,
                                           boolean_type_node, src_data,
-                                          null_pointer_node);  
+                                          null_pointer_node);
 
              gfc_add_expr_to_block (&fnblock, build3_v (COND_EXPR, null_cond,
                                                         tmp, null_data));
@@ -8030,7 +8039,7 @@ gfc_alloc_allocatable_for_assignment (gfc_loopinfo *loop,
     as = NULL;
 
   /* If the lhs shape is not the same as the rhs jump to setting the
-     bounds and doing the reallocation.......  */ 
+     bounds and doing the reallocation.......  */
   for (n = 0; n < expr1->rank; n++)
     {
       /* Check the shape.  */
@@ -8051,13 +8060,13 @@ gfc_alloc_allocatable_for_assignment (gfc_loopinfo *loop,
       tmp = build3_v (COND_EXPR, cond,
                      build1_v (GOTO_EXPR, jump_label1),
                      build_empty_stmt (input_location));
-      gfc_add_expr_to_block (&fblock, tmp);      
+      gfc_add_expr_to_block (&fblock, tmp);
     }
 
   /* ....else jump past the (re)alloc code.  */
   tmp = build1_v (GOTO_EXPR, jump_label2);
   gfc_add_expr_to_block (&fblock, tmp);
-    
+
   /* Add the label to start automatic (re)allocation.  */
   tmp = build1_v (LABEL_EXPR, jump_label1);
   gfc_add_expr_to_block (&fblock, tmp);
@@ -8096,7 +8105,7 @@ gfc_alloc_allocatable_for_assignment (gfc_loopinfo *loop,
      unallocated allocatable variable, then it is allocated with each
      deferred type parameter equal to the corresponding type parameters
      of expr , with the shape of expr , and with each lower bound equal
-     to the corresponding element of LBOUND(expr)."  
+     to the corresponding element of LBOUND(expr)."
      Reuse size1 to keep a dimension-by-dimension track of the
      stride of the new array.  */
   size1 = gfc_index_one_node;
@@ -8340,7 +8349,7 @@ gfc_trans_deferred_array (gfc_symbol * sym, gfc_wrapped_block * block)
                                                sym->backend_decl);
       type = TREE_TYPE (descriptor);
     }
-  
+
   /* NULLIFY the data pointer.  */
   if (GFC_DESCRIPTOR_TYPE_P (type) && !sym->attr.save)
     gfc_conv_descriptor_data_set (&init, descriptor, null_pointer_node);
index 01d3595..9452e27 100644 (file)
@@ -198,16 +198,31 @@ gfc_vtable_final_get (tree decl)
 #undef VTABLE_FINAL_FIELD
 
 
-/* Obtain the vptr of the last class reference in an expression.  */
+/* Obtain the vptr of the last class reference in an expression.
+   Return NULL_TREE if no class reference is found.  */
 
 tree
 gfc_get_vptr_from_expr (tree expr)
 {
-  tree tmp = expr;
-  while (tmp && !GFC_CLASS_TYPE_P (TREE_TYPE (tmp)))
-    tmp = TREE_OPERAND (tmp, 0);
-  tmp = gfc_class_vptr_get (tmp);
-  return tmp;
+  tree tmp;
+  tree type;
+
+  for (tmp = expr; tmp; tmp = TREE_OPERAND (tmp, 0))
+    {
+      type = TREE_TYPE (tmp);
+      while (type)
+       {
+         if (GFC_CLASS_TYPE_P (type))
+           return gfc_class_vptr_get (tmp);
+         if (type != TYPE_CANONICAL (type))
+           type = TYPE_CANONICAL (type);
+         else
+           type = NULL_TREE;
+       }
+      if (TREE_CODE (tmp) == VAR_DECL)
+       break;
+    }
+  return NULL_TREE;
 }
 
 
@@ -594,7 +609,7 @@ gfc_conv_class_to_class (gfc_se *parmse, gfc_expr *e, gfc_typespec class_ts,
     }
   else
     {
-      if (CLASS_DATA (e)->attr.codimension)
+      if (TREE_TYPE (parmse->expr) != TREE_TYPE (ctree))
        parmse->expr = fold_build1_loc (input_location, VIEW_CONVERT_EXPR,
                                        TREE_TYPE (ctree), parmse->expr);
       gfc_add_modify (&block, ctree, parmse->expr);
@@ -1562,6 +1577,7 @@ gfc_conv_component_ref (gfc_se * se, gfc_ref * ref)
       c->norestrict_decl = f2;
       field = f2;
     }
+
   tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
                         decl, field, NULL_TREE);
 
index 8394bf9..cd9bde6 100644 (file)
@@ -1,6 +1,6 @@
 /* Backend support for Fortran 95 basic types and derived types.
    Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
-   2010, 2011, 2012
+   2010, 2011, 2012, 2013
    Free Software Foundation, Inc.
    Contributed by Paul Brook <paul@nowt.org>
    and Steven Bosscher <s.bosscher@student.tudelft.nl>
@@ -124,7 +124,7 @@ int gfc_atomic_logical_kind;
 
 /* The kind size used for record offsets. If the target system supports
    kind=8, this will be set to 8, otherwise it is set to 4.  */
-int gfc_intio_kind; 
+int gfc_intio_kind;
 
 /* The integer kind used to store character lengths.  */
 int gfc_charlen_int_kind;
@@ -138,7 +138,7 @@ gfc_try
 gfc_check_any_c_kind (gfc_typespec *ts)
 {
   int i;
-  
+
   for (i = 0; i < ISOCBINDING_NUMBER; i++)
     {
       /* Check for any C interoperable kind for the given type/kind in ts.
@@ -400,7 +400,7 @@ gfc_init_kinds (void)
       i_index += 1;
     }
 
-  /* Set the kind used to match GFC_INT_IO in libgfortran.  This is 
+  /* Set the kind used to match GFC_INT_IO in libgfortran.  This is
      used for large file access.  */
 
   if (saw_i8)
@@ -408,8 +408,8 @@ gfc_init_kinds (void)
   else
     gfc_intio_kind = 4;
 
-  /* If we do not at least have kind = 4, everything is pointless.  */  
-  gcc_assert(saw_i4);  
+  /* If we do not at least have kind = 4, everything is pointless.  */
+  gcc_assert(saw_i4);
 
   /* Set the maximum integer kind.  Used with at least BOZ constants.  */
   gfc_max_integer_kind = gfc_integer_kinds[i_index - 1].kind;
@@ -550,7 +550,7 @@ gfc_init_kinds (void)
   else
     gfc_default_real_kind = gfc_real_kinds[0].kind;
 
-  /* Choose the default double kind.  If -fdefault-real and -fdefault-double 
+  /* Choose the default double kind.  If -fdefault-real and -fdefault-double
      are specified, we use kind=8, if it's available.  If -fdefault-real is
      specified without -fdefault-double, we use kind=16, if it's available.
      Otherwise we do not change anything.  */
@@ -1624,10 +1624,10 @@ gfc_get_nodesc_array_type (tree etype, gfc_array_spec * as, gfc_packed packed,
          type = build_pointer_type (type);
 
          if (restricted)
-           type = build_qualified_type (type, TYPE_QUAL_RESTRICT);     
+           type = build_qualified_type (type, TYPE_QUAL_RESTRICT);
 
          GFC_ARRAY_TYPE_P (type) = 1;
-         TYPE_LANG_SPECIFIC (type) = TYPE_LANG_SPECIFIC (TREE_TYPE (type)); 
+         TYPE_LANG_SPECIFIC (type) = TYPE_LANG_SPECIFIC (TREE_TYPE (type));
        }
 
       return type;
@@ -2286,7 +2286,7 @@ gfc_copy_dt_decls_ifequal (gfc_symbol *from, gfc_symbol *to,
      a derived type, we need a copy of its component declarations.
      This is done by recursing into gfc_get_derived_type and
      ensures that the component's component declarations have
-     been built.  If it is a character, we need the character 
+     been built.  If it is a character, we need the character
      length, as well.  */
   for (; to_cm; to_cm = to_cm->next, from_cm = from_cm->next)
     {
@@ -2367,7 +2367,7 @@ gfc_get_derived_type (gfc_symbol * derived)
          BT_INTEGER that needs to fit a void * for the purpose of the
          iso_c_binding derived types.  */
       derived->ts.f90_type = BT_VOID;
-      
+
       return derived->backend_decl;
     }
 
@@ -2532,6 +2532,15 @@ gfc_get_derived_type (gfc_symbol * derived)
          field_type = build_pointer_type_for_mode (TREE_TYPE (field_type),
                                                    ptr_mode, true);
 
+      /* Ensure that the CLASS language specific flag is set.  */
+      if (c->ts.type == BT_CLASS)
+       {
+         if (POINTER_TYPE_P (field_type))
+           GFC_CLASS_TYPE_P (TREE_TYPE (field_type)) = 1;
+         else
+           GFC_CLASS_TYPE_P (field_type) = 1;
+       }
+
       field = gfc_add_field_to_struct (typenode,
                                       get_identifier (c->name),
                                       field_type, &chain);
@@ -2832,7 +2841,7 @@ gfc_get_function_type (gfc_symbol * sym)
           && sym->ts.kind == gfc_default_real_kind
           && !sym->attr.always_explicit)
     {
-      /* Special case: f2c calling conventions require that (scalar) 
+      /* Special case: f2c calling conventions require that (scalar)
         default REAL functions return the C type double instead.  f2c
         compatibility is only an issue with functions that don't
         require an explicit interface, as only these could be
index 2e5c99d..0f15221 100644 (file)
@@ -1,3 +1,10 @@
+2013-01-06  Paul Thomas  <pault@gcc.gnu.org>
+
+       PR fortran/PR53876
+       PR fortran/PR54990
+       PR fortran/PR54992
+       * gfortran.dg/class_array_15.f03: New test.
+
 2013-01-06  Mikael Morin  <mikael@gcc.gnu.org>
 
        PR fortran/42769
diff --git a/gcc/testsuite/gfortran.dg/class_array_15.f03 b/gcc/testsuite/gfortran.dg/class_array_15.f03
new file mode 100644 (file)
index 0000000..7d1d4d7
--- /dev/null
@@ -0,0 +1,116 @@
+! { dg-do run }
+!
+! Tests the fixes for three bugs with the same underlying cause.  All are regressions
+! that come about because class array elements end up with a different tree type
+! to the class array.  In addition, the language specific flag that marks a class
+! container is not being set.
+!
+! PR53876 contributed by Prince Ogunbade  <pogos77@hotmail.com>
+! PR54990 contributed by Janus Weil  <janus@gcc.gnu.org>
+! PR54992 contributed by Tobias Burnus  <burnus@gcc.gnu.org>
+! The two latter bugs were reported by Andrew Benson
+! starting at http://gcc.gnu.org/ml/fortran/2012-10/msg00087.html
+!
+module G_Nodes
+  type :: nc
+    type(tn), pointer :: hostNode
+  end type nc
+  type, extends(nc) :: ncBh
+  end type ncBh
+  type, public, extends(ncBh) :: ncBhStd
+    double precision :: massSeedData
+  end type ncBhStd
+  type, public :: tn
+    class (ncBh), allocatable, dimension(:) :: cBh
+  end type tn
+  type(ncBhStd) :: defaultBhC
+contains
+  subroutine Node_C_Bh_Move(targetNode)
+    implicit none
+    type (tn  ), intent(inout) , target       :: targetNode
+    class(ncBh), allocatable   , dimension(:) :: instancesTemporary
+! These two lines resulted in the wrong result:
+    allocate(instancesTemporary(2),source=defaultBhC)
+    call Move_Alloc(instancesTemporary,targetNode%cBh)
+! These two lines gave the correct result:
+!!deallocate(targetNode%cBh)
+!!allocate(targetNode%cBh(2))
+    targetNode%cBh(1)%hostNode => targetNode
+    targetNode%cBh(2)%hostNode => targetNode
+    return
+  end subroutine Node_C_Bh_Move
+  function bhGet(self,instance)
+    implicit none
+    class (ncBh), pointer               :: bhGet
+    class (tn  ), intent(inout), target :: self
+    integer     , intent(in   )         :: instance
+    bhGet => self%cBh(instance)
+    return
+  end function bhGet
+end module G_Nodes
+
+  call pr53876
+  call pr54990
+  call pr54992
+end
+
+subroutine pr53876
+  IMPLICIT NONE
+  TYPE :: individual
+    integer :: icomp ! Add an extra component to test offset
+    REAL, DIMENSION(:), ALLOCATABLE :: genes
+  END TYPE
+  CLASS(individual), DIMENSION(:), ALLOCATABLE :: indv
+  allocate (indv(2), source = [individual(1, [99,999]), &
+                               individual(2, [999,9999])])
+  CALL display_indv(indv(2)) ! Similarly, reference 2nd element to test offset
+CONTAINS
+  SUBROUTINE display_indv(self)
+    CLASS(individual),  INTENT(IN) :: self
+    if (any(self%genes .ne. [999,9999]) )call abort
+  END SUBROUTINE
+END
+
+subroutine pr54990
+  implicit none
+  type :: ncBhStd
+    integer :: i
+  end type
+  type, extends(ncBhStd) :: ncBhStde
+    integer :: i2(2)
+  end type
+  type :: tn
+    integer :: i ! Add an extra component to test offset
+    class (ncBhStd), allocatable, dimension(:) :: cBh
+  end type
+  integer :: i
+  type(tn), target :: a
+  allocate (a%cBh(2), source = [(ncBhStde(i*99, [1,2]), i = 1,2)])
+  select type (q => a%cBh(2)) ! Similarly, reference 2nd element to test offset
+    type is (ncBhStd)
+      call abort
+    type is (ncBhStde)
+      if (q%i .ne. 198) call abort ! This tests that the component really gets the
+  end select                       ! language specific flag denoting a class type
+end
+
+subroutine pr54992  ! This test remains as the original.
+  use G_Nodes
+  implicit none
+  type (tn), target  :: b
+  class(ncBh), pointer :: bh
+  class(ncBh), allocatable, dimension(:) :: t
+  allocate(b%cBh(1),source=defaultBhC)
+  b%cBh(1)%hostNode => b
+! #1 this worked
+  if (loc(b) .ne. loc(b%cBh(1)%hostNode)) call abort
+  call Node_C_Bh_Move(b)
+! #2 this worked
+  if (loc(b) .ne. loc(b%cBh(1)%hostNode)) call abort
+  if (loc(b) .ne. loc(b%cBh(2)%hostNode)) call abort
+! #3 this did not
+  bh => bhGet(b,instance=1)
+  if (loc (b) .ne. loc(bh%hostNode)) call abort
+  bh => bhGet(b,instance=2)
+  if (loc (b) .ne. loc(bh%hostNode)) call abort
+end