}
-/* A helper function for gfc_conv_intrinsic_array_transfer to compute
- the size of tree expressions in bytes. */
-static tree
-gfc_size_in_bytes (gfc_se *se, gfc_expr *e)
-{
- tree tmp;
-
- if (e->ts.type == BT_CHARACTER)
- tmp = se->string_length;
- else
- {
- if (e->rank)
- {
- tmp = gfc_get_element_type (TREE_TYPE (se->expr));
- tmp = size_in_bytes (tmp);
- }
- else
- tmp = size_in_bytes (TREE_TYPE (TREE_TYPE (se->expr)));
- }
-
- return fold_convert (gfc_array_index_type, tmp);
-}
-
-
/* Array transfer statement.
DEST(1:N) = TRANSFER (SOURCE, MOLD[, SIZE])
where:
tree tmp;
tree extent;
tree source;
+ tree source_type;
tree source_bytes;
+ tree mold_type;
tree dest_word_len;
tree size_words;
tree size_bytes;
gfc_conv_expr_reference (&argse, arg->expr);
source = argse.expr;
+ source_type = TREE_TYPE (build_fold_indirect_ref (argse.expr));
+
/* Obtain the source word length. */
- tmp = gfc_size_in_bytes (&argse, arg->expr);
+ if (arg->expr->ts.type == BT_CHARACTER)
+ tmp = fold_convert (gfc_array_index_type, argse.string_length);
+ else
+ tmp = fold_convert (gfc_array_index_type,
+ size_in_bytes (source_type));
}
else
{
argse.want_pointer = 0;
gfc_conv_expr_descriptor (&argse, arg->expr, ss);
source = gfc_conv_descriptor_data_get (argse.expr);
+ source_type = gfc_get_element_type (TREE_TYPE (argse.expr));
/* Repack the source if not a full variable array. */
if (!(arg->expr->expr_type == EXPR_VARIABLE
}
/* Obtain the source word length. */
- tmp = gfc_size_in_bytes (&argse, arg->expr);
+ if (arg->expr->ts.type == BT_CHARACTER)
+ tmp = fold_convert (gfc_array_index_type, argse.string_length);
+ else
+ tmp = fold_convert (gfc_array_index_type,
+ size_in_bytes (source_type));
/* Obtain the size of the array in bytes. */
extent = gfc_create_var (gfc_array_index_type, NULL);
gfc_add_block_to_block (&se->pre, &argse.pre);
gfc_add_block_to_block (&se->post, &argse.post);
- /* Now convert MOLD. The sole output is:
+ /* Now convert MOLD. The outputs are:
+ mold_type = the TREE type of MOLD
dest_word_len = destination word length in bytes. */
arg = arg->next;
if (ss == gfc_ss_terminator)
{
gfc_conv_expr_reference (&argse, arg->expr);
-
- /* Obtain the source word length. */
- tmp = gfc_size_in_bytes (&argse, arg->expr);
+ mold_type = TREE_TYPE (build_fold_indirect_ref (argse.expr));
}
else
{
gfc_init_se (&argse, NULL);
argse.want_pointer = 0;
gfc_conv_expr_descriptor (&argse, arg->expr, ss);
-
- /* Obtain the source word length. */
- tmp = gfc_size_in_bytes (&argse, arg->expr);
+ mold_type = gfc_get_element_type (TREE_TYPE (argse.expr));
}
+ if (arg->expr->ts.type == BT_CHARACTER)
+ {
+ tmp = fold_convert (gfc_array_index_type, argse.string_length);
+ mold_type = gfc_get_character_type_len (arg->expr->ts.kind, tmp);
+ }
+ else
+ tmp = fold_convert (gfc_array_index_type,
+ size_in_bytes (mold_type));
+
dest_word_len = gfc_create_var (gfc_array_index_type, NULL);
gfc_add_modify_expr (&se->pre, dest_word_len, tmp);
/* Build a destination descriptor, using the pointer, source, as the
data field. This is already allocated so set callee_alloc.
FIXME callee_alloc is not set! */
-
- tmp = gfc_typenode_for_spec (&expr->ts);
+
gfc_trans_create_temp_array (&se->pre, &se->post, se->loop,
- info, tmp, false, true, false);
+ info, mold_type, false, true, false);
+
+ /* Cast the pointer to the result. */
+ tmp = gfc_conv_descriptor_data_get (info->descriptor);
+ tmp = fold_convert (pvoid_type_node, tmp);
/* Use memcpy to do the transfer. */
tmp = build_call_expr (built_in_decls[BUILT_IN_MEMCPY],
3,
- gfc_conv_descriptor_data_get (info->descriptor),
+ tmp,
fold_convert (pvoid_type_node, source),
size_bytes);
gfc_add_expr_to_block (&se->pre, tmp);
--- /dev/null
+! { dg-do run }\r
+! Tests fix for PR31193, in which the character length for MOLD in\r
+! case 1 below was not being translated correctly for character\r
+! constants and an ICE ensued. The further cases are either checks\r
+! or new bugs that were found in the course of development cases 3 & 5.\r
+!\r
+! Contributed by Brooks Moses <brooks@gcc.gnu.org>\r
+!\r
+function NumOccurances (string, chr, isel) result(n)\r
+ character(*),intent(in) :: string\r
+ character(1),intent(in) :: chr\r
+ integer :: isel\r
+!\r
+! return number of occurances of character in given string\r
+!\r
+ select case (isel)\r
+ case (1)\r
+ n=count(transfer(string, char(1), len(string))==chr)\r
+ case (2)\r
+ n=count(transfer(string, chr, len(string))==chr)\r
+ case (3)\r
+ n=count(transfer(string, "a", len(string))==chr)\r
+ case (4)\r
+ n=count(transfer(string, (/"a","b"/), len(string))==chr)\r
+ case (5)\r
+ n=count(transfer(string, string(1:1), len(string))==chr)\r
+ end select\r
+ return\r
+end\r
+\r
+ if (NumOccurances("abacadae", "a", 1) .ne. 4) call abort ()\r
+ if (NumOccurances("abacadae", "a", 2) .ne. 4) call abort ()\r
+ if (NumOccurances("abacadae", "a", 3) .ne. 4) call abort ()\r
+ if (NumOccurances("abacadae", "a", 4) .ne. 4) call abort ()\r
+ if (NumOccurances("abacadae", "a", 5) .ne. 4) call abort ()\r
+end\r