Dear All,

This patch started out fixing a single source of memory leak and then
went on to fix various other issues that I found upon investigation.

The fortran ChangeLog entry is sufficiently descripive that I do not
think that there is a need to say more.

Bootstrapped and regtested on x86_64/FC21 - OK for trunk?

I am rather sure that some of the issues go further back than 6.0. I
will investigate what should be fixed for 5.2.

Cheers

Paul

2015-05-23  Paul Thomas  <pa...@gcc.gnu.org>

    PR fortran/66079
    * trans-expr.c (gfc_conv_procedure_call): Allocatable scalar
    function results must be freed and nullified after use. Create
    a temporary to hold the result to prevent duplicate calls.
    * trans-stmt.c (gfc_trans_allocate): Prevent memory leaks by
    not evaluating expr3 for scalar derived types with allocatable
    components. Fixed character length allocatable results and
    dummies need to be dereferenced. Also, if al_len is NULL use
    memsz for the string copy.

2015-05-23  Paul Thomas  <pa...@gcc.gnu.org>

    PR fortran/66079
    * gfortran.dg/allocatable_scalar_13.f90: New test
Index: gcc/fortran/trans-expr.c
===================================================================
*** gcc/fortran/trans-expr.c    (revision 223234)
--- gcc/fortran/trans-expr.c    (working copy)
*************** gfc_conv_procedure_call (gfc_se * se, gf
*** 5877,5882 ****
--- 5877,5896 ----
    fntype = TREE_TYPE (TREE_TYPE (se->expr));
    se->expr = build_call_vec (TREE_TYPE (fntype), se->expr, arglist);
  
+   /* Allocatable scalar function results must be freed and nullified
+      after use. This necessitates the creation of a temporary to
+      hold the result to prevent duplicate calls.  */
+   if (!byref && sym->ts.type != BT_CHARACTER
+       && sym->attr.allocatable && !sym->attr.dimension)
+     {
+       tmp = gfc_create_var (TREE_TYPE (se->expr), NULL);
+       gfc_add_modify (&se->pre, tmp, se->expr);
+       se->expr = tmp;
+       tmp = gfc_call_free (tmp);
+       gfc_add_expr_to_block (&post, tmp);
+       gfc_add_modify (&post, se->expr, build_int_cst (TREE_TYPE (se->expr), 
0));
+     }
+ 
    /* If we have a pointer function, but we don't want a pointer, e.g.
       something like
          x = f()
Index: gcc/fortran/trans-stmt.c
===================================================================
*** gcc/fortran/trans-stmt.c    (revision 223233)
--- gcc/fortran/trans-stmt.c    (working copy)
*************** gfc_trans_allocate (gfc_code * code)
*** 5200,5206 ****
                }
              /* else expr3 = NULL_TREE set above.  */
            }
!         else
            {
              /* In all other cases evaluate the expr3 and create a
                 temporary.  */
--- 5200,5207 ----
                }
              /* else expr3 = NULL_TREE set above.  */
            }
!         else if (!(code->expr3->ts.type == BT_DERIVED
!                    && code->expr3->ts.u.derived->attr.alloc_comp))
            {
              /* In all other cases evaluate the expr3 and create a
                 temporary.  */
*************** gfc_trans_allocate (gfc_code * code)
*** 5626,5631 ****
--- 5627,5633 ----
                            fold_convert (TREE_TYPE (al_len),
                                          integer_zero_node));
        }
+ 
        if (code->expr3 && !code->expr3->mold)
        {
          /* Initialization via SOURCE block
*************** gfc_trans_allocate (gfc_code * code)
*** 5650,5655 ****
--- 5652,5669 ----
                        se.expr :
                        build_fold_indirect_ref_loc (input_location,
                                                     se.expr);
+ 
+             /* Fixed length allocatable results and dummies need further
+                dereferencing.  */
+             if (!expr->ts.deferred
+                 && TREE_CODE (se.expr) == PARM_DECL)
+               tmp = build_fold_indirect_ref_loc (input_location, tmp);
+ 
+             /* Fixed length allocations need this because al_len is
+                never set.  */
+             if (al_len == NULL_TREE)
+               al_len = memsz;
+ 
              gfc_trans_string_copy (&block, al_len, tmp,
                                     code->expr3->ts.kind,
                                     expr3_len, expr3,

Reply via email to