public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Paul Richard Thomas <paul.richard.thomas@gmail.com>
To: Andre Vehreschild <vehre@gmx.de>
Cc: "fortran@gcc.gnu.org" <fortran@gcc.gnu.org>,
	gcc-patches <gcc-patches@gcc.gnu.org>,
		Damian Rouson <damian@sourceryinstitute.org>
Subject: Re: [Patch, fortran] PR66079 - [6 Regression] memory leak with source allocation in internal subprogram
Date: Mon, 25 May 2015 10:25:00 -0000	[thread overview]
Message-ID: <CAGkQGiK9toG47ywxaWYOWpvHOEA98btpYPXFTx8HN4=82kzW2g@mail.gmail.com> (raw)
In-Reply-To: <CAGkQGiJzt4y7n4KMgO+Z9ooh2HPgj=SG5Vm9wanJeGMZoxePbg@mail.gmail.com>

[-- Attachment #1: Type: text/plain, Size: 4663 bytes --]

Dear All,

Lets see if I can get it right this time :-)

Note that I have changed the name of the temporary variable in
trans_allocate from 'atmp' to 'expr3' so that it is not confused with
array temporaries. I am not suree how much of the testcase is
pertinent after the reform of the evaluation of expr3 performed by
Andre. However, there were still memory leaks that are fixed by the
attached patch.

Bootstrapped and regtested on a current trunk - OK for trunk?

Paul

2015-05-23  Paul Thomas  <pault@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): Rename temporary variable
    as 'expr3'. Deallocate allocatable components of non-variable
    expr3s.

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

    PR fortran/66079
    * gfortran.dg/allocatable_scalar_13.f90: New test


On 24 May 2015 at 09:51, Paul Richard Thomas
<paul.richard.thomas@gmail.com> wrote:
> Dear Andre,
>
> I'll put both points right. Thanks for pointing them out.
>
> Cheers
>
> Paul
>
> On 23 May 2015 at 19:52, Andre Vehreschild <vehre@gmx.de> wrote:
>> Hi Paul,
>>
>> does this patch apply to current trunk cleanly? I get an issue with the last
>> hunk, because all of the prerequisites are gone since r223445. The string copy
>> is completely handled by the trans_assignment at the bottom of the if
>> (code->expr3) block. Therefore I doubt the patches last hunk is needed any
>> longer.
>>
>> Do you have an example why this hunk is needed?
>>
>> 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.  */
>>
>> When I get the code right, than all derived-typed source= expressions that have
>> an allocatable component will not be prepared for copy to the allocated object.
>> This also means, that functions returning an object of such a type are called
>> multiple times. Once for each object to allocate. Is this really desired?
>>
>> I am sorry, that I have to say that, but the check2305.diff file does not bring
>> the testcase with it.
>>
>> Regards,
>>         Andre
>>
>>
>> On Sat, 23 May 2015 14:48:53 +0200
>> Paul Richard Thomas <paul.richard.thomas@gmail.com> wrote:
>>
>>> 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  <pault@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  <pault@gcc.gnu.org>
>>>
>>>     PR fortran/66079
>>>     * gfortran.dg/allocatable_scalar_13.f90: New test
>>
>>
>> --
>> Andre Vehreschild * Email: vehre ad gmx dot de
>
>
>
> --
> Outside of a dog, a book is a man's best friend. Inside of a dog it's
> too dark to read.
>
> Groucho Marx



-- 
Outside of a dog, a book is a man's best friend. Inside of a dog it's
too dark to read.

Groucho Marx

[-- Attachment #2: submit.diff --]
[-- Type: text/plain, Size: 5355 bytes --]

Index: gcc/fortran/trans-expr.c
===================================================================
*** gcc/fortran/trans-expr.c	(revision 223641)
--- 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 223641)
--- gcc/fortran/trans-stmt.c	(working copy)
*************** gfc_trans_allocate (gfc_code * code)
*** 5214,5219 ****
--- 5214,5220 ----
  				     false, false);
  	  gfc_add_block_to_block (&block, &se.pre);
  	  gfc_add_block_to_block (&post, &se.post);
+ 
  	  /* Prevent aliasing, i.e., se.expr may be already a
  		 variable declaration.  */
  	  if (!VAR_P (se.expr))
*************** gfc_trans_allocate (gfc_code * code)
*** 5223,5230 ****
  						 se.expr);
  	      /* We need a regular (non-UID) symbol here, therefore give a
  		 prefix.  */
! 	      var = gfc_create_var (TREE_TYPE (tmp), "atmp");
  	      gfc_add_modify_loc (input_location, &block, var, tmp);
  	      tmp = var;
  	    }
  	  else
--- 5224,5243 ----
  						 se.expr);
  	      /* We need a regular (non-UID) symbol here, therefore give a
  		 prefix.  */
! 	      var = gfc_create_var (TREE_TYPE (tmp), "expr3");
  	      gfc_add_modify_loc (input_location, &block, var, tmp);
+ 
+ 	      /* Deallocate any allocatable components after all the allocations
+ 		 and assignments of expr3 have been completed.  */
+ 	      if (code->expr3->ts.type == BT_DERIVED
+ 		  && code->expr3->rank == 0
+ 		  && code->expr3->ts.u.derived->attr.alloc_comp)
+ 		{
+ 		  tmp = gfc_deallocate_alloc_comp (code->expr3->ts.u.derived,
+ 						   var, 0);
+ 		  gfc_add_expr_to_block (&post, tmp);
+ 		}
+ 
  	      tmp = var;
  	    }
  	  else
Index: gcc/testsuite/gfortran.dg/allocatable_scalar_13.f90
===================================================================
*** gcc/testsuite/gfortran.dg/allocatable_scalar_13.f90	(revision 0)
--- gcc/testsuite/gfortran.dg/allocatable_scalar_13.f90	(working copy)
***************
*** 0 ****
--- 1,70 ----
+ ! { dg-do run }
+ ! { dg-options "-fdump-tree-original" }
+ !
+ ! Test the fix for PR66079. The original problem was with the first
+ ! allocate statement. The rest of this testcase fixes problems found
+ ! whilst working on it!
+ !
+ ! Reported by Damian Rouson  <damian@sourceryinstitute.org>
+ !
+   type subdata
+     integer, allocatable :: b
+   endtype
+ !  block
+     call newRealVec
+ !  end block
+ contains
+   subroutine newRealVec
+     type(subdata), allocatable :: d, e, f
+     character(:), allocatable :: g, h, i
+     character(8), allocatable :: j
+     allocate(d,source=subdata(1)) ! memory was lost, now OK
+     allocate(e,source=d) ! OK
+     allocate(f,source=create (99)) ! memory was lost, now OK
+     if (d%b .ne. 1) call abort
+     if (e%b .ne. 1) call abort
+     if (f%b .ne. 99) call abort
+     allocate (g, source = greeting1("good day"))
+     if (g .ne. "good day") call abort
+     allocate (h, source = greeting2("hello"))
+     if (h .ne. "hello") call abort
+     allocate (i, source = greeting3("hiya!"))
+     if (i .ne. "hiya!") call abort
+     call greeting4 (j, "Goodbye ") ! Test that dummy arguments are OK
+     if (j .ne. "Goodbye ") call abort
+   end subroutine
+ 
+   function create (arg) result(res)
+     integer :: arg
+     type(subdata), allocatable :: res, res1
+     allocate(res, res1, source = subdata(arg))
+   end function
+ 
+   function greeting1 (arg) result(res) ! memory was lost, now OK
+     character(*) :: arg
+     Character(:), allocatable :: res
+     allocate(res, source = arg)
+   end function
+ 
+   function greeting2 (arg) result(res)
+     character(5) :: arg
+     Character(:), allocatable :: res
+     allocate(res, source = arg)
+   end function
+ 
+   function greeting3 (arg) result(res)
+     character(5) :: arg
+     Character(5), allocatable :: res, res1
+     allocate(res, res1, source = arg) ! Caused an ICE
+     if (res1 .ne. res) call abort
+   end function
+ 
+   subroutine greeting4 (res, arg)
+     character(8), intent(in) :: arg
+     Character(8), allocatable, intent(out) :: res
+     allocate(res, source = arg) ! Caused an ICE
+   end subroutine
+ end
+ ! { dg-final { scan-tree-dump-times "builtin_malloc" 20 "original" } }
+ ! { dg-final { scan-tree-dump-times "builtin_free" 21 "original" } }
+ ! { dg-final { cleanup-tree-dump "original" } }

  reply	other threads:[~2015-05-25  7:30 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-05-23 17:53 Paul Richard Thomas
2015-05-23 21:30 ` Andre Vehreschild
2015-05-23 21:35   ` Paul Richard Thomas
2015-05-24 18:55     ` Andre Vehreschild
2015-05-24 11:25   ` Paul Richard Thomas
2015-05-25 10:25     ` Paul Richard Thomas [this message]
2015-05-25 11:52       ` Andre Vehreschild
2015-05-25 18:09         ` Mikael Morin
2015-05-27  8:38         ` Paul Richard Thomas
2015-05-27 14:16           ` Andre Vehreschild
2015-05-27 16:42             ` Mikael Morin
2015-05-27 21:28               ` Steve Kargl
2015-05-28 15:22                 ` Mikael Morin
2015-05-28 15:24                   ` Andre Vehreschild
2015-05-25 18:08       ` Mikael Morin
2015-05-25 18:41         ` Steve Kargl
2015-06-11 16:00         ` Paul Richard Thomas
2015-10-18 20:04     ` Paul Richard Thomas

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='CAGkQGiK9toG47ywxaWYOWpvHOEA98btpYPXFTx8HN4=82kzW2g@mail.gmail.com' \
    --to=paul.richard.thomas@gmail.com \
    --cc=damian@sourceryinstitute.org \
    --cc=fortran@gcc.gnu.org \
    --cc=gcc-patches@gcc.gnu.org \
    --cc=vehre@gmx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).