https://gcc.gnu.org/g:5731adaf8c102ff49bf672487d476fccdb10fcf3

commit 5731adaf8c102ff49bf672487d476fccdb10fcf3
Author: Mikael Morin <mik...@gcc.gnu.org>
Date:   Sun Dec 15 17:55:45 2024 +0100

    Sauvegarde correction null_actual_6

Diff:
---
 gcc/fortran/trans-array.cc | 145 +++++++++++++++++++++++++++++++--------------
 gcc/fortran/trans-array.h  |   5 +-
 gcc/fortran/trans-expr.cc  |  45 +++++++++++++-
 3 files changed, 146 insertions(+), 49 deletions(-)

diff --git a/gcc/fortran/trans-array.cc b/gcc/fortran/trans-array.cc
index c02fbde0ceaf..00e4b086e843 100644
--- a/gcc/fortran/trans-array.cc
+++ b/gcc/fortran/trans-array.cc
@@ -592,10 +592,10 @@ get_size_info (gfc_typespec &ts)
        if (POINTER_TYPE_P (type))
          type = TREE_TYPE (type);
        gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
-       tree elt_type = TREE_TYPE (type);
+       tree char_type = TREE_TYPE (type);
        tree len = ts.u.cl->backend_decl;
        return fold_build2_loc (input_location, MULT_EXPR, size_type_node,
-                               size_in_bytes (elt_type),
+                               size_in_bytes (char_type),
                                fold_convert (size_type_node, len));
       }
 
@@ -613,8 +613,61 @@ get_size_info (gfc_typespec &ts)
 }
 
 
+class init_info
+{
+public:
+  virtual bool initialize_data () const { return false; }
+  virtual tree get_data_value () const { return NULL_TREE; }
+  virtual gfc_typespec *get_type () const { return nullptr; }
+};
+
+
+class default_init : public init_info
+{
+private:
+  const symbol_attribute &attr; 
+
+public:
+  default_init (const symbol_attribute &arg_attr) : attr(arg_attr) { }
+  virtual bool initialize_data () const { return !attr.pointer; }
+  virtual tree get_data_value () const {
+    if (!initialize_data ())
+      return NULL_TREE;
+
+    return null_pointer_node;
+  }
+};
+
+class nullification : public init_info
+{
+private:
+  gfc_typespec &ts;
+
+public:
+  nullification(gfc_typespec &arg_ts) : ts(arg_ts) { }
+  virtual bool initialize_data () const { return true; }
+  virtual tree get_data_value () const { return null_pointer_node; }
+  virtual gfc_typespec *get_type () const { return &ts; }
+};
+
+class scalar_value : public init_info
+{
+private:
+  gfc_typespec &ts;
+  tree value;
+
+public:
+  scalar_value(gfc_typespec &arg_ts, tree arg_value)
+    : ts(arg_ts), value(arg_value) { }
+  virtual bool initialize_data () const { return true; }
+  virtual tree get_data_value () const { return value; }
+  virtual gfc_typespec *get_type () const { return &ts; }
+};
+
+
 static tree
-build_dtype (gfc_typespec &ts, int rank, const symbol_attribute &)
+build_dtype (gfc_typespec &ts, int rank, const symbol_attribute &,
+            const init_info &init)
 {
   vec<constructor_elt, va_gc> *v = nullptr;
 
@@ -622,11 +675,17 @@ build_dtype (gfc_typespec &ts, int rank, const 
symbol_attribute &)
 
   tree fields = TYPE_FIELDS (type);
 
-  if (ts.type != BT_CLASS)
+  gfc_typespec *type_info = init.get_type ();
+  if (type_info == nullptr)
+    type_info = &ts;
+
+  if (!(type_info->type == BT_CLASS
+       || (type_info->type == BT_CHARACTER
+           && type_info->deferred)))
     {
       tree elem_len_field = gfc_advance_chain (fields, GFC_DTYPE_ELEM_LEN);
       tree elem_len_val = fold_convert (TREE_TYPE (elem_len_field),
-                                       get_size_info (ts));
+                                       get_size_info (*type_info));
       CONSTRUCTOR_APPEND_ELT (v, elem_len_field, elem_len_val);
     }
 
@@ -641,11 +700,11 @@ build_dtype (gfc_typespec &ts, int rank, const 
symbol_attribute &)
       CONSTRUCTOR_APPEND_ELT (v, rank_field, rank_val);
     }
 
-  if (ts.type != BT_CLASS)
+  if (type_info->type != BT_CLASS)
     {
       tree type_info_field = gfc_advance_chain (fields, GFC_DTYPE_TYPE);
       tree type_info_val = build_int_cst (TREE_TYPE (type_info_field),
-                                         get_type_info (ts));
+                                         get_type_info (*type_info));
       CONSTRUCTOR_APPEND_ELT (v, type_info_field, type_info_val);
     }
 
@@ -657,7 +716,7 @@ build_dtype (gfc_typespec &ts, int rank, const 
symbol_attribute &)
 
 vec<constructor_elt, va_gc> *
 get_descriptor_init (tree type, gfc_typespec &ts, int rank,
-                    const symbol_attribute &attr, tree data_value)
+                    const symbol_attribute &attr, const init_info &init)
 {
   vec<constructor_elt, va_gc> *v = nullptr;
 
@@ -666,14 +725,15 @@ get_descriptor_init (tree type, gfc_typespec &ts, int 
rank,
   tree fields = TYPE_FIELDS (type);
 
   /* Don't init pointers by default.  */
-  if (data_value)
+  if (init.initialize_data ())
     {
       tree data_field = gfc_advance_chain (fields, DATA_FIELD);
+      tree data_value = init.get_data_value ();
       CONSTRUCTOR_APPEND_ELT (v, data_field, data_value);
     }
 
   tree dtype_field = gfc_advance_chain (fields, DTYPE_FIELD);
-  tree dtype_value = build_dtype (ts, rank, attr);
+  tree dtype_value = build_dtype (ts, rank, attr, init);
   CONSTRUCTOR_APPEND_ELT (v, dtype_field, dtype_value);
 
   if (flag_coarray == GFC_FCOARRAY_LIB && attr.codimension)
@@ -698,27 +758,8 @@ get_default_array_descriptor_init (tree type, gfc_typespec 
&ts, int rank,
 {
   gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
   gcc_assert (DATA_FIELD == 0);
-  tree fields = TYPE_FIELDS (type);
-
-  /* Don't init pointers by default.  */
-  tree data_value;
-  if (attr.pointer)
-    data_value = NULL_TREE;
-  else
-    {
-      tree data_field = gfc_advance_chain (fields, DATA_FIELD);
-      data_value = fold_convert (TREE_TYPE (data_field), null_pointer_node);
-    }
 
-  return get_descriptor_init (type, ts, rank, attr, data_value);
-}
-
-
-vec<constructor_elt, va_gc> *
-get_default_scalar_descriptor_init (tree type, gfc_typespec &ts, int rank,
-                                  const symbol_attribute &attr, tree value)
-{
-  return get_descriptor_init (type, ts, rank, attr, value);
+  return get_descriptor_init (type, ts, rank, attr, default_init (attr));
 }
 
 
@@ -726,10 +767,7 @@ vec<constructor_elt, va_gc> *
 get_null_array_descriptor_init (tree type, gfc_typespec &ts, int rank,
                                const symbol_attribute &attr)
 {
-  symbol_attribute attr2 = attr;
-  attr2.pointer = 0;
-
-  return get_default_array_descriptor_init (type, ts, rank, attr2);
+  return get_descriptor_init (type, ts, rank, attr, nullification (ts));
 }
 
 
@@ -740,8 +778,8 @@ gfc_build_default_array_descriptor (tree type, gfc_typespec 
&ts, int rank,
   gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
 
   return build_constructor (type,
-                           get_default_array_descriptor_init (type, ts, rank,
-                                                              attr));
+                           get_descriptor_init (type, ts, rank, attr,
+                                                default_init (attr)));
 }
 
 
@@ -1017,8 +1055,31 @@ gfc_clear_descriptor (stmtblock_t *block, gfc_symbol 
*sym, tree descriptor)
 
 
 void
-gfc_clear_scalar_descriptor (stmtblock_t *block, tree descriptor, 
-                            gfc_symbol *sym, tree value)
+gfc_clear_descriptor (stmtblock_t *block, gfc_symbol *sym, 
+                     gfc_expr *expr, tree descriptor)
+{
+  symbol_attribute attr;
+
+  gfc_array_spec *as = sym->ts.type == BT_CLASS
+                      ? CLASS_DATA (sym)->as
+                      : sym->as;
+  int rank = as == nullptr
+            ? 0
+            : as->type == AS_ASSUMED_RANK
+              ? expr->rank
+              : as->rank;
+
+  attr = gfc_symbol_attr (sym);
+
+  init_struct (block, descriptor,
+              get_null_array_descriptor_init (TREE_TYPE (descriptor),
+                                              expr->ts, rank, attr));
+}
+
+
+void
+gfc_set_scalar_descriptor (stmtblock_t *block, tree descriptor, 
+                          gfc_symbol *sym, gfc_expr *expr, tree value)
 {
   symbol_attribute attr;
 
@@ -1026,7 +1087,7 @@ gfc_clear_scalar_descriptor (stmtblock_t *block, tree 
descriptor,
 
   init_struct (block, descriptor,
               get_descriptor_init (TREE_TYPE (descriptor), sym->ts, 0,
-                                   attr, value));
+                                   attr, scalar_value (expr->ts, value)));
 }
 
 
@@ -1553,12 +1614,8 @@ gfc_get_array_span (tree desc, gfc_expr *expr)
 void
 gfc_trans_static_array_pointer (gfc_symbol * sym)
 {
-  tree type;
-
   gcc_assert (TREE_STATIC (sym->backend_decl));
-  /* Just zero the data member.  */
-  type = TREE_TYPE (sym->backend_decl);
-  DECL_INITIAL (sym->backend_decl) = gfc_build_null_descriptor (type);
+  gfc_clear_descriptor (nullptr, sym, sym->backend_decl);
 }
 
 
diff --git a/gcc/fortran/trans-array.h b/gcc/fortran/trans-array.h
index c6e4b2c63a5d..4b3c4c644924 100644
--- a/gcc/fortran/trans-array.h
+++ b/gcc/fortran/trans-array.h
@@ -141,8 +141,9 @@ void gfc_conv_resolve_dependencies (gfc_loopinfo *, gfc_ss 
*, gfc_ss *);
 /* Build a null array descriptor constructor.  */
 tree gfc_build_null_descriptor (tree);
 tree gfc_build_default_class_descriptor (tree, gfc_typespec &);
-void gfc_clear_descriptor (stmtblock_t *block, gfc_symbol *sym, tree 
descriptor);
-void gfc_clear_scalar_descriptor (stmtblock_t *block, tree, gfc_symbol *, 
tree);
+void gfc_clear_descriptor (stmtblock_t *block, gfc_symbol *, tree);
+void gfc_clear_descriptor (stmtblock_t *block, gfc_symbol *, gfc_expr *, tree);
+void gfc_set_scalar_descriptor (stmtblock_t *block, tree, gfc_symbol *, 
gfc_expr *, tree);
 
 /* Get a single array element.  */
 void gfc_conv_array_ref (gfc_se *, gfc_array_ref *, gfc_expr *, locus *);
diff --git a/gcc/fortran/trans-expr.cc b/gcc/fortran/trans-expr.cc
index ce8392b7547b..758c45b7d347 100644
--- a/gcc/fortran/trans-expr.cc
+++ b/gcc/fortran/trans-expr.cc
@@ -106,7 +106,7 @@ get_scalar_to_descriptor_type (tree scalar, 
symbol_attribute attr)
 
 
 tree
-gfc_conv_scalar_null_to_descriptor (gfc_se *se, gfc_symbol *sym, tree scalar)
+gfc_conv_scalar_null_to_descriptor (gfc_se *se, gfc_symbol *sym, gfc_expr 
*expr, tree scalar)
 {
   symbol_attribute attr = sym->attr;
 
@@ -124,7 +124,7 @@ gfc_conv_scalar_null_to_descriptor (gfc_se *se, gfc_symbol 
*sym, tree scalar)
   if (!POINTER_TYPE_P (TREE_TYPE (scalar)))
     scalar = gfc_build_addr_expr (NULL_TREE, scalar);
 
-  gfc_clear_scalar_descriptor (&se->pre, desc, sym, scalar);
+  gfc_set_scalar_descriptor (&se->pre, desc, sym, expr, scalar);
 
   /* Copy pointer address back - but only if it could have changed and
      if the actual argument is a pointer and not, e.g., NULL().  */
@@ -136,6 +136,42 @@ gfc_conv_scalar_null_to_descriptor (gfc_se *se, gfc_symbol 
*sym, tree scalar)
 }
 
 
+tree
+gfc_conv_null_array_descriptor (gfc_se *se, gfc_symbol *sym, gfc_expr *expr)
+{
+#if 0
+  symbol_attribute attr = sym->attr;
+#endif
+  tree lower[GFC_MAX_DIMENSIONS], upper[GFC_MAX_DIMENSIONS];
+
+  for (int i = 0; i < expr->rank; i++)
+    {
+      lower[i] = gfc_index_zero_node;
+      upper[i] = gfc_index_one_node;
+    }
+
+  tree elt_type = gfc_typenode_for_spec (&sym->ts);
+  tree desc_type = gfc_get_array_type_bounds (elt_type, expr->rank, 0,
+                                             lower, upper, 0,
+                                             GFC_ARRAY_UNKNOWN, false);
+  tree desc = gfc_create_var (desc_type, "desc");
+  DECL_ARTIFICIAL (desc) = 1;
+
+  gfc_clear_descriptor (&se->pre, sym, expr, desc);
+
+#if 0
+  /* Copy pointer address back - but only if it could have changed and
+     if the actual argument is a pointer and not, e.g., NULL().  */
+  if ((attr.pointer || attr.allocatable) && attr.intent != INTENT_IN)
+    gfc_add_modify (&se->post, scalar,
+                   fold_convert (TREE_TYPE (scalar),
+                                 gfc_conv_descriptor_data_get (desc)));
+#endif
+
+  return desc;
+}
+
+
 tree
 gfc_conv_scalar_to_descriptor (gfc_se *se, tree scalar, symbol_attribute attr)
 {
@@ -6431,7 +6467,10 @@ conv_null_actual (gfc_se * parmse, gfc_expr * e, 
gfc_symbol * fsym)
          if (fsym->as && fsym->as->type == AS_ASSUMED_RANK)
            {
              tree tmp = parmse->expr;
-             tmp = gfc_conv_scalar_null_to_descriptor (parmse, fsym, tmp);
+             if (e->rank == 0)
+               tmp = gfc_conv_scalar_null_to_descriptor (parmse, fsym, e, tmp);
+             else
+               tmp = gfc_conv_null_array_descriptor (parmse, fsym, e);
              parmse->expr = gfc_build_addr_expr (NULL_TREE, tmp);
            }
          else

Reply via email to