From 40f201864ffd59ee5936db9ba75bc918227a6798 Mon Sep 17 00:00:00 2001 From: Paul Brook Date: Wed, 25 Aug 2004 16:50:13 +0000 Subject: [PATCH] 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 --- gcc/fortran/ChangeLog | 29 +++ gcc/fortran/trans-array.c | 219 ++++++++++++++++---- gcc/fortran/trans-array.h | 3 +- gcc/fortran/trans-const.c | 2 +- gcc/fortran/trans-expr.c | 12 +- gcc/fortran/trans-types.c | 29 ++- gcc/fortran/trans-types.h | 1 + gcc/fortran/trans.h | 3 +- gcc/testsuite/ChangeLog | 5 + gcc/testsuite/gfortran.dg/string_ctor_1.f90 | 49 +++++ 10 files changed, 292 insertions(+), 60 deletions(-) create mode 100644 gcc/testsuite/gfortran.dg/string_ctor_1.f90 diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index f93b3a434dc..85be1029682 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,32 @@ +2004-08-25 Paul Brook + + 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 * trans.h (build2_v, build3_v): New macros. diff --git a/gcc/fortran/trans-array.c b/gcc/fortran/trans-array.c index b8480fdfa32..5bccd96cfd7 100644 --- a/gcc/fortran/trans-array.c +++ b/gcc/fortran/trans-array.c @@ -527,7 +527,7 @@ gfc_trans_allocate_array_storage (gfc_loopinfo * loop, gfc_ss_info * info, tree gfc_trans_allocate_temp_array (gfc_loopinfo * loop, gfc_ss_info * info, - tree eltype, tree string_length) + tree eltype) { tree type; tree desc; @@ -617,10 +617,6 @@ gfc_trans_allocate_temp_array (gfc_loopinfo * loop, gfc_ss_info * info, size = gfc_evaluate_now (size, &loop->pre); } - /* TODO: Where does the string length go? */ - if (string_length) - gfc_todo_error ("temporary arrays of strings"); - /* Get the size of the array. */ nelem = size; if (size) @@ -651,6 +647,55 @@ gfc_put_offset_into_var (stmtblock_t * pblock, tree * poffset, } +/* Assign an element of an array constructor. */ + +static void +gfc_trans_array_ctor_element (stmtblock_t * pblock, tree pointer, + tree offset, gfc_se * se, gfc_expr * expr) +{ + tree tmp; + tree args; + + gfc_conv_expr (se, expr); + + /* Store the value. */ + tmp = gfc_build_indirect_ref (pointer); + tmp = gfc_build_array_ref (tmp, offset); + if (expr->ts.type == BT_CHARACTER) + { + gfc_conv_string_parameter (se); + if (POINTER_TYPE_P (TREE_TYPE (tmp))) + { + /* The temporary is an array of pointers. */ + se->expr = fold_convert (TREE_TYPE (tmp), se->expr); + gfc_add_modify_expr (&se->pre, tmp, se->expr); + } + else + { + /* The temporary is an array of string values. */ + tmp = gfc_build_addr_expr (pchar_type_node, tmp); + /* We know the temporary and the value will be the same length, + so can use memcpy. */ + args = gfc_chainon_list (NULL_TREE, tmp); + args = gfc_chainon_list (args, se->expr); + args = gfc_chainon_list (args, se->string_length); + tmp = built_in_decls[BUILT_IN_MEMCPY]; + tmp = gfc_build_function_call (tmp, args); + gfc_add_expr_to_block (&se->pre, tmp); + } + } + else + { + /* TODO: Should the frontend already have done this conversion? */ + se->expr = fold_convert (TREE_TYPE (tmp), se->expr); + gfc_add_modify_expr (&se->pre, tmp, se->expr); + } + + gfc_add_block_to_block (pblock, &se->pre); + gfc_add_block_to_block (pblock, &se->post); +} + + /* Add the contents of an array to the constructor. */ static void @@ -688,21 +733,17 @@ gfc_trans_array_constructor_subarray (stmtblock_t * pblock, gfc_copy_loopinfo_to_se (&se, &loop); se.ss = ss; - gfc_conv_expr (&se, expr); - gfc_add_block_to_block (&body, &se.pre); + if (expr->ts.type == BT_CHARACTER) + gfc_todo_error ("character arrays in constructors"); - /* Store the value. */ - tmp = gfc_build_indirect_ref (pointer); - tmp = gfc_build_array_ref (tmp, *poffset); - gfc_add_modify_expr (&body, tmp, se.expr); + gfc_trans_array_ctor_element (&body, pointer, *poffset, &se, expr); + assert (se.ss == gfc_ss_terminator); /* Increment the offset. */ tmp = build2 (PLUS_EXPR, gfc_array_index_type, *poffset, gfc_index_one_node); gfc_add_modify_expr (&body, *poffset, tmp); /* Finish the loop. */ - gfc_add_block_to_block (&body, &se.post); - assert (se.ss == gfc_ss_terminator); gfc_trans_scalarizing_loops (&loop, &body); gfc_add_block_to_block (&loop.pre, &loop.post); tmp = gfc_finish_block (&loop.pre); @@ -720,7 +761,6 @@ gfc_trans_array_constructor_value (stmtblock_t * pblock, tree type, tree * poffset, tree * offsetvar) { tree tmp; - tree ref; stmtblock_t body; tree loopbody; gfc_se se; @@ -763,14 +803,8 @@ gfc_trans_array_constructor_value (stmtblock_t * pblock, tree type, { /* Scalar values. */ gfc_init_se (&se, NULL); - gfc_conv_expr (&se, c->expr); - gfc_add_block_to_block (&body, &se.pre); - - ref = gfc_build_indirect_ref (pointer); - ref = gfc_build_array_ref (ref, *poffset); - gfc_add_modify_expr (&body, ref, - fold_convert (TREE_TYPE (ref), se.expr)); - gfc_add_block_to_block (&body, &se.post); + gfc_trans_array_ctor_element (&body, pointer, *poffset, &se, + c->expr); *poffset = fold (build2 (PLUS_EXPR, gfc_array_index_type, *poffset, gfc_index_one_node)); @@ -791,6 +825,16 @@ gfc_trans_array_constructor_value (stmtblock_t * pblock, tree type, { gfc_init_se (&se, NULL); gfc_conv_constant (&se, p->expr); + if (p->expr->ts.type == BT_CHARACTER + && POINTER_TYPE_P (TREE_TYPE (TREE_TYPE + (TREE_TYPE (pointer))))) + { + /* For constant character array constructors we build + an array of pointers. */ + se.expr = gfc_build_addr_expr (pchar_type_node, + se.expr); + } + list = tree_cons (NULL_TREE, se.expr, list); c = p; p = p->next; @@ -974,6 +1018,86 @@ gfc_get_array_cons_size (mpz_t * size, gfc_constructor * c) } +/* Figure out the string length of a variable reference expression. + Used by get_array_ctor_strlen. */ + +static void +get_array_ctor_var_strlen (gfc_expr * expr, tree * len) +{ + gfc_ref *ref; + gfc_typespec *ts; + + /* Don't bother if we already know the length is a constant. */ + if (*len && INTEGER_CST_P (*len)) + return; + + ts = &expr->symtree->n.sym->ts; + for (ref = expr->ref; ref; ref = ref->next) + { + switch (ref->type) + { + case REF_ARRAY: + /* Array references don't change teh sting length. */ + break; + + case COMPONENT_REF: + /* Use the length of the component. */ + ts = &ref->u.c.component->ts; + break; + + default: + /* TODO: Substrings are tricky because we can't evaluate the + expression more than once. For now we just give up, and hope + we can figure it out elsewhere. */ + return; + } + } + + *len = ts->cl->backend_decl; +} + + +/* Figure out the string length of a character array constructor. + Returns TRUE if all elements are character constants. */ + +static bool +get_array_ctor_strlen (gfc_constructor * c, tree * len) +{ + bool is_const; + + is_const = TRUE; + for (; c; c = c->next) + { + switch (c->expr->expr_type) + { + case EXPR_CONSTANT: + if (!(*len && INTEGER_CST_P (*len))) + *len = build_int_cstu (gfc_strlen_type_node, + c->expr->value.character.length); + break; + + case EXPR_ARRAY: + if (!get_array_ctor_strlen (c->expr->value.constructor, len)) + is_const = FALSE; + break; + + case EXPR_VARIABLE: + is_const = false; + get_array_ctor_var_strlen (c->expr, len); + break; + + default: + is_const = FALSE; + /* TODO: For now we just ignore anything we don't know how to + handle, and hope we can figure it out a different way. */ + break; + } + } + + return is_const; +} + + /* Array constructors are handled by constructing a temporary, then using that within the scalarization loop. This is not optimal, but seems by far the simplest method. */ @@ -986,13 +1110,28 @@ gfc_trans_array_constructor (gfc_loopinfo * loop, gfc_ss * ss) tree desc; tree size; tree type; + bool const_string; - if (ss->expr->ts.type == BT_CHARACTER) - gfc_todo_error ("Character string array constructors"); - type = gfc_typenode_for_spec (&ss->expr->ts); ss->data.info.dimen = loop->dimen; - size = - gfc_trans_allocate_temp_array (loop, &ss->data.info, type, NULL_TREE); + + if (ss->expr->ts.type == BT_CHARACTER) + { + const_string = get_array_ctor_strlen (ss->expr->value.constructor, + &ss->string_length); + if (!ss->string_length) + gfc_todo_error ("complex character array constructors"); + + type = gfc_get_character_type_len (ss->expr->ts.kind, ss->string_length); + if (const_string) + type = build_pointer_type (type); + } + else + { + const_string = TRUE; + type = gfc_typenode_for_spec (&ss->expr->ts); + } + + size = gfc_trans_allocate_temp_array (loop, &ss->data.info, type); desc = ss->data.info.descriptor; offset = gfc_index_zero_node; @@ -1057,7 +1196,7 @@ gfc_add_loop_ss_code (gfc_loopinfo * loop, gfc_ss * ss, bool subscript) gfc_add_block_to_block (&loop->post, &se.post); ss->data.scalar.expr = se.expr; - ss->data.scalar.string_length = se.string_length; + ss->string_length = se.string_length; break; case GFC_SS_REFERENCE: @@ -1068,7 +1207,7 @@ gfc_add_loop_ss_code (gfc_loopinfo * loop, gfc_ss * ss, bool subscript) gfc_add_block_to_block (&loop->post, &se.post); ss->data.scalar.expr = gfc_evaluate_now (se.expr, &loop->pre); - ss->data.scalar.string_length = se.string_length; + ss->string_length = se.string_length; break; case GFC_SS_SECTION: @@ -1129,6 +1268,7 @@ gfc_conv_ss_descriptor (stmtblock_t * block, gfc_ss * ss, int base) gfc_conv_expr_lhs (&se, ss->expr); gfc_add_block_to_block (block, &se.pre); ss->data.info.descriptor = se.expr; + ss->string_length = se.string_length; if (base) { @@ -1496,11 +1636,7 @@ gfc_conv_scalarized_array_ref (gfc_se * se, gfc_array_ref * ar) void gfc_conv_tmp_array_ref (gfc_se * se) { - tree desc; - - desc = se->ss->data.info.descriptor; - /* TODO: We need the string length for string variables. */ - + se->string_length = se->ss->string_length; gfc_conv_scalarized_array_ref (se, NULL); } @@ -2247,7 +2383,7 @@ gfc_conv_resolve_dependencies (gfc_loopinfo * loop, gfc_ss * dest, loop->temp_ss->type = GFC_SS_TEMP; loop->temp_ss->data.temp.type = gfc_get_element_type (TREE_TYPE (dest->data.info.descriptor)); - loop->temp_ss->data.temp.string_length = NULL_TREE; + loop->temp_ss->string_length = NULL_TREE; loop->temp_ss->data.temp.dimen = loop->dimen; loop->temp_ss->next = gfc_ss_terminator; gfc_add_ss_to_loop (loop, loop->temp_ss); @@ -2295,7 +2431,7 @@ gfc_conv_loop_setup (gfc_loopinfo * loop) if (ss->type == GFC_SS_CONSTRUCTOR) { /* An unknown size constructor will always be rank one. - Higher rank constructors will wither have known shape, + Higher rank constructors will either have known shape, or still be wrapped in a call to reshape. */ assert (loop->dimen == 1); /* Try to figure out the size of the constructor. */ @@ -2337,7 +2473,7 @@ gfc_conv_loop_setup (gfc_loopinfo * loop) */ if (!specinfo) loopspec[n] = ss; - /* TODO: Is != contructor correct? */ + /* TODO: Is != constructor correct? */ else if (loopspec[n]->type != GFC_SS_CONSTRUCTOR) { if (integer_onep (info->stride[n]) @@ -2433,13 +2569,12 @@ gfc_conv_loop_setup (gfc_loopinfo * loop) { assert (loop->temp_ss->type == GFC_SS_TEMP); tmp = loop->temp_ss->data.temp.type; - len = loop->temp_ss->data.temp.string_length; + len = loop->temp_ss->string_length; n = loop->temp_ss->data.temp.dimen; memset (&loop->temp_ss->data.info, 0, sizeof (gfc_ss_info)); loop->temp_ss->type = GFC_SS_SECTION; loop->temp_ss->data.info.dimen = n; - gfc_trans_allocate_temp_array (loop, &loop->temp_ss->data.info, - tmp, len); + gfc_trans_allocate_temp_array (loop, &loop->temp_ss->data.info, tmp); } for (n = 0; n < loop->temp_dim; n++) @@ -3502,10 +3637,10 @@ gfc_conv_expr_descriptor (gfc_se * se, gfc_expr * expr, gfc_ss * ss) loop.temp_ss->data.temp.type = gfc_typenode_for_spec (&expr->ts); /* Which can hold our string, if present. */ if (expr->ts.type == BT_CHARACTER) - se->string_length = loop.temp_ss->data.temp.string_length + se->string_length = loop.temp_ss->string_length = TYPE_SIZE_UNIT (loop.temp_ss->data.temp.type); else - loop.temp_ss->data.temp.string_length = NULL; + loop.temp_ss->string_length = NULL; loop.temp_ss->data.temp.dimen = loop.dimen; gfc_add_ss_to_loop (&loop, loop.temp_ss); } diff --git a/gcc/fortran/trans-array.h b/gcc/fortran/trans-array.h index ee7db9beaee..9cd0fcecd78 100644 --- a/gcc/fortran/trans-array.h +++ b/gcc/fortran/trans-array.h @@ -27,8 +27,7 @@ tree gfc_array_deallocate (tree); void gfc_array_allocate (gfc_se *, gfc_ref *, tree); /* Generate code to allocate a temporary array. */ -tree gfc_trans_allocate_temp_array (gfc_loopinfo *, gfc_ss_info *, tree, - tree); +tree gfc_trans_allocate_temp_array (gfc_loopinfo *, gfc_ss_info *, tree); /* Generate function entry code for allocation of compiler allocated array variables. */ diff --git a/gcc/fortran/trans-const.c b/gcc/fortran/trans-const.c index 25a945905e4..8ea0d5cc119 100644 --- a/gcc/fortran/trans-const.c +++ b/gcc/fortran/trans-const.c @@ -353,7 +353,7 @@ gfc_conv_constant (gfc_se * se, gfc_expr * expr) assert (se->ss->expr == 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); return; } diff --git a/gcc/fortran/trans-expr.c b/gcc/fortran/trans-expr.c index 50aa9ca338a..cbf2dd1fb67 100644 --- a/gcc/fortran/trans-expr.c +++ b/gcc/fortran/trans-expr.c @@ -231,9 +231,8 @@ gfc_conv_component_ref (gfc_se * se, gfc_ref * ref) if (c->ts.type == BT_CHARACTER) { tmp = c->ts.cl->backend_decl; - assert (tmp); - if (!INTEGER_CST_P (tmp)) - gfc_todo_error ("Unknown length character component"); + /* Components must always be constant length. */ + assert (tmp && INTEGER_CST_P (tmp)); se->string_length = tmp; } @@ -260,6 +259,7 @@ gfc_conv_variable (gfc_se * se, gfc_expr * expr) /* A scalarized term. We already know the descriptor. */ se->expr = se->ss->data.info.descriptor; + se->string_length = se->ss->string_length; ref = se->ss->data.info.ref; } else @@ -1040,7 +1040,7 @@ gfc_conv_function_call (gfc_se * se, gfc_symbol * sym, tmp = gfc_typenode_for_spec (&sym->ts); info->dimen = se->loop->dimen; /* 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. */ tmp = @@ -1711,7 +1711,7 @@ gfc_conv_expr (gfc_se * se, gfc_expr * expr) /* Substitute a scalar expression evaluated outside the scalarization loop. */ 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); return; } @@ -1799,7 +1799,7 @@ gfc_conv_expr_reference (gfc_se * se, gfc_expr * expr) && se->ss->type == GFC_SS_REFERENCE) { 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); return; } diff --git a/gcc/fortran/trans-types.c b/gcc/fortran/trans-types.c index 6fdb84a2645..e88842d1a21 100644 --- a/gcc/fortran/trans-types.c +++ b/gcc/fortran/trans-types.c @@ -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 -gfc_get_character_type (int kind, gfc_charlen * cl) +gfc_get_character_type_len (int kind, tree len) { tree base; - tree type; - tree len; tree bounds; + tree type; switch (kind) { @@ -287,14 +286,25 @@ gfc_get_character_type (int kind, gfc_charlen * cl) 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); type = build_array_type (base, bounds); TYPE_STRING_FLAG (type) = 1; 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. */ @@ -480,6 +490,9 @@ gfc_is_nodesc_array (gfc_symbol * sym) return 1; } + +/* Create an array descriptor type. */ + static tree gfc_build_array_type (tree type, gfc_array_spec * as) { @@ -584,7 +597,9 @@ gfc_get_dtype (tree type, int rank) break; 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); diff --git a/gcc/fortran/trans-types.h b/gcc/fortran/trans-types.h index 82eb8574caa..ebab5a1acc0 100644 --- a/gcc/fortran/trans-types.h +++ b/gcc/fortran/trans-types.h @@ -112,6 +112,7 @@ tree gfc_get_real_type (int); tree gfc_get_complex_type (int); tree gfc_get_logical_type (int); tree gfc_get_character_type (int, gfc_charlen *); +tree gfc_get_character_type_len (int, tree); tree gfc_sym_type (gfc_symbol *); tree gfc_typenode_for_spec (gfc_typespec *); diff --git a/gcc/fortran/trans.h b/gcc/fortran/trans.h index b9b467bb33f..504504689ec 100644 --- a/gcc/fortran/trans.h +++ b/gcc/fortran/trans.h @@ -162,13 +162,13 @@ typedef struct gfc_ss gfc_ss_type type; gfc_expr *expr; mpz_t *shape; + tree string_length; union { /* If type is GFC_SS_SCALAR or GFC_SS_REFERENCE. */ struct { tree expr; - tree string_length; } scalar; @@ -179,7 +179,6 @@ typedef struct gfc_ss assigned expression. */ int dimen; tree type; - tree string_length; } temp; /* All other types. */ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 4647822b261..888b38a94d2 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2004-08-25 Paul Brook + + PR fortran/17144 + * gfortran.dg/string_ctor_1.f90: New test. + 2004-08-25 Kriang Lerdsuwanakij PR c++/14428 diff --git a/gcc/testsuite/gfortran.dg/string_ctor_1.f90 b/gcc/testsuite/gfortran.dg/string_ctor_1.f90 new file mode 100644 index 00000000000..3242ea8f9e3 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/string_ctor_1.f90 @@ -0,0 +1,49 @@ +! { 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 + -- 2.30.2