https://gcc.gnu.org/g:1d87733fb2a12c4ed75b1d84af0731dfa646f0cd
commit 1d87733fb2a12c4ed75b1d84af0731dfa646f0cd Author: Mikael Morin <mik...@gcc.gnu.org> Date: Tue Feb 4 11:16:32 2025 +0100 Sauvegarde factorisation set_descriptor_from_scalar Correction régression allocate_with_source_15.f03 Nettoyage correction Correction régression allocate_with_mold_3 Correction allocate_with_source_16.f90 Correction régression assumed_rank_21.f90 Correction coarray_allocate_8.f08 Correction régression pr86470.f90 Correction régression dummy_3.f90 Diff: --- gcc/fortran/trans-array.cc | 204 +++++++++++++++++++++++++++++++-------------- gcc/fortran/trans-array.h | 2 +- gcc/fortran/trans-expr.cc | 67 +++++++++------ gcc/fortran/trans-types.cc | 47 +++++++---- gcc/fortran/trans-types.h | 1 + gcc/fortran/trans.h | 1 + 6 files changed, 218 insertions(+), 104 deletions(-) diff --git a/gcc/fortran/trans-array.cc b/gcc/fortran/trans-array.cc index 97d9f882ee4c..fd34c64fb16e 100644 --- a/gcc/fortran/trans-array.cc +++ b/gcc/fortran/trans-array.cc @@ -92,6 +92,7 @@ along with GCC; see the file COPYING3. If not see #include "trans-array.h" #include "trans-const.h" #include "dependency.h" +#include "gimplify.h" static bool gfc_get_array_constructor_size (mpz_t *, gfc_constructor_base); @@ -602,7 +603,7 @@ gfc_conv_descriptor_sm_get (tree desc, tree dim) } -static int +static bt get_type_info (const bt &type) { switch (type) @@ -613,11 +614,13 @@ get_type_info (const bt &type) case BT_COMPLEX: case BT_DERIVED: case BT_CHARACTER: - case BT_CLASS: case BT_VOID: case BT_UNSIGNED: return type; + case BT_CLASS: + return BT_DERIVED; + case BT_PROCEDURE: case BT_ASSUMED: return BT_VOID; @@ -674,9 +677,15 @@ get_size_info (gfc_typespec &ts) class modify_info { public: + virtual bool set_dtype () const { return is_initialization (); } + virtual bool use_tree_type () const { return false; } virtual bool is_initialization () const { return false; } virtual bool initialize_data () const { return false; } + virtual bool set_span () const { return false; } + virtual bool set_token () const { return true; } virtual tree get_data_value () const { return NULL_TREE; } + virtual bt get_type_type (const gfc_typespec &) const { return BT_UNKNOWN; } + virtual tree get_length (gfc_typespec *ts) const { return get_size_info (*ts); } }; class nullification : public modify_info @@ -700,8 +709,14 @@ class init_info : public modify_info public: virtual bool is_initialization () const { return true; } virtual gfc_typespec *get_type () const { return nullptr; } + virtual bt get_type_type (const gfc_typespec &) const; }; +bt +init_info::get_type_type (const gfc_typespec & type_info) const +{ + return get_type_info (type_info.type); +} class default_init : public init_info { @@ -731,23 +746,103 @@ public: virtual gfc_typespec *get_type () const { return &ts; } }; -class scalar_value : public init_info + +class scalar_value : public modify_info { private: - gfc_typespec &ts; + bool initialisation; + gfc_typespec *ts; tree value; + bool use_tree_type_; + bool clear_token; + tree get_elt_type () const; public: scalar_value(gfc_typespec &arg_ts, tree arg_value) - : ts(arg_ts), value(arg_value) { } + : initialisation(true), ts(&arg_ts), value(arg_value), use_tree_type_ (false), clear_token(true) { } + scalar_value(tree arg_value) + : initialisation(true), ts(nullptr), value(arg_value), use_tree_type_ (true), clear_token(false) { } + virtual bool is_initialization () const { return initialisation; } virtual bool initialize_data () const { return true; } - virtual tree get_data_value () const { return value; } - virtual gfc_typespec *get_type () const { return &ts; } + virtual tree get_data_value () const; + virtual gfc_typespec *get_type () const { return ts; } + virtual bool set_span () const { return true; } + virtual bool use_tree_type () const { return use_tree_type_; } + virtual bool set_token () const { return clear_token; } + virtual bt get_type_type (const gfc_typespec &) const; + virtual tree get_length (gfc_typespec *ts) const; }; +tree +scalar_value::get_data_value () const +{ + if (POINTER_TYPE_P (TREE_TYPE (value))) + return value; + else + return gfc_build_addr_expr (NULL_TREE, value); +} + +tree +scalar_value::get_elt_type () const +{ + tree tmp = value; + + if (POINTER_TYPE_P (TREE_TYPE (tmp))) + tmp = TREE_TYPE (tmp); + + tree etype = TREE_TYPE (tmp); + + /* For arrays, which are not scalar coarrays. */ + if (TREE_CODE (etype) == ARRAY_TYPE && !TYPE_STRING_FLAG (etype)) + etype = TREE_TYPE (etype); + + return etype; +} + +bt +scalar_value::get_type_type (const gfc_typespec & type_info) const +{ + bt n; + if (use_tree_type ()) + { + tree etype = get_elt_type (); + gfc_get_type_info (etype, &n, nullptr); + } + else + n = get_type_info (type_info.type); + + return n; +} + +tree +scalar_value::get_length (gfc_typespec * type_info) const +{ + bt n; + tree size; + if (use_tree_type ()) + { + if (TREE_CODE (value) == COMPONENT_REF) + { + tree parent_obj = TREE_OPERAND (value, 0); + tree len; + if (GFC_CLASS_TYPE_P (TREE_TYPE (parent_obj)) + && gfc_class_len_get (parent_obj, &len)) + return len; + } + + tree etype = get_elt_type (); + gfc_get_type_info (etype, &n, &size); + } + else + size = modify_info::get_length (type_info); + + return size; +} + + 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; @@ -758,15 +853,17 @@ build_dtype (gfc_typespec &ts, int rank, const symbol_attribute &, gfc_typespec *type_info = init.get_type (); if (type_info == nullptr) - type_info = &ts; + type_info = ts; - if (!(type_info->type == BT_CLASS - || (type_info->type == BT_CHARACTER - && type_info->deferred))) + if (!(init.is_initialization () + && type_info + && (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 (*type_info)); + init.get_length (type_info)); CONSTRUCTOR_APPEND_ELT (v, elem_len_field, elem_len_val); } @@ -782,10 +879,8 @@ build_dtype (gfc_typespec &ts, int rank, const symbol_attribute &, } 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 (type_info->type == BT_CLASS - ? BT_DERIVED - : type_info->type)); + bt n = init.get_type_type (*type_info); + tree type_info_val = build_int_cst (TREE_TYPE (type_info_field), n); CONSTRUCTOR_APPEND_ELT (v, type_info_field, type_info_val); return build_constructor (type, v); @@ -809,24 +904,36 @@ get_descriptor_init (tree type, gfc_typespec *ts, int rank, { tree data_field = gfc_advance_chain (fields, DATA_FIELD); tree data_value = init.get_data_value (); + data_value = fold_convert (TREE_TYPE (data_field), data_value); CONSTRUCTOR_APPEND_ELT (v, data_field, data_value); } if (init.is_initialization ()) { 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, static_cast<const init_info &> (init)); CONSTRUCTOR_APPEND_ELT (v, dtype_field, dtype_value); } - if (flag_coarray == GFC_FCOARRAY_LIB && attr->codimension) + if (init.set_span ()) + { + tree span_field = gfc_advance_chain (fields, SPAN_FIELD); + tree span_value = build_zero_cst (TREE_TYPE (span_field)); + CONSTRUCTOR_APPEND_ELT (v, span_field, span_value); + } + + if (flag_coarray == GFC_FCOARRAY_LIB && attr->codimension + && init.set_token ()) { /* Declare the variable static so its array descriptor stays present after leaving the scope. It may still be accessed through another image. This may happen, for example, with the caf_mpi implementation. */ - tree token_field = gfc_advance_chain (fields, CAF_TOKEN_FIELD); + bool dim_present = GFC_TYPE_ARRAY_RANK (type) > 0 + || GFC_TYPE_ARRAY_CORANK (type) > 0; + tree token_field = gfc_advance_chain (fields, + CAF_TOKEN_FIELD - (!dim_present)); tree token_value = fold_convert (TREE_TYPE (token_field), null_pointer_node); CONSTRUCTOR_APPEND_ELT (v, token_field, token_value); @@ -1063,7 +1170,8 @@ init_struct (stmtblock_t *block, tree data_ref, init_kind kind, FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (value), i, field, field_init) { tree ref = fold_build3_loc (input_location, COMPONENT_REF, - TREE_TYPE (field), data_ref, + TREE_TYPE (field), + unshare_expr (data_ref), field, NULL_TREE); init_struct (block, ref, field_init); } @@ -1084,7 +1192,8 @@ init_struct (stmtblock_t *block, tree data_ref, init_kind kind, { tree field_decl = ce->index; tree ref = fold_build3_loc (input_location, COMPONENT_REF, - TREE_TYPE (field_decl), data_ref, + TREE_TYPE (field_decl), + unshare_expr (data_ref), field_decl, NULL_TREE); init_struct (block, ref, ce->value); } @@ -1199,6 +1308,16 @@ gfc_set_scalar_descriptor (stmtblock_t *block, tree descriptor, } +void +gfc_set_descriptor_from_scalar (stmtblock_t *block, tree desc, tree scalar, + symbol_attribute *attr) +{ + init_struct (block, desc, + get_descriptor_init (TREE_TYPE (desc), nullptr, 0, attr, + scalar_value (scalar))); +} + + /* Build a null array descriptor constructor. */ tree @@ -1828,47 +1947,6 @@ gfc_get_scalar_to_descriptor_type (tree scalar, symbol_attribute attr) } -void -gfc_set_descriptor_from_scalar (stmtblock_t *block, tree desc, tree scalar, - symbol_attribute scalar_attr, bool is_class, - tree cond_optional) -{ - tree type = gfc_get_scalar_to_descriptor_type (scalar, scalar_attr); - if (POINTER_TYPE_P (type)) - type = TREE_TYPE (type); - - tree etype = gfc_get_element_type (type); - tree dtype_val; - if (etype == void_type_node) - dtype_val = gfc_get_dtype_rank_type (0, TREE_TYPE (scalar)); - else - dtype_val = gfc_get_dtype (type); - - tree dtype_ref = gfc_conv_descriptor_dtype (desc); - gfc_add_modify (block, dtype_ref, dtype_val); - - gfc_conv_descriptor_span_set (block, desc, integer_zero_node); - - tree tmp; - if (is_class) - tmp = gfc_class_data_get (scalar); - else - tmp = scalar; - - if (!POINTER_TYPE_P (TREE_TYPE (tmp))) - tmp = gfc_build_addr_expr (NULL_TREE, tmp); - - if (cond_optional) - { - tmp = build3_loc (input_location, COND_EXPR, TREE_TYPE (tmp), - cond_optional, tmp, - fold_convert (TREE_TYPE (scalar), - null_pointer_node)); - } - - gfc_conv_descriptor_data_set (block, desc, tmp); -} - void gfc_copy_sequence_descriptor (stmtblock_t &block, tree lhs_desc, tree rhs_desc, bool assumed_rank_lhs) diff --git a/gcc/fortran/trans-array.h b/gcc/fortran/trans-array.h index a4e49ba705ee..97cf7f8cb41f 100644 --- a/gcc/fortran/trans-array.h +++ b/gcc/fortran/trans-array.h @@ -149,7 +149,7 @@ void gfc_set_descriptor_with_shape (stmtblock_t *, tree, tree, gfc_expr *, locus *); tree gfc_get_scalar_to_descriptor_type (tree scalar, symbol_attribute attr); void gfc_set_descriptor_from_scalar (stmtblock_t *, tree, tree, - symbol_attribute, bool, tree); + symbol_attribute *); void gfc_copy_sequence_descriptor (stmtblock_t &, tree, tree, bool); void gfc_set_gfc_from_cfi (stmtblock_t *, stmtblock_t *, tree, tree, tree, gfc_symbol *, bool, bool, bool); diff --git a/gcc/fortran/trans-expr.cc b/gcc/fortran/trans-expr.cc index 7de96638f159..8bf985dcac58 100644 --- a/gcc/fortran/trans-expr.cc +++ b/gcc/fortran/trans-expr.cc @@ -167,8 +167,7 @@ gfc_conv_scalar_to_descriptor (gfc_se *se, tree scalar, symbol_attribute attr) scalar = tmp; } - gfc_set_descriptor_from_scalar (&se->pre, desc, scalar, attr, - false, NULL_TREE); + gfc_set_descriptor_from_scalar (&se->pre, desc, scalar, &attr); /* Copy pointer address back - but only if it could have changed and if the actual argument is a pointer and not, e.g., NULL(). */ @@ -311,8 +310,8 @@ gfc_class_vptr_get (tree decl) } -tree -gfc_class_len_get (tree decl) +bool +gfc_class_len_get (tree decl, tree * result) { tree len; /* For class arrays decl may be a temporary descriptor handle, the len is @@ -324,9 +323,22 @@ gfc_class_len_get (tree decl) decl = build_fold_indirect_ref_loc (input_location, decl); len = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (decl)), CLASS_LEN_FIELD); - return fold_build3_loc (input_location, COMPONENT_REF, - TREE_TYPE (len), decl, len, - NULL_TREE); + if (len == NULL_TREE) + return false; + + *result = fold_build3_loc (input_location, COMPONENT_REF, + TREE_TYPE (len), decl, len, + NULL_TREE); + return true; +} + + +tree +gfc_class_len_get (tree decl) +{ + tree result; + gfc_class_len_get (decl, &result); + return result; } @@ -336,20 +348,11 @@ gfc_class_len_get (tree decl) static tree gfc_class_len_or_zero_get (tree decl) { - tree len; - /* For class arrays decl may be a temporary descriptor handle, the vptr is - then available through the saved descriptor. */ - if (VAR_P (decl) && DECL_LANG_SPECIFIC (decl) - && GFC_DECL_SAVED_DESCRIPTOR (decl)) - decl = GFC_DECL_SAVED_DESCRIPTOR (decl); - if (POINTER_TYPE_P (TREE_TYPE (decl))) - decl = build_fold_indirect_ref_loc (input_location, decl); - len = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (decl)), - CLASS_LEN_FIELD); - return len != NULL_TREE ? fold_build3_loc (input_location, COMPONENT_REF, - TREE_TYPE (len), decl, len, - NULL_TREE) - : build_zero_cst (gfc_charlen_type_node); + tree result; + if (gfc_class_len_get (decl, &result)) + return result; + else + return build_zero_cst (gfc_charlen_type_node); } @@ -953,9 +956,18 @@ gfc_conv_derived_to_class (gfc_se *parmse, gfc_expr *e, gfc_symbol *fsym, /* Scalar to an assumed-rank array. */ if (fsym->ts.u.derived->components->as) - gfc_set_descriptor_from_scalar (&parmse->pre, ctree, - parmse->expr, gfc_expr_attr (e), - false, cond_optional); + { + tree tmp = parmse->expr; + if (cond_optional) + { + tmp = build3_loc (input_location, COND_EXPR, TREE_TYPE (tmp), + cond_optional, tmp, + fold_convert (TREE_TYPE (tmp), + null_pointer_node)); + } + symbol_attribute attr = gfc_expr_attr (e); + gfc_set_descriptor_from_scalar (&parmse->pre, ctree, tmp, &attr); + } else { tmp = fold_convert (TREE_TYPE (ctree), parmse->expr); @@ -1330,8 +1342,11 @@ gfc_conv_class_to_class (gfc_se *parmse, gfc_expr *e, gfc_typespec class_ts, && e->rank != class_ts.u.derived->components->as->rank) { if (e->rank == 0) - gfc_set_descriptor_from_scalar (&block, ctree, parmse->expr, - gfc_expr_attr (e), true, NULL_TREE); + { + tree data = gfc_class_data_get (parmse->expr); + symbol_attribute attr = gfc_expr_attr (e); + gfc_set_descriptor_from_scalar (&block, ctree, data, &attr); + } else gfc_class_array_data_assign (&block, ctree, parmse->expr, false); } diff --git a/gcc/fortran/trans-types.cc b/gcc/fortran/trans-types.cc index 3374778cb650..c22d9bffd27a 100644 --- a/gcc/fortran/trans-types.cc +++ b/gcc/fortran/trans-types.cc @@ -1686,23 +1686,13 @@ gfc_get_desc_dim_type (void) } -/* Return the DTYPE for an array. This describes the type and type parameters - of the array. */ -/* TODO: Only call this when the value is actually used, and make all the - unknown cases abort. */ - -tree -gfc_get_dtype_rank_type (int rank, tree etype) +void +gfc_get_type_info (tree etype, bt *type, tree *psize) { - tree ptype; tree size; - int n; - tree tmp; - tree dtype; - tree field; - vec<constructor_elt, va_gc> *v = NULL; + bt n; - ptype = etype; + tree ptype = etype; while (TREE_CODE (etype) == POINTER_TYPE || TREE_CODE (etype) == ARRAY_TYPE) { @@ -1757,6 +1747,12 @@ gfc_get_dtype_rank_type (int rank, tree etype) gcc_unreachable (); } + if (type) + *type = n; + + if (psize == nullptr) + return; + switch (n) { case BT_CHARACTER: @@ -1776,6 +1772,29 @@ gfc_get_dtype_rank_type (int rank, tree etype) STRIP_NOPS (size); size = fold_convert (size_type_node, size); + + if (psize) + *psize = size; +} + + +/* Return the DTYPE for an array. This describes the type and type parameters + of the array. */ +/* TODO: Only call this when the value is actually used, and make all the + unknown cases abort. */ + +tree +gfc_get_dtype_rank_type (int rank, tree etype) +{ + tree size; + bt n; + tree tmp; + tree dtype; + tree field; + vec<constructor_elt, va_gc> *v = NULL; + + gfc_get_type_info (etype, &n, &size); + tmp = get_dtype_type_node (); field = gfc_advance_chain (TYPE_FIELDS (tmp), GFC_DTYPE_ELEM_LEN); diff --git a/gcc/fortran/trans-types.h b/gcc/fortran/trans-types.h index aba841da9cb5..1f1281524507 100644 --- a/gcc/fortran/trans-types.h +++ b/gcc/fortran/trans-types.h @@ -116,6 +116,7 @@ bool gfc_return_by_reference (gfc_symbol *); bool gfc_is_nodesc_array (gfc_symbol *); /* Return the DTYPE for an array. */ +void gfc_get_type_info (tree, bt *, tree *); tree gfc_get_dtype_rank_type (int, tree); tree gfc_get_dtype (tree, int *rank = NULL); diff --git a/gcc/fortran/trans.h b/gcc/fortran/trans.h index 81d5bb436536..28f81578e591 100644 --- a/gcc/fortran/trans.h +++ b/gcc/fortran/trans.h @@ -430,6 +430,7 @@ gfc_wrapped_block; tree gfc_class_set_static_fields (tree, tree, tree); tree gfc_class_data_get (tree); tree gfc_class_vptr_get (tree); +bool gfc_class_len_get (tree, tree *); tree gfc_class_len_get (tree); tree gfc_resize_class_size_with_len (stmtblock_t *, tree, tree); gfc_expr * gfc_find_and_cut_at_last_class_ref (gfc_expr *, bool is_mold = false,