re PR fortran/60458 (Error message on associate: deferred type parameter and requires...
authorPaul Thomas <pault@gcc.gnu.org>
Wed, 4 Oct 2017 10:43:45 +0000 (10:43 +0000)
committerPaul Thomas <pault@gcc.gnu.org>
Wed, 4 Oct 2017 10:43:45 +0000 (10:43 +0000)
2017-10-04  Paul Thomas  <pault@gcc.gnu.org>

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  <pault@gcc.gnu.org>

PR fortran/77296
* gfortran.dg/associate_32.f03 : New test.

From-SVN: r253400

gcc/fortran/ChangeLog
gcc/fortran/resolve.c
gcc/fortran/symbol.c
gcc/fortran/trans-decl.c
gcc/fortran/trans-stmt.c
gcc/testsuite/ChangeLog
gcc/testsuite/gfortran.dg/associate_32.f03 [new file with mode: 0644]

index 6f904b1e73535becc703f8986d4e4e9847379588..c38b34b944e66993d19940f8c58a4465dd592b16 100644 (file)
@@ -1,3 +1,19 @@
+2017-10-04  Paul Thomas  <pault@gcc.gnu.org>
+
+       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  <tkoenig@gcc.gnu.org>
 
        * io.c (match_wait_element): Correctly match END and EOR tags.
index 698cf6de2fdc4a8392fc73ddde80b60126b80658..e6f95d513d34d00407ec0699533530f8c9df7dae 100644 (file)
@@ -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);
index 68a76c4e4cf123e0b914938c2cfdd1d6511017e1..4c109fdfbad0d7cf526549e1125c7887fa5ed481 100644 (file)
@@ -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;
 
index d227d519c63c66fab01a9a319a5c43300c47cf64..b4f515f21d9551d833655a7fc8a2a563a8a8d5f4 100644 (file)
@@ -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))
index 925ea636258d4617b983c49e583648553e6df96d..7a76b8ead3166dcc0062272ef01cd5d352513954 100644 (file)
@@ -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;
        }
index 192fac794c85307ef2dba5a39d3ce128e2d62e7b..883392f796cc6b8000854186197cd71b89fb9b8a 100644 (file)
@@ -1,3 +1,8 @@
+2017-10-04  Paul Thomas  <pault@gcc.gnu.org>
+
+       PR fortran/77296
+       * gfortran.dg/associate_32.f03 : New test.
+
 2017-10-04  Paolo Carlini  <paolo.carlini@oracle.com>
 
        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 (file)
index 0000000..9a1f598
--- /dev/null
@@ -0,0 +1,93 @@
+! { dg-do run }
+!
+! Tests fix for PR77296 and other bugs found on the way.
+!
+! Contributed by Matt Thompson  <matthew.thompson@nasa.gov>
+!
+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