[multiple changes]

2006-10-05  Erik Edelmann <edelmann@gcc.gnu.org>
	    Paul Thomas <pault@gcc.gnu.org>

	PR fortran/20541
	* interface.c (gfc_compare_derived_types): Add comparison of
	the allocatable field.
	* intrinsic.c (add_subroutines): Add MOVE_ALLOC.
	* trans-expr.c (gfc_conv_aliased_arg, gfc_trans_subarray_assign,
	gfc_trans_subcomponent_assign, gfc_conv_string_parameter,
	gfc_trans_scalar_assign): Add extra arguments l_is_temp
	and r_is_var to references to latter function.
	(gfc_conv_function_call): Add enum for types of argument and
	an associated variable parm_kind. Deallocate components of
	INTENT(OUT) and non-variable arrays.
	(gfc_trans_subcomponent_assign): Add block to assign arrays
	to allocatable components.
	(gfc_trans_scalar_assign): Add block to handle assignments of
	derived types with allocatable components, using the above new
	arguments to control allocation/deallocation of memory and the
	copying of allocated arrays.
	* trans-array.c (gfc_array_allocate): Remove old identification 
	of pointer and replace with that of an allocatable array. Add
	nullify of structures with allocatable components. 
	(gfc_conv_array_initializer): Treat EXPR_NULL.
	(gfc_conv_array_parameter): Deallocate allocatable components
	of non-variable structures.
	(gfc_trans_dealloc_allocated): Use second argument of library
	deallocate to inhibit, without error, freeing NULL pointers.
	(get_full_array_size): New function to return the size of a
	full array.
	(gfc_duplicate_allocatable): New function to allocate and copy
	allocated data.
	(structure_alloc_comps): New recursive function to deallocate,
	nullify or copy allocatable components.
	(gfc_nullify_alloc_comp, gfc_deallocate_alloc_comp,
	gfc_copy_alloc_comp): New interface functions to call previous.
	(gfc_trans_deferred_array): Add the code to nullify allocatable
	components, when entering scope, and to deallocate them on
	leaving. Do not call gfc_trans_static_array_pointer and return
	for structures with allocatable components and default
	initializers.
	* symbol.c (gfc_set_component_attr): Set allocatable field.
	(gfc_get_component_attr): Set the allocatable attribute.
	* intrinsic.h : Prototype for gfc_check_move_alloc.
	* decl.c (build_struct): Apply TR15581 constraints for
	allocatable components.
	(variable_decl): Default initializer is always NULL for
	allocatable components.
	(match_attr_spec): Allow, or not, allocatable components,
	according to the standard in force.
	* trans-array.h : Prototypes for gfc_nullify_alloc_comp,
	gfc_deallocate_alloc_comp, gfc_copy_alloc_comp and
	gfc_duplicate_allocatable.
	* gfortran.texi : Add mention of TR15581 extensions.
	* gfortran.h : Add attribute alloc_comp, add
	gfc_components field allocatable and add the prototype
	for gfc_expr_to_initialize.
	* trans-stmt.c (generate_loop_for_temp_to_lhs,
	generate_loop_for_rhs_to_temp, gfc_trans_where_assign,
	gfc_trans_where_3): Add extra arguments to calls to
	gfc_trans_scalar_assign and set appropriately.
	(gfc_trans_allocate): Nullify allocatable components.
	(gfc_trans_deallocate): Deallocate to ultimate allocatable
	components but stop at ultimate pointer components.
	* module.c (mio_symbol_attribute, mio_symbol_attribute,
	mio_component): Add module support for allocatable
	components.
	* trans-types.c (gfc_get_derived_type): Treat allocatable
	components.
	* trans.h : Add two boolean arguments to
	gfc_trans_scalar_assign.
	* resolve.c (resolve_structure_cons): Check conformance of
	constructor element and the component.
	(resolve_allocate_expr): Add expression to nullify the
	constructor expression for allocatable components.
	(resolve_transfer): Inhibit I/O of derived types with
	allocatable components.
	(resolve_fl_derived): Skip check of bounds of allocatable
	components.
	* trans-decl.c (gfc_get_symbol_decl): Add derived types
	with allocatable components to deferred variable.
	(gfc_trans_deferred_vars): Make calls for derived types
	with allocatable components to gfc_trans_deferred_array.
	(gfc_generate_function_code): Nullify allocatable
	component function result on entry.
	* parse.c (parse_derived): Set symbol attr.allocatable if
	allocatable components are present.
	* check.c (gfc_check_allocated): Enforce attr.allocatable
	for intrinsic arguments.
	(gfc_check_move_alloc): Check arguments of move_alloc.
	* primary.c (gfc_variable_attr): Set allocatable attribute.
	* intrinsic.texi : Add index entry and section for
	for move_alloc.

	PR fortran/29115
	* resolve.c (resolve_structure_cons): It is an error if the
	pointer component elements of a derived type constructor are
	not pointer or target.


	PR fortran/29211
	* trans-stmt.c (generate_loop_for_temp_to_lhs,
	generate_loop_for_rhs_to_temp): Provide a string length for
	the temporary by copying that of the other side of the scalar
	assignment.


2006-10-05  Paul Thomas  <pault@gcc.gnu.org>
	    Erik Edelmann  <edelmann@gcc.gnu.org>

	PR libgfortran/20541
	* Makefile.in : Add move_alloc.
	* intrinsics/move_alloc.c: New function.
	* Makefile.am : Add move_alloc.



2006-10-05  Erik Edelmann  <edelmann@gcc.gnu.org>
	    Paul Thomas  <pault@gcc.gnu.org>

	PR fortran/20541
	* gfortran.dg/alloc_comp_basics_1.f90: New test.
	* gfortran.dg/alloc_comp_basics_2.f90: New test.
	* gfortran.dg/alloc_comp_assign_1.f90: New test.
	* gfortran.dg/alloc_comp_assign_2.f90: New test.
	* gfortran.dg/alloc_comp_assign_3.f90: New test.
	* gfortran.dg/alloc_comp_assign_4.f90: New test.
	* gfortran.dg/alloc_comp_constraint_1.f90: New test.
	* gfortran.dg/alloc_comp_constraint_2.f90: New test.
	* gfortran.dg/alloc_comp_constraint_3.f90: New test.
	* gfortran.dg/alloc_comp_constructor_1.f90: New test.
	* gfortran.dg/alloc_comp_constructor_2.f90: New test.
	* gfortran.dg/alloc_comp_initializer_1.f90: New test.
	* gfortran.dg/alloc_comp_std.f90: New test.
	* gfortran.dg/move_alloc.f90: New test.

	PR fortran/29115
	* gfortran.dg/derived_constructor_comps_2.f90: New test.

	PR fortran/29211
	* gfortran.dg/forall_char_dependencies_1.f90: New test.

From-SVN: r117558
This commit is contained in:
Paul Thomas 2006-10-08 16:21:55 +00:00
parent 4afa41f130
commit 5046aff56b
42 changed files with 1878 additions and 106 deletions

View file

@ -1,3 +1,111 @@
2006-10-08 Erik Edelmann <edelmann@gcc.gnu.org>
Paul Thomas <pault@gcc.gnu.org>
PR fortran/20541
* interface.c (gfc_compare_derived_types): Add comparison of
the allocatable field.
* intrinsic.c (add_subroutines): Add MOVE_ALLOC.
* trans-expr.c (gfc_conv_aliased_arg, gfc_trans_subarray_assign,
gfc_trans_subcomponent_assign, gfc_conv_string_parameter,
gfc_trans_scalar_assign): Add extra arguments l_is_temp
and r_is_var to references to latter function.
(gfc_conv_function_call): Add enum for types of argument and
an associated variable parm_kind. Deallocate components of
INTENT(OUT) and non-variable arrays.
(gfc_trans_subcomponent_assign): Add block to assign arrays
to allocatable components.
(gfc_trans_scalar_assign): Add block to handle assignments of
derived types with allocatable components, using the above new
arguments to control allocation/deallocation of memory and the
copying of allocated arrays.
* trans-array.c (gfc_array_allocate): Remove old identification
of pointer and replace with that of an allocatable array. Add
nullify of structures with allocatable components.
(gfc_conv_array_initializer): Treat EXPR_NULL.
(gfc_conv_array_parameter): Deallocate allocatable components
of non-variable structures.
(gfc_trans_dealloc_allocated): Use second argument of library
deallocate to inhibit, without error, freeing NULL pointers.
(get_full_array_size): New function to return the size of a
full array.
(gfc_duplicate_allocatable): New function to allocate and copy
allocated data.
(structure_alloc_comps): New recursive function to deallocate,
nullify or copy allocatable components.
(gfc_nullify_alloc_comp, gfc_deallocate_alloc_comp,
gfc_copy_alloc_comp): New interface functions to call previous.
(gfc_trans_deferred_array): Add the code to nullify allocatable
components, when entering scope, and to deallocate them on
leaving. Do not call gfc_trans_static_array_pointer and return
for structures with allocatable components and default
initializers.
* symbol.c (gfc_set_component_attr): Set allocatable field.
(gfc_get_component_attr): Set the allocatable attribute.
* intrinsic.h : Prototype for gfc_check_move_alloc.
* decl.c (build_struct): Apply TR15581 constraints for
allocatable components.
(variable_decl): Default initializer is always NULL for
allocatable components.
(match_attr_spec): Allow, or not, allocatable components,
according to the standard in force.
* trans-array.h : Prototypes for gfc_nullify_alloc_comp,
gfc_deallocate_alloc_comp, gfc_copy_alloc_comp and
gfc_duplicate_allocatable.
* gfortran.texi : Add mention of TR15581 extensions.
* gfortran.h : Add attribute alloc_comp, add
gfc_components field allocatable and add the prototype
for gfc_expr_to_initialize.
* trans-stmt.c (generate_loop_for_temp_to_lhs,
generate_loop_for_rhs_to_temp, gfc_trans_where_assign,
gfc_trans_where_3): Add extra arguments to calls to
gfc_trans_scalar_assign and set appropriately.
(gfc_trans_allocate): Nullify allocatable components.
(gfc_trans_deallocate): Deallocate to ultimate allocatable
components but stop at ultimate pointer components.
* module.c (mio_symbol_attribute, mio_symbol_attribute,
mio_component): Add module support for allocatable
components.
* trans-types.c (gfc_get_derived_type): Treat allocatable
components.
* trans.h : Add two boolean arguments to
gfc_trans_scalar_assign.
* resolve.c (resolve_structure_cons): Check conformance of
constructor element and the component.
(resolve_allocate_expr): Add expression to nullify the
constructor expression for allocatable components.
(resolve_transfer): Inhibit I/O of derived types with
allocatable components.
(resolve_fl_derived): Skip check of bounds of allocatable
components.
* trans-decl.c (gfc_get_symbol_decl): Add derived types
with allocatable components to deferred variable.
(gfc_trans_deferred_vars): Make calls for derived types
with allocatable components to gfc_trans_deferred_array.
(gfc_generate_function_code): Nullify allocatable
component function result on entry.
* parse.c (parse_derived): Set symbol attr.allocatable if
allocatable components are present.
* check.c (gfc_check_allocated): Enforce attr.allocatable
for intrinsic arguments.
(gfc_check_move_alloc): Check arguments of move_alloc.
* primary.c (gfc_variable_attr): Set allocatable attribute.
* intrinsic.texi : Add index entry and section for
for move_alloc.
2006-10-08 Paul Thomas <pault@gcc.gnu.org>
PR fortran/29115
* resolve.c (resolve_structure_cons): It is an error if the
pointer component elements of a derived type constructor are
not pointer or target.
PR fortran/29211
* trans-stmt.c (generate_loop_for_temp_to_lhs,
generate_loop_for_rhs_to_temp): Provide a string length for
the temporary by copying that of the other side of the scalar
assignment.
2006-10-08 Tobias Burnus <burnus@net-b.de>
PR fortran/28585

View file

@ -477,13 +477,16 @@ gfc_check_all_any (gfc_expr * mask, gfc_expr * dim)
try
gfc_check_allocated (gfc_expr * array)
{
symbol_attribute attr;
if (variable_check (array, 0) == FAILURE)
return FAILURE;
if (array_check (array, 0) == FAILURE)
return FAILURE;
if (!array->symtree->n.sym->attr.allocatable)
attr = gfc_variable_attr (array, NULL);
if (!attr.allocatable)
{
gfc_error ("'%s' argument of '%s' intrinsic at %L must be ALLOCATABLE",
gfc_current_intrinsic_arg[0], gfc_current_intrinsic,
@ -1814,6 +1817,64 @@ gfc_check_merge (gfc_expr * tsource, gfc_expr * fsource, gfc_expr * mask)
return SUCCESS;
}
try
gfc_check_move_alloc (gfc_expr * from, gfc_expr * to)
{
symbol_attribute attr;
if (variable_check (from, 0) == FAILURE)
return FAILURE;
if (array_check (from, 0) == FAILURE)
return FAILURE;
attr = gfc_variable_attr (from, NULL);
if (!attr.allocatable)
{
gfc_error ("'%s' argument of '%s' intrinsic at %L must be ALLOCATABLE",
gfc_current_intrinsic_arg[0], gfc_current_intrinsic,
&from->where);
return FAILURE;
}
if (variable_check (to, 0) == FAILURE)
return FAILURE;
if (array_check (to, 0) == FAILURE)
return FAILURE;
attr = gfc_variable_attr (to, NULL);
if (!attr.allocatable)
{
gfc_error ("'%s' argument of '%s' intrinsic at %L must be ALLOCATABLE",
gfc_current_intrinsic_arg[0], gfc_current_intrinsic,
&to->where);
return FAILURE;
}
if (same_type_check (from, 0, to, 1) == FAILURE)
return FAILURE;
if (to->rank != from->rank)
{
gfc_error ("the '%s' and '%s' arguments of '%s' intrinsic at %L must "
"have the same rank %d/%d", gfc_current_intrinsic_arg[0],
gfc_current_intrinsic_arg[1], gfc_current_intrinsic,
&to->where, from->rank, to->rank);
return FAILURE;
}
if (to->ts.kind != from->ts.kind)
{
gfc_error ("the '%s' and '%s' arguments of '%s' intrinsic at %L must "
"be of the same kind %d/%d", gfc_current_intrinsic_arg[0],
gfc_current_intrinsic_arg[1], gfc_current_intrinsic,
&to->where, from->ts.kind, to->ts.kind);
return FAILURE;
}
return SUCCESS;
}
try
gfc_check_nearest (gfc_expr * x, gfc_expr * s)

View file

@ -962,14 +962,31 @@ build_struct (const char *name, gfc_charlen * cl, gfc_expr ** init,
/* Check array components. */
if (!c->dimension)
return SUCCESS;
{
if (c->allocatable)
{
gfc_error ("Allocatable component at %C must be an array");
return FAILURE;
}
else
return SUCCESS;
}
if (c->pointer)
{
if (c->as->type != AS_DEFERRED)
{
gfc_error ("Pointer array component of structure at %C "
"must have a deferred shape");
gfc_error ("Pointer array component of structure at %C must have a "
"deferred shape");
return FAILURE;
}
}
else if (c->allocatable)
{
if (c->as->type != AS_DEFERRED)
{
gfc_error ("Allocatable component of structure at %C must have a "
"deferred shape");
return FAILURE;
}
}
@ -1284,6 +1301,14 @@ variable_decl (int elem)
}
}
if (initializer != NULL && current_attr.allocatable
&& gfc_current_state () == COMP_DERIVED)
{
gfc_error ("Initialization of allocatable component at %C is not allowed");
m = MATCH_ERROR;
goto cleanup;
}
/* Check if we are parsing an enumeration and if the current enumerator
variable has an initializer or not. If it does not have an
initializer, the initialization value of the previous enumerator
@ -1315,8 +1340,9 @@ variable_decl (int elem)
t = add_init_expr_to_sym (name, &initializer, &var_locus);
else
{
if (current_ts.type == BT_DERIVED && !current_attr.pointer
&& !initializer)
if (current_ts.type == BT_DERIVED
&& !current_attr.pointer
&& !initializer)
initializer = gfc_default_initializer (&current_ts);
t = build_struct (name, cl, &initializer, &as);
}
@ -2141,11 +2167,24 @@ match_attr_spec (void)
&& d != DECL_DIMENSION && d != DECL_POINTER
&& d != DECL_COLON && d != DECL_NONE)
{
gfc_error ("Attribute at %L is not allowed in a TYPE definition",
&seen_at[d]);
m = MATCH_ERROR;
goto cleanup;
if (d == DECL_ALLOCATABLE)
{
if (gfc_notify_std (GFC_STD_F2003,
"In the selected standard, the ALLOCATABLE "
"attribute at %C is not allowed in a TYPE "
"definition") == FAILURE)
{
m = MATCH_ERROR;
goto cleanup;
}
}
else
{
gfc_error ("Attribute at %L is not allowed in a TYPE definition",
&seen_at[d]);
m = MATCH_ERROR;
goto cleanup;
}
}
if ((d == DECL_PRIVATE || d == DECL_PUBLIC)

View file

@ -2406,7 +2406,7 @@ gfc_default_initializer (gfc_typespec *ts)
/* See if we have a default initializer. */
for (c = ts->derived->components; c; c = c->next)
{
if (c->initializer && init == NULL)
if ((c->initializer || c->allocatable) && init == NULL)
init = gfc_get_expr ();
}
@ -2430,6 +2430,13 @@ gfc_default_initializer (gfc_typespec *ts)
if (c->initializer)
tail->expr = gfc_copy_expr (c->initializer);
if (c->allocatable)
{
tail->expr = gfc_get_expr ();
tail->expr->expr_type = EXPR_NULL;
tail->expr->ts = c->ts;
}
}
return init;
}

View file

@ -532,6 +532,9 @@ typedef struct
/* Special attributes for Cray pointers, pointees. */
unsigned cray_pointer:1, cray_pointee:1;
/* The symbol is a derived type with allocatable components, possibly nested.
*/
unsigned alloc_comp:1;
}
symbol_attribute;
@ -649,7 +652,7 @@ typedef struct gfc_component
const char *name;
gfc_typespec ts;
int pointer, dimension;
int pointer, allocatable, dimension;
gfc_array_spec *as;
tree backend_decl;
@ -1972,6 +1975,7 @@ void gfc_resolve_omp_do_blocks (gfc_code *, gfc_namespace *);
void gfc_free_actual_arglist (gfc_actual_arglist *);
gfc_actual_arglist *gfc_copy_actual_arglist (gfc_actual_arglist *);
const char *gfc_extract_int (gfc_expr *, int *);
gfc_expr *gfc_expr_to_initialize (gfc_expr *);
gfc_expr *gfc_build_conversion (gfc_expr *);
void gfc_free_ref_list (gfc_ref *);

View file

@ -374,6 +374,9 @@ gfc_compare_derived_types (gfc_symbol * derived1, gfc_symbol * derived2)
if (dt1->dimension != dt2->dimension)
return 0;
if (dt1->allocatable != dt2->allocatable)
return 0;
if (dt1->dimension && gfc_compare_array_spec (dt1->as, dt2->as) == 0)
return 0;

View file

@ -2424,6 +2424,11 @@ add_subroutines (void)
length, BT_INTEGER, di, OPTIONAL, st, BT_INTEGER, di, OPTIONAL,
trim_name, BT_LOGICAL, dl, OPTIONAL);
add_sym_2s ("move_alloc", 0, BT_UNKNOWN, 0, GFC_STD_F2003,
gfc_check_move_alloc, NULL, NULL,
f, BT_UNKNOWN, 0, REQUIRED,
t, BT_UNKNOWN, 0, REQUIRED);
add_sym_5s ("mvbits", 1, BT_UNKNOWN, 0, GFC_STD_F95,
gfc_check_mvbits, gfc_simplify_mvbits, gfc_resolve_mvbits,
f, BT_INTEGER, di, REQUIRED, fp, BT_INTEGER, di, REQUIRED,

View file

@ -154,6 +154,7 @@ try gfc_check_free (gfc_expr *);
try gfc_check_fstat_sub (gfc_expr *, gfc_expr *, gfc_expr *);
try gfc_check_gerror (gfc_expr *);
try gfc_check_getlog (gfc_expr *);
try gfc_check_move_alloc (gfc_expr *, gfc_expr *);
try gfc_check_mvbits (gfc_expr *, gfc_expr *, gfc_expr *, gfc_expr *,
gfc_expr *);
try gfc_check_random_number (gfc_expr *);

View file

@ -181,6 +181,7 @@ Some intrinsics have documentation yet to be completed as indicated by 'document
* @code{MINVAL}: MINVAL, Minimum value of an array
* @code{MOD}: MOD, Remainder function
* @code{MODULO}: MODULO, Modulo function
* @code{MOVE_ALLOC}: MOVE_ALLOC, Move allocation from one object to another
* @code{MVBITS}: MVBITS, Move bits from one integer to another
* @code{NEAREST}: NEAREST, Nearest representable number
* @code{NEW_LINE}: NEW_LINE, New line character
@ -5834,6 +5835,50 @@ Elemental subroutine
@node MOVE_ALLOC
@section @code{MOVE_ALLOC} --- Move allocation from one object to another
@findex @code{MOVE_ALLOC} intrinsic
@cindex MOVE_ALLOC
@table @asis
@item @emph{Description}:
@code{MOVE_ALLOC(SRC, DEST)} moves the allocation from @var{SRC} to
@var{DEST}. @var{SRC} will become deallocated in the process.
@item @emph{Option}:
f2003, gnu
@item @emph{Class}:
Subroutine
@item @emph{Syntax}:
@code{CALL MOVE_ALLOC(SRC, DEST)}
@item @emph{Arguments}:
@multitable @columnfractions .15 .80
@item @var{SRC} @tab @code{ALLOCATABLE}, @code{INTENT(INOUT)}, may be of any type and kind.
@item @var{DEST} @tab @code{ALLOCATABLE}, @code{INTENT(OUT)}, shall be of the same type, kind and rank as @var{SRC}
@end multitable
@item @emph{Return value}:
None
@item @emph{Example}:
@smallexample
program test_move_alloc
integer, allocatable :: a(:), b(:)
allocate(a(3))
a = [ 1, 2, 3 ]
call move_alloc(a, b)
print *, allocated(a), allocated(b)
print *, b
end program test_move_alloc
@end smallexample
@end table
@node NEAREST
@section @code{NEAREST} --- Nearest representable number
@findex @code{NEAREST} intrinsic

View file

@ -1435,7 +1435,7 @@ typedef enum
AB_DATA, AB_IN_NAMELIST, AB_IN_COMMON,
AB_FUNCTION, AB_SUBROUTINE, AB_SEQUENCE, AB_ELEMENTAL, AB_PURE,
AB_RECURSIVE, AB_GENERIC, AB_ALWAYS_EXPLICIT, AB_CRAY_POINTER,
AB_CRAY_POINTEE, AB_THREADPRIVATE
AB_CRAY_POINTEE, AB_THREADPRIVATE, AB_ALLOC_COMP
}
ab_attribute;
@ -1465,6 +1465,7 @@ static const mstring attr_bits[] =
minit ("ALWAYS_EXPLICIT", AB_ALWAYS_EXPLICIT),
minit ("CRAY_POINTER", AB_CRAY_POINTER),
minit ("CRAY_POINTEE", AB_CRAY_POINTEE),
minit ("ALLOC_COMP", AB_ALLOC_COMP),
minit (NULL, -1)
};
@ -1555,6 +1556,8 @@ mio_symbol_attribute (symbol_attribute * attr)
MIO_NAME(ab_attribute) (AB_CRAY_POINTER, attr_bits);
if (attr->cray_pointee)
MIO_NAME(ab_attribute) (AB_CRAY_POINTEE, attr_bits);
if (attr->alloc_comp)
MIO_NAME(ab_attribute) (AB_ALLOC_COMP, attr_bits);
mio_rparen ();
@ -1644,6 +1647,9 @@ mio_symbol_attribute (symbol_attribute * attr)
case AB_CRAY_POINTEE:
attr->cray_pointee = 1;
break;
case AB_ALLOC_COMP:
attr->alloc_comp = 1;
break;
}
}
}
@ -1951,6 +1957,7 @@ mio_component (gfc_component * c)
mio_integer (&c->dimension);
mio_integer (&c->pointer);
mio_integer (&c->allocatable);
mio_expr (&c->initializer);
mio_rparen ();

View file

@ -1499,6 +1499,8 @@ parse_derived (void)
int compiling_type, seen_private, seen_sequence, seen_component, error_flag;
gfc_statement st;
gfc_state_data s;
gfc_symbol *sym;
gfc_component *c;
error_flag = 0;
@ -1595,6 +1597,18 @@ parse_derived (void)
}
}
/* Look for allocatable components. */
sym = gfc_current_block ();
for (c = sym->components; c; c = c->next)
{
if (c->allocatable || (c->ts.type == BT_DERIVED
&& c->ts.derived->attr.alloc_comp))
{
sym->attr.alloc_comp = 1;
break;
}
}
pop_state ();
}

View file

@ -1715,7 +1715,7 @@ check_substring:
symbol_attribute
gfc_variable_attr (gfc_expr * expr, gfc_typespec * ts)
{
int dimension, pointer, target;
int dimension, pointer, allocatable, target;
symbol_attribute attr;
gfc_ref *ref;
@ -1727,6 +1727,7 @@ gfc_variable_attr (gfc_expr * expr, gfc_typespec * ts)
dimension = attr.dimension;
pointer = attr.pointer;
allocatable = attr.allocatable;
target = attr.target;
if (pointer)
@ -1747,12 +1748,12 @@ gfc_variable_attr (gfc_expr * expr, gfc_typespec * ts)
break;
case AR_SECTION:
pointer = 0;
allocatable = pointer = 0;
dimension = 1;
break;
case AR_ELEMENT:
pointer = 0;
allocatable = pointer = 0;
break;
case AR_UNKNOWN:
@ -1767,18 +1768,20 @@ gfc_variable_attr (gfc_expr * expr, gfc_typespec * ts)
*ts = ref->u.c.component->ts;
pointer = ref->u.c.component->pointer;
allocatable = ref->u.c.component->allocatable;
if (pointer)
target = 1;
break;
case REF_SUBSTRING:
pointer = 0;
allocatable = pointer = 0;
break;
}
attr.dimension = dimension;
attr.pointer = pointer;
attr.allocatable = allocatable;
attr.target = target;
return attr;

View file

@ -593,6 +593,7 @@ resolve_structure_cons (gfc_expr * expr)
gfc_constructor *cons;
gfc_component *comp;
try t;
symbol_attribute a;
t = SUCCESS;
cons = expr->value.constructor;
@ -615,6 +616,17 @@ resolve_structure_cons (gfc_expr * expr)
continue;
}
if (cons->expr->expr_type != EXPR_NULL
&& comp->as && comp->as->rank != cons->expr->rank
&& (comp->allocatable || cons->expr->rank))
{
gfc_error ("The rank of the element in the derived type "
"constructor at %L does not match that of the "
"component (%d/%d)", &cons->expr->where,
cons->expr->rank, comp->as ? comp->as->rank : 0);
t = FAILURE;
}
/* If we don't have the right type, try to convert it. */
if (!gfc_compare_types (&cons->expr->ts, &comp->ts))
@ -629,6 +641,19 @@ resolve_structure_cons (gfc_expr * expr)
else
t = gfc_convert_type (cons->expr, &comp->ts, 1);
}
if (!comp->pointer || cons->expr->expr_type == EXPR_NULL)
continue;
a = gfc_expr_attr (cons->expr);
if (!a.pointer && !a.target)
{
t = FAILURE;
gfc_error ("The element in the derived type constructor at %L, "
"for pointer component '%s' should be a POINTER or "
"a TARGET", &cons->expr->where, comp->name);
}
}
return t;
@ -3408,7 +3433,8 @@ find_sym_in_expr (gfc_symbol *sym, gfc_expr *e)
/* Given the expression node e for an allocatable/pointer of derived type to be
allocated, get the expression node to be initialized afterwards (needed for
derived types with default initializers). */
derived types with default initializers, and derived types with allocatable
components that need nullification.) */
static gfc_expr *
expr_to_initialize (gfc_expr * e)
@ -3532,8 +3558,7 @@ resolve_allocate_expr (gfc_expr * e, gfc_code * code)
init_st->loc = code->loc;
init_st->op = EXEC_ASSIGN;
init_st->expr = expr_to_initialize (e);
init_st->expr2 = init_e;
init_st->expr2 = init_e;
init_st->next = code->next;
code->next = init_st;
}
@ -4164,6 +4189,13 @@ resolve_transfer (gfc_code * code)
return;
}
if (ts->derived->attr.alloc_comp)
{
gfc_error ("Data transfer element at %L cannot have "
"ALLOCATABLE components", &code->loc);
return;
}
if (derived_inaccessible (ts->derived))
{
gfc_error ("Data transfer element at %L cannot have "
@ -5545,7 +5577,7 @@ resolve_fl_derived (gfc_symbol *sym)
}
}
if (c->pointer || c->as == NULL)
if (c->pointer || c->allocatable || c->as == NULL)
continue;
for (i = 0; i < c->as->rank; i++)
@ -5606,16 +5638,28 @@ resolve_fl_namelist (gfc_symbol *sym)
}
}
/* Reject namelist arrays that are not constant shape. */
for (nl = sym->namelist; nl; nl = nl->next)
{
if (is_non_constant_shape_array (nl->sym))
{
gfc_error ("The array '%s' must have constant shape to be "
"a NAMELIST object at %L", nl->sym->name,
&sym->declared_at);
return FAILURE;
}
/* Reject namelist arrays that are not constant shape. */
for (nl = sym->namelist; nl; nl = nl->next)
{
if (is_non_constant_shape_array (nl->sym))
{
gfc_error ("The array '%s' must have constant shape to be "
"a NAMELIST object at %L", nl->sym->name,
&sym->declared_at);
return FAILURE;
}
}
/* Namelist objects cannot have allocatable components. */
for (nl = sym->namelist; nl; nl = nl->next)
{
if (nl->sym->ts.type == BT_DERIVED
&& nl->sym->ts.derived->attr.alloc_comp)
{
gfc_error ("NAMELIST object '%s' at %L cannot have ALLOCATABLE "
"components", nl->sym->name, &sym->declared_at);
return FAILURE;
}
}
/* 14.1.2 A module or internal procedure represent local entities
@ -6370,6 +6414,14 @@ resolve_equivalence_derived (gfc_symbol *derived, gfc_symbol *sym, gfc_expr *e)
return FAILURE;
}
/* Shall not have allocatable components. */
if (derived->attr.alloc_comp)
{
gfc_error ("Derived type variable '%s' at %L cannot have ALLOCATABLE "
"components to be an EQUIVALENCE object",sym->name, &e->where);
return FAILURE;
}
for (; c ; c = c->next)
{
d = c->ts.derived;

View file

@ -1523,6 +1523,7 @@ gfc_set_component_attr (gfc_component * c, symbol_attribute * attr)
c->dimension = attr->dimension;
c->pointer = attr->pointer;
c->allocatable = attr->allocatable;
}
@ -1536,6 +1537,7 @@ gfc_get_component_attr (symbol_attribute * attr, gfc_component * c)
gfc_clear_attr (attr);
attr->dimension = c->dimension;
attr->pointer = c->pointer;
attr->allocatable = c->allocatable;
}

View file

@ -3236,32 +3236,27 @@ gfc_array_allocate (gfc_se * se, gfc_expr * expr, tree pstat)
tree size;
gfc_expr **lower;
gfc_expr **upper;
gfc_ref *ref;
int allocatable_array;
int must_be_pointer;
gfc_ref *ref, *prev_ref = NULL;
bool allocatable_array;
ref = expr->ref;
/* In Fortran 95, components can only contain pointers, so that,
in ALLOCATE (foo%bar(2)), bar must be a pointer component.
We test this by checking for ref->next.
An implementation of TR 15581 would need to change this. */
if (ref)
must_be_pointer = ref->next != NULL;
else
must_be_pointer = 0;
/* Find the last reference in the chain. */
while (ref && ref->next != NULL)
{
gcc_assert (ref->type != REF_ARRAY || ref->u.ar.type == AR_ELEMENT);
prev_ref = ref;
ref = ref->next;
}
if (ref == NULL || ref->type != REF_ARRAY)
return false;
if (!prev_ref)
allocatable_array = expr->symtree->n.sym->attr.allocatable;
else
allocatable_array = prev_ref->u.c.component->allocatable;
/* Figure out the size of the array. */
switch (ref->u.ar.type)
{
@ -3294,11 +3289,6 @@ gfc_array_allocate (gfc_se * se, gfc_expr * expr, tree pstat)
tmp = gfc_conv_descriptor_data_addr (se->expr);
pointer = gfc_evaluate_now (tmp, &se->pre);
if (must_be_pointer)
allocatable_array = 0;
else
allocatable_array = expr->symtree->n.sym->attr.allocatable;
if (TYPE_PRECISION (gfc_array_index_type) == 32)
{
if (allocatable_array)
@ -3325,6 +3315,14 @@ gfc_array_allocate (gfc_se * se, gfc_expr * expr, tree pstat)
tmp = gfc_conv_descriptor_offset (se->expr);
gfc_add_modify_expr (&se->pre, tmp, offset);
if (expr->ts.type == BT_DERIVED
&& expr->ts.derived->attr.alloc_comp)
{
tmp = gfc_nullify_alloc_comp (expr->ts.derived, se->expr,
ref->u.ar.as->rank);
gfc_add_expr_to_block (&se->pre, tmp);
}
return true;
}
@ -3465,6 +3463,9 @@ gfc_conv_array_initializer (tree type, gfc_expr * expr)
}
break;
case EXPR_NULL:
return gfc_build_null_descriptor (type);
default:
gcc_unreachable ();
}
@ -4547,6 +4548,17 @@ gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, gfc_ss * ss, int g77)
se->want_pointer = 1;
gfc_conv_expr_descriptor (se, expr, ss);
/* Deallocate the allocatable components of structures that are
not variable. */
if (expr->ts.type == BT_DERIVED
&& expr->ts.derived->attr.alloc_comp
&& expr->expr_type != EXPR_VARIABLE)
{
tmp = build_fold_indirect_ref (se->expr);
tmp = gfc_deallocate_alloc_comp (expr->ts.derived, tmp, expr->rank);
gfc_add_expr_to_block (&se->post, tmp);
}
if (g77)
{
desc = se->expr;
@ -4595,25 +4607,322 @@ tree
gfc_trans_dealloc_allocated (tree descriptor)
{
tree tmp;
tree deallocate;
tree ptr;
tree var;
stmtblock_t block;
gfc_start_block (&block);
deallocate = gfc_array_deallocate (descriptor, null_pointer_node);
tmp = gfc_conv_descriptor_data_get (descriptor);
tmp = build2 (NE_EXPR, boolean_type_node, tmp,
build_int_cst (TREE_TYPE (tmp), 0));
tmp = build3_v (COND_EXPR, tmp, deallocate, build_empty_stmt ());
tmp = gfc_conv_descriptor_data_addr (descriptor);
var = gfc_evaluate_now (tmp, &block);
tmp = gfc_create_var (gfc_array_index_type, NULL);
ptr = build_fold_addr_expr (tmp);
/* Call array_deallocate with an int* present in the second argument.
Although it is ignored here, it's presence ensures that arrays that
are already deallocated are ignored. */
tmp = gfc_chainon_list (NULL_TREE, var);
tmp = gfc_chainon_list (tmp, ptr);
tmp = build_function_call_expr (gfor_fndecl_deallocate, tmp);
gfc_add_expr_to_block (&block, tmp);
tmp = gfc_finish_block (&block);
return tmp;
return gfc_finish_block (&block);
}
/* NULLIFY an allocatable/pointer array on function entry, free it on exit. */
/* This helper function calculates the size in words of a full array. */
static tree
get_full_array_size (stmtblock_t *block, tree decl, int rank)
{
tree idx;
tree nelems;
tree tmp;
idx = gfc_rank_cst[rank - 1];
nelems = gfc_conv_descriptor_ubound (decl, idx);
tmp = gfc_conv_descriptor_lbound (decl, idx);
tmp = build2 (MINUS_EXPR, gfc_array_index_type, nelems, tmp);
tmp = build2 (PLUS_EXPR, gfc_array_index_type,
tmp, gfc_index_one_node);
tmp = gfc_evaluate_now (tmp, block);
nelems = gfc_conv_descriptor_stride (decl, idx);
tmp = build2 (MULT_EXPR, gfc_array_index_type, nelems, tmp);
return gfc_evaluate_now (tmp, block);
}
/* Allocate dest to the same size as src, and copy src -> dest. */
tree
gfc_duplicate_allocatable(tree dest, tree src, tree type, int rank)
{
tree tmp;
tree size;
tree nelems;
tree args;
tree null_cond;
tree null_data;
stmtblock_t block;
/* If the source is null, set the destination to null. */
gfc_init_block (&block);
gfc_conv_descriptor_data_set (&block, dest, null_pointer_node);
null_data = gfc_finish_block (&block);
gfc_init_block (&block);
nelems = get_full_array_size (&block, src, rank);
size = fold_build2 (MULT_EXPR, gfc_array_index_type, nelems,
TYPE_SIZE_UNIT (gfc_get_element_type (type)));
/* Allocate memory to the destination. */
tmp = gfc_chainon_list (NULL_TREE, size);
if (gfc_index_integer_kind == 4)
tmp = build_function_call_expr (gfor_fndecl_internal_malloc, tmp);
else if (gfc_index_integer_kind == 8)
tmp = build_function_call_expr (gfor_fndecl_internal_malloc64, tmp);
else
gcc_unreachable ();
tmp = fold (convert (TREE_TYPE (gfc_conv_descriptor_data_get (src)),
tmp));
gfc_conv_descriptor_data_set (&block, dest, tmp);
/* We know the temporary and the value will be the same length,
so can use memcpy. */
tmp = gfc_conv_descriptor_data_get (dest);
args = gfc_chainon_list (NULL_TREE, tmp);
tmp = gfc_conv_descriptor_data_get (src);
args = gfc_chainon_list (args, tmp);
args = gfc_chainon_list (args, size);
tmp = built_in_decls[BUILT_IN_MEMCPY];
tmp = build_function_call_expr (tmp, args);
gfc_add_expr_to_block (&block, tmp);
tmp = gfc_finish_block (&block);
/* Null the destination if the source is null; otherwise do
the allocate and copy. */
null_cond = gfc_conv_descriptor_data_get (src);
null_cond = convert (pvoid_type_node, null_cond);
null_cond = build2 (NE_EXPR, boolean_type_node, null_cond,
null_pointer_node);
return build3_v (COND_EXPR, null_cond, tmp, null_data);
}
/* Recursively traverse an object of derived type, generating code to
deallocate, nullify or copy allocatable components. This is the work horse
function for the functions named in this enum. */
enum {DEALLOCATE_ALLOC_COMP = 1, NULLIFY_ALLOC_COMP, COPY_ALLOC_COMP};
static tree
structure_alloc_comps (gfc_symbol * der_type, tree decl,
tree dest, int rank, int purpose)
{
gfc_component *c;
gfc_loopinfo loop;
stmtblock_t fnblock;
stmtblock_t loopbody;
tree tmp;
tree comp;
tree dcmp;
tree nelems;
tree index;
tree var;
tree cdecl;
tree ctype;
tree vref, dref;
tree null_cond = NULL_TREE;
gfc_init_block (&fnblock);
/* If this an array of derived types with allocatable components
build a loop and recursively call this function. */
if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
|| GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl)))
{
tmp = gfc_conv_array_data (decl);
var = build_fold_indirect_ref (tmp);
/* Get the number of elements - 1 and set the counter. */
if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl)))
{
/* Use the descriptor for an allocatable array. Since this
is a full array reference, we only need the descriptor
information from dimension = rank. */
tmp = get_full_array_size (&fnblock, decl, rank);
tmp = build2 (MINUS_EXPR, gfc_array_index_type,
tmp, gfc_index_one_node);
null_cond = gfc_conv_descriptor_data_get (decl);
null_cond = build2 (NE_EXPR, boolean_type_node, null_cond,
build_int_cst (TREE_TYPE (tmp), 0));
}
else
{
/* Otherwise use the TYPE_DOMAIN information. */
tmp = array_type_nelts (TREE_TYPE (decl));
tmp = fold_convert (gfc_array_index_type, tmp);
}
/* Remember that this is, in fact, the no. of elements - 1. */
nelems = gfc_evaluate_now (tmp, &fnblock);
index = gfc_create_var (gfc_array_index_type, "S");
/* Build the body of the loop. */
gfc_init_block (&loopbody);
vref = gfc_build_array_ref (var, index);
if (purpose == COPY_ALLOC_COMP)
{
tmp = gfc_duplicate_allocatable (dest, decl, TREE_TYPE(decl), rank);
gfc_add_expr_to_block (&fnblock, tmp);
tmp = build_fold_indirect_ref (gfc_conv_descriptor_data_get (dest));
dref = gfc_build_array_ref (tmp, index);
tmp = structure_alloc_comps (der_type, vref, dref, rank, purpose);
}
else
tmp = structure_alloc_comps (der_type, vref, NULL_TREE, rank, purpose);
gfc_add_expr_to_block (&loopbody, tmp);
/* Build the loop and return. */
gfc_init_loopinfo (&loop);
loop.dimen = 1;
loop.from[0] = gfc_index_zero_node;
loop.loopvar[0] = index;
loop.to[0] = nelems;
gfc_trans_scalarizing_loops (&loop, &loopbody);
gfc_add_block_to_block (&fnblock, &loop.pre);
tmp = gfc_finish_block (&fnblock);
if (null_cond != NULL_TREE)
tmp = build3_v (COND_EXPR, null_cond, tmp, build_empty_stmt ());
return tmp;
}
/* Otherwise, act on the components or recursively call self to
act on a chain of components. */
for (c = der_type->components; c; c = c->next)
{
bool cmp_has_alloc_comps = (c->ts.type == BT_DERIVED)
&& c->ts.derived->attr.alloc_comp;
cdecl = c->backend_decl;
ctype = TREE_TYPE (cdecl);
switch (purpose)
{
case DEALLOCATE_ALLOC_COMP:
/* Do not deallocate the components of ultimate pointer
components. */
if (cmp_has_alloc_comps && !c->pointer)
{
comp = build3 (COMPONENT_REF, ctype, decl, cdecl, NULL_TREE);
rank = c->as ? c->as->rank : 0;
tmp = structure_alloc_comps (c->ts.derived, comp, NULL_TREE,
rank, purpose);
gfc_add_expr_to_block (&fnblock, tmp);
}
if (c->allocatable)
{
comp = build3 (COMPONENT_REF, ctype, decl, cdecl, NULL_TREE);
tmp = gfc_trans_dealloc_allocated (comp);
gfc_add_expr_to_block (&fnblock, tmp);
}
break;
case NULLIFY_ALLOC_COMP:
if (c->pointer)
continue;
else if (c->allocatable)
{
comp = build3 (COMPONENT_REF, ctype, decl, cdecl, NULL_TREE);
gfc_conv_descriptor_data_set (&fnblock, comp, null_pointer_node);
}
else if (cmp_has_alloc_comps)
{
comp = build3 (COMPONENT_REF, ctype, decl, cdecl, NULL_TREE);
rank = c->as ? c->as->rank : 0;
tmp = structure_alloc_comps (c->ts.derived, comp, NULL_TREE,
rank, purpose);
gfc_add_expr_to_block (&fnblock, tmp);
}
break;
case COPY_ALLOC_COMP:
if (c->pointer)
continue;
/* We need source and destination components. */
comp = build3 (COMPONENT_REF, ctype, decl, cdecl, NULL_TREE);
dcmp = build3 (COMPONENT_REF, ctype, dest, cdecl, NULL_TREE);
dcmp = fold_convert (TREE_TYPE (comp), dcmp);
if (c->allocatable && !cmp_has_alloc_comps)
{
tmp = gfc_duplicate_allocatable(dcmp, comp, ctype, c->as->rank);
gfc_add_expr_to_block (&fnblock, tmp);
}
if (cmp_has_alloc_comps)
{
rank = c->as ? c->as->rank : 0;
tmp = fold_convert (TREE_TYPE (dcmp), comp);
gfc_add_modify_expr (&fnblock, dcmp, tmp);
tmp = structure_alloc_comps (c->ts.derived, comp, dcmp,
rank, purpose);
gfc_add_expr_to_block (&fnblock, tmp);
}
break;
default:
gcc_unreachable ();
break;
}
}
return gfc_finish_block (&fnblock);
}
/* Recursively traverse an object of derived type, generating code to
nullify allocatable components. */
tree
gfc_nullify_alloc_comp (gfc_symbol * der_type, tree decl, int rank)
{
return structure_alloc_comps (der_type, decl, NULL_TREE, rank,
NULLIFY_ALLOC_COMP);
}
/* Recursively traverse an object of derived type, generating code to
deallocate allocatable components. */
tree
gfc_deallocate_alloc_comp (gfc_symbol * der_type, tree decl, int rank)
{
return structure_alloc_comps (der_type, decl, NULL_TREE, rank,
DEALLOCATE_ALLOC_COMP);
}
/* Recursively traverse an object of derived type, generating code to
copy its allocatable components. */
tree
gfc_copy_alloc_comp (gfc_symbol * der_type, tree decl, tree dest, int rank)
{
return structure_alloc_comps (der_type, decl, dest, rank, COPY_ALLOC_COMP);
}
/* NULLIFY an allocatable/pointer array on function entry, free it on exit.
Do likewise, recursively if necessary, with the allocatable components of
derived types. */
tree
gfc_trans_deferred_array (gfc_symbol * sym, tree body)
@ -4623,16 +4932,22 @@ gfc_trans_deferred_array (gfc_symbol * sym, tree body)
tree descriptor;
stmtblock_t fnblock;
locus loc;
int rank;
bool sym_has_alloc_comp;
sym_has_alloc_comp = (sym->ts.type == BT_DERIVED)
&& sym->ts.derived->attr.alloc_comp;
/* Make sure the frontend gets these right. */
if (!(sym->attr.pointer || sym->attr.allocatable))
fatal_error
("Possible frontend bug: Deferred array size without pointer or allocatable attribute.");
if (!(sym->attr.pointer || sym->attr.allocatable || sym_has_alloc_comp))
fatal_error ("Possible frontend bug: Deferred array size without pointer, "
"allocatable attribute or derived type without allocatable "
"components.");
gfc_init_block (&fnblock);
gcc_assert (TREE_CODE (sym->backend_decl) == VAR_DECL
|| TREE_CODE (sym->backend_decl) == PARM_DECL);
|| TREE_CODE (sym->backend_decl) == PARM_DECL);
if (sym->ts.type == BT_CHARACTER
&& !INTEGER_CST_P (sym->ts.cl->backend_decl))
@ -4653,7 +4968,10 @@ gfc_trans_deferred_array (gfc_symbol * sym, tree body)
gfc_set_backend_locus (&sym->declared_at);
descriptor = sym->backend_decl;
if (TREE_STATIC (descriptor))
/* Although static, derived types with deafult initializers and
allocatable components must not be nulled wholesale; instead they
are treated component by component. */
if (TREE_STATIC (descriptor) && !sym_has_alloc_comp)
{
/* SAVEd variables are not freed on exit. */
gfc_trans_static_array_pointer (sym);
@ -4662,22 +4980,40 @@ gfc_trans_deferred_array (gfc_symbol * sym, tree body)
/* Get the descriptor type. */
type = TREE_TYPE (sym->backend_decl);
if (!GFC_DESCRIPTOR_TYPE_P (type))
if (sym_has_alloc_comp && !(sym->attr.pointer || sym->attr.allocatable))
{
rank = sym->as ? sym->as->rank : 0;
tmp = gfc_nullify_alloc_comp (sym->ts.derived, descriptor, rank);
gfc_add_expr_to_block (&fnblock, tmp);
}
else if (!GFC_DESCRIPTOR_TYPE_P (type))
{
/* If the backend_decl is not a descriptor, we must have a pointer
to one. */
descriptor = build_fold_indirect_ref (sym->backend_decl);
type = TREE_TYPE (descriptor);
gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
}
/* NULLIFY the data pointer. */
gfc_conv_descriptor_data_set (&fnblock, descriptor, null_pointer_node);
if (GFC_DESCRIPTOR_TYPE_P (type))
gfc_conv_descriptor_data_set (&fnblock, descriptor, null_pointer_node);
gfc_add_expr_to_block (&fnblock, body);
gfc_set_backend_locus (&loc);
/* Allocatable arrays need to be freed when they go out of scope. */
/* Allocatable arrays need to be freed when they go out of scope.
The allocatable components of pointers must not be touched. */
if (sym_has_alloc_comp && !(sym->attr.function || sym->attr.result)
&& !sym->attr.pointer)
{
int rank;
rank = sym->as ? sym->as->rank : 0;
tmp = gfc_deallocate_alloc_comp (sym->ts.derived, descriptor, rank);
gfc_add_expr_to_block (&fnblock, tmp);
}
if (sym->attr.allocatable)
{
tmp = gfc_trans_dealloc_allocated (sym->backend_decl);

View file

@ -43,6 +43,15 @@ tree gfc_trans_dummy_array_bias (gfc_symbol *, tree, tree);
tree gfc_trans_g77_array (gfc_symbol *, tree);
/* Generate code to deallocate an array, if it is allocated. */
tree gfc_trans_dealloc_allocated (tree);
tree gfc_duplicate_allocatable(tree dest, tree src, tree type, int rank);
tree gfc_nullify_alloc_comp (gfc_symbol *, tree, int);
tree gfc_deallocate_alloc_comp (gfc_symbol *, tree, int);
tree gfc_copy_alloc_comp (gfc_symbol *, tree, tree, int);
/* Add initialization for deferred arrays. */
tree gfc_trans_deferred_array (gfc_symbol *, tree);
/* Generate an initializer for a static pointer or allocatable array. */

View file

@ -964,6 +964,9 @@ gfc_get_symbol_decl (gfc_symbol * sym)
GFC_DECL_PACKED_ARRAY (decl) = 1;
}
if (sym->ts.type == BT_DERIVED && sym->ts.derived->attr.alloc_comp)
gfc_defer_symbol_init (sym);
gfc_finish_var_decl (decl, sym);
if (sym->ts.type == BT_CHARACTER)
@ -2572,6 +2575,8 @@ gfc_trans_deferred_vars (gfc_symbol * proc_sym, tree fnbody)
for (sym = proc_sym->tlink; sym != proc_sym; sym = sym->tlink)
{
bool sym_has_alloc_comp = (sym->ts.type == BT_DERIVED)
&& sym->ts.derived->attr.alloc_comp;
if (sym->attr.dimension)
{
switch (sym->as->type)
@ -2614,13 +2619,18 @@ gfc_trans_deferred_vars (gfc_symbol * proc_sym, tree fnbody)
break;
case AS_DEFERRED:
fnbody = gfc_trans_deferred_array (sym, fnbody);
if (!sym_has_alloc_comp)
fnbody = gfc_trans_deferred_array (sym, fnbody);
break;
default:
gcc_unreachable ();
}
if (sym_has_alloc_comp)
fnbody = gfc_trans_deferred_array (sym, fnbody);
}
else if (sym_has_alloc_comp)
fnbody = gfc_trans_deferred_array (sym, fnbody);
else if (sym->ts.type == BT_CHARACTER)
{
gfc_get_backend_locus (&loc);
@ -2972,10 +2982,12 @@ gfc_generate_function_code (gfc_namespace * ns)
tree old_context;
tree decl;
tree tmp;
tree tmp2;
stmtblock_t block;
stmtblock_t body;
tree result;
gfc_symbol *sym;
int rank;
sym = ns->proc_name;
@ -3135,7 +3147,6 @@ gfc_generate_function_code (gfc_namespace * ns)
tmp = gfc_finish_block (&body);
/* Add code to create and cleanup arrays. */
tmp = gfc_trans_deferred_vars (sym, tmp);
gfc_add_expr_to_block (&block, tmp);
if (TREE_TYPE (DECL_RESULT (fndecl)) != void_type_node)
{
@ -3150,7 +3161,18 @@ gfc_generate_function_code (gfc_namespace * ns)
else
result = sym->result->backend_decl;
if (result == NULL_TREE)
if (result != NULL_TREE && sym->attr.function
&& sym->ts.type == BT_DERIVED
&& sym->ts.derived->attr.alloc_comp)
{
rank = sym->as ? sym->as->rank : 0;
tmp2 = gfc_nullify_alloc_comp (sym->ts.derived, result, rank);
gfc_add_expr_to_block (&block, tmp2);
}
gfc_add_expr_to_block (&block, tmp);
if (result == NULL_TREE)
warning (0, "Function return value not set");
else
{
@ -3161,6 +3183,9 @@ gfc_generate_function_code (gfc_namespace * ns)
gfc_add_expr_to_block (&block, tmp);
}
}
else
gfc_add_expr_to_block (&block, tmp);
/* Add all the decls we created during processing. */
decl = saved_function_decls;

View file

@ -1701,7 +1701,7 @@ gfc_conv_aliased_arg (gfc_se * parmse, gfc_expr * expr,
if (intent != INTENT_OUT)
{
tmp = gfc_trans_scalar_assign (&lse, &rse, expr->ts.type);
tmp = gfc_trans_scalar_assign (&lse, &rse, expr->ts, true, false);
gfc_add_expr_to_block (&body, tmp);
gcc_assert (rse.ss == gfc_ss_terminator);
gfc_trans_scalarizing_loops (&loop, &body);
@ -1792,7 +1792,7 @@ gfc_conv_aliased_arg (gfc_se * parmse, gfc_expr * expr,
gcc_assert (lse.ss == gfc_ss_terminator);
tmp = gfc_trans_scalar_assign (&lse, &rse, expr->ts.type);
tmp = gfc_trans_scalar_assign (&lse, &rse, expr->ts, false, false);
gfc_add_expr_to_block (&body, tmp);
/* Generate the copying loops. */
@ -1864,6 +1864,7 @@ gfc_conv_function_call (gfc_se * se, gfc_symbol * sym,
gfc_ss *argss;
gfc_ss_info *info;
int byref;
int parm_kind;
tree type;
tree var;
tree len;
@ -1877,6 +1878,7 @@ gfc_conv_function_call (gfc_se * se, gfc_symbol * sym,
gfc_expr *e;
gfc_symbol *fsym;
stmtblock_t post;
enum {MISSING = 0, ELEMENTAL, SCALAR, SCALAR_POINTER, ARRAY};
arglist = NULL_TREE;
retargs = NULL_TREE;
@ -1919,6 +1921,7 @@ gfc_conv_function_call (gfc_se * se, gfc_symbol * sym,
{
e = arg->expr;
fsym = formal ? formal->sym : NULL;
parm_kind = MISSING;
if (e == NULL)
{
@ -1947,6 +1950,7 @@ gfc_conv_function_call (gfc_se * se, gfc_symbol * sym,
/* An elemental function inside a scalarized loop. */
gfc_init_se (&parmse, se);
gfc_conv_expr_reference (&parmse, e);
parm_kind = ELEMENTAL;
}
else
{
@ -1957,12 +1961,14 @@ gfc_conv_function_call (gfc_se * se, gfc_symbol * sym,
if (argss == gfc_ss_terminator)
{
gfc_conv_expr_reference (&parmse, e);
parm_kind = SCALAR;
if (fsym && fsym->attr.pointer
&& e->expr_type != EXPR_NULL)
{
/* Scalar pointer dummy args require an extra level of
indirection. The null pointer already contains
this level of indirection. */
parm_kind = SCALAR_POINTER;
parmse.expr = build_fold_addr_expr (parmse.expr);
}
}
@ -2050,6 +2056,49 @@ gfc_conv_function_call (gfc_se * se, gfc_symbol * sym,
gfc_add_block_to_block (&se->pre, &parmse.pre);
gfc_add_block_to_block (&post, &parmse.post);
/* Allocated allocatable components of derived types must be
deallocated for INTENT(OUT) dummy arguments and non-variable
scalars. Non-variable arrays are dealt with in trans-array.c
(gfc_conv_array_parameter). */
if (e && e->ts.type == BT_DERIVED
&& e->ts.derived->attr.alloc_comp
&& ((formal && formal->sym->attr.intent == INTENT_OUT)
||
(e->expr_type != EXPR_VARIABLE && !e->rank)))
{
int parm_rank;
tmp = build_fold_indirect_ref (parmse.expr);
parm_rank = e->rank;
switch (parm_kind)
{
case (ELEMENTAL):
case (SCALAR):
parm_rank = 0;
break;
case (SCALAR_POINTER):
tmp = build_fold_indirect_ref (tmp);
break;
case (ARRAY):
tmp = parmse.expr;
break;
}
tmp = gfc_deallocate_alloc_comp (e->ts.derived, tmp, parm_rank);
if (e->expr_type == EXPR_VARIABLE && e->symtree->n.sym->attr.optional)
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
pointer. */
if (parmse.string_length != NULL_TREE)
@ -2636,7 +2685,7 @@ gfc_trans_subarray_assign (tree dest, gfc_component * cm, gfc_expr * expr)
gfc_conv_expr (&rse, expr);
tmp = gfc_trans_scalar_assign (&lse, &rse, cm->ts.type);
tmp = gfc_trans_scalar_assign (&lse, &rse, cm->ts, true, false);
gfc_add_expr_to_block (&body, tmp);
gcc_assert (rse.ss == gfc_ss_terminator);
@ -2657,17 +2706,22 @@ gfc_trans_subarray_assign (tree dest, gfc_component * cm, gfc_expr * expr)
return gfc_finish_block (&block);
}
/* Assign a single component of a derived type constructor. */
static tree
gfc_trans_subcomponent_assign (tree dest, gfc_component * cm, gfc_expr * expr)
{
gfc_se se;
gfc_se lse;
gfc_ss *rss;
stmtblock_t block;
tree tmp;
tree offset;
int n;
gfc_start_block (&block);
if (cm->pointer)
{
gfc_init_se (&se, NULL);
@ -2700,8 +2754,68 @@ gfc_trans_subcomponent_assign (tree dest, gfc_component * cm, gfc_expr * expr)
}
else if (cm->dimension)
{
tmp = gfc_trans_subarray_assign (dest, cm, expr);
gfc_add_expr_to_block (&block, tmp);
if (cm->allocatable && expr->expr_type == EXPR_NULL)
gfc_conv_descriptor_data_set (&block, dest, null_pointer_node);
else if (cm->allocatable)
{
tree tmp2;
gfc_init_se (&se, NULL);
rss = gfc_walk_expr (expr);
se.want_pointer = 0;
gfc_conv_expr_descriptor (&se, expr, rss);
gfc_add_block_to_block (&block, &se.pre);
tmp = fold_convert (TREE_TYPE (dest), se.expr);
gfc_add_modify_expr (&block, dest, tmp);
if (cm->ts.type == BT_DERIVED && cm->ts.derived->attr.alloc_comp)
tmp = gfc_copy_alloc_comp (cm->ts.derived, se.expr, dest,
cm->as->rank);
else
tmp = gfc_duplicate_allocatable (dest, se.expr,
TREE_TYPE(cm->backend_decl),
cm->as->rank);
gfc_add_expr_to_block (&block, tmp);
gfc_add_block_to_block (&block, &se.post);
gfc_conv_descriptor_data_set (&block, se.expr, null_pointer_node);
/* Shift the lbound and ubound of temporaries to being unity, rather
than zero, based. Calculate the offset for all cases. */
offset = gfc_conv_descriptor_offset (dest);
gfc_add_modify_expr (&block, offset, gfc_index_zero_node);
tmp2 =gfc_create_var (gfc_array_index_type, NULL);
for (n = 0; n < expr->rank; n++)
{
if (expr->expr_type != EXPR_VARIABLE
&& expr->expr_type != EXPR_CONSTANT)
{
tmp = gfc_conv_descriptor_ubound (dest, gfc_rank_cst[n]);
gfc_add_modify_expr (&block, tmp,
fold_build2 (PLUS_EXPR,
gfc_array_index_type,
tmp, gfc_index_one_node));
tmp = gfc_conv_descriptor_lbound (dest, gfc_rank_cst[n]);
gfc_add_modify_expr (&block, tmp, gfc_index_one_node);
}
tmp = fold_build2 (MULT_EXPR, gfc_array_index_type,
gfc_conv_descriptor_lbound (dest,
gfc_rank_cst[n]),
gfc_conv_descriptor_stride (dest,
gfc_rank_cst[n]));
gfc_add_modify_expr (&block, tmp2, tmp);
tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type, offset, tmp2);
gfc_add_modify_expr (&block, offset, tmp);
}
}
else
{
tmp = gfc_trans_subarray_assign (dest, cm, expr);
gfc_add_expr_to_block (&block, tmp);
}
}
else if (expr->ts.type == BT_DERIVED)
{
@ -2722,8 +2836,6 @@ gfc_trans_subcomponent_assign (tree dest, gfc_component * cm, gfc_expr * expr)
else
{
/* Scalar component. */
gfc_se lse;
gfc_init_se (&se, NULL);
gfc_init_se (&lse, NULL);
@ -2731,7 +2843,7 @@ gfc_trans_subcomponent_assign (tree dest, gfc_component * cm, gfc_expr * expr)
if (cm->ts.type == BT_CHARACTER)
lse.string_length = cm->ts.cl->backend_decl;
lse.expr = dest;
tmp = gfc_trans_scalar_assign (&lse, &se, cm->ts.type);
tmp = gfc_trans_scalar_assign (&lse, &se, cm->ts, true, false);
gfc_add_expr_to_block (&block, tmp);
}
return gfc_finish_block (&block);
@ -2791,10 +2903,14 @@ gfc_conv_structure (gfc_se * se, gfc_expr * expr, int init)
}
cm = expr->ts.derived->components;
for (c = expr->value.constructor; c; c = c->next, cm = cm->next)
{
/* Skip absent members in default initializers. */
if (!c->expr)
/* Skip absent members in default initializers and allocatable
components. Although the latter have a default initializer
of EXPR_NULL,... by default, the static nullify is not needed
since this is done every time we come into scope. */
if (!c->expr || cm->allocatable)
continue;
val = gfc_conv_initializer (c->expr, &cm->ts,
@ -3089,16 +3205,19 @@ gfc_conv_string_parameter (gfc_se * se)
/* Generate code for assignment of scalar variables. Includes character
strings. */
strings and derived types with allocatable components. */
tree
gfc_trans_scalar_assign (gfc_se * lse, gfc_se * rse, bt type)
gfc_trans_scalar_assign (gfc_se * lse, gfc_se * rse, gfc_typespec ts,
bool l_is_temp, bool r_is_var)
{
stmtblock_t block;
tree tmp;
tree cond;
gfc_init_block (&block);
if (type == BT_CHARACTER)
if (ts.type == BT_CHARACTER)
{
gcc_assert (lse->string_length != NULL_TREE
&& rse->string_length != NULL_TREE);
@ -3112,6 +3231,50 @@ gfc_trans_scalar_assign (gfc_se * lse, gfc_se * rse, bt type)
gfc_trans_string_copy (&block, lse->string_length, lse->expr,
rse->string_length, rse->expr);
}
else if (ts.type == BT_DERIVED && ts.derived->attr.alloc_comp)
{
cond = NULL_TREE;
/* Are the rhs and the lhs the same? */
if (r_is_var)
{
cond = fold_build2 (EQ_EXPR, boolean_type_node,
build_fold_addr_expr (lse->expr),
build_fold_addr_expr (rse->expr));
cond = gfc_evaluate_now (cond, &lse->pre);
}
/* Deallocate the lhs allocated components as long as it is not
the same as the rhs. */
if (!l_is_temp)
{
tmp = gfc_deallocate_alloc_comp (ts.derived, lse->expr, 0);
if (r_is_var)
tmp = build3_v (COND_EXPR, cond, build_empty_stmt (), tmp);
gfc_add_expr_to_block (&lse->pre, tmp);
}
gfc_add_block_to_block (&block, &lse->pre);
gfc_add_block_to_block (&block, &rse->pre);
gfc_add_modify_expr (&block, lse->expr,
fold_convert (TREE_TYPE (lse->expr), rse->expr));
/* Do a deep copy if the rhs is a variable, if it is not the
same as the lhs. Otherwise, nullify the data fields so that the
lhs retains the allocated resources. */
if (r_is_var)
{
tmp = gfc_copy_alloc_comp (ts.derived, rse->expr, lse->expr, 0);
tmp = build3_v (COND_EXPR, cond, build_empty_stmt (), tmp);
gfc_add_expr_to_block (&block, tmp);
}
else
{
tmp = gfc_nullify_alloc_comp (ts.derived, rse->expr, 0);
gfc_add_expr_to_block (&block, tmp);
}
}
else
{
gfc_add_block_to_block (&block, &lse->pre);
@ -3217,6 +3380,7 @@ gfc_trans_assignment (gfc_expr * expr1, gfc_expr * expr2)
tree tmp;
stmtblock_t block;
stmtblock_t body;
bool l_is_temp;
/* Special case a single function returning an array. */
if (expr2->expr_type == EXPR_FUNCTION && expr2->rank > 0)
@ -3295,10 +3459,12 @@ gfc_trans_assignment (gfc_expr * expr1, gfc_expr * expr2)
else
gfc_init_block (&body);
l_is_temp = (lss != gfc_ss_terminator && loop.temp_ss != NULL);
/* Translate the expression. */
gfc_conv_expr (&rse, expr2);
if (lss != gfc_ss_terminator && loop.temp_ss != NULL)
if (l_is_temp)
{
gfc_conv_tmp_array_ref (&lse);
gfc_advance_se_ss_chain (&lse);
@ -3306,7 +3472,8 @@ gfc_trans_assignment (gfc_expr * expr1, gfc_expr * expr2)
else
gfc_conv_expr (&lse, expr1);
tmp = gfc_trans_scalar_assign (&lse, &rse, expr1->ts.type);
tmp = gfc_trans_scalar_assign (&lse, &rse, expr1->ts, l_is_temp,
expr2->expr_type == EXPR_VARIABLE);
gfc_add_expr_to_block (&body, tmp);
if (lss == gfc_ss_terminator)
@ -3319,7 +3486,7 @@ gfc_trans_assignment (gfc_expr * expr1, gfc_expr * expr2)
gcc_assert (lse.ss == gfc_ss_terminator
&& rse.ss == gfc_ss_terminator);
if (loop.temp_ss != NULL)
if (l_is_temp)
{
gfc_trans_scalarized_loop_boundary (&loop, &body);
@ -3339,9 +3506,10 @@ gfc_trans_assignment (gfc_expr * expr1, gfc_expr * expr2)
gcc_assert (lse.ss == gfc_ss_terminator
&& rse.ss == gfc_ss_terminator);
tmp = gfc_trans_scalar_assign (&lse, &rse, expr1->ts.type);
tmp = gfc_trans_scalar_assign (&lse, &rse, expr1->ts, false, false);
gfc_add_expr_to_block (&body, tmp);
}
/* Generate the copying loops. */
gfc_trans_scalarizing_loops (&loop, &body);

View file

@ -1802,7 +1802,8 @@ generate_loop_for_temp_to_lhs (gfc_expr *expr, tree tmp1, tree count3,
gfc_conv_expr (&lse, expr);
/* Use the scalar assignment. */
tmp = gfc_trans_scalar_assign (&lse, &rse, expr->ts.type);
rse.string_length = lse.string_length;
tmp = gfc_trans_scalar_assign (&lse, &rse, expr->ts, false, false);
/* Form the mask expression according to the mask tree list. */
if (wheremask)
@ -1897,7 +1898,9 @@ generate_loop_for_rhs_to_temp (gfc_expr *expr2, tree tmp1, tree count3,
}
/* Use the scalar assignment. */
tmp = gfc_trans_scalar_assign (&lse, &rse, expr2->ts.type);
lse.string_length = rse.string_length;
tmp = gfc_trans_scalar_assign (&lse, &rse, expr2->ts, true,
expr2->expr_type == EXPR_VARIABLE);
/* Form the mask expression according to the mask tree list. */
if (wheremask)
@ -2978,7 +2981,8 @@ gfc_trans_where_assign (gfc_expr *expr1, gfc_expr *expr2,
maskexpr = fold_build1 (TRUTH_NOT_EXPR, TREE_TYPE (maskexpr), maskexpr);
/* Use the scalar assignment as is. */
tmp = gfc_trans_scalar_assign (&lse, &rse, expr1->ts.type);
tmp = gfc_trans_scalar_assign (&lse, &rse, expr1->ts,
loop.temp_ss != NULL, false);
tmp = build3_v (COND_EXPR, maskexpr, tmp, build_empty_stmt ());
gfc_add_expr_to_block (&body, tmp);
@ -3031,7 +3035,7 @@ gfc_trans_where_assign (gfc_expr *expr1, gfc_expr *expr2,
maskexpr);
/* Use the scalar assignment as is. */
tmp = gfc_trans_scalar_assign (&lse, &rse, expr1->ts.type);
tmp = gfc_trans_scalar_assign (&lse, &rse, expr1->ts, false, false);
tmp = build3_v (COND_EXPR, maskexpr, tmp, build_empty_stmt ());
gfc_add_expr_to_block (&body, tmp);
@ -3406,8 +3410,8 @@ gfc_trans_where_3 (gfc_code * cblock, gfc_code * eblock)
gfc_conv_expr (&edse, edst);
}
tstmt = gfc_trans_scalar_assign (&tdse, &tsse, tdst->ts.type);
estmt = eblock ? gfc_trans_scalar_assign (&edse, &esse, edst->ts.type)
tstmt = gfc_trans_scalar_assign (&tdse, &tsse, tdst->ts, false, false);
estmt = eblock ? gfc_trans_scalar_assign (&edse, &esse, edst->ts, false, false)
: build_empty_stmt ();
tmp = build3_v (COND_EXPR, cexpr, tstmt, estmt);
gfc_add_expr_to_block (&body, tmp);
@ -3591,6 +3595,14 @@ gfc_trans_allocate (gfc_code * code)
parm, tmp, build_empty_stmt ());
gfc_add_expr_to_block (&se.pre, tmp);
}
if (expr->ts.type == BT_DERIVED && expr->ts.derived->attr.alloc_comp)
{
tmp = build_fold_indirect_ref (se.expr);
tmp = gfc_nullify_alloc_comp (expr->ts.derived, tmp, 0);
gfc_add_expr_to_block (&se.pre, tmp);
}
}
tmp = gfc_finish_block (&se.pre);
@ -3675,6 +3687,26 @@ gfc_trans_deallocate (gfc_code * code)
se.descriptor_only = 1;
gfc_conv_expr (&se, expr);
if (expr->ts.type == BT_DERIVED
&& expr->ts.derived->attr.alloc_comp)
{
gfc_ref *ref;
gfc_ref *last = NULL;
for (ref = expr->ref; ref; ref = ref->next)
if (ref->type == REF_COMPONENT)
last = ref;
/* Do not deallocate the components of a derived type
ultimate pointer component. */
if (!(last && last->u.c.component->pointer)
&& !(!last && expr->symtree->n.sym->attr.pointer))
{
tmp = gfc_deallocate_alloc_comp (expr->ts.derived, se.expr,
expr->rank);
gfc_add_expr_to_block (&se.pre, tmp);
}
}
if (expr->rank)
tmp = gfc_array_deallocate (se.expr, pstat);
else

View file

@ -1486,12 +1486,15 @@ gfc_get_derived_type (gfc_symbol * derived)
/* Derived types in an interface body obtain their parent reference
through the proc_name symbol. */
ns = derived->ns->parent ? derived->ns->parent
: derived->ns->proc_name->ns->parent;
: derived->ns->proc_name->ns;
for (; ns; ns = ns->parent)
{
for (dt = ns->derived_types; dt; dt = dt->next)
{
if (dt->derived == derived)
continue;
if (dt->derived->backend_decl == NULL
&& gfc_compare_derived_types (dt->derived, derived))
gfc_get_derived_type (dt->derived);
@ -1550,7 +1553,7 @@ gfc_get_derived_type (gfc_symbol * derived)
required. */
if (c->dimension)
{
if (c->pointer)
if (c->pointer || c->allocatable)
{
/* Pointers to arrays aren't actually pointer types. The
descriptors are separate, but the data is common. */

View file

@ -307,7 +307,7 @@ int gfc_conv_function_call (gfc_se *, gfc_symbol *, gfc_actual_arglist *);
/* gfc_trans_* shouldn't call push/poplevel, use gfc_push/pop_scope */
/* Generate code for a scalar assignment. */
tree gfc_trans_scalar_assign (gfc_se *, gfc_se *, bt);
tree gfc_trans_scalar_assign (gfc_se *, gfc_se *, gfc_typespec, bool, bool);
/* Translate COMMON blocks. */
void gfc_trans_common (gfc_namespace *);

View file

@ -1,3 +1,30 @@
2006-10-08 Erik Edelmann <edelmann@gcc.gnu.org>
Paul Thomas <pault@gcc.gnu.org>
PR fortran/20541
* gfortran.dg/alloc_comp_basics_1.f90: New test.
* gfortran.dg/alloc_comp_basics_2.f90: New test.
* gfortran.dg/alloc_comp_assign_1.f90: New test.
* gfortran.dg/alloc_comp_assign_2.f90: New test.
* gfortran.dg/alloc_comp_assign_3.f90: New test.
* gfortran.dg/alloc_comp_assign_4.f90: New test.
* gfortran.dg/alloc_comp_constraint_1.f90: New test.
* gfortran.dg/alloc_comp_constraint_2.f90: New test.
* gfortran.dg/alloc_comp_constraint_3.f90: New test.
* gfortran.dg/alloc_comp_constructor_1.f90: New test.
* gfortran.dg/alloc_comp_constructor_2.f90: New test.
* gfortran.dg/alloc_comp_initializer_1.f90: New test.
* gfortran.dg/alloc_comp_std.f90: New test.
* gfortran.dg/move_alloc.f90: New test.
2006-10-08 Paul Thomas <pault@gcc.gnu.org>
PR fortran/29115
* gfortran.dg/derived_constructor_comps_2.f90: New test.
PR fortran/29211
* gfortran.dg/forall_char_dependencies_1.f90: New test.
2006-10-08 Tobias Burnus <burnus@net-b.de>
PR fortran/28585

View file

@ -0,0 +1,57 @@
! { dg-do run }
! Test assignments of derived type with allocatable components (PR 20541).
!
! Contributed by Erik Edelmann <eedelmann@gcc.gnu.org>
! and Paul Thomas <pault@gcc.gnu.org>
!
type :: ivs
character(1), allocatable :: chars(:)
end type ivs
type(ivs) :: a, b
type(ivs) :: x(3), y(3)
allocate(a%chars(5))
a%chars = (/"h","e","l","l","o"/)
! An intrinsic assignment must deallocate the l-value and copy across
! the array from the r-value.
b = a
if (any (b%chars .ne. (/"h","e","l","l","o"/))) call abort ()
if (allocated (a%chars) .eqv. .false.) call abort ()
! Scalar to array needs to copy the derived type, to its ultimate components,
! to each of the l-value elements. */
x = b
x(2)%chars = (/"g","'","d","a","y"/)
if (any (x(1)%chars .ne. (/"h","e","l","l","o"/))) call abort ()
if (any (x(2)%chars .ne. (/"g","'","d","a","y"/))) call abort ()
if (allocated (b%chars) .eqv. .false.) call abort ()
deallocate (x(1)%chars, x(2)%chars, x(3)%chars)
! Array intrinsic assignments are like their scalar counterpart and
! must deallocate each element of the l-value and copy across the
! arrays from the r-value elements.
allocate(x(1)%chars(5), x(2)%chars(5), x(3)%chars(5))
x(1)%chars = (/"h","e","l","l","o"/)
x(2)%chars = (/"g","'","d","a","y"/)
x(3)%chars = (/"g","o","d","a","g"/)
y(2:1:-1) = x(1:2)
if (any (y(1)%chars .ne. (/"g","'","d","a","y"/))) call abort ()
if (any (y(2)%chars .ne. (/"h","e","l","l","o"/))) call abort ()
if (any (x(3)%chars .ne. (/"g","o","d","a","g"/))) call abort ()
! In the case of an assignment where there is a dependency, so that a
! temporary is necessary, each element must be copied to its
! destination after it has been deallocated.
y(2:3) = y(1:2)
if (any (y(1)%chars .ne. (/"g","'","d","a","y"/))) call abort ()
if (any (y(2)%chars .ne. (/"g","'","d","a","y"/))) call abort ()
if (any (y(3)%chars .ne. (/"h","e","l","l","o"/))) call abort ()
! An identity assignment must not do any deallocation....!
y = y
if (any (y(1)%chars .ne. (/"g","'","d","a","y"/))) call abort ()
if (any (y(2)%chars .ne. (/"g","'","d","a","y"/))) call abort ()
if (any (y(3)%chars .ne. (/"h","e","l","l","o"/))) call abort ()
end

View file

@ -0,0 +1,57 @@
! { dg-do run }
! Test FORALL and WHERE with derived types with allocatable components (PR 20541).
!
! Contributed by Erik Edelmann <eedelmann@gcc.gnu.org>
! and Paul Thomas <pault@gcc.gnu.org>
!
type :: a
integer, allocatable :: i(:)
end type a
type :: b
type (a), allocatable :: at(:)
end type b
type(a) :: x(2)
type(b) :: y(2), z(2)
integer i, m(4)
! Start with scalar and array element assignments in FORALL.
x(1) = a ((/1, 2, 3, 4/))
x(2) = a ((/1, 2, 3, 4/) + 10)
forall (j = 1:2, i = 1:4, x(j)%i(i) > 2 + (j-1)*10) x(j)%i(i) = j*4-i
if (any ((/((x(i)%i(j), j = 1,4), i = 1,2)/) .ne. &
(/1, 2, 1, 0, 11, 12, 5, 4/))) call abort ()
y(1) = b ((/x(1),x(2)/))
y(2) = b ((/x(2),x(1)/))
forall (k = 1:2, j=1:2, i = 1:4, y(k)%at(j)%i(i) <= 10)
y(k)%at(j)%i(i) = j*4-i+k
end forall
if (any ((/(((y(k)%at(i)%i(j), j = 1,4), i = 1,2), k = 1,2)/) .ne. &
(/4,3,2,1,11,12,6,5,11,12,3,2,9,8,7,6/))) call abort ()
! Now simple assignments in WHERE.
where (y(1)%at(1)%i > 2) y(1)%at(1)%i = 0
if (any( (/(((y(k)%at(i)%i(j), j = 1,4), i = 1,2), k = 1,2)/) .ne. &
(/0,0,2,1,11,12,6,5,11,12,3,2,9,8,7,6/))) call abort ()
where (y((2))%at(:)%i(2) > 8)
y(2)%at(:)%i(2) = 77
end where
if (any ((/(((y(k)%at(i)%i(j), j = 1,4), i = 1,2), k = 1,2)/) .ne. &
(/0,0,2,1,11,12,6,5,11,77,3,2,9,8,7,6/))) call abort ()
! Check that temporaries and full array alloctable component assignments
! are correctly handled in FORALL.
x = (/a ((/1,2,3,4/)),a ((/5,6,7,8/))/)
forall (i=1:2) y(i) = b ((/x(i)/))
forall (i=1:2) y(i) = y(3-i) ! This needs a temporary.
forall (i=1:2) z(i) = y(i)
if (any ((/(((z(k)%at(i)%i(j), j = 1,4), i = 1,1), k = 1,2)/) .ne. &
(/(/5,6,7,8/),(/1,2,3,4/)/))) call abort ()
end

View file

@ -0,0 +1,36 @@
! { dg-do run }
! Test assignments of nested derived types with allocatable components(PR 20541).
!
! Contributed by Erik Edelmann <eedelmann@gcc.gnu.org>
! and Paul Thomas <pault@gcc.gnu.org>
!
type :: a
integer, allocatable :: i(:)
end type a
type :: b
type (a), allocatable :: at(:)
end type b
type(a) :: x(2)
type(b) :: y(2), z(2)
integer i, m(4)
x(1) = a((/1,2,3,4/))
x(2) = a((/1,2,3,4/)+10)
y(1) = b((/x(1),x(2)/))
y(2) = b((/x(2),x(1)/))
y(2) = y(1)
forall (j=1:2,k=1:4, y(1)%at(j)%i(k) .ne. y(2)%at(j)%i(k)) &
y(1)%at(j)%i(k) = 999
if (any ((/((y(1)%at(j)%i(k), k=1,4),j=1,2)/) .eq. 999)) call abort ()
z = y
forall (i=1:2,j=1:2,k=1:4, z(i)%at(j)%i(k) .ne. y(i)%at(j)%i(k)) &
z(i)%at(j)%i(k) = 999
if (any ((/(((z(i)%at(j)%i(k), k=1,4),j=1,2),i=1,2)/) .eq. 999)) call abort ()
end

View file

@ -0,0 +1,63 @@
! { dg-do run }
! Test assignments of nested derived types with character allocatable
! components(PR 20541). Subroutine test_ab6 checks out a bug in a test
! version of gfortran's allocatable arrays.
!
! Contributed by Erik Edelmann <eedelmann@gcc.gnu.org>
! and Paul Thomas <pault@gcc.gnu.org>
!
type :: a
character(4), allocatable :: ch(:)
end type a
type :: b
type (a), allocatable :: at(:)
end type b
type(a) :: x(2)
type(b) :: y(2), z(2)
character(4) :: chr1(4) = (/"abcd","efgh","ijkl","mnop"/)
character(4) :: chr2(4) = (/"qrst","uvwx","yz12","3456"/)
x(1) = a(chr1)
! Check constructor with character array constructors.
x(2) = a((/"qrst","uvwx","yz12","3456"/))
y(1) = b((/x(1),x(2)/))
y(2) = b((/x(2),x(1)/))
y(2) = y(1)
if (any((/((y(2)%at(i)%ch(j),j=1,4),i=1,2)/) .ne. &
(/chr1, chr2/))) call abort ()
call test_ab6 ()
contains
subroutine test_ab6 ()
! This subroutine tests the presence of a scalar derived type, intermediate
! in a chain of derived types with allocatable components.
! Contributed by Salvatore Filippone <salvatore.filippone@uniroma2.it>
type b
type(a) :: a
end type b
type c
type(b), allocatable :: b(:)
end type c
type(c) :: p
type(b) :: bv
p = c((/b(a((/"Mary","Lamb"/)))/))
bv = p%b(1)
if (any ((bv%a%ch(:)) .ne. (/"Mary","Lamb"/))) call abort ()
end subroutine test_ab6
end

View file

@ -0,0 +1,143 @@
! { dg-do run}
! { dg-options "-O2 -fdump-tree-original" }
!
! Check some basic functionality of allocatable components, including that they
! are nullified when created and automatically deallocated when
! 1. A variable goes out of scope
! 2. INTENT(OUT) dummies
! 3. Function results
!
!
! Contributed by Erik Edelmann <eedelmann@gcc.gnu.org>
! and Paul Thomas <pault@gcc.gnu.org>
!
module alloc_m
implicit none
type :: alloc1
real, allocatable :: x(:)
end type alloc1
end module alloc_m
program alloc
use alloc_m
implicit none
type :: alloc2
type(alloc1), allocatable :: a1(:)
integer, allocatable :: a2(:)
end type alloc2
type(alloc2) :: b
integer :: i
type(alloc2), allocatable :: c(:)
if (allocated(b%a2) .OR. allocated(b%a1)) then
write (0, *) 'main - 1'
call abort()
end if
! 3 calls to _gfortran_deallocate (INTENT(OUT) dummy)
call allocate_alloc2(b)
call check_alloc2(b)
do i = 1, size(b%a1)
! 1 call to _gfortran_deallocate
deallocate(b%a1(i)%x)
end do
! 3 calls to _gfortran_deallocate (INTENT(OUT) dummy)
call allocate_alloc2(b)
call check_alloc2(return_alloc2())
! 3 calls to _gfortran_deallocate (function result)
allocate(c(1))
! 3 calls to _gfortran_deallocate (INTENT(OUT) dummy)
call allocate_alloc2(c(1))
! 4 calls to _gfortran_deallocate
deallocate(c)
! 7 calls to _gfortran_deallocate (b (3) and c(4) goes aout of scope)
contains
subroutine allocate_alloc2(b)
type(alloc2), intent(out) :: b
integer :: i
if (allocated(b%a2) .OR. allocated(b%a1)) then
write (0, *) 'allocate_alloc2 - 1'
call abort()
end if
allocate (b%a2(3))
b%a2 = [ 1, 2, 3 ]
allocate (b%a1(3))
do i = 1, 3
if (allocated(b%a1(i)%x)) then
write (0, *) 'allocate_alloc2 - 2', i
call abort()
end if
allocate (b%a1(i)%x(3))
b%a1(i)%x = i + [ 1.0, 2.0, 3.0 ]
end do
end subroutine allocate_alloc2
type(alloc2) function return_alloc2() result(b)
if (allocated(b%a2) .OR. allocated(b%a1)) then
write (0, *) 'return_alloc2 - 1'
call abort()
end if
allocate (b%a2(3))
b%a2 = [ 1, 2, 3 ]
allocate (b%a1(3))
do i = 1, 3
if (allocated(b%a1(i)%x)) then
write (0, *) 'return_alloc2 - 2', i
call abort()
end if
allocate (b%a1(i)%x(3))
b%a1(i)%x = i + [ 1.0, 2.0, 3.0 ]
end do
end function return_alloc2
subroutine check_alloc2(b)
type(alloc2), intent(in) :: b
if (.NOT.(allocated(b%a2) .AND. allocated(b%a1))) then
write (0, *) 'check_alloc2 - 1'
call abort()
end if
if (any(b%a2 /= [ 1, 2, 3 ])) then
write (0, *) 'check_alloc2 - 2'
call abort()
end if
do i = 1, 3
if (.NOT.allocated(b%a1(i)%x)) then
write (0, *) 'check_alloc2 - 3', i
call abort()
end if
if (any(b%a1(i)%x /= i + [ 1.0, 2.0, 3.0 ])) then
write (0, *) 'check_alloc2 - 4', i
call abort()
end if
end do
end subroutine check_alloc2
end program alloc
! { dg-final { scan-tree-dump-times "deallocate" 38 "original" } }
! { dg-final { cleanup-tree-dump "original" } }

View file

@ -0,0 +1,39 @@
! { dg-do run }
! Check "double" allocations of allocatable components (PR 20541).
!
! Contributed by Erik Edelmann <eedelmann@gcc.gnu.org>
! and Paul Thomas <pault@gcc.gnu.org>
!
program main
implicit none
type foo
integer, dimension(:), allocatable :: array
end type foo
type(foo),allocatable,dimension(:) :: mol
type(foo),pointer,dimension(:) :: molp
integer :: i
allocate (mol(1))
allocate (mol(1), stat=i)
!print *, i ! /= 0
if (i == 0) call abort()
allocate (mol(1)%array(5))
allocate (mol(1)%array(5),stat=i)
!print *, i ! /= 0
if (i == 0) call abort()
allocate (molp(1))
allocate (molp(1), stat=i)
!print *, i ! == 0
if (i /= 0) call abort()
allocate (molp(1)%array(5))
allocate (molp(1)%array(5),stat=i)
!print *, i ! /= 0
if (i == 0) call abort()
end program main

View file

@ -0,0 +1,22 @@
! { dg-do compile }
! Check that we don't allow IO or NAMELISTs with types with allocatable
! components (PR 20541)
program main
type :: foo
integer, allocatable :: x(:)
end type foo
type :: bar
type(foo) :: x
end type bar
type(foo) :: a
type(bar) :: b
namelist /blah/ a ! { dg-error "cannot have ALLOCATABLE components" }
write (*, *) a ! { dg-error "cannot have ALLOCATABLE components" }
read (*, *) b ! { dg-error "cannot have ALLOCATABLE components" }
end program main

View file

@ -0,0 +1,15 @@
! { dg-do compile }
! Check that equivalence with allocatable components isn't allowed (PR 20541)
program main
type :: foo
sequence
integer, allocatable :: x(:)
end type foo
type(foo) :: a
integer :: b
equivalence (a, b) ! { dg-error "cannot have ALLOCATABLE components" }
end program main

View file

@ -0,0 +1,12 @@
! { dg-do compile }
! Check that default initializer for allocatable components isn't accepted (PR
! 20541)
program main
type :: foo
integer, allocatable :: a(:) = [ 1 ] ! { dg-error "Initialization of allocatable" }
integer :: x ! Just to avoid "extra" error messages about empty type.
end type foo
end program main

View file

@ -0,0 +1,108 @@
! { dg-do run }
! { dg-options "-fdump-tree-original" }
! Test constructors of derived type with allocatable components (PR 20541).
!
! Contributed by Erik Edelmann <eedelmann@gcc.gnu.org>
! and Paul Thomas <pault@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
type (mytype) :: x
type (thytype) :: foo = thytype(reshape ([43, 100, 54, 76], [2,2]))
integer :: y(0:1, -1:0) = reshape ([42, 99, 55, 77], [2,2])
integer, allocatable :: yy(:,:)
type (thytype), allocatable :: bar(:)
integer :: i
! Check that null() works
x = mytype(null(), null())
if (allocated(x%a) .or. allocated(x%q)) call abort()
! Check that unallocated allocatables work
x = mytype(yy, bar)
if (allocated(x%a) .or. allocated(x%q)) call abort()
! Check that non-allocatables work
x = mytype(y, [foo, foo])
if (.not.allocated(x%a) .or. .not.allocated(x%q)) call abort()
if (any(lbound(x%a) /= lbound(y))) call abort()
if (any(ubound(x%a) /= ubound(y))) call abort()
if (any(x%a /= y)) call abort()
if (size(x%q) /= 2) call abort()
do i = 1, 2
if (any(x%q(i)%a /= foo%a)) call abort()
end do
! Check that allocated allocatables work
allocate(yy(size(y,1), size(y,2)))
yy = y
allocate(bar(2))
bar = [foo, foo]
x = mytype(yy, bar)
if (.not.allocated(x%a) .or. .not.allocated(x%q)) call abort()
if (any(x%a /= y)) call abort()
if (size(x%q) /= 2) call abort()
do i = 1, 2
if (any(x%q(i)%a /= foo%a)) call abort()
end do
! Functions returning arrays
x = mytype(bluhu(), null())
if (.not.allocated(x%a) .or. allocated(x%q)) call abort()
if (any(x%a /= reshape ([41, 98, 54, 76], [2,2]))) call abort()
! Functions returning allocatable arrays
x = mytype(blaha(), null())
if (.not.allocated(x%a) .or. allocated(x%q)) call abort()
if (any(x%a /= reshape ([40, 97, 53, 75], [2,2]))) call abort()
! Check that passing the constructor to a procedure works
call check_mytype (mytype(y, [foo, foo]))
contains
subroutine check_mytype(x)
type(mytype), intent(in) :: x
integer :: i
if (.not.allocated(x%a) .or. .not.allocated(x%q)) call abort()
if (any(lbound(x%a) /= lbound(y))) call abort()
if (any(ubound(x%a) /= ubound(y))) call abort()
if (any(x%a /= y)) call abort()
if (size(x%q) /= 2) call abort()
do i = 1, 2
if (any(x%q(i)%a /= foo%a)) call abort()
end do
end subroutine check_mytype
function bluhu()
integer :: bluhu(2,2)
bluhu = reshape ([41, 98, 54, 76], [2,2])
end function bluhu
function blaha()
integer, allocatable :: blaha(:,:)
allocate(blaha(2,2))
blaha = reshape ([40, 97, 53, 75], [2,2])
end function blaha
end program test_constructor
! { dg-final { scan-tree-dump-times "deallocate" 18 "original" } }
! { dg-final { cleanup-tree-dump "original" } }

View file

@ -0,0 +1,26 @@
! { dg-do run }
! Test constructors of nested derived types with allocatable components(PR 20541).
!
! Contributed by Erik Edelmann <eedelmann@gcc.gnu.org>
! and Paul Thomas <pault@gcc.gnu.org>
!
type :: thytype
integer(4), allocatable :: h(:)
end type thytype
type :: mytype
type(thytype), allocatable :: q(:)
end type mytype
type (mytype) :: x
type (thytype) :: w(2)
integer :: y(2) =(/1,2/)
w = (/thytype(y), thytype (2*y)/)
x = mytype (w)
if (any ((/((x%q(j)%h(i),j=1,2),i=1,2)/) .ne. (/1,2,2,4/))) call abort ()
x = mytype ((/thytype(3*y), thytype (4*y)/))
if (any ((/((x%q(j)%h(i),j=1,2),i=1,2)/) .ne. (/3,4,6,8/))) call abort ()
end

View file

@ -0,0 +1,71 @@
! { dg-do run }
! This checks the correct functioning of derived types with default initializers
! and allocatable components.
!
! Contributed by Salvatore Filippone <salvatore.filippone@uniroma2.it>
!
module p_type_mod
type m_type
integer, allocatable :: p(:)
end type m_type
type basep_type
type(m_type), allocatable :: av(:)
type(m_type), pointer :: ap => null ()
integer :: i = 101
end type basep_type
type p_type
type(basep_type), allocatable :: basepv(:)
integer :: p1 , p2 = 1
end type p_type
end module p_type_mod
program foo
use p_type_mod
implicit none
type(m_type), target :: a
type(p_type) :: pre
type(basep_type) :: wee
call test_ab8 ()
a = m_type ((/101,102/))
call p_bld (a, pre)
if (associated (wee%ap) .or. wee%i /= 101) call abort ()
wee%ap => a
if (.not.associated (wee%ap) .or. allocated (wee%av)) call abort ()
wee = basep_type ((/m_type ((/201, 202, 203/))/), null (), 99)
if (.not.allocated (wee%av) .or. associated (wee%ap) .or. (wee%i .ne. 99)) call abort ()
contains
! Check that allocatable components are nullified after allocation.
subroutine test_ab8 ()
type(p_type) :: p
integer :: ierr
if (.not.allocated(p%basepv)) then
allocate(p%basepv(1),stat=ierr)
endif
if (allocated (p%basepv) .neqv. .true.) call abort ()
if (allocated (p%basepv(1)%av) .neqv. .false.) call abort
if (p%basepv(1)%i .ne. 101) call abort ()
end subroutine test_ab8
subroutine p_bld (a, p)
use p_type_mod
type (m_type) :: a
type(p_type) :: p
if (any (a%p .ne. (/101,102/))) call abort ()
if (allocated (p%basepv) .or. (p%p2 .ne. 1)) call abort ()
end subroutine p_bld
end program foo
! { dg-final { cleanup-modules "p_type_mod" } }

View file

@ -0,0 +1,12 @@
! { dg-do compile }
! Check that default initializer for allocatable components isn't accepted (PR
! 20541)
program main
type :: foo
integer, allocatable :: a(:) = [ 1 ] ! { dg-error "Initialization of allocatable" }
integer :: x ! Just to avoid "extra" error messages about empty type.
end type foo
end program main

View file

@ -0,0 +1,14 @@
! { dg-do compile }
! { dg-options "-std=f95" }
!
! Check that we don't accept allocatable components for -std=f95 (PR 20541)
!
program main
type :: foo
integer, allocatable :: bar(:) ! { dg-error "ALLOCATABLE attribute" }
integer :: x ! Just to avoid "extra" error messages about empty type.
end type foo
end program main

View file

@ -0,0 +1,15 @@
! { dg-do compile }
! Tests fix for PR29115, in which an ICE would be produced by
! non-pointer elements being supplied to the pointer components
! in a derived type constructor.
!
! Contributed by Paul Thomas <pault@gcc.gnu.org>
!
type :: homer
integer, pointer :: bart(:)
end type homer
type(homer) :: marge
integer :: duff_beer
marge = homer (duff_beer) ! { dg-error "should be a POINTER or a TARGET" }
end

View file

@ -0,0 +1,13 @@
! { dg-do compile }
! Tests fix for PR29211, in which an ICE would be produced by FORALL assignments
! with dependencies.
!
! Contributed by Paul Thomas <pault@gcc.gnu.org>
!
character(12), dimension(2) :: a, b
a= (/"abcdefghijkl","mnopqrstuvwx"/)
! OK because it uses gfc_trans_assignment
forall (i=1:2) b(i) = a(i)
! Was broken - gfc_trans_assign_need_temp had no handling of string lengths
forall (i=1:2) a(3-i) = a(i)
end

View file

@ -0,0 +1,39 @@
! { dg-do run }
! Test the move_alloc intrinsic.
!
! Contributed by Erik Edelmann <eedelmann@gcc.gnu.org>
! and Paul Thomas <pault@gcc.gnu.org>
!
program test_move_alloc
implicit none
integer, allocatable :: x(:), y(:), temp(:)
character(4), allocatable :: a(:), b(:)
integer :: i
allocate (x(2))
allocate (a(2))
x = [ 42, 77 ]
call move_alloc (x, y)
if (allocated(x)) call abort()
if (.not.allocated(y)) call abort()
if (any(y /= [ 42, 77 ])) call abort()
a = [ "abcd", "efgh" ]
call move_alloc (a, b)
if (allocated(a)) call abort()
if (.not.allocated(b)) call abort()
if (any(b /= [ "abcd", "efgh" ])) call abort()
! Now one of the intended applications of move_alloc; resizing
call move_alloc (y, temp)
allocate (y(6), stat=i)
if (i /= 0) call abort()
y(1:2) = temp
y(3:) = 99
deallocate(temp)
if (any(y /= [ 42, 77, 99, 99, 99, 99 ])) call abort()
end program test_move_alloc

View file

@ -1,3 +1,11 @@
2006-10-08 Paul Thomas <pault@gcc.gnu.org>
Erik Edelmann <edelmann@gcc.gnu.org>
PR libgfortran/20541
* Makefile.in : Add move_alloc.
* intrinsics/move_alloc.c: New function.
* Makefile.am : Add move_alloc.
2006-10-08 Francois-Xavier Coudert <coudert@clipper.ens.fr>
PR libfortran/26540

View file

@ -169,12 +169,12 @@ am__objects_30 = associated.lo abort.lo access.lo args.lo bessel.lo \
eoshift2.lo etime.lo exit.lo fget.lo flush.lo fnum.lo ftell.lo \
gerror.lo getcwd.lo getlog.lo getXid.lo hyper.lo hostnm.lo \
kill.lo ierrno.lo ishftc.lo link.lo malloc.lo mvbits.lo \
pack_generic.lo perror.lo signal.lo size.lo sleep.lo \
spread_generic.lo string_intrinsics.lo system.lo rand.lo \
random.lo rename.lo reshape_generic.lo reshape_packed.lo \
selected_int_kind.lo selected_real_kind.lo stat.lo symlnk.lo \
system_clock.lo time.lo transpose_generic.lo tty.lo umask.lo \
unlink.lo unpack_generic.lo in_pack_generic.lo \
move_alloc.lo pack_generic.lo perror.lo signal.lo size.lo \
sleep.lo spread_generic.lo string_intrinsics.lo system.lo \
rand.lo random.lo rename.lo reshape_generic.lo \
reshape_packed.lo selected_int_kind.lo selected_real_kind.lo \
stat.lo symlnk.lo system_clock.lo time.lo transpose_generic.lo \
tty.lo umask.lo unlink.lo unpack_generic.lo in_pack_generic.lo \
in_unpack_generic.lo
am__objects_31 =
am__objects_32 = _abs_c4.lo _abs_c8.lo _abs_c10.lo _abs_c16.lo \
@ -427,6 +427,7 @@ intrinsics/ishftc.c \
intrinsics/link.c \
intrinsics/malloc.c \
intrinsics/mvbits.c \
intrinsics/move_alloc.c \
intrinsics/pack_generic.c \
intrinsics/perror.c \
intrinsics/signal.c \
@ -2409,6 +2410,9 @@ malloc.lo: intrinsics/malloc.c
mvbits.lo: intrinsics/mvbits.c
$(LIBTOOL) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mvbits.lo `test -f 'intrinsics/mvbits.c' || echo '$(srcdir)/'`intrinsics/mvbits.c
move_alloc.lo: intrinsics/move_alloc.c
$(LIBTOOL) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o move_alloc.lo `test -f 'intrinsics/move_alloc.c' || echo '$(srcdir)/'`intrinsics/move_alloc.c
pack_generic.lo: intrinsics/pack_generic.c
$(LIBTOOL) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o pack_generic.lo `test -f 'intrinsics/pack_generic.c' || echo '$(srcdir)/'`intrinsics/pack_generic.c

View file

@ -0,0 +1,67 @@
/* Generic implementation of the MOVE_ALLOC intrinsic
Copyright (C) 2006 Free Software Foundation, Inc.
Contributed by Paul Thomas
This file is part of the GNU Fortran 95 runtime library (libgfortran).
Libgfortran is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
In addition to the permissions in the GNU General Public License, the
Free Software Foundation gives you unlimited permission to link the
compiled version of this file into combinations with other programs,
and to distribute those combinations without any restriction coming
from the use of this file. (The General Public License restrictions
do apply in other respects; for example, they cover modification of
the file, and distribution when not linked into a combine
executable.)
Ligbfortran is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public
License along with libgfortran; see the file COPYING. If not,
write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA. */
#include "libgfortran.h"
extern void move_alloc (gfc_array_char *, gfc_array_char *);
export_proto(move_alloc);
void
move_alloc (gfc_array_char * from, gfc_array_char * to)
{
int i;
internal_free (to->data);
for (i = 0; i < GFC_DESCRIPTOR_RANK (from); i++)
{
to->dim[i].lbound = from->dim[i].lbound;
to->dim[i].ubound = from->dim[i].ubound;
to->dim[i].stride = from->dim[i].stride;
from->dim[i].stride = 0;
from->dim[i].ubound = from->dim[i].lbound;
}
to->offset = from->offset;
to->dtype = from->dtype;
to->data = from->data;
from->data = NULL;
}
extern void move_alloc_c (gfc_array_char *, GFC_INTEGER_4,
gfc_array_char *, GFC_INTEGER_4);
export_proto(move_alloc_c);
void
move_alloc_c (gfc_array_char * from, GFC_INTEGER_4 from_length __attribute__((unused)),
gfc_array_char * to, GFC_INTEGER_4 to_length __attribute__((unused)))
{
move_alloc (from, to);
}