aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorPaul Thomas <pault@gcc.gnu.org>2015-01-18 15:52:49 +0000
committerPaul Thomas <pault@gcc.gnu.org>2015-01-18 15:52:49 +0000
commita878f8e80c753f5ff2726b2eabea7239e93be486 (patch)
tree75b1935cf96f9816a14a93f980a4101f05050482 /gcc
parentfded3d73da69224b9abdd03fa71d274c76fbe3c6 (diff)
downloadgcc-a878f8e80c753f5ff2726b2eabea7239e93be486.zip
gcc-a878f8e80c753f5ff2726b2eabea7239e93be486.tar.gz
gcc-a878f8e80c753f5ff2726b2eabea7239e93be486.tar.bz2
re PR fortran/64578 ([OOP] Seg-fault and ICE with unlimited polymorphic array pointer function)
2015-01-18 Paul Thomas <pault@gcc.gnu.org> PR fortran/64578 * trans-expr.c (gfc_trans_subcomponent_assign): Use a deep copy for allocatable components, where the source is a variable. 2015-01-18 Paul Thomas <pault@gcc.gnu.org> PR fortran/64578 * gfortran.dg/block_13.f08: New test From-SVN: r219818
Diffstat (limited to 'gcc')
-rw-r--r--gcc/fortran/ChangeLog6
-rw-r--r--gcc/fortran/trans-expr.c12
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gfortran.dg/block_13.f0858
4 files changed, 79 insertions, 2 deletions
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog
index e91159a..3f308f7 100644
--- a/gcc/fortran/ChangeLog
+++ b/gcc/fortran/ChangeLog
@@ -1,5 +1,11 @@
2015-01-18 Paul Thomas <pault@gcc.gnu.org>
+ PR fortran/64578
+ * trans-expr.c (gfc_trans_subcomponent_assign): Use a deep copy
+ for allocatable components, where the source is a variable.
+
+2015-01-18 Paul Thomas <pault@gcc.gnu.org>
+
PR fortran/55901
* primary.c (gfc_match_varspec): Exclude dangling associate-
names with dimension 0 from being counted as arrays.
diff --git a/gcc/fortran/trans-expr.c b/gcc/fortran/trans-expr.c
index 79eed1e..fca6d33 100644
--- a/gcc/fortran/trans-expr.c
+++ b/gcc/fortran/trans-expr.c
@@ -6474,8 +6474,16 @@ gfc_trans_subcomponent_assign (tree dest, gfc_component * cm, gfc_expr * expr,
gfc_init_se (&se, NULL);
gfc_conv_expr (&se, expr);
gfc_add_block_to_block (&block, &se.pre);
- gfc_add_modify (&block, dest,
- fold_convert (TREE_TYPE (dest), se.expr));
+ if (cm->ts.u.derived->attr.alloc_comp
+ && expr->expr_type == EXPR_VARIABLE)
+ {
+ tmp = gfc_copy_alloc_comp (cm->ts.u.derived, se.expr,
+ dest, expr->rank);
+ gfc_add_expr_to_block (&block, tmp);
+ }
+ else
+ gfc_add_modify (&block, dest,
+ fold_convert (TREE_TYPE (dest), se.expr));
gfc_add_block_to_block (&block, &se.post);
}
else
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 34e40ff..8871283 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,10 @@
2015-01-18 Paul Thomas <pault@gcc.gnu.org>
+ PR fortran/64578
+ * gfortran.dg/block_13.f08: New test
+
+2015-01-18 Paul Thomas <pault@gcc.gnu.org>
+
PR fortran/55901
* gfortran.dg/associate_1.f03: Allow test for character with
automatic length.
diff --git a/gcc/testsuite/gfortran.dg/block_13.f08 b/gcc/testsuite/gfortran.dg/block_13.f08
new file mode 100644
index 0000000..5956a90
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/block_13.f08
@@ -0,0 +1,58 @@
+! { dg-do run }
+! Checks the fix for PR57959. The first assignment to a was proceeding
+! without a deep copy. Since the anum field of 'uKnot' was being pointed
+! to twice, the frees in the finally block, following the BLOCK caused
+! a double free.
+!
+! Contributed by Tobias Burnus <burnus@gcc.gnu.org>
+!
+program main
+ implicit none
+ type :: type1
+ real, allocatable :: anum
+ character(len = :), allocatable :: chr
+ end type type1
+ real, parameter :: five = 5.0
+ real, parameter :: point_one = 0.1
+
+ type :: type2
+ type(type1) :: temp
+ end type type2
+ block
+ type(type1) :: uKnot
+ type(type2) :: a
+
+ uKnot = type1 (five, "hello")
+ call check (uKnot%anum, five)
+ call check_chr (uKnot%chr, "hello")
+
+ a = type2 (uKnot) ! Deep copy needed here
+ call check (a%temp%anum, five)
+ call check_chr (a%temp%chr, "hello")
+
+ a = type2 (type1(point_one, "goodbye")) ! Not here
+ call check (a%temp%anum, point_one)
+ call check_chr (a%temp%chr, "goodbye")
+
+ a = type2 (foo (five)) ! Not here
+ call check (a%temp%anum, five)
+ call check_chr (a%temp%chr, "foo set me")
+ end block
+contains
+ subroutine check (arg1, arg2)
+ real :: arg1, arg2
+ if (arg1 .ne. arg2) call abort ()
+ end subroutine
+
+ subroutine check_chr (arg1, arg2)
+ character(*) :: arg1, arg2
+ if (len (arg1) .ne. len (arg2)) call abort
+ if (arg1 .ne. arg2) call abort
+ end subroutine
+
+ type(type1) function foo (arg)
+ real :: arg
+ foo = type1 (arg, "foo set me")
+ end function
+end
+