aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTobias Burnus <burnus@net-b.de>2012-09-17 14:30:16 +0200
committerTobias Burnus <burnus@gcc.gnu.org>2012-09-17 14:30:16 +0200
commit640a4c59ed729e48250032b039a5239cd95c1d41 (patch)
tree7e1a47ffe9d2fe14f016937cb36cf80cd59c0e55
parentc6423ef3e00856eb88fb7fceb0f08b6068ddd926 (diff)
downloadgcc-640a4c59ed729e48250032b039a5239cd95c1d41.zip
gcc-640a4c59ed729e48250032b039a5239cd95c1d41.tar.gz
gcc-640a4c59ed729e48250032b039a5239cd95c1d41.tar.bz2
re PR fortran/54603 ([F03] Wrong code with structure constructor for proc-pointer components)
2012-09-17 Tobias Burnus <burnus@net-b.de> PR fortran/54603 * trans-expr.c (gfc_trans_subcomponent_assign): Handle proc-pointer components. 2012-09-17 Tobias Burnus <burnus@net-b.de> PR fortran/54603 * gfortran.dg/structure_constructor_11.f90: New. From-SVN: r191382
-rw-r--r--gcc/fortran/ChangeLog7
-rw-r--r--gcc/fortran/trans-expr.c9
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gfortran.dg/structure_constructor_11.f9096
4 files changed, 115 insertions, 2 deletions
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog
index b2950f7..3f6e3be 100644
--- a/gcc/fortran/ChangeLog
+++ b/gcc/fortran/ChangeLog
@@ -1,5 +1,12 @@
2012-09-17 Tobias Burnus <burnus@net-b.de>
+ PR fortran/54603
+ * trans-expr.c (gfc_trans_subcomponent_assign): Handle
+ proc-pointer components.
+
+2012-09-17 Tobias Burnus <burnus@net-b.de>
+
+ PR fortran/54599
* error.c (error_print): Move increment out of the assert.
* interface.c (gfc_compare_derived_types): Add assert.
(get_expr_storage_size): Remove always-true logical condition.
diff --git a/gcc/fortran/trans-expr.c b/gcc/fortran/trans-expr.c
index 84a4b34..98634c3 100644
--- a/gcc/fortran/trans-expr.c
+++ b/gcc/fortran/trans-expr.c
@@ -5506,11 +5506,11 @@ gfc_trans_subcomponent_assign (tree dest, gfc_component * cm, gfc_expr * expr)
gfc_start_block (&block);
- if (cm->attr.pointer)
+ if (cm->attr.pointer || cm->attr.proc_pointer)
{
gfc_init_se (&se, NULL);
/* Pointer component. */
- if (cm->attr.dimension)
+ if (cm->attr.dimension && !cm->attr.proc_pointer)
{
/* Array pointer. */
if (expr->expr_type == EXPR_NULL)
@@ -5530,6 +5530,11 @@ gfc_trans_subcomponent_assign (tree dest, gfc_component * cm, gfc_expr * expr)
se.want_pointer = 1;
gfc_conv_expr (&se, expr);
gfc_add_block_to_block (&block, &se.pre);
+
+ if (expr->symtree && expr->symtree->n.sym->attr.proc_pointer
+ && expr->symtree->n.sym->attr.dummy)
+ se.expr = build_fold_indirect_ref_loc (input_location, se.expr);
+
gfc_add_modify (&block, dest,
fold_convert (TREE_TYPE (dest), se.expr));
gfc_add_block_to_block (&block, &se.post);
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index ead2a97..eb1f595 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2012-09-17 Tobias Burnus <burnus@net-b.de>
+
+ PR fortran/54603
+ * gfortran.dg/structure_constructor_11.f90: New.
+
2012-09-17 Jakub Jelinek <jakub@redhat.com>
PR tree-optimization/54563
diff --git a/gcc/testsuite/gfortran.dg/structure_constructor_11.f90 b/gcc/testsuite/gfortran.dg/structure_constructor_11.f90
new file mode 100644
index 0000000..167f8e7
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/structure_constructor_11.f90
@@ -0,0 +1,96 @@
+! { dg-do run}
+! { dg-options "-fdump-tree-original" }
+!
+! PR fortran/54603
+!
+! Contributed by Kacper Kowalik
+!
+module foo
+ implicit none
+
+ interface
+ subroutine cg_ext
+ implicit none
+ end subroutine cg_ext
+ end interface
+
+ type :: ext_ptr
+ procedure(cg_ext), nopass, pointer :: init
+ procedure(cg_ext), nopass, pointer :: cleanup
+ end type ext_ptr
+
+ type :: ext_ptr_array
+ type(ext_ptr) :: a
+ contains
+ procedure :: epa_init
+ end type ext_ptr_array
+
+ type(ext_ptr_array) :: bar
+
+contains
+ subroutine epa_init(this, init, cleanup)
+ implicit none
+ class(ext_ptr_array), intent(inout) :: this
+ procedure(cg_ext), pointer, intent(in) :: init
+ procedure(cg_ext), pointer, intent(in) :: cleanup
+
+ this%a = ext_ptr(null(), null()) ! Wrong code
+ this%a = ext_ptr(init, cleanup) ! Wrong code
+
+ this%a%init => init ! OK
+ this%a%cleanup => cleanup ! OK
+
+ this%a = ext_ptr(this%a%init,this%a%cleanup) ! ICE in fold_convert_loc
+ end subroutine epa_init
+
+end module foo
+
+program ala
+ use foo, only: bar
+ implicit none
+ integer :: count1, count2
+ count1 = 0
+ count2 = 0
+
+ call setme
+ call bar%a%cleanup()
+ call bar%a%init()
+
+ ! They should be called once
+ if (count1 /= 23 .or. count2 /= 42) call abort ()
+
+contains
+
+ subroutine dummy1
+ implicit none
+ !print *, 'dummy1'
+ count1 = 23
+ end subroutine dummy1
+
+ subroutine dummy2
+ implicit none
+ !print *, 'dummy2'
+ count2 = 42
+ end subroutine dummy2
+
+ subroutine setme
+ use foo, only: bar, cg_ext
+ implicit none
+ procedure(cg_ext), pointer :: a_init, a_clean
+
+ a_init => dummy1
+ a_clean => dummy2
+ call bar%epa_init(a_init, a_clean)
+ end subroutine setme
+
+end program ala
+
+! { dg-final { scan-tree-dump-times "ext_ptr.\[0-9\]+.init = 0B;" 1 "original" } }
+! { dg-final { scan-tree-dump-times "ext_ptr.\[0-9\]+.cleanup = 0B;" 1 "original" } }
+! { dg-final { scan-tree-dump-times "ext_ptr.1.init = \\*init;" 1 "original" } }
+! { dg-final { scan-tree-dump-times "ext_ptr.1.cleanup = \\*cleanup;" 1 "original" } }
+! { dg-final { scan-tree-dump-times "this->_data->a.init = \\*init;" 1 "original" } }
+! { dg-final { scan-tree-dump-times "this->_data->a.cleanup = \\*cleanup;" 1 "original" } }
+! { dg-final { scan-tree-dump-times "ext_ptr.\[0-9\]+.init = this->_data->a.init;" 1 "original" } }
+! { dg-final { scan-tree-dump-times "ext_ptr.\[0-9\]+.cleanup = this->_data->a.cleanup;" 1 "original" } }
+! { dg-final { cleanup-tree-dump "original" } }