diff options
author | pault <pault@138bc75d-0d04-0410-961f-82ee72b054a4> | 2016-09-20 19:54:21 +0000 |
---|---|---|
committer | pault <pault@138bc75d-0d04-0410-961f-82ee72b054a4> | 2016-09-20 19:54:21 +0000 |
commit | 12cdcb9d74f55c165366ca1b1eeec013a0ce72ef (patch) | |
tree | b79ad0a85f6191e8e72d8a85039eda8ae7122c25 /gcc/fortran/trans-array.c | |
parent | 3671d3f0f3ac90ac5cf866c354aead6a04cad290 (diff) | |
download | gcc-12cdcb9d74f55c165366ca1b1eeec013a0ce72ef.tar.gz |
2016-20-10 Paul Thomas <pault@gcc.gnu.org>
* trans-array.c (gfc_conv_expr_descriptor): Detect class object
with an abstract declared type. Use the type of the data field
and the dynamic element length from the symbol backend_decl.
* trans-decl.c (gfc_trans_deferred_vars): Initialize the
descriptor of allocatable class arrays..
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/fortran-dev@240287 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/fortran/trans-array.c')
-rw-r--r-- | gcc/fortran/trans-array.c | 27 |
1 files changed, 26 insertions, 1 deletions
diff --git a/gcc/fortran/trans-array.c b/gcc/fortran/trans-array.c index a7d9331b58b..7706ba95423 100644 --- a/gcc/fortran/trans-array.c +++ b/gcc/fortran/trans-array.c @@ -7017,6 +7017,7 @@ gfc_conv_expr_descriptor (gfc_se *se, gfc_expr *expr) int full; bool subref_array_target = false; bool assumed_size = false; + bool abstract_class = false; gfc_expr *arg, *ss_expr; if (se->want_coarray) @@ -7340,7 +7341,19 @@ gfc_conv_expr_descriptor (gfc_se *se, gfc_expr *expr) } desc = info->descriptor; - elem_type = gfc_typenode_for_spec(&expr->ts); + + /* Classes with an abstract declared type present particular problems + because they mess up the 'desc' totally and they have to be detected + to provide the dynamic type elem_len. + TODO extend this to all class expressions. */ + abstract_class = gfc_expr_attr (expr).abstract + && expr->expr_type == EXPR_VARIABLE + && expr->symtree->n.sym->ts.type == BT_CLASS; + + if (abstract_class) + elem_type = gfc_typenode_for_spec(&CLASS_DATA (expr->symtree->n.sym)->ts); + else + elem_type = gfc_typenode_for_spec(&expr->ts); if (se->direct_byref && !se->byref_noassign) { @@ -7372,6 +7385,18 @@ gfc_conv_expr_descriptor (gfc_se *se, gfc_expr *expr) /* Set elem_len, version, rank, dtype and attribute. */ if (expr->ts.type == BT_CHARACTER && !is_subref_array (expr)) elem_len = size_of_string_in_bytes (expr->ts.kind, se->string_length); + else if (abstract_class) + { + tmp = expr->symtree->n.sym->backend_decl; + if (DECL_LANG_SPECIFIC (tmp) && GFC_DECL_SAVED_DESCRIPTOR (tmp)) + tmp = GFC_DECL_SAVED_DESCRIPTOR (tmp); + + tmp = gfc_get_vptr_from_expr (tmp); + if (tmp != NULL_TREE) + elem_len = gfc_vptr_size_get (tmp); + else + elem_len = size_in_bytes (gfc_get_element_type (TREE_TYPE (desc))); + } else /* TODO Set this to the size of elem_type rather than the size of the descriptor elements. */ |