diff options
author | Tobias Burnus <burnus@net-b.de> | 2013-07-30 09:18:54 +0200 |
---|---|---|
committer | Tobias Burnus <burnus@gcc.gnu.org> | 2013-07-30 09:18:54 +0200 |
commit | b882aaa84d700fc91c00ad314e876ce40aab370b (patch) | |
tree | 73dced4e09b669c48b2b9e9dd25db72d0c002a75 /gcc/fortran | |
parent | 14a8763670981928cef330b7bf8c0244bb982a29 (diff) | |
download | gcc-b882aaa84d700fc91c00ad314e876ce40aab370b.zip gcc-b882aaa84d700fc91c00ad314e876ce40aab370b.tar.gz gcc-b882aaa84d700fc91c00ad314e876ce40aab370b.tar.bz2 |
re PR fortran/57530 ([OOP] Wrongly rejects type_pointer => class_target (which have identical declared type))
2013-07-30 Tobias Burnus <burnus@net-b.de>
PR fortran/57530
* trans-expr.c (gfc_trans_class_assign): Handle CLASS array
functions.
(gfc_trans_pointer_assign): Ditto and support pointer assignment
of a polymorphic var to a nonpolymorphic var.
2013-07-30 Tobias Burnus <burnus@net-b.de>
PR fortran/57530
* gfortran.dg/pointer_assign_8.f90: New.
* gfortran.dg/pointer_assign_9.f90: New.
* gfortran.dg/pointer_assign_10.f90: New.
* gfortran.dg/pointer_assign_11.f90: New.
From-SVN: r201328
Diffstat (limited to 'gcc/fortran')
-rw-r--r-- | gcc/fortran/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/fortran/trans-expr.c | 103 |
2 files changed, 104 insertions, 7 deletions
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index 0d9788d..6e00cdc 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,11 @@ +2013-07-30 Tobias Burnus <burnus@net-b.de> + + PR fortran/57530 + * trans-expr.c (gfc_trans_class_assign): Handle CLASS array + functions. + (gfc_trans_pointer_assign): Ditto and support pointer assignment of + a polymorphic var to a nonpolymorphic var. + 2013-07-22 Po Chang <pchang9@cs.wisc.edu> * match.c (gfc_match_call): Exit loop after setting i. diff --git a/gcc/fortran/trans-expr.c b/gcc/fortran/trans-expr.c index e0cdd49..74e95b0 100644 --- a/gcc/fortran/trans-expr.c +++ b/gcc/fortran/trans-expr.c @@ -1043,7 +1043,7 @@ assign_vptr: gfc_add_data_component (expr2); goto assign; } - else if (CLASS_DATA (expr2)->attr.dimension) + else if (CLASS_DATA (expr2)->attr.dimension && expr2->expr_type != EXPR_FUNCTION) { /* Insert an additional assignment which sets the '_vptr' field. */ lhs = gfc_copy_expr (expr1); @@ -1061,9 +1061,10 @@ assign_vptr: /* Do the actual CLASS assignment. */ if (expr2->ts.type == BT_CLASS - && !CLASS_DATA (expr2)->attr.dimension) + && !CLASS_DATA (expr2)->attr.dimension) op = EXEC_ASSIGN; - else + else if (expr2->expr_type != EXPR_FUNCTION || expr2->ts.type != BT_CLASS + || !CLASS_DATA (expr2)->attr.dimension) gfc_add_data_component (expr1); assign: @@ -6417,6 +6418,7 @@ gfc_trans_pointer_assign (gfc_code * code) tree gfc_trans_pointer_assignment (gfc_expr * expr1, gfc_expr * expr2) { + gfc_expr *expr1_vptr = NULL; gfc_se lse; gfc_se rse; stmtblock_t block; @@ -6437,6 +6439,15 @@ gfc_trans_pointer_assignment (gfc_expr * expr1, gfc_expr * expr2) if (!scalar) gfc_free_ss_chain (ss); + if (expr1->ts.type == BT_DERIVED && expr2->ts.type == BT_CLASS + && expr2->expr_type != EXPR_FUNCTION) + { + gfc_add_data_component (expr2); + /* The following is required as gfc_add_data_component doesn't + update ts.type if there is a tailing REF_ARRAY. */ + expr2->ts.type = BT_DERIVED; + } + if (scalar) { /* Scalar pointers. */ @@ -6485,8 +6496,11 @@ gfc_trans_pointer_assignment (gfc_expr * expr1, gfc_expr * expr2) build_int_cst (gfc_charlen_type_node, 0)); } + if (expr1->ts.type == BT_DERIVED && expr2->ts.type == BT_CLASS) + rse.expr = gfc_class_data_get (rse.expr); + gfc_add_modify (&block, lse.expr, - fold_convert (TREE_TYPE (lse.expr), rse.expr)); + fold_convert (TREE_TYPE (lse.expr), rse.expr)); gfc_add_block_to_block (&block, &rse.post); gfc_add_block_to_block (&block, &lse.post); @@ -6508,8 +6522,12 @@ gfc_trans_pointer_assignment (gfc_expr * expr1, gfc_expr * expr2) break; rank_remap = (remap && remap->u.ar.end[0]); + gfc_init_se (&lse, NULL); if (remap) lse.descriptor_only = 1; + if (expr2->expr_type == EXPR_FUNCTION && expr2->ts.type == BT_CLASS + && expr1->ts.type == BT_CLASS) + expr1_vptr = gfc_copy_expr (expr1); gfc_conv_expr_descriptor (&lse, expr1); strlen_lhs = lse.string_length; desc = lse.expr; @@ -6526,8 +6544,51 @@ gfc_trans_pointer_assignment (gfc_expr * expr1, gfc_expr * expr2) gfc_init_se (&rse, NULL); rse.direct_byref = 1; rse.byref_noassign = 1; - gfc_conv_expr_descriptor (&rse, expr2); - strlen_rhs = rse.string_length; + + if (expr2->expr_type == EXPR_FUNCTION && expr2->ts.type == BT_CLASS) + { + gfc_conv_function_expr (&rse, expr2); + + if (expr1->ts.type != BT_CLASS) + rse.expr = gfc_class_data_get (rse.expr); + else + { + tmp = gfc_create_var (TREE_TYPE (rse.expr), "ptrtemp"); + gfc_add_modify (&lse.pre, tmp, rse.expr); + + gfc_add_vptr_component (expr1_vptr); + gfc_init_se (&rse, NULL); + rse.want_pointer = 1; + gfc_conv_expr (&rse, expr1_vptr); + gfc_add_modify (&lse.pre, rse.expr, + fold_convert (TREE_TYPE (rse.expr), + gfc_class_vptr_get (tmp))); + rse.expr = gfc_class_data_get (tmp); + } + } + else if (expr2->expr_type == EXPR_FUNCTION) + { + tree bound[GFC_MAX_DIMENSIONS]; + int i; + + for (i = 0; i < expr2->rank; i++) + bound[i] = NULL_TREE; + tmp = gfc_typenode_for_spec (&expr2->ts); + tmp = gfc_get_array_type_bounds (tmp, expr2->rank, 0, + bound, bound, 0, + GFC_ARRAY_POINTER_CONT, false); + tmp = gfc_create_var (tmp, "ptrtemp"); + lse.expr = tmp; + lse.direct_byref = 1; + gfc_conv_expr_descriptor (&lse, expr2); + strlen_rhs = lse.string_length; + rse.expr = tmp; + } + else + { + gfc_conv_expr_descriptor (&rse, expr2); + strlen_rhs = rse.string_length; + } } else if (expr2->expr_type == EXPR_VARIABLE) { @@ -6551,12 +6612,37 @@ gfc_trans_pointer_assignment (gfc_expr * expr1, gfc_expr * expr2) gfc_add_modify (&lse.post, GFC_DECL_SPAN(decl), tmp); } } + else if (expr2->expr_type == EXPR_FUNCTION && expr2->ts.type == BT_CLASS) + { + gfc_init_se (&rse, NULL); + rse.want_pointer = 1; + gfc_conv_function_expr (&rse, expr2); + if (expr1->ts.type != BT_CLASS) + { + rse.expr = gfc_class_data_get (rse.expr); + gfc_add_modify (&lse.pre, desc, rse.expr); + } + else + { + tmp = gfc_create_var (TREE_TYPE (rse.expr), "ptrtemp"); + gfc_add_modify (&lse.pre, tmp, rse.expr); + + gfc_add_vptr_component (expr1_vptr); + gfc_init_se (&rse, NULL); + rse.want_pointer = 1; + gfc_conv_expr (&rse, expr1_vptr); + gfc_add_modify (&lse.pre, rse.expr, + fold_convert (TREE_TYPE (rse.expr), + gfc_class_vptr_get (tmp))); + rse.expr = gfc_class_data_get (tmp); + gfc_add_modify (&lse.pre, desc, rse.expr); + } + } else { /* Assign to a temporary descriptor and then copy that temporary to the pointer. */ tmp = gfc_create_var (TREE_TYPE (desc), "ptrtemp"); - lse.expr = tmp; lse.direct_byref = 1; gfc_conv_expr_descriptor (&lse, expr2); @@ -6564,6 +6650,9 @@ gfc_trans_pointer_assignment (gfc_expr * expr1, gfc_expr * expr2) gfc_add_modify (&lse.pre, desc, tmp); } + if (expr1_vptr) + gfc_free_expr (expr1_vptr); + gfc_add_block_to_block (&block, &lse.pre); if (rank_remap) gfc_add_block_to_block (&block, &rse.pre); |