diff options
author | Paul Thomas <pault@gcc.gnu.org> | 2006-05-26 05:09:18 +0000 |
---|---|---|
committer | Paul Thomas <pault@gcc.gnu.org> | 2006-05-26 05:09:18 +0000 |
commit | 014057c510440341c2f1135c23fd4da2a42f765b (patch) | |
tree | 77c6438a1e7d93720520b1669b3cd5510e89eeea /gcc/fortran | |
parent | 3d26efa9eb9e6f032611bf559a6c31c925fc7295 (diff) | |
download | gcc-014057c510440341c2f1135c23fd4da2a42f765b.zip gcc-014057c510440341c2f1135c23fd4da2a42f765b.tar.gz gcc-014057c510440341c2f1135c23fd4da2a42f765b.tar.bz2 |
re PR fortran/27709 (Using size of array pointer component as dimension of function result causes gfortran internal error.)
2006-05-26 Paul Thomas <pault@gcc.gnu.org>
PR fortran/27709
* resolve.c (find_array_spec): Add gfc_symbol, derived, and
use to track repeated component references.
PR fortran/27155
PR fortran/27449
* trans-intrinsic.c (gfc_conv_intrinsic_array_transfer): Use
se->string_length throughout and use memcpy to populate the
expression returned to the scalarizer.
(gfc_size_in_bytes): New function.
2006-05-26 Paul Thomas <pault@gcc.gnu.org>
PR fortran/27709
* gfortran.dg/spec_expr_4.f90: New test.
PR fortran/27155
* gfortran.dg/transfer_array_intrinsic_4.f90: New test.
From-SVN: r114127
Diffstat (limited to 'gcc/fortran')
-rw-r--r-- | gcc/fortran/ChangeLog | 13 | ||||
-rw-r--r-- | gcc/fortran/resolve.c | 16 | ||||
-rw-r--r-- | gcc/fortran/trans-intrinsic.c | 53 |
3 files changed, 70 insertions, 12 deletions
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index 7f80e37..0117eb6 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,16 @@ +2006-05-26 Paul Thomas <pault@gcc.gnu.org> + + PR fortran/27709 + * resolve.c (find_array_spec): Add gfc_symbol, derived, and + use to track repeated component references. + + PR fortran/27155 + PR fortran/27449 + * trans-intrinsic.c (gfc_conv_intrinsic_array_transfer): Use + se->string_length throughout and use memcpy to populate the + expression returned to the scalarizer. + (gfc_size_in_bytes): New function. + 2006-05-21 Paul Thomas <pault@gcc.gnu.org> PR fortran/27613 diff --git a/gcc/fortran/resolve.c b/gcc/fortran/resolve.c index 0affecc..660f1c0 100644 --- a/gcc/fortran/resolve.c +++ b/gcc/fortran/resolve.c @@ -2285,9 +2285,11 @@ find_array_spec (gfc_expr * e) { gfc_array_spec *as; gfc_component *c; + gfc_symbol *derived; gfc_ref *ref; as = e->symtree->n.sym->as; + derived = NULL; for (ref = e->ref; ref; ref = ref->next) switch (ref->type) @@ -2301,9 +2303,19 @@ find_array_spec (gfc_expr * e) break; case REF_COMPONENT: - for (c = e->symtree->n.sym->ts.derived->components; c; c = c->next) + if (derived == NULL) + derived = e->symtree->n.sym->ts.derived; + + c = derived->components; + + for (; c; c = c->next) if (c == ref->u.c.component) - break; + { + /* Track the sequence of component references. */ + if (c->ts.type == BT_DERIVED) + derived = c->ts.derived; + break; + } if (c == NULL) gfc_internal_error ("find_array_spec(): Component not found"); diff --git a/gcc/fortran/trans-intrinsic.c b/gcc/fortran/trans-intrinsic.c index eb5286e..1d1858c 100644 --- a/gcc/fortran/trans-intrinsic.c +++ b/gcc/fortran/trans-intrinsic.c @@ -2482,6 +2482,30 @@ gfc_conv_intrinsic_adjust (gfc_se * se, gfc_expr * expr, tree fndecl) } +/* A helper function for gfc_conv_intrinsic_array_transfer to compute + the size of tree expressions in bytes. */ +static tree +gfc_size_in_bytes (gfc_se *se, gfc_expr *e) +{ + tree tmp; + + if (e->ts.type == BT_CHARACTER) + tmp = se->string_length; + else + { + if (e->rank) + { + tmp = gfc_get_element_type (TREE_TYPE (se->expr)); + tmp = size_in_bytes (tmp); + } + else + tmp = size_in_bytes (TREE_TYPE (TREE_TYPE (se->expr))); + } + + return fold_convert (gfc_array_index_type, tmp); +} + + /* Array transfer statement. DEST(1:N) = TRANSFER (SOURCE, MOLD[, SIZE]) where: @@ -2504,6 +2528,7 @@ gfc_conv_intrinsic_array_transfer (gfc_se * se, gfc_expr * expr) tree lower; tree stride; tree stmt; + tree args; gfc_actual_arglist *arg; gfc_se argse; gfc_ss *ss; @@ -2530,8 +2555,7 @@ gfc_conv_intrinsic_array_transfer (gfc_se * se, gfc_expr * expr) source = argse.expr; /* Obtain the source word length. */ - tmp = size_in_bytes(TREE_TYPE(TREE_TYPE (source))); - tmp = fold_convert (gfc_array_index_type, tmp); + tmp = gfc_size_in_bytes (&argse, arg->expr); } else { @@ -2569,8 +2593,7 @@ gfc_conv_intrinsic_array_transfer (gfc_se * se, gfc_expr * expr) } /* Obtain the source word length. */ - tmp = gfc_get_element_type (TREE_TYPE(argse.expr)); - tmp = fold_convert (gfc_array_index_type, size_in_bytes (tmp)); + tmp = gfc_size_in_bytes (&argse, arg->expr); /* Obtain the size of the array in bytes. */ extent = gfc_create_var (gfc_array_index_type, NULL); @@ -2606,16 +2629,18 @@ gfc_conv_intrinsic_array_transfer (gfc_se * se, gfc_expr * expr) if (ss == gfc_ss_terminator) { gfc_conv_expr_reference (&argse, arg->expr); - tmp = TREE_TYPE(TREE_TYPE (argse.expr)); - tmp = fold_convert (gfc_array_index_type, size_in_bytes(tmp)); + + /* Obtain the source word length. */ + tmp = gfc_size_in_bytes (&argse, arg->expr); } else { gfc_init_se (&argse, NULL); argse.want_pointer = 0; gfc_conv_expr_descriptor (&argse, arg->expr, ss); - tmp = gfc_get_element_type (TREE_TYPE(argse.expr)); - tmp = fold_convert (gfc_array_index_type, size_in_bytes (tmp)); + + /* Obtain the source word length. */ + tmp = gfc_size_in_bytes (&argse, arg->expr); } dest_word_len = gfc_create_var (gfc_array_index_type, NULL); @@ -2687,10 +2712,18 @@ gfc_conv_intrinsic_array_transfer (gfc_se * se, gfc_expr * expr) data field. This is already allocated so set callee_alloc. */ tmp = gfc_typenode_for_spec (&expr->ts); gfc_trans_create_temp_array (&se->pre, &se->post, se->loop, - info, tmp, false, false, true); + info, tmp, false, true, false); + /* Use memcpy to do the transfer. */ + tmp = gfc_conv_descriptor_data_get (info->descriptor); + args = gfc_chainon_list (NULL_TREE, tmp); tmp = fold_convert (pvoid_type_node, source); - gfc_conv_descriptor_data_set (&se->pre, info->descriptor, tmp); + args = gfc_chainon_list (args, source); + args = gfc_chainon_list (args, size_bytes); + tmp = built_in_decls[BUILT_IN_MEMCPY]; + tmp = build_function_call_expr (tmp, args); + gfc_add_expr_to_block (&se->pre, tmp); + se->expr = info->descriptor; if (expr->ts.type == BT_CHARACTER) se->string_length = dest_word_len; |