Commit 40f20186 by Paul Brook Committed by Paul Brook

re PR fortran/17144 (Not Implemented: Character string array constructors /…

re PR fortran/17144 (Not Implemented: Character string array constructors / Assignment to char array)

	PR fortran/17144
	* trans-array.c (gfc_trans_allocate_temp_array): Remove
	string_length argument.
	(gfc_trans_array_ctor_element): New function.
	(gfc_trans_array_constructor_subarray): Use it.
	(gfc_trans_array_constructor_value): Ditto.  Handle constant
	character arrays.
	(get_array_ctor_var_strlen, get_array_ctor_strlen): New functions.
	(gfc_trans_array_constructor): Use them.
	(gfc_add_loop_ss_code): Update to new gfc_ss layout.
	(gfc_conv_ss_descriptor): Remember section string length.
	(gfc_conv_scalarized_array_ref): Ditto.  Remove dead code.
	(gfc_conv_resolve_dependencies): Update to new gfc_ss layout.
	(gfc_conv_expr_descriptor): Ditto.
	(gfc_conv_loop_setup): Ditto.  Spelling fixes.
	* trans-array.h (gfc_trans_allocate_temp_array): Update prototype.
	* trans-const.c (gfc_conv_constant):  Update to new gfc_ss layout.
	* trans-expr.c (gfc_conv_component_ref): Turn error into ICE.
	(gfc_conv_variable): Set string_length from section.
	(gfc_conv_function_call): Remove extra argument.
	(gfc_conv_expr, gfc_conv_expr_reference): Update to new gfc_ss layout.
	* trans-types.c (gfc_get_character_type_len): New function.
	(gfc_get_character_type): Use it.
	(gfc_get_dtype): Return zero for internal types.
	* trans-types.h (gfc_get_character_type_len): Add prototype.
	* trans.h (struct gfc_ss): Move string_length out of union.
testsuite/
	* gfortran.dg/string_ctor_1.f90: New test.

From-SVN: r86558
parent 923ab88c
2004-08-25 Paul Brook <paul@codesourcery.com>
PR fortran/17144
* trans-array.c (gfc_trans_allocate_temp_array): Remove
string_length argument.
(gfc_trans_array_ctor_element): New function.
(gfc_trans_array_constructor_subarray): Use it.
(gfc_trans_array_constructor_value): Ditto. Handle constant
character arrays.
(get_array_ctor_var_strlen, get_array_ctor_strlen): New functions.
(gfc_trans_array_constructor): Use them.
(gfc_add_loop_ss_code): Update to new gfc_ss layout.
(gfc_conv_ss_descriptor): Remember section string length.
(gfc_conv_scalarized_array_ref): Ditto. Remove dead code.
(gfc_conv_resolve_dependencies): Update to new gfc_ss layout.
(gfc_conv_expr_descriptor): Ditto.
(gfc_conv_loop_setup): Ditto. Spelling fixes.
* trans-array.h (gfc_trans_allocate_temp_array): Update prototype.
* trans-const.c (gfc_conv_constant): Update to new gfc_ss layout.
* trans-expr.c (gfc_conv_component_ref): Turn error into ICE.
(gfc_conv_variable): Set string_length from section.
(gfc_conv_function_call): Remove extra argument.
(gfc_conv_expr, gfc_conv_expr_reference): Update to new gfc_ss layout.
* trans-types.c (gfc_get_character_type_len): New function.
(gfc_get_character_type): Use it.
(gfc_get_dtype): Return zero for internal types.
* trans-types.h (gfc_get_character_type_len): Add prototype.
* trans.h (struct gfc_ss): Move string_length out of union.
2004-08-25 Tobias Schlueter <tobias.schlueter@physik.uni-muenchen.de> 2004-08-25 Tobias Schlueter <tobias.schlueter@physik.uni-muenchen.de>
* trans.h (build2_v, build3_v): New macros. * trans.h (build2_v, build3_v): New macros.
......
...@@ -27,8 +27,7 @@ tree gfc_array_deallocate (tree); ...@@ -27,8 +27,7 @@ tree gfc_array_deallocate (tree);
void gfc_array_allocate (gfc_se *, gfc_ref *, tree); void gfc_array_allocate (gfc_se *, gfc_ref *, tree);
/* Generate code to allocate a temporary array. */ /* Generate code to allocate a temporary array. */
tree gfc_trans_allocate_temp_array (gfc_loopinfo *, gfc_ss_info *, tree, tree gfc_trans_allocate_temp_array (gfc_loopinfo *, gfc_ss_info *, tree);
tree);
/* Generate function entry code for allocation of compiler allocated array /* Generate function entry code for allocation of compiler allocated array
variables. */ variables. */
......
...@@ -353,7 +353,7 @@ gfc_conv_constant (gfc_se * se, gfc_expr * expr) ...@@ -353,7 +353,7 @@ gfc_conv_constant (gfc_se * se, gfc_expr * expr)
assert (se->ss->expr == expr); assert (se->ss->expr == expr);
se->expr = se->ss->data.scalar.expr; se->expr = se->ss->data.scalar.expr;
se->string_length = se->ss->data.scalar.string_length; se->string_length = se->ss->string_length;
gfc_advance_se_ss_chain (se); gfc_advance_se_ss_chain (se);
return; return;
} }
......
...@@ -231,9 +231,8 @@ gfc_conv_component_ref (gfc_se * se, gfc_ref * ref) ...@@ -231,9 +231,8 @@ gfc_conv_component_ref (gfc_se * se, gfc_ref * ref)
if (c->ts.type == BT_CHARACTER) if (c->ts.type == BT_CHARACTER)
{ {
tmp = c->ts.cl->backend_decl; tmp = c->ts.cl->backend_decl;
assert (tmp); /* Components must always be constant length. */
if (!INTEGER_CST_P (tmp)) assert (tmp && INTEGER_CST_P (tmp));
gfc_todo_error ("Unknown length character component");
se->string_length = tmp; se->string_length = tmp;
} }
...@@ -260,6 +259,7 @@ gfc_conv_variable (gfc_se * se, gfc_expr * expr) ...@@ -260,6 +259,7 @@ gfc_conv_variable (gfc_se * se, gfc_expr * expr)
/* A scalarized term. We already know the descriptor. */ /* A scalarized term. We already know the descriptor. */
se->expr = se->ss->data.info.descriptor; se->expr = se->ss->data.info.descriptor;
se->string_length = se->ss->string_length;
ref = se->ss->data.info.ref; ref = se->ss->data.info.ref;
} }
else else
...@@ -1040,7 +1040,7 @@ gfc_conv_function_call (gfc_se * se, gfc_symbol * sym, ...@@ -1040,7 +1040,7 @@ gfc_conv_function_call (gfc_se * se, gfc_symbol * sym,
tmp = gfc_typenode_for_spec (&sym->ts); tmp = gfc_typenode_for_spec (&sym->ts);
info->dimen = se->loop->dimen; info->dimen = se->loop->dimen;
/* Allocate a temporary to store the result. */ /* Allocate a temporary to store the result. */
gfc_trans_allocate_temp_array (se->loop, info, tmp, NULL_TREE); gfc_trans_allocate_temp_array (se->loop, info, tmp);
/* Zero the first stride to indicate a temporary. */ /* Zero the first stride to indicate a temporary. */
tmp = tmp =
...@@ -1711,7 +1711,7 @@ gfc_conv_expr (gfc_se * se, gfc_expr * expr) ...@@ -1711,7 +1711,7 @@ gfc_conv_expr (gfc_se * se, gfc_expr * expr)
/* Substitute a scalar expression evaluated outside the scalarization /* Substitute a scalar expression evaluated outside the scalarization
loop. */ loop. */
se->expr = se->ss->data.scalar.expr; se->expr = se->ss->data.scalar.expr;
se->string_length = se->ss->data.scalar.string_length; se->string_length = se->ss->string_length;
gfc_advance_se_ss_chain (se); gfc_advance_se_ss_chain (se);
return; return;
} }
...@@ -1799,7 +1799,7 @@ gfc_conv_expr_reference (gfc_se * se, gfc_expr * expr) ...@@ -1799,7 +1799,7 @@ gfc_conv_expr_reference (gfc_se * se, gfc_expr * expr)
&& se->ss->type == GFC_SS_REFERENCE) && se->ss->type == GFC_SS_REFERENCE)
{ {
se->expr = se->ss->data.scalar.expr; se->expr = se->ss->data.scalar.expr;
se->string_length = se->ss->data.scalar.string_length; se->string_length = se->ss->string_length;
gfc_advance_se_ss_chain (se); gfc_advance_se_ss_chain (se);
return; return;
} }
......
...@@ -267,15 +267,14 @@ gfc_get_logical_type (int kind) ...@@ -267,15 +267,14 @@ gfc_get_logical_type (int kind)
} }
} }
/* Get a type node for a character kind. */ /* Create a character type with the given kind and length. */
tree tree
gfc_get_character_type (int kind, gfc_charlen * cl) gfc_get_character_type_len (int kind, tree len)
{ {
tree base; tree base;
tree type;
tree len;
tree bounds; tree bounds;
tree type;
switch (kind) switch (kind)
{ {
...@@ -287,14 +286,25 @@ gfc_get_character_type (int kind, gfc_charlen * cl) ...@@ -287,14 +286,25 @@ gfc_get_character_type (int kind, gfc_charlen * cl)
fatal_error ("character kind=%d not available", kind); fatal_error ("character kind=%d not available", kind);
} }
len = (cl == 0) ? NULL_TREE : cl->backend_decl;
bounds = build_range_type (gfc_array_index_type, gfc_index_one_node, len); bounds = build_range_type (gfc_array_index_type, gfc_index_one_node, len);
type = build_array_type (base, bounds); type = build_array_type (base, bounds);
TYPE_STRING_FLAG (type) = 1; TYPE_STRING_FLAG (type) = 1;
return type; return type;
} }
/* Get a type node for a character kind. */
tree
gfc_get_character_type (int kind, gfc_charlen * cl)
{
tree len;
len = (cl == NULL) ? NULL_TREE : cl->backend_decl;
return gfc_get_character_type_len (kind, len);
}
/* Covert a basic type. This will be an array for character types. */ /* Covert a basic type. This will be an array for character types. */
...@@ -480,6 +490,9 @@ gfc_is_nodesc_array (gfc_symbol * sym) ...@@ -480,6 +490,9 @@ gfc_is_nodesc_array (gfc_symbol * sym)
return 1; return 1;
} }
/* Create an array descriptor type. */
static tree static tree
gfc_build_array_type (tree type, gfc_array_spec * as) gfc_build_array_type (tree type, gfc_array_spec * as)
{ {
...@@ -584,7 +597,9 @@ gfc_get_dtype (tree type, int rank) ...@@ -584,7 +597,9 @@ gfc_get_dtype (tree type, int rank)
break; break;
default: default:
abort (); /* TODO: Don't do dtype for temporary descriptorless arrays. */
/* We can strange array types for temporary arrays. */
return gfc_index_zero_node;
} }
assert (rank <= GFC_DTYPE_RANK_MASK); assert (rank <= GFC_DTYPE_RANK_MASK);
......
...@@ -112,6 +112,7 @@ tree gfc_get_real_type (int); ...@@ -112,6 +112,7 @@ tree gfc_get_real_type (int);
tree gfc_get_complex_type (int); tree gfc_get_complex_type (int);
tree gfc_get_logical_type (int); tree gfc_get_logical_type (int);
tree gfc_get_character_type (int, gfc_charlen *); tree gfc_get_character_type (int, gfc_charlen *);
tree gfc_get_character_type_len (int, tree);
tree gfc_sym_type (gfc_symbol *); tree gfc_sym_type (gfc_symbol *);
tree gfc_typenode_for_spec (gfc_typespec *); tree gfc_typenode_for_spec (gfc_typespec *);
......
...@@ -162,13 +162,13 @@ typedef struct gfc_ss ...@@ -162,13 +162,13 @@ typedef struct gfc_ss
gfc_ss_type type; gfc_ss_type type;
gfc_expr *expr; gfc_expr *expr;
mpz_t *shape; mpz_t *shape;
tree string_length;
union union
{ {
/* If type is GFC_SS_SCALAR or GFC_SS_REFERENCE. */ /* If type is GFC_SS_SCALAR or GFC_SS_REFERENCE. */
struct struct
{ {
tree expr; tree expr;
tree string_length;
} }
scalar; scalar;
...@@ -179,7 +179,6 @@ typedef struct gfc_ss ...@@ -179,7 +179,6 @@ typedef struct gfc_ss
assigned expression. */ assigned expression. */
int dimen; int dimen;
tree type; tree type;
tree string_length;
} }
temp; temp;
/* All other types. */ /* All other types. */
......
2004-08-25 Paul Brook <paul@codesourcery.com>
PR fortran/17144
* gfortran.dg/string_ctor_1.f90: New test.
2004-08-25 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net> 2004-08-25 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
PR c++/14428 PR c++/14428
......
! { dg-do run }
! Program to test character array constructors.
! PR17144
subroutine test1 (n, t, u)
integer n
character(len=n) :: s(2)
character(len=*) :: t
character(len=*) :: u
! A variable array constructor.
s = (/t, u/)
! An array constructor as part of an expression.
if (any (s .ne. (/"Hell", "Worl"/))) call abort
end subroutine
subroutine test2
character*5 :: s(2)
! A constant array constructor
s = (/"Hello", "World"/)
if ((s(1) .ne. "Hello") .or. (s(2) .ne. "World")) call abort
end subroutine
subroutine test3
character*1 s(26)
character*26 t
integer i
! A large array constructor
s = (/'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', &
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'/)
do i=1, 26
t(i:i) = s(i)
end do
! Assignment with dependency
s = (/(s(27-i), i=1, 26)/)
do i=1, 26
t(i:i) = s(i)
end do
if (t .ne. "zyxwvutsrqponmlkjihgfedcba") call abort
end subroutine
program string_ctor_1
call test1 (4, "Hello", "World")
call test2
call test3
end program
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