Commit 2c69d527 by Paul Thomas

re PR fortran/34820 (internal compiler error: in gfc_conv_descriptor_data_get,…

re PR fortran/34820 (internal compiler error: in gfc_conv_descriptor_data_get, at fortran/trans-array.c:147)

2008-11-24  Paul Thomas  <pault@gcc.gnu.org>

	PR fortran/34820
	* trans-expr.c (gfc_conv_function_call): Remove all code to
	deallocate intent out derived types with allocatable
	components.
	(gfc_trans_assignment_1): An assignment from a scalar to an
	array of derived types with allocatable components, requires
	a deep copy to each array element and deallocation of the
	converted rhs expression afterwards.
	* trans-array.c : Minor whitespace.
	* trans-decl.c (init_intent_out_dt): Add code to deallocate
	allocatable components of derived types with intent out.
	(generate_local_decl): If these types are unused, set them
	referenced anyway but allow the uninitialized warning.

	PR fortran/34143
	* trans-expr.c (gfc_trans_subcomponent_assign): If a conversion
	expression has a null data pointer argument, nullify the
	allocatable component.

	PR fortran/32795
	* trans-expr.c (gfc_trans_subcomponent_assign): Only nullify
	the data pointer if the source is not a variable.

2008-11-24  Paul Thomas  <pault@gcc.gnu.org>

	PR fortran/34820
	* gfortran.dg/alloc_comp_constructor_6.f90 : New test.
	* gfortran.dg/alloc_comp_basics_1.f90 : Reduce expected refs to
	'builtin_free' from 24 to 18.

	PR fortran/34143
	* gfortran.dg/alloc_comp_constructor_5.f90 : New test.

	PR fortran/32795
	* gfortran.dg/alloc_comp_constructor_4.f90 : New test.

From-SVN: r142148
parent e4b95210
2008-11-24 Paul Thomas <pault@gcc.gnu.org>
PR fortran/34820
* trans-expr.c (gfc_conv_function_call): Remove all code to
deallocate intent out derived types with allocatable
components.
(gfc_trans_assignment_1): An assignment from a scalar to an
array of derived types with allocatable components, requires
a deep copy to each array element and deallocation of the
converted rhs expression afterwards.
* trans-array.c : Minor whitespace.
* trans-decl.c (init_intent_out_dt): Add code to deallocate
allocatable components of derived types with intent out.
(generate_local_decl): If these types are unused, set them
referenced anyway but allow the uninitialized warning.
PR fortran/34143
* trans-expr.c (gfc_trans_subcomponent_assign): If a conversion
expression has a null data pointer argument, nullify the
allocatable component.
PR fortran/32795
* trans-expr.c (gfc_trans_subcomponent_assign): Only nullify
the data pointer if the source is not a variable.
2008-11-23 Paul Thomas <pault@gcc.gnu.org> 2008-11-23 Paul Thomas <pault@gcc.gnu.org>
PR fortran/37735 PR fortran/37735
......
...@@ -5276,7 +5276,6 @@ gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, gfc_ss * ss, int g77, ...@@ -5276,7 +5276,6 @@ gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, gfc_ss * ss, int g77,
gfc_conv_expr_descriptor (se, expr, ss); gfc_conv_expr_descriptor (se, expr, ss);
} }
/* Deallocate the allocatable components of structures that are /* Deallocate the allocatable components of structures that are
not variable. */ not variable. */
if (expr->ts.type == BT_DERIVED if (expr->ts.type == BT_DERIVED
......
...@@ -2781,20 +2781,34 @@ gfc_init_default_dt (gfc_symbol * sym, tree body) ...@@ -2781,20 +2781,34 @@ gfc_init_default_dt (gfc_symbol * sym, tree body)
} }
/* Initialize INTENT(OUT) derived type dummies. */ /* Initialize INTENT(OUT) derived type dummies. As well as giving
them their default initializer, if they do not have allocatable
components, they have their allocatable components deallocated. */
static tree static tree
init_intent_out_dt (gfc_symbol * proc_sym, tree body) init_intent_out_dt (gfc_symbol * proc_sym, tree body)
{ {
stmtblock_t fnblock; stmtblock_t fnblock;
gfc_formal_arglist *f; gfc_formal_arglist *f;
tree tmp;
gfc_init_block (&fnblock); gfc_init_block (&fnblock);
for (f = proc_sym->formal; f; f = f->next) for (f = proc_sym->formal; f; f = f->next)
if (f->sym && f->sym->attr.intent == INTENT_OUT if (f->sym && f->sym->attr.intent == INTENT_OUT
&& f->sym->ts.type == BT_DERIVED && f->sym->ts.type == BT_DERIVED)
&& !f->sym->ts.derived->attr.alloc_comp {
&& f->sym->value) if (f->sym->ts.derived->attr.alloc_comp)
body = gfc_init_default_dt (f->sym, body); {
tmp = gfc_deallocate_alloc_comp (f->sym->ts.derived,
f->sym->backend_decl,
f->sym->as ? f->sym->as->rank : 0);
gfc_add_expr_to_block (&fnblock, tmp);
}
if (!f->sym->ts.derived->attr.alloc_comp
&& f->sym->value)
body = gfc_init_default_dt (f->sym, body);
}
gfc_add_expr_to_block (&fnblock, body); gfc_add_expr_to_block (&fnblock, body);
return gfc_finish_block (&fnblock); return gfc_finish_block (&fnblock);
...@@ -3482,10 +3496,10 @@ generate_local_decl (gfc_symbol * sym) ...@@ -3482,10 +3496,10 @@ generate_local_decl (gfc_symbol * sym)
if (sym->attr.flavor == FL_VARIABLE) if (sym->attr.flavor == FL_VARIABLE)
{ {
if (!sym->attr.dummy && !sym->ns->proc_name->attr.entry_master) if (!sym->attr.dummy && !sym->ns->proc_name->attr.entry_master)
generate_dependency_declarations (sym); generate_dependency_declarations (sym);
if (sym->attr.referenced) if (sym->attr.referenced)
gfc_get_symbol_decl (sym); gfc_get_symbol_decl (sym);
/* INTENT(out) dummy arguments are likely meant to be set. */ /* INTENT(out) dummy arguments are likely meant to be set. */
else if (warn_unused_variable else if (warn_unused_variable
&& sym->attr.dummy && sym->attr.dummy
...@@ -3502,20 +3516,34 @@ generate_local_decl (gfc_symbol * sym) ...@@ -3502,20 +3516,34 @@ generate_local_decl (gfc_symbol * sym)
&& !(sym->attr.in_common || sym->attr.use_assoc || sym->mark)) && !(sym->attr.in_common || sym->attr.use_assoc || sym->mark))
gfc_warning ("Unused variable '%s' declared at %L", sym->name, gfc_warning ("Unused variable '%s' declared at %L", sym->name,
&sym->declared_at); &sym->declared_at);
/* For variable length CHARACTER parameters, the PARM_DECL already /* For variable length CHARACTER parameters, the PARM_DECL already
references the length variable, so force gfc_get_symbol_decl references the length variable, so force gfc_get_symbol_decl
even when not referenced. If optimize > 0, it will be optimized even when not referenced. If optimize > 0, it will be optimized
away anyway. But do this only after emitting -Wunused-parameter away anyway. But do this only after emitting -Wunused-parameter
warning if requested. */ warning if requested. */
if (sym->attr.dummy && ! sym->attr.referenced if (sym->attr.dummy && !sym->attr.referenced
&& sym->ts.type == BT_CHARACTER && sym->ts.type == BT_CHARACTER
&& sym->ts.cl->backend_decl != NULL && sym->ts.cl->backend_decl != NULL
&& TREE_CODE (sym->ts.cl->backend_decl) == VAR_DECL) && TREE_CODE (sym->ts.cl->backend_decl) == VAR_DECL)
{ {
sym->attr.referenced = 1; sym->attr.referenced = 1;
gfc_get_symbol_decl (sym); gfc_get_symbol_decl (sym);
} }
/* INTENT(out) dummy arguments with allocatable components are reset
by default and need to be set referenced to generate the code for
automatic lengths. */
if (sym->attr.dummy && !sym->attr.referenced
&& sym->ts.type == BT_DERIVED
&& sym->ts.derived->attr.alloc_comp
&& sym->attr.intent == INTENT_OUT)
{
sym->attr.referenced = 1;
gfc_get_symbol_decl (sym);
}
/* Check for dependencies in the array specification and string /* Check for dependencies in the array specification and string
length, adding the necessary declarations to the function. We length, adding the necessary declarations to the function. We
mark the symbol now, as well as in traverse_ns, to prevent mark the symbol now, as well as in traverse_ns, to prevent
......
...@@ -2742,14 +2742,11 @@ gfc_conv_function_call (gfc_se * se, gfc_symbol * sym, ...@@ -2742,14 +2742,11 @@ gfc_conv_function_call (gfc_se * se, gfc_symbol * sym,
gfc_add_block_to_block (&post, &parmse.post); gfc_add_block_to_block (&post, &parmse.post);
/* Allocated allocatable components of derived types must be /* Allocated allocatable components of derived types must be
deallocated for INTENT(OUT) dummy arguments and non-variable deallocated for non-variable scalars. Non-variable arrays are
scalars. Non-variable arrays are dealt with in trans-array.c dealt with in trans-array.c(gfc_conv_array_parameter). */
(gfc_conv_array_parameter). */
if (e && e->ts.type == BT_DERIVED if (e && e->ts.type == BT_DERIVED
&& e->ts.derived->attr.alloc_comp && e->ts.derived->attr.alloc_comp
&& ((formal && formal->sym->attr.intent == INTENT_OUT) && (e->expr_type != EXPR_VARIABLE && !e->rank))
||
(e->expr_type != EXPR_VARIABLE && !e->rank)))
{ {
int parm_rank; int parm_rank;
tmp = build_fold_indirect_ref (parmse.expr); tmp = build_fold_indirect_ref (parmse.expr);
...@@ -2764,24 +2761,10 @@ gfc_conv_function_call (gfc_se * se, gfc_symbol * sym, ...@@ -2764,24 +2761,10 @@ gfc_conv_function_call (gfc_se * se, gfc_symbol * sym,
case (SCALAR_POINTER): case (SCALAR_POINTER):
tmp = build_fold_indirect_ref (tmp); tmp = build_fold_indirect_ref (tmp);
break; break;
case (ARRAY):
tmp = parmse.expr;
break;
} }
tmp = gfc_deallocate_alloc_comp (e->ts.derived, tmp, parm_rank); tmp = gfc_deallocate_alloc_comp (e->ts.derived, tmp, parm_rank);
if (e->expr_type == EXPR_VARIABLE && e->symtree->n.sym->attr.optional) gfc_add_expr_to_block (&se->post, tmp);
tmp = build3_v (COND_EXPR, gfc_conv_expr_present (e->symtree->n.sym),
tmp, build_empty_stmt ());
if (e->expr_type != EXPR_VARIABLE)
/* Don't deallocate non-variables until they have been used. */
gfc_add_expr_to_block (&se->post, tmp);
else
{
gcc_assert (formal && formal->sym->attr.intent == INTENT_OUT);
gfc_add_expr_to_block (&se->pre, tmp);
}
} }
/* Character strings are passed as two parameters, a length and a /* Character strings are passed as two parameters, a length and a
...@@ -3610,9 +3593,10 @@ gfc_trans_subcomponent_assign (tree dest, gfc_component * cm, gfc_expr * expr) ...@@ -3610,9 +3593,10 @@ gfc_trans_subcomponent_assign (tree dest, gfc_component * cm, gfc_expr * expr)
cm->as->rank); cm->as->rank);
gfc_add_expr_to_block (&block, tmp); gfc_add_expr_to_block (&block, tmp);
gfc_add_block_to_block (&block, &se.post); gfc_add_block_to_block (&block, &se.post);
gfc_conv_descriptor_data_set (&block, se.expr, null_pointer_node);
if (expr->expr_type != EXPR_VARIABLE)
gfc_conv_descriptor_data_set (&block, se.expr, null_pointer_node);
/* Shift the lbound and ubound of temporaries to being unity, rather /* Shift the lbound and ubound of temporaries to being unity, rather
than zero, based. Calculate the offset for all cases. */ than zero, based. Calculate the offset for all cases. */
...@@ -3644,6 +3628,35 @@ gfc_trans_subcomponent_assign (tree dest, gfc_component * cm, gfc_expr * expr) ...@@ -3644,6 +3628,35 @@ gfc_trans_subcomponent_assign (tree dest, gfc_component * cm, gfc_expr * expr)
tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type, offset, tmp2); tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type, offset, tmp2);
gfc_add_modify (&block, offset, tmp); gfc_add_modify (&block, offset, tmp);
} }
if (expr->expr_type == EXPR_FUNCTION
&& expr->value.function.isym
&& expr->value.function.isym->conversion
&& expr->value.function.actual->expr
&& expr->value.function.actual->expr->expr_type
== EXPR_VARIABLE)
{
/* If a conversion expression has a null data pointer
argument, nullify the allocatable component. */
gfc_symbol *s;
tree non_null_expr;
tree null_expr;
s = expr->value.function.actual->expr->symtree->n.sym;
if (s->attr.allocatable || s->attr.pointer)
{
non_null_expr = gfc_finish_block (&block);
gfc_start_block (&block);
gfc_conv_descriptor_data_set (&block, dest,
null_pointer_node);
null_expr = gfc_finish_block (&block);
tmp = gfc_conv_descriptor_data_get (s->backend_decl);
tmp = build2 (EQ_EXPR, boolean_type_node, tmp,
fold_convert (TREE_TYPE (tmp),
null_pointer_node));
return build3_v (COND_EXPR, tmp, null_expr,
non_null_expr);
}
}
} }
else else
{ {
...@@ -4533,6 +4546,7 @@ gfc_trans_assignment_1 (gfc_expr * expr1, gfc_expr * expr2, bool init_flag) ...@@ -4533,6 +4546,7 @@ gfc_trans_assignment_1 (gfc_expr * expr1, gfc_expr * expr2, bool init_flag)
stmtblock_t block; stmtblock_t block;
stmtblock_t body; stmtblock_t body;
bool l_is_temp; bool l_is_temp;
bool scalar_to_array;
/* Assignment of the form lhs = rhs. */ /* Assignment of the form lhs = rhs. */
gfc_start_block (&block); gfc_start_block (&block);
...@@ -4616,9 +4630,24 @@ gfc_trans_assignment_1 (gfc_expr * expr1, gfc_expr * expr2, bool init_flag) ...@@ -4616,9 +4630,24 @@ gfc_trans_assignment_1 (gfc_expr * expr1, gfc_expr * expr2, bool init_flag)
else else
gfc_conv_expr (&lse, expr1); gfc_conv_expr (&lse, expr1);
/* Assignments of scalar derived types with allocatable components
to arrays must be done with a deep copy and the rhs temporary
must have its components deallocated afterwards. */
scalar_to_array = (expr2->ts.type == BT_DERIVED
&& expr2->ts.derived->attr.alloc_comp
&& expr2->expr_type != EXPR_VARIABLE
&& !gfc_is_constant_expr (expr2)
&& expr1->rank && !expr2->rank);
if (scalar_to_array)
{
tmp = gfc_deallocate_alloc_comp (expr2->ts.derived, rse.expr, 0);
gfc_add_expr_to_block (&loop.post, tmp);
}
tmp = gfc_trans_scalar_assign (&lse, &rse, expr1->ts, tmp = gfc_trans_scalar_assign (&lse, &rse, expr1->ts,
l_is_temp || init_flag, l_is_temp || init_flag,
expr2->expr_type == EXPR_VARIABLE); (expr2->expr_type == EXPR_VARIABLE)
|| scalar_to_array);
gfc_add_expr_to_block (&body, tmp); gfc_add_expr_to_block (&body, tmp);
if (lss == gfc_ss_terminator) if (lss == gfc_ss_terminator)
......
2008-11-24 Paul Thomas <pault@gcc.gnu.org>
PR fortran/34820
* gfortran.dg/alloc_comp_constructor_6.f90 : New test.
* gfortran.dg/alloc_comp_basics_1.f90 : Reduce expected refs to
'builtin_free' from 24 to 18.
PR fortran/34143
* gfortran.dg/alloc_comp_constructor_5.f90 : New test.
PR fortran/32795
* gfortran.dg/alloc_comp_constructor_4.f90 : New test.
2008-11-23 Paul Thomas <pault@gcc.gnu.org> 2008-11-23 Paul Thomas <pault@gcc.gnu.org>
PR fortran/37735 PR fortran/37735
......
! { dg-do run }
! Tests the fix for PR34820, in which the nullification of the
! automatic array iregion occurred in the caller, rather than the
! callee. Since 'nproc' was not available, an ICE ensued. During
! the bug fix, it was found that the scalar to array assignment
! of derived types with allocatable components did not work and
! the fix of this is tested too.
!
! Contributed by Toon Moene <toon@moene.indiv.nluug.nl>
!
module grid_io
type grid_index_region
integer, allocatable::lons(:)
end type grid_index_region
contains
subroutine read_grid_header()
integer :: npiece = 1
type(grid_index_region),allocatable :: iregion(:)
allocate (iregion(npiece + 1))
call read_iregion(npiece,iregion)
if (size(iregion) .ne. npiece + 1) call abort
if (.not.allocated (iregion(npiece)%lons)) call abort
if (allocated (iregion(npiece+1)%lons)) call abort
if (any (iregion(npiece)%lons .ne. [(i, i = 1, npiece)])) call abort
deallocate (iregion)
end subroutine read_grid_header
subroutine read_iregion (nproc,iregion)
integer,intent(in)::nproc
type(grid_index_region), intent(OUT)::iregion(1:nproc)
integer :: iarg(nproc)
iarg = [(i, i = 1, nproc)]
iregion = grid_index_region (iarg) !
end subroutine read_iregion
end module grid_io
use grid_io
call read_grid_header
end
! { dg-final { cleanup-tree-dump "grid_io" } }
...@@ -139,6 +139,6 @@ contains ...@@ -139,6 +139,6 @@ contains
end subroutine check_alloc2 end subroutine check_alloc2
end program alloc end program alloc
! { dg-final { scan-tree-dump-times "builtin_free" 27 "original" } } ! { dg-final { scan-tree-dump-times "builtin_free" 21 "original" } }
! { dg-final { cleanup-tree-dump "original" } } ! { dg-final { cleanup-tree-dump "original" } }
! { dg-final { cleanup-modules "alloc_m" } } ! { dg-final { cleanup-modules "alloc_m" } }
! { dg-do run }
! Tests the fix for PR32795, which was primarily about memory leakage is
! certain combinations of alloctable components and constructors. This test
! which appears in comment #2 of the PR has the advantage of a wrong
! numeric result which is symptomatic.
!
! Contributed by Tobias Burnus <burnus@gcc.gnu.org>
!
type :: a
integer, allocatable :: i(:)
end type a
type(a) :: x, y
x = a ([1, 2, 3])
y = a (x%i(:)) ! used to cause a memory leak and wrong result
if (any (x%i .ne. [1, 2, 3])) call abort
end
! { dg-do run }
! { dg-options "-fdefault-integer-8" }
! Tests the fix for PR34143, in which the implicit conversion of yy, with
! fdefault-integer-8, would cause a segfault at runtime.
!
! Contributed by Thomas Koenig <tkoenig@gcc.gnu.org>
!
Program test_constructor
implicit none
type :: thytype
integer(4) :: a(2,2)
end type thytype
type :: mytype
integer(4), allocatable :: a(:, :)
type(thytype), allocatable :: q(:)
end type mytype
integer, allocatable :: yy(:,:)
type (thytype), allocatable :: bar(:)
type (mytype) :: x, y
x = mytype(yy, bar)
if (allocated (x%a) .or. allocated (x%q)) call abort
allocate (yy(2,2))
allocate (bar(2))
yy = reshape ([10,20,30,40],[2,2])
bar = thytype (reshape ([1,2,3,4],[2,2]))
! Check that unallocated allocatables work
y = mytype(yy, bar)
if (.not.allocated (y%a) .or. .not.allocated (y%q)) call abort
end program test_constructor
! { dg-do run }
! { dg-options "-fdefault-integer-8 -O2" }
! Tests the fix for PR34143, where the implicit type
! conversion in the derived type constructor would fail,
! when 'yy' was not allocated. The testscase is an
! extract from alloc_comp_constructor.f90.
!
! Reported by Thomas Koenig <tkoenig@gcc.gnu.org>
!
Program test_constructor
implicit none
type :: thytype
integer(4) :: a(2,2)
end type thytype
type :: mytype
integer(4), allocatable :: a(:, :)
type(thytype), allocatable :: q(:)
end type mytype
integer, allocatable :: yy(:,:)
type (thytype), allocatable :: bar(:)
call non_alloc
call alloc
contains
subroutine non_alloc
type (mytype) :: x
x = mytype(yy, bar)
if (allocated (x%a) .or. allocated (x%q)) call abort
end subroutine non_alloc
subroutine alloc
type (mytype) :: x
allocate (yy(2,2))
allocate (bar(2))
yy = reshape ([10,20,30,40],[2,2])
bar = thytype (reshape ([1,2,3,4],[2,2]))
x = mytype(yy, bar)
if (.not.allocated (x%a) .or. .not.allocated (x%q)) call abort
end subroutine alloc
end program test_constructor
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment