From 707905d0773e5a8eebb9ba65164f43dc08c658b1 Mon Sep 17 00:00:00 2001 From: Paul Thomas Date: Wed, 4 Oct 2017 10:43:45 +0000 Subject: [PATCH] re PR fortran/60458 (Error message on associate: deferred type parameter and requires either the pointer or allocatable attribute) 2017-10-04 Paul Thomas PR fortran/60458 PR fortran/77296 * resolve.c (resolve_assoc_var): Deferred character type associate names must not receive an integer conatant length. * symbol.c (gfc_is_associate_pointer): Deferred character length functions also require an associate pointer. * trans-decl.c (gfc_get_symbol_decl): Deferred character length functions or derived type components require the assoc name to have variable string length. * trans-stmt.c (trans_associate_var): Set the string length of deferred string length associate names. The address expression is not needed for allocatable, pointer or dummy targets. Change the comment about defered string length targets. 2017-10-04 Paul Thomas PR fortran/77296 * gfortran.dg/associate_32.f03 : New test. From-SVN: r253400 --- gcc/fortran/ChangeLog | 16 ++++ gcc/fortran/resolve.c | 2 +- gcc/fortran/symbol.c | 6 ++ gcc/fortran/trans-decl.c | 8 ++ gcc/fortran/trans-stmt.c | 45 ++++++++++- gcc/testsuite/ChangeLog | 5 ++ gcc/testsuite/gfortran.dg/associate_32.f03 | 93 ++++++++++++++++++++++ 7 files changed, 171 insertions(+), 4 deletions(-) create mode 100644 gcc/testsuite/gfortran.dg/associate_32.f03 diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index 6f904b1e735..c38b34b944e 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,19 @@ +2017-10-04 Paul Thomas + + PR fortran/60458 + PR fortran/77296 + * resolve.c (resolve_assoc_var): Deferred character type + associate names must not receive an integer conatant length. + * symbol.c (gfc_is_associate_pointer): Deferred character + length functions also require an associate pointer. + * trans-decl.c (gfc_get_symbol_decl): Deferred character + length functions or derived type components require the assoc + name to have variable string length. + * trans-stmt.c (trans_associate_var): Set the string length of + deferred string length associate names. The address expression + is not needed for allocatable, pointer or dummy targets. Change + the comment about defered string length targets. + 2017-10-03 Thomas Koenig * io.c (match_wait_element): Correctly match END and EOR tags. diff --git a/gcc/fortran/resolve.c b/gcc/fortran/resolve.c index 698cf6de2fd..e6f95d513d3 100644 --- a/gcc/fortran/resolve.c +++ b/gcc/fortran/resolve.c @@ -8530,7 +8530,7 @@ resolve_assoc_var (gfc_symbol* sym, bool resolve_target) if (!sym->ts.u.cl) sym->ts.u.cl = target->ts.u.cl; - if (!sym->ts.u.cl->length) + if (!sym->ts.u.cl->length && !sym->ts.deferred) sym->ts.u.cl->length = gfc_get_int_expr (gfc_default_integer_kind, NULL, target->value.character.length); diff --git a/gcc/fortran/symbol.c b/gcc/fortran/symbol.c index 68a76c4e4cf..4c109fdfbad 100644 --- a/gcc/fortran/symbol.c +++ b/gcc/fortran/symbol.c @@ -5054,6 +5054,12 @@ gfc_is_associate_pointer (gfc_symbol* sym) if (sym->ts.type == BT_CLASS) return true; + if (sym->ts.type == BT_CHARACTER + && sym->ts.deferred + && sym->assoc->target + && sym->assoc->target->expr_type == EXPR_FUNCTION) + return true; + if (!sym->assoc->variable) return false; diff --git a/gcc/fortran/trans-decl.c b/gcc/fortran/trans-decl.c index d227d519c63..b4f515f21d9 100644 --- a/gcc/fortran/trans-decl.c +++ b/gcc/fortran/trans-decl.c @@ -1694,6 +1694,14 @@ gfc_get_symbol_decl (gfc_symbol * sym) string length is a variable, it is not finished a second time. */ if (sym->ts.type == BT_CHARACTER) { + if (sym->attr.associate_var + && sym->ts.deferred + && sym->assoc && sym->assoc->target + && ((sym->assoc->target->expr_type == EXPR_VARIABLE + && sym->assoc->target->symtree->n.sym->ts.type != BT_CHARACTER) + || sym->assoc->target->expr_type == EXPR_FUNCTION)) + sym->ts.u.cl->backend_decl = NULL_TREE; + if (sym->attr.associate_var && sym->ts.u.cl->backend_decl && VAR_P (sym->ts.u.cl->backend_decl)) diff --git a/gcc/fortran/trans-stmt.c b/gcc/fortran/trans-stmt.c index 925ea636258..7a76b8ead31 100644 --- a/gcc/fortran/trans-stmt.c +++ b/gcc/fortran/trans-stmt.c @@ -1533,6 +1533,7 @@ trans_associate_var (gfc_symbol *sym, gfc_wrapped_block *block) bool need_len_assign; bool whole_array = true; gfc_ref *ref; + symbol_attribute attr; gcc_assert (sym->assoc); e = sym->assoc->target; @@ -1592,6 +1593,17 @@ trans_associate_var (gfc_symbol *sym, gfc_wrapped_block *block) gfc_conv_expr_descriptor (&se, e); + if (sym->ts.type == BT_CHARACTER + && sym->ts.deferred + && !sym->attr.select_type_temporary + && VAR_P (sym->ts.u.cl->backend_decl) + && se.string_length != sym->ts.u.cl->backend_decl) + { + gfc_add_modify (&se.pre, sym->ts.u.cl->backend_decl, + fold_convert (gfc_charlen_type_node, + se.string_length)); + } + /* If we didn't already do the pointer assignment, set associate-name descriptor to the one generated for the temporary. */ if ((!sym->assoc->variable && !cst_array_ctor) @@ -1758,8 +1770,35 @@ trans_associate_var (gfc_symbol *sym, gfc_wrapped_block *block) need_len_assign = need_len_assign && sym->ts.type == BT_CHARACTER; } - tmp = TREE_TYPE (sym->backend_decl); - tmp = gfc_build_addr_expr (tmp, se.expr); + if (sym->ts.type == BT_CHARACTER + && sym->ts.deferred + && !sym->attr.select_type_temporary + && VAR_P (sym->ts.u.cl->backend_decl) + && se.string_length != sym->ts.u.cl->backend_decl) + { + gfc_add_modify (&se.pre, sym->ts.u.cl->backend_decl, + fold_convert (gfc_charlen_type_node, + se.string_length)); + if (e->expr_type == EXPR_FUNCTION) + { + tmp = gfc_call_free (sym->backend_decl); + gfc_add_expr_to_block (&se.post, tmp); + } + } + + attr = gfc_expr_attr (e); + if (sym->ts.type == BT_CHARACTER && e->ts.type == BT_CHARACTER + && (attr.allocatable || attr.pointer || attr.dummy)) + { + /* These are pointer types already. */ + tmp = fold_convert (TREE_TYPE (sym->backend_decl), se.expr); + } + else + { + tmp = TREE_TYPE (sym->backend_decl); + tmp = gfc_build_addr_expr (tmp, se.expr); + } + gfc_add_modify (&se.pre, sym->backend_decl, tmp); gfc_add_init_cleanup (block, gfc_finish_block( &se.pre), @@ -1784,7 +1823,7 @@ trans_associate_var (gfc_symbol *sym, gfc_wrapped_block *block) gfc_init_se (&se, NULL); if (e->symtree->n.sym->ts.type == BT_CHARACTER) { - /* What about deferred strings? */ + /* Deferred strings are dealt with in the preceeding. */ gcc_assert (!e->symtree->n.sym->ts.deferred); tmp = e->symtree->n.sym->ts.u.cl->backend_decl; } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 192fac794c8..883392f796c 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2017-10-04 Paul Thomas + + PR fortran/77296 + * gfortran.dg/associate_32.f03 : New test. + 2017-10-04 Paolo Carlini PR c++/78816 diff --git a/gcc/testsuite/gfortran.dg/associate_32.f03 b/gcc/testsuite/gfortran.dg/associate_32.f03 new file mode 100644 index 00000000000..9a1f5983df0 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/associate_32.f03 @@ -0,0 +1,93 @@ +! { dg-do run } +! +! Tests fix for PR77296 and other bugs found on the way. +! +! Contributed by Matt Thompson +! +program test + + implicit none + type :: str_type + character(len=:), allocatable :: str + end type + + character(len=:), allocatable :: s, sd(:) + character(len=2), allocatable :: sf, sfd(:) + character(len=6) :: str + type(str_type) :: string + + s = 'ab' + associate(ss => s) + if (ss .ne. 'ab') call abort ! This is the original bug. + ss = 'c' + end associate + if (s .ne. 'c ') call abort ! No reallocation within ASSOCIATE block! + + sf = 'c' + associate(ss => sf) + if (ss .ne. 'c ') call abort ! This the bug in comment #2 of the PR. + ss = 'cd' + end associate + + sd = [s, sf] + associate(ss => sd) + if (any (ss .ne. ['c ','cd'])) call abort + end associate + + sfd = [sd,'ef'] + associate(ss => sfd) + if (any (ss .ne. ['c ','cd','ef'])) call abort + ss = ['gh'] + end associate + if (any (sfd .ne. ['gh','cd','ef'])) call abort ! No reallocation! + + string%str = 'xyz' + associate(ss => string%str) + if (ss .ne. 'xyz') call abort + ss = 'c' + end associate + if (string%str .ne. 'c ') call abort ! No reallocation! + + str = "foobar" + call test_char (5 , str) + IF (str /= "abcder") call abort + + associate(ss => foo()) + if (ss .ne. 'pqrst') call abort + end associate + + associate(ss => bar()) + if (ss(2) .ne. 'uvwxy') call abort + end associate + +! The deallocation is not strictly necessary but it does allow +! other memory leakage to be tested for. + deallocate (s, sd, sf, sfd, string%str) +contains + +! This is a modified version of the subroutine in associate_1.f03. +! 'str' is now a dummy. + SUBROUTINE test_char (n, str) + INTEGER, INTENT(IN) :: n + + CHARACTER(LEN=n) :: str + + ASSOCIATE (my => str) + IF (LEN (my) /= n) call abort + IF (my /= "fooba") call abort + my = "abcde" + END ASSOCIATE + IF (str /= "abcde") call abort + END SUBROUTINE test_char + + function foo() result(res) + character (len=:), pointer :: res + allocate (res, source = 'pqrst') + end function + + function bar() result(res) + character (len=:), allocatable :: res(:) + allocate (res, source = ['pqrst','uvwxy']) + end function + +end program test -- 2.30.2