diff options
author | Paul Thomas <pault@gcc.gnu.org> | 2023-06-28 12:38:58 +0100 |
---|---|---|
committer | Paul Thomas <pault@gcc.gnu.org> | 2023-06-28 12:38:58 +0100 |
commit | 3521768e8e3c448052c5bd3e8fde412e9cf5d70f (patch) | |
tree | 712a8d50da805e6d9aa69e0b47657f5e107f4f35 /gcc/fortran | |
parent | 4afbebcdc5780d28e52b7d65643e462c7c3882ce (diff) | |
download | gcc-3521768e8e3c448052c5bd3e8fde412e9cf5d70f.zip gcc-3521768e8e3c448052c5bd3e8fde412e9cf5d70f.tar.gz gcc-3521768e8e3c448052c5bd3e8fde412e9cf5d70f.tar.bz2 |
Fortran: Enable class expressions in structure constructors [PR49213]
2023-06-28 Paul Thomas <pault@gcc.gnu.org>
gcc/fortran
PR fortran/49213
* expr.cc (gfc_is_ptr_fcn): Remove reference to class_pointer.
* resolve.cc (resolve_assoc_var): Call gfc_is_ptr_fcn to allow
associate names with pointer function targets to be used in
variable definition context.
* trans-decl.cc (get_symbol_decl): Remove extraneous line.
* trans-expr.cc (alloc_scalar_allocatable_subcomponent): Obtain
size of intrinsic and character expressions.
(gfc_trans_subcomponent_assign): Expand assignment to class
components to include intrinsic and character expressions.
gcc/testsuite/
PR fortran/49213
* gfortran.dg/pr49213.f90 : New test
Diffstat (limited to 'gcc/fortran')
-rw-r--r-- | gcc/fortran/expr.cc | 4 | ||||
-rw-r--r-- | gcc/fortran/resolve.cc | 5 | ||||
-rw-r--r-- | gcc/fortran/trans-decl.cc | 1 | ||||
-rw-r--r-- | gcc/fortran/trans-expr.cc | 59 |
4 files changed, 57 insertions, 12 deletions
diff --git a/gcc/fortran/expr.cc b/gcc/fortran/expr.cc index c960dfe..e418f1f 100644 --- a/gcc/fortran/expr.cc +++ b/gcc/fortran/expr.cc @@ -816,9 +816,7 @@ bool gfc_is_ptr_fcn (gfc_expr *e) { return e != NULL && e->expr_type == EXPR_FUNCTION - && (gfc_expr_attr (e).pointer - || (e->ts.type == BT_CLASS - && CLASS_DATA (e)->attr.class_pointer)); + && gfc_expr_attr (e).pointer; } diff --git a/gcc/fortran/resolve.cc b/gcc/fortran/resolve.cc index 82e6ac5..8e018b6 100644 --- a/gcc/fortran/resolve.cc +++ b/gcc/fortran/resolve.cc @@ -1350,6 +1350,9 @@ resolve_structure_cons (gfc_expr *expr, int init) && CLASS_DATA (comp)->as) rank = CLASS_DATA (comp)->as->rank; + if (comp->ts.type == BT_CLASS && cons->expr->ts.type != BT_CLASS) + gfc_find_vtab (&cons->expr->ts); + if (cons->expr->expr_type != EXPR_NULL && rank != cons->expr->rank && (comp->attr.allocatable || cons->expr->rank)) { @@ -1381,7 +1384,7 @@ resolve_structure_cons (gfc_expr *expr, int init) gfc_basic_typename (comp->ts.type)); t = false; } - else + else if (!UNLIMITED_POLY (comp)) { bool t2 = gfc_convert_type (cons->expr, &comp->ts, 1); if (t) diff --git a/gcc/fortran/trans-decl.cc b/gcc/fortran/trans-decl.cc index 18589e1..b0fd25e 100644 --- a/gcc/fortran/trans-decl.cc +++ b/gcc/fortran/trans-decl.cc @@ -1915,7 +1915,6 @@ gfc_get_symbol_decl (gfc_symbol * sym) gcc_assert (!sym->value || sym->value->expr_type == EXPR_NULL); } - gfc_finish_var_decl (decl, sym); if (sym->ts.type == BT_CHARACTER) diff --git a/gcc/fortran/trans-expr.cc b/gcc/fortran/trans-expr.cc index 63e3cf9..ad0cdf9 100644 --- a/gcc/fortran/trans-expr.cc +++ b/gcc/fortran/trans-expr.cc @@ -8805,6 +8805,7 @@ alloc_scalar_allocatable_subcomponent (stmtblock_t *block, tree comp, tree size; tree size_in_bytes; tree lhs_cl_size = NULL_TREE; + gfc_se se; if (!comp) return; @@ -8839,16 +8840,30 @@ alloc_scalar_allocatable_subcomponent (stmtblock_t *block, tree comp, } else if (cm->ts.type == BT_CLASS) { - gcc_assert (expr2->ts.type == BT_CLASS || expr2->ts.type == BT_DERIVED); - if (expr2->ts.type == BT_DERIVED) + if (expr2->ts.type != BT_CLASS) { - tmp = gfc_get_symbol_decl (expr2->ts.u.derived); - size = TYPE_SIZE_UNIT (tmp); + if (expr2->ts.type == BT_CHARACTER) + { + gfc_init_se (&se, NULL); + gfc_conv_expr (&se, expr2); + size = build_int_cst (gfc_charlen_type_node, expr2->ts.kind); + size = fold_build2_loc (input_location, MULT_EXPR, + gfc_charlen_type_node, + se.string_length, size); + size = fold_convert (size_type_node, size); + } + else + { + if (expr2->ts.type == BT_DERIVED) + tmp = gfc_get_symbol_decl (expr2->ts.u.derived); + else + tmp = gfc_typenode_for_spec (&expr2->ts); + size = TYPE_SIZE_UNIT (tmp); + } } else { gfc_expr *e2vtab; - gfc_se se; e2vtab = gfc_find_and_cut_at_last_class_ref (expr2); gfc_add_vptr_component (e2vtab); gfc_add_size_component (e2vtab); @@ -8999,6 +9014,7 @@ gfc_trans_subcomponent_assign (tree dest, gfc_component * cm, { gfc_init_se (&se, NULL); gfc_conv_expr (&se, expr); + tree size; /* Take care about non-array allocatable components here. The alloc_* routine below is motivated by the alloc_scalar_allocatable_for_ @@ -9014,7 +9030,7 @@ gfc_trans_subcomponent_assign (tree dest, gfc_component * cm, && expr->symtree->n.sym->attr.dummy) se.expr = build_fold_indirect_ref_loc (input_location, se.expr); - if (cm->ts.type == BT_CLASS && expr->ts.type == BT_DERIVED) + if (cm->ts.type == BT_CLASS) { tmp = gfc_class_data_get (dest); tmp = build_fold_indirect_ref_loc (input_location, tmp); @@ -9029,7 +9045,6 @@ gfc_trans_subcomponent_assign (tree dest, gfc_component * cm, /* For deferred strings insert a memcpy. */ if (cm->ts.type == BT_CHARACTER && cm->ts.deferred) { - tree size; gcc_assert (se.string_length || expr->ts.u.cl->backend_decl); size = size_of_string_in_bytes (cm->ts.kind, se.string_length ? se.string_length @@ -9037,6 +9052,36 @@ gfc_trans_subcomponent_assign (tree dest, gfc_component * cm, tmp = gfc_build_memcpy_call (tmp, se.expr, size); gfc_add_expr_to_block (&block, tmp); } + else if (cm->ts.type == BT_CLASS) + { + /* Fix the expression for memcpy. */ + if (expr->expr_type != EXPR_VARIABLE) + se.expr = gfc_evaluate_now (se.expr, &block); + + if (expr->ts.type == BT_CHARACTER) + { + size = build_int_cst (gfc_charlen_type_node, expr->ts.kind); + size = fold_build2_loc (input_location, MULT_EXPR, + gfc_charlen_type_node, + se.string_length, size); + size = fold_convert (size_type_node, size); + } + else + size = TYPE_SIZE_UNIT (gfc_typenode_for_spec (&expr->ts)); + + /* Now copy the expression to the constructor component _data. */ + gfc_add_expr_to_block (&block, + gfc_build_memcpy_call (tmp, se.expr, size)); + + /* Fill the unlimited polymorphic _len field. */ + if (UNLIMITED_POLY (cm) && expr->ts.type == BT_CHARACTER) + { + tmp = gfc_class_len_get (gfc_get_class_from_expr (tmp)); + gfc_add_modify (&block, tmp, + fold_convert (TREE_TYPE (tmp), + se.string_length)); + } + } else gfc_add_modify (&block, tmp, fold_convert (TREE_TYPE (tmp), se.expr)); |