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 | |
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')
-rw-r--r-- | gcc/fortran/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/fortran/trans-expr.c | 103 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/testsuite/gfortran.dg/pointer_assign_10.f90 | 36 | ||||
-rw-r--r-- | gcc/testsuite/gfortran.dg/pointer_assign_11.f90 | 51 | ||||
-rw-r--r-- | gcc/testsuite/gfortran.dg/pointer_assign_8.f90 | 46 | ||||
-rw-r--r-- | gcc/testsuite/gfortran.dg/pointer_assign_9.f90 | 36 |
7 files changed, 281 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); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 3c6e5e8..734d78a 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,11 @@ +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. + 2013-07-30 Zhenqiang Chen <zhenqiang.chen@linaro.org> * gcc.target/arm/pr57637.c: New testcase. diff --git a/gcc/testsuite/gfortran.dg/pointer_assign_10.f90 b/gcc/testsuite/gfortran.dg/pointer_assign_10.f90 new file mode 100644 index 0000000..756e530 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/pointer_assign_10.f90 @@ -0,0 +1,36 @@ +! { dg-do run } +! +! PR fortran/57530 +! +! +! TYPE => TYPE pointer assignment for functions +! +module m + implicit none + type t + integer :: ii = 55 + end type t +contains + function f1() + type(t), pointer :: f1 + allocate (f1) + f1%ii = 123 + end function f1 + function f2() + type(t), pointer :: f2(:) + allocate (f2(3)) + f2(:)%ii = [-11,-22,-33] + end function f2 +end module m + +program test + use m + implicit none + type(t), pointer :: p1, p2(:), p3(:,:) + p1 => f1() + if (p1%ii /= 123) call abort () + p2 => f2() + if (any (p2%ii /= [-11,-22,-33])) call abort () + p3(2:2,1:3) => f2() + if (any (p3(2,:)%ii /= [-11,-22,-33])) call abort () +end program test diff --git a/gcc/testsuite/gfortran.dg/pointer_assign_11.f90 b/gcc/testsuite/gfortran.dg/pointer_assign_11.f90 new file mode 100644 index 0000000..f32c531 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/pointer_assign_11.f90 @@ -0,0 +1,51 @@ +! { dg-do run } +! +! PR fortran/57530 +! +! +! CLASS => CLASS pointer assignment for function results +! +module m + implicit none + type t + integer :: ii = 55 + end type t + type, extends(t) :: t2 + end type t2 +contains + function f1() + class(t), pointer :: f1 + allocate (f1) + f1%ii = 123 + end function f1 + function f2() + class(t), pointer :: f2(:) + allocate (f2(3)) + f2(:)%ii = [-11,-22,-33] + end function f2 +end module m + +program test + use m + implicit none + class(t), pointer :: p1, p2(:), p3(:,:) + type(t) :: my_t + type(t2) :: my_t2 + + allocate (t2 :: p1, p2(1), p3(1,1)) + if (.not. same_type_as (p1, my_t2)) call abort() + if (.not. same_type_as (p2, my_t2)) call abort() + if (.not. same_type_as (p3, my_t2)) call abort() + + p1 => f1() + if (p1%ii /= 123) call abort () + if (.not. same_type_as (p1, my_t)) call abort() + + p2 => f2() + if (any (p2%ii /= [-11,-22,-33])) call abort () + if (.not. same_type_as (p2, my_t)) call abort() + + p3(2:2,1:3) => f2() + if (any (p3(2,:)%ii /= [-11,-22,-33])) call abort () + if (.not. same_type_as (p3, my_t)) call abort() +end program test diff --git a/gcc/testsuite/gfortran.dg/pointer_assign_8.f90 b/gcc/testsuite/gfortran.dg/pointer_assign_8.f90 new file mode 100644 index 0000000..e8fb2c3 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/pointer_assign_8.f90 @@ -0,0 +1,46 @@ +! { dg-do run } +! +! PR fortran/57530 +! +! +! TYPE => CLASS pointer assignment for variables +! +module m + implicit none + type t + integer :: ii = 55 + end type t +contains + subroutine sub (tgt, tgt2) + class(t), target :: tgt, tgt2(:) + type(t), pointer :: ptr, ptr2(:), ptr3(:,:) + + if (tgt%ii /= 43) call abort() + if (size (tgt2) /= 3) call abort() + if (any (tgt2(:)%ii /= [11,22,33])) call abort() + + ptr => tgt ! TYPE => CLASS + ptr2 => tgt2 ! TYPE => CLASS + ptr3(-3:-3,1:3) => tgt2 ! TYPE => CLASS + + if (.not. associated(ptr)) call abort() + if (.not. associated(ptr2)) call abort() + if (.not. associated(ptr3)) call abort() + if (.not. associated(ptr,tgt)) call abort() + if (.not. associated(ptr2,tgt2)) call abort() + if (ptr%ii /= 43) call abort() + if (size (ptr2) /= 3) call abort() + if (size (ptr3) /= 3) call abort() + if (any (ptr2(:)%ii /= [11,22,33])) call abort() + if (any (shape (ptr3) /= [1,3])) call abort() + if (any (ptr3(-3,:)%ii /= [11,22,33])) call abort() + end subroutine sub +end module m + +use m +type(t), target :: x +type(t), target :: y(3) +x%ii = 43 +y(:)%ii = [11,22,33] +call sub(x,y) +end diff --git a/gcc/testsuite/gfortran.dg/pointer_assign_9.f90 b/gcc/testsuite/gfortran.dg/pointer_assign_9.f90 new file mode 100644 index 0000000..7f8152a --- /dev/null +++ b/gcc/testsuite/gfortran.dg/pointer_assign_9.f90 @@ -0,0 +1,36 @@ +! { dg-do run } +! +! PR fortran/57530 +! +! +! TYPE => CLASS pointer assignment for functions +! +module m + implicit none + type t + integer :: ii = 55 + end type t +contains + function f1() + class(t), pointer :: f1 + allocate (f1) + f1%ii = 123 + end function f1 + function f2() + class(t), pointer :: f2(:) + allocate (f2(3)) + f2(:)%ii = [-11,-22,-33] + end function f2 +end module m + +program test + use m + implicit none + type(t), pointer :: p1, p2(:),p3(:,:) + p1 => f1() + if (p1%ii /= 123) call abort () + p2 => f2() + if (any (p2%ii /= [-11,-22,-33])) call abort () + p3(2:2,1:3) => f2() + if (any (p3(2,:)%ii /= [-11,-22,-33])) call abort () +end program test |