https://gcc.gnu.org/g:c7cdf4adf4da35194d460805953e62ef70384a43
commit c7cdf4adf4da35194d460805953e62ef70384a43 Author: Mikael Morin <mik...@gcc.gnu.org> Date: Thu Dec 12 20:44:58 2024 +0100 Sauvegarde compilation OK Diff: --- gcc/fortran/trans-array.cc | 247 +++++++++++++++++++++++++++++++++++++++------ gcc/fortran/trans-array.h | 1 + gcc/fortran/trans-expr.cc | 38 ++++++- 3 files changed, 250 insertions(+), 36 deletions(-) diff --git a/gcc/fortran/trans-array.cc b/gcc/fortran/trans-array.cc index 4a686e8bf20b..a9b2d19b355a 100644 --- a/gcc/fortran/trans-array.cc +++ b/gcc/fortran/trans-array.cc @@ -656,8 +656,8 @@ build_dtype (gfc_typespec &ts, int rank, const symbol_attribute &) /* Build a null array descriptor constructor. */ vec<constructor_elt, va_gc> * -get_default_descriptor_init (tree type, gfc_typespec &ts, int rank, - const symbol_attribute &attr) +get_descriptor_init (tree type, gfc_typespec &ts, int rank, + const symbol_attribute &attr, tree data_value) { vec<constructor_elt, va_gc> *v = nullptr; @@ -666,10 +666,9 @@ get_default_descriptor_init (tree type, gfc_typespec &ts, int rank, tree fields = TYPE_FIELDS (type); /* Don't init pointers by default. */ - if (!attr.pointer) + if (data_value) { tree data_field = gfc_advance_chain (fields, DATA_FIELD); - tree data_value = fold_convert (TREE_TYPE (data_field), null_pointer_node); CONSTRUCTOR_APPEND_ELT (v, data_field, data_value); } @@ -694,43 +693,73 @@ get_default_descriptor_init (tree type, gfc_typespec &ts, int rank, vec<constructor_elt, va_gc> * -get_null_descriptor_init (tree type, gfc_typespec &ts, int rank, - const symbol_attribute &attr) +get_default_array_descriptor_init (tree type, gfc_typespec &ts, int rank, + const symbol_attribute &attr) +{ + 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) + { + 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); +} + + +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_descriptor_init (type, ts, rank, attr2); + return get_default_array_descriptor_init (type, ts, rank, attr2); } tree -gfc_build_default_descriptor (tree type, gfc_typespec &ts, int rank, - const symbol_attribute &attr) +gfc_build_default_array_descriptor (tree type, gfc_typespec &ts, int rank, + const symbol_attribute &attr) { gcc_assert (GFC_DESCRIPTOR_TYPE_P (type)); return build_constructor (type, - get_default_descriptor_init (type, ts, rank, attr)); + get_default_array_descriptor_init (type, ts, rank, + attr)); } tree -gfc_build_null_descriptor (tree type, gfc_typespec &ts, int rank, - const symbol_attribute &attr) +gfc_build_null_array_descriptor (tree type, gfc_typespec &ts, int rank, + const symbol_attribute &attr) { gcc_assert (GFC_DESCRIPTOR_TYPE_P (type)); return build_constructor (type, - get_null_descriptor_init (type, ts, rank, attr)); + get_null_array_descriptor_init (type, ts, rank, + attr)); } tree -gfc_build_null_descriptor (tree type, gfc_typespec &ts, - const symbol_attribute &attr) +gfc_build_null_array_descriptor (tree type, gfc_typespec &ts, + const symbol_attribute &attr) { - return gfc_build_null_descriptor (type, ts, -1, attr); + return gfc_build_null_array_descriptor (type, ts, -1, attr); } @@ -754,10 +783,10 @@ gfc_build_default_class_descriptor (tree type, gfc_typespec &ts) && flag_coarray != GFC_FCOARRAY_LIB)) { gcc_assert (GFC_DESCRIPTOR_TYPE_P (data_type)); - data_value = gfc_build_null_descriptor (data_type, - ts, - ts.u.derived->components->as->rank, - ts.u.derived->components->attr); + gfc_component *data_comp = ts.u.derived->components; + data_value = gfc_build_null_array_descriptor (data_type, ts, + data_comp->as->rank, + data_comp->attr); } else { @@ -797,12 +826,159 @@ gfc_clear_descriptor (gfc_expr *var_ref, gfc_se &var) attr = gfc_expr_attr (var_ref); gfc_add_modify (&var.pre, var.expr, - gfc_build_null_descriptor (TREE_TYPE (var.expr), var_ref->ts, - rank, attr)); + gfc_build_null_array_descriptor (TREE_TYPE (var.expr), + var_ref->ts, + rank, attr)); } -void +static int +field_count (tree type) +{ + gcc_assert (TREE_CODE (type) == RECORD_TYPE); + + int count = 0; + tree field = TYPE_FIELDS (type); + while (field != NULL_TREE) + { + count++; + field = DECL_CHAIN (field); + } + + return count; +} + + +bool +complete_init_p (tree type, vec<constructor_elt, va_gc> *init_values) +{ + return (unsigned) field_count (type) == vec_safe_length (init_values); +} + + +static bool +modifiable_p (tree data_ref) +{ + switch (TREE_CODE (data_ref)) + { + case CONST_DECL: + return false; + + case VAR_DECL: + case PARM_DECL: + case RESULT_DECL: + return !TREE_CONSTANT (data_ref) && !TREE_READONLY (data_ref); + + case COMPONENT_REF: + { + tree field_decl = TREE_OPERAND (data_ref, 1); + + if (TREE_CONSTANT (field_decl) || TREE_READONLY (field_decl)) + return false; + } + + /* fallthrough */ + case ARRAY_REF: + case ARRAY_RANGE_REF: + case REALPART_EXPR: + case IMAGPART_EXPR: + case VIEW_CONVERT_EXPR: + case NOP_EXPR: + { + tree parent_ref = TREE_OPERAND (data_ref, 0); + return modifiable_p (parent_ref); + } + + default: + gcc_unreachable (); + } +} + + +typedef enum +{ + SINGLE, + MULTIPLE +} init_kind; + +typedef union +{ + tree single; + vec<constructor_elt, va_gc> *multiple; +} init_values; + +static void +init_struct (stmtblock_t *block, tree data_ref, tree value); + +static void +init_struct (stmtblock_t *block, tree data_ref, init_kind kind, + init_values values) +{ + tree type = TREE_TYPE (data_ref); + gcc_assert (TREE_CODE (type) == RECORD_TYPE); + + if (kind == SINGLE) + { + tree value = values.single; + if (TREE_STATIC (data_ref) + || !modifiable_p (data_ref)) + DECL_INITIAL (data_ref) = value; + else if (TREE_CODE (value) == CONSTRUCTOR) + { + unsigned i; + tree field, field_init; + 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, + field, NULL_TREE); + init_struct (block, ref, field_init); + } + } + else + gfc_add_modify (block, data_ref, value); + } + else if (TREE_STATIC (data_ref)) + return init_struct (block, data_ref, + build_constructor (type, values.multiple)); + else + { + unsigned i; + constructor_elt *ce; + FOR_EACH_VEC_ELT (*values.multiple, i, ce) + { + tree field_decl = ce->index; + tree ref = fold_build3_loc (input_location, COMPONENT_REF, + TREE_TYPE (field_decl), data_ref, + field_decl, NULL_TREE); + init_struct (block, ref, ce->value); + } + } +} + + +static void +init_struct (stmtblock_t *block, tree data_ref, tree value) +{ + init_values wrapped_values; + wrapped_values.single = value; + + return init_struct (block, data_ref, SINGLE, wrapped_values); +} + + +static void +init_struct (stmtblock_t *block, tree data_ref, + vec<constructor_elt, va_gc> *values) +{ + init_values wrapped_values; + wrapped_values.multiple = values; + + return init_struct (block, data_ref, MULTIPLE, wrapped_values); +} + + +static void set_from_constructor_elts (stmtblock_t *block, tree data_ref, vec<constructor_elt, va_gc> *constructor_values) { @@ -831,14 +1007,23 @@ gfc_clear_descriptor (stmtblock_t *block, gfc_symbol *sym, tree descriptor) attr = gfc_symbol_attr (sym); - if (TREE_STATIC (descriptor)) - gfc_add_modify (block, descriptor, - gfc_build_null_descriptor (TREE_TYPE (descriptor), sym->ts, - rank, attr)); - else - set_from_constructor_elts (block, descriptor, - get_null_descriptor_init (TREE_TYPE (descriptor), - sym->ts, rank, attr)); + init_struct (block, descriptor, + get_null_array_descriptor_init (TREE_TYPE (descriptor), + sym->ts, rank, attr)); +} + + +void +gfc_clear_scalar_descriptor (stmtblock_t *block, tree descriptor, + gfc_symbol *sym, tree value) +{ + symbol_attribute attr; + + attr = gfc_symbol_attr (sym); + + init_struct (block, descriptor, + get_descriptor_init (TREE_TYPE (descriptor), sym->ts, 0, + attr, value)); } diff --git a/gcc/fortran/trans-array.h b/gcc/fortran/trans-array.h index 58b7a6aec336..c6e4b2c63a5d 100644 --- a/gcc/fortran/trans-array.h +++ b/gcc/fortran/trans-array.h @@ -142,6 +142,7 @@ void gfc_conv_resolve_dependencies (gfc_loopinfo *, gfc_ss *, gfc_ss *); 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); /* 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 dcbc75844fda..ce8392b7547b 100644 --- a/gcc/fortran/trans-expr.cc +++ b/gcc/fortran/trans-expr.cc @@ -104,6 +104,38 @@ get_scalar_to_descriptor_type (tree scalar, symbol_attribute attr) akind, !(attr.pointer || attr.target)); } + +tree +gfc_conv_scalar_null_to_descriptor (gfc_se *se, gfc_symbol *sym, tree scalar) +{ + symbol_attribute attr = sym->attr; + + tree type = get_scalar_to_descriptor_type (scalar, attr); + tree desc = gfc_create_var (type, "desc"); + DECL_ARTIFICIAL (desc) = 1; + + if (CONSTANT_CLASS_P (scalar)) + { + tree tmp; + tmp = gfc_create_var (TREE_TYPE (scalar), "scalar"); + gfc_add_modify (&se->pre, tmp, scalar); + scalar = tmp; + } + if (!POINTER_TYPE_P (TREE_TYPE (scalar))) + scalar = gfc_build_addr_expr (NULL_TREE, scalar); + + gfc_clear_scalar_descriptor (&se->pre, desc, sym, 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(). */ + 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))); + return desc; +} + + tree gfc_conv_scalar_to_descriptor (gfc_se *se, tree scalar, symbol_attribute attr) { @@ -6398,12 +6430,8 @@ conv_null_actual (gfc_se * parmse, gfc_expr * e, gfc_symbol * fsym) correct rank. */ if (fsym->as && fsym->as->type == AS_ASSUMED_RANK) { - tree rank; tree tmp = parmse->expr; - tmp = gfc_conv_scalar_to_descriptor (parmse, tmp, fsym->attr); - rank = gfc_conv_descriptor_rank (tmp); - gfc_add_modify (&parmse->pre, rank, - build_int_cst (TREE_TYPE (rank), e->rank)); + tmp = gfc_conv_scalar_null_to_descriptor (parmse, fsym, tmp); parmse->expr = gfc_build_addr_expr (NULL_TREE, tmp); } else