This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Fix PR42958


This tries to fix PR42958 (conditional free is bad, allocating max<1, 
size> is bad) in a way that user allocation and allocated checks
still work.  Thus it adds a flag to gfc_call_malloc whether we
need the max<1,size> computation or not.  Now, I'm not sure which
paths to gfc_call_malloc are actually for user allocations (nor
am I sure how a complete set of those look like) - most callsites
mention "temporary" in the comments before the allocation.
Thus I'd appreciate if somebody would add a testcase verifying
that a zero allocation still results in a successful allocated
check and that I transformed calls correctly.

Unconditional free should be ok for gfortran emitted calls as
I understand they are internal calls and user code can have
manual allocated checks if they want to omit the call for
speed reasons (thus, no reason to duplicate that in the
middle-end interface).

Bootstrap and regtest running on x86_64-unknown-linux-gnu.

Comments?

Thanks,
Richard.

2010-04-29  Richard Guenther  <rguenther@suse.de>

	PR fortran/42958
	* trans-array.c (gfc_trans_allocate_array_storage): Ajust.
	(gfc_trans_auto_array_allocation): Likewise.
	(duplicate_allocatable): Likewise.
	* trans-expr.c (gfc_conv_string_tmp): Likewise.
	* trans-stmt.c (gfc_do_allocate): Likewise.
	* trans.c (gfc_call_malloc): Add parameter denoting if this
	is a user allocation.  Do not allocate at least one byte
	if not so.
	(gfc_call_free): Omit check for NULL pointer.
	* trans.h (gfc_call_malloc): Adjust prototype.
	* trans-intrinsic.c (gfc_conv_intrinsic_transfer): Adjust.

Index: gcc/fortran/trans-array.c
===================================================================
*** gcc/fortran/trans-array.c	(revision 158895)
--- gcc/fortran/trans-array.c	(working copy)
*************** gfc_trans_allocate_array_storage (stmtbl
*** 604,610 ****
  	  /* Allocate memory to hold the data or call internal_pack.  */
  	  if (initial == NULL_TREE)
  	    {
! 	      tmp = gfc_call_malloc (pre, NULL, size);
  	      tmp = gfc_evaluate_now (tmp, pre);
  	    }
  	  else
--- 604,610 ----
  	  /* Allocate memory to hold the data or call internal_pack.  */
  	  if (initial == NULL_TREE)
  	    {
! 	      tmp = gfc_call_malloc (pre, NULL, size, false);
  	      tmp = gfc_evaluate_now (tmp, pre);
  	    }
  	  else
*************** gfc_trans_allocate_array_storage (stmtbl
*** 635,641 ****
  		 need to allocate and copy manually.  */
  
  	      gfc_start_block (&do_copying);
! 	      tmp = gfc_call_malloc (&do_copying, NULL, size);
  	      tmp = fold_convert (TREE_TYPE (packed), tmp);
  	      gfc_add_modify (&do_copying, packed, tmp);
  	      tmp = gfc_build_memcpy_call (packed, source_data, size);
--- 635,641 ----
  		 need to allocate and copy manually.  */
  
  	      gfc_start_block (&do_copying);
! 	      tmp = gfc_call_malloc (&do_copying, NULL, size, false);
  	      tmp = fold_convert (TREE_TYPE (packed), tmp);
  	      gfc_add_modify (&do_copying, packed, tmp);
  	      tmp = gfc_build_memcpy_call (packed, source_data, size);
*************** gfc_trans_auto_array_allocation (tree de
*** 4420,4426 ****
  		      fold_convert (gfc_array_index_type, tmp));
  
    /* Allocate memory to hold the data.  */
!   tmp = gfc_call_malloc (&block, TREE_TYPE (decl), size);
    gfc_add_modify (&block, decl, tmp);
  
    /* Set offset of the array.  */
--- 4420,4426 ----
  		      fold_convert (gfc_array_index_type, tmp));
  
    /* Allocate memory to hold the data.  */
!   tmp = gfc_call_malloc (&block, TREE_TYPE (decl), size, false);
    gfc_add_modify (&block, decl, tmp);
  
    /* Set offset of the array.  */
*************** duplicate_allocatable(tree dest, tree sr
*** 5894,5900 ****
        size = TYPE_SIZE_UNIT (type);
        if (!no_malloc)
  	{
! 	  tmp = gfc_call_malloc (&block, type, size);
  	  tmp = fold_build2 (MODIFY_EXPR, void_type_node, dest,
  			     fold_convert (type, tmp));
  	  gfc_add_expr_to_block (&block, tmp);
--- 5894,5900 ----
        size = TYPE_SIZE_UNIT (type);
        if (!no_malloc)
  	{
! 	  tmp = gfc_call_malloc (&block, type, size, true);
  	  tmp = fold_build2 (MODIFY_EXPR, void_type_node, dest,
  			     fold_convert (type, tmp));
  	  gfc_add_expr_to_block (&block, tmp);
*************** duplicate_allocatable(tree dest, tree sr
*** 5917,5923 ****
        if (!no_malloc)
  	{
  	  tmp = TREE_TYPE (gfc_conv_descriptor_data_get (src));
! 	  tmp = gfc_call_malloc (&block, tmp, size);
  	  gfc_conv_descriptor_data_set (&block, dest, tmp);
  	}
  
--- 5917,5923 ----
        if (!no_malloc)
  	{
  	  tmp = TREE_TYPE (gfc_conv_descriptor_data_get (src));
! 	  tmp = gfc_call_malloc (&block, tmp, size, true);
  	  gfc_conv_descriptor_data_set (&block, dest, tmp);
  	}
  
Index: gcc/fortran/trans-expr.c
===================================================================
*** gcc/fortran/trans-expr.c	(revision 158895)
--- gcc/fortran/trans-expr.c	(working copy)
*************** gfc_conv_string_tmp (gfc_se * se, tree t
*** 1139,1145 ****
        tmp = gfc_call_malloc (&se->pre, type,
  			     fold_build2 (MULT_EXPR, TREE_TYPE (len), len,
  					  fold_convert (TREE_TYPE (len),
! 							TYPE_SIZE (type))));
        gfc_add_modify (&se->pre, var, tmp);
  
        /* Free the temporary afterwards.  */
--- 1139,1146 ----
        tmp = gfc_call_malloc (&se->pre, type,
  			     fold_build2 (MULT_EXPR, TREE_TYPE (len), len,
  					  fold_convert (TREE_TYPE (len),
! 							TYPE_SIZE (type))),
! 			     false);
        gfc_add_modify (&se->pre, var, tmp);
  
        /* Free the temporary afterwards.  */
Index: gcc/fortran/trans-stmt.c
===================================================================
*** gcc/fortran/trans-stmt.c	(revision 158895)
--- gcc/fortran/trans-stmt.c	(working copy)
*************** gfc_do_allocate (tree bytesize, tree siz
*** 2192,2198 ****
        tmpvar = gfc_create_var (build_pointer_type (type), "temp");
        *pdata = convert (pvoid_type_node, tmpvar);
  
!       tmp = gfc_call_malloc (pblock, TREE_TYPE (tmpvar), bytesize);
        gfc_add_modify (pblock, tmpvar, tmp);
      }
    return tmpvar;
--- 2192,2198 ----
        tmpvar = gfc_create_var (build_pointer_type (type), "temp");
        *pdata = convert (pvoid_type_node, tmpvar);
  
!       tmp = gfc_call_malloc (pblock, TREE_TYPE (tmpvar), bytesize, false);
        gfc_add_modify (pblock, tmpvar, tmp);
      }
    return tmpvar;
Index: gcc/fortran/trans.c
===================================================================
*** gcc/fortran/trans.c	(revision 158895)
--- gcc/fortran/trans.c	(working copy)
*************** gfc_trans_runtime_check (bool error, boo
*** 495,505 ****
  }
  
  
! /* Call malloc to allocate size bytes of memory, with special conditions:
        + if size <= 0, return a malloced area of size 1,
        + if malloc returns NULL, issue a runtime error.  */
  tree
! gfc_call_malloc (stmtblock_t * block, tree type, tree size)
  {
    tree tmp, msg, malloc_result, null_result, res;
    stmtblock_t block2;
--- 495,506 ----
  }
  
  
! /* Call malloc to allocate size bytes of memory, with special conditions
!    in case GFC_RTCHECK_MEM is enabled or USER_ALLOC_P is true
        + if size <= 0, return a malloced area of size 1,
        + if malloc returns NULL, issue a runtime error.  */
  tree
! gfc_call_malloc (stmtblock_t * block, tree type, tree size, bool user_alloc_p)
  {
    tree tmp, msg, malloc_result, null_result, res;
    stmtblock_t block2;
*************** gfc_call_malloc (stmtblock_t * block, tr
*** 515,522 ****
    /* Call malloc.  */
    gfc_start_block (&block2);
  
!   size = fold_build2 (MAX_EXPR, size_type_node, size,
! 		      build_int_cst (size_type_node, 1));
  
    gfc_add_modify (&block2, res,
  		  fold_convert (prvoid_type_node,
--- 516,528 ----
    /* Call malloc.  */
    gfc_start_block (&block2);
  
!   /* Allocation of size zero is well-defined but the result cannot be
!      distinguished from an error.  So if we want to check if malloc
!      was successful allocate at least one byte.  */
!   if (user_alloc_p
!       || (gfc_option.rtcheck & GFC_RTCHECK_MEM))
!     size = fold_build2 (MAX_EXPR, size_type_node, size,
! 			build_int_cst (size_type_node, 1));
  
    gfc_add_modify (&block2, res,
  		  fold_convert (prvoid_type_node,
*************** gfc_allocate_array_with_status (stmtbloc
*** 782,806 ****
  }
  
  
! /* Free a given variable, if it's not NULL.  */
  tree
  gfc_call_free (tree var)
  {
    stmtblock_t block;
!   tree tmp, cond, call;
  
    if (TREE_TYPE (var) != TREE_TYPE (pvoid_type_node))
      var = fold_convert (pvoid_type_node, var);
  
    gfc_start_block (&block);
    var = gfc_evaluate_now (var, &block);
-   cond = fold_build2 (NE_EXPR, boolean_type_node, var,
- 		      build_int_cst (pvoid_type_node, 0));
    call = build_call_expr_loc (input_location,
! 			  built_in_decls[BUILT_IN_FREE], 1, var);
!   tmp = fold_build3 (COND_EXPR, void_type_node, cond, call,
! 		     build_empty_stmt (input_location));
!   gfc_add_expr_to_block (&block, tmp);
  
    return gfc_finish_block (&block);
  }
--- 788,808 ----
  }
  
  
! /* Free a given variable.  */
  tree
  gfc_call_free (tree var)
  {
    stmtblock_t block;
!   tree call;
  
    if (TREE_TYPE (var) != TREE_TYPE (pvoid_type_node))
      var = fold_convert (pvoid_type_node, var);
  
    gfc_start_block (&block);
    var = gfc_evaluate_now (var, &block);
    call = build_call_expr_loc (input_location,
! 			      built_in_decls[BUILT_IN_FREE], 1, var);
!   gfc_add_expr_to_block (&block, call);
  
    return gfc_finish_block (&block);
  }
Index: gcc/fortran/trans.h
===================================================================
*** gcc/fortran/trans.h	(revision 158895)
--- gcc/fortran/trans.h	(working copy)
*************** void gfc_trans_same_strlen_check (const
*** 469,475 ****
  tree gfc_call_free (tree);
  
  /* Allocate memory after performing a few checks.  */
! tree gfc_call_malloc (stmtblock_t *, tree, tree);
  
  /* Build a memcpy call.  */
  tree gfc_build_memcpy_call (tree, tree, tree);
--- 469,475 ----
  tree gfc_call_free (tree);
  
  /* Allocate memory after performing a few checks.  */
! tree gfc_call_malloc (stmtblock_t *, tree, tree, bool);
  
  /* Build a memcpy call.  */
  tree gfc_build_memcpy_call (tree, tree, tree);
Index: gcc/fortran/trans-intrinsic.c
===================================================================
*** gcc/fortran/trans-intrinsic.c	(revision 158895)
--- gcc/fortran/trans-intrinsic.c	(working copy)
*************** scalar_transfer:
*** 4470,4476 ****
  	 and copy the source into it.  */
        gfc_init_block (&block);
        tmp = gfc_get_pchar_type (expr->ts.kind);
!       tmp = gfc_call_malloc (&block, tmp, dest_word_len);
        gfc_add_modify (&block, tmpdecl,
  		      fold_convert (TREE_TYPE (ptr), tmp));
        tmp = build_call_expr_loc (input_location,
--- 4470,4476 ----
  	 and copy the source into it.  */
        gfc_init_block (&block);
        tmp = gfc_get_pchar_type (expr->ts.kind);
!       tmp = gfc_call_malloc (&block, tmp, dest_word_len, false);
        gfc_add_modify (&block, tmpdecl,
  		      fold_convert (TREE_TYPE (ptr), tmp));
        tmp = build_call_expr_loc (input_location,


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]