Commit fa1ed658 by Janus Weil

re PR fortran/54917 ([OOP] TRANSFER on polymorphic variable causes ICE)

2012-11-06  Janus Weil  <janus@gcc.gnu.org>

	PR fortran/54917
	* target-memory.c (gfc_target_expr_size,gfc_target_interpret_expr):
	Handle BT_CLASS.
	* trans-intrinsic.c (gfc_conv_intrinsic_transfer): Add support for
	polymorphic arguments.

2012-11-06  Janus Weil  <janus@gcc.gnu.org>

	PR fortran/54917
	* gfortran.dg/transfer_class_1.f90: New.
	* gfortran.dg/transfer_class_2.f90: New.

From-SVN: r193226
parent b887f1a0
2012-11-06 Janus Weil <janus@gcc.gnu.org>
PR fortran/54917
* target-memory.c (gfc_target_expr_size,gfc_target_interpret_expr):
Handle BT_CLASS.
* trans-intrinsic.c (gfc_conv_intrinsic_transfer): Add support for
polymorphic arguments.
2012-11-04 Janus Weil <janus@gcc.gnu.org> 2012-11-04 Janus Weil <janus@gcc.gnu.org>
PR fortran/55199 PR fortran/55199
......
...@@ -121,6 +121,7 @@ gfc_target_expr_size (gfc_expr *e) ...@@ -121,6 +121,7 @@ gfc_target_expr_size (gfc_expr *e)
case BT_HOLLERITH: case BT_HOLLERITH:
return e->representation.length; return e->representation.length;
case BT_DERIVED: case BT_DERIVED:
case BT_CLASS:
{ {
/* Determine type size without clobbering the typespec for ISO C /* Determine type size without clobbering the typespec for ISO C
binding types. */ binding types. */
...@@ -572,6 +573,9 @@ gfc_target_interpret_expr (unsigned char *buffer, size_t buffer_size, ...@@ -572,6 +573,9 @@ gfc_target_interpret_expr (unsigned char *buffer, size_t buffer_size,
gfc_interpret_character (buffer, buffer_size, result); gfc_interpret_character (buffer, buffer_size, result);
break; break;
case BT_CLASS:
result->ts = CLASS_DATA (result)->ts;
/* Fall through. */
case BT_DERIVED: case BT_DERIVED:
result->representation.length = result->representation.length =
gfc_interpret_derived (buffer, buffer_size, result); gfc_interpret_derived (buffer, buffer_size, result);
......
...@@ -5348,6 +5348,7 @@ gfc_conv_intrinsic_transfer (gfc_se * se, gfc_expr * expr) ...@@ -5348,6 +5348,7 @@ gfc_conv_intrinsic_transfer (gfc_se * se, gfc_expr * expr)
stmtblock_t block; stmtblock_t block;
int n; int n;
bool scalar_mold; bool scalar_mold;
gfc_expr *source_expr, *mold_expr;
info = NULL; info = NULL;
if (se->loop) if (se->loop)
...@@ -5357,6 +5358,7 @@ gfc_conv_intrinsic_transfer (gfc_se * se, gfc_expr * expr) ...@@ -5357,6 +5358,7 @@ gfc_conv_intrinsic_transfer (gfc_se * se, gfc_expr * expr)
source_bytes = length of the source in bytes source_bytes = length of the source in bytes
source = pointer to the source data. */ source = pointer to the source data. */
arg = expr->value.function.actual; arg = expr->value.function.actual;
source_expr = arg->expr;
/* Ensure double transfer through LOGICAL preserves all /* Ensure double transfer through LOGICAL preserves all
the needed bits. */ the needed bits. */
...@@ -5376,18 +5378,28 @@ gfc_conv_intrinsic_transfer (gfc_se * se, gfc_expr * expr) ...@@ -5376,18 +5378,28 @@ gfc_conv_intrinsic_transfer (gfc_se * se, gfc_expr * expr)
if (arg->expr->rank == 0) if (arg->expr->rank == 0)
{ {
gfc_conv_expr_reference (&argse, arg->expr); gfc_conv_expr_reference (&argse, arg->expr);
if (arg->expr->ts.type == BT_CLASS)
source = gfc_class_data_get (argse.expr);
else
source = argse.expr; source = argse.expr;
source_type = TREE_TYPE (build_fold_indirect_ref_loc (input_location,
argse.expr));
/* Obtain the source word length. */ /* Obtain the source word length. */
if (arg->expr->ts.type == BT_CHARACTER) switch (arg->expr->ts.type)
{
case BT_CHARACTER:
tmp = size_of_string_in_bytes (arg->expr->ts.kind, tmp = size_of_string_in_bytes (arg->expr->ts.kind,
argse.string_length); argse.string_length);
else break;
case BT_CLASS:
tmp = gfc_vtable_size_get (argse.expr);
break;
default:
source_type = TREE_TYPE (build_fold_indirect_ref_loc (input_location,
source));
tmp = fold_convert (gfc_array_index_type, tmp = fold_convert (gfc_array_index_type,
size_in_bytes (source_type)); size_in_bytes (source_type));
break;
}
} }
else else
{ {
...@@ -5464,6 +5476,7 @@ gfc_conv_intrinsic_transfer (gfc_se * se, gfc_expr * expr) ...@@ -5464,6 +5476,7 @@ gfc_conv_intrinsic_transfer (gfc_se * se, gfc_expr * expr)
mold_type = the TREE type of MOLD mold_type = the TREE type of MOLD
dest_word_len = destination word length in bytes. */ dest_word_len = destination word length in bytes. */
arg = arg->next; arg = arg->next;
mold_expr = arg->expr;
gfc_init_se (&argse, NULL); gfc_init_se (&argse, NULL);
...@@ -5494,15 +5507,20 @@ gfc_conv_intrinsic_transfer (gfc_se * se, gfc_expr * expr) ...@@ -5494,15 +5507,20 @@ gfc_conv_intrinsic_transfer (gfc_se * se, gfc_expr * expr)
mold_type = gfc_get_int_type (arg->expr->ts.kind); mold_type = gfc_get_int_type (arg->expr->ts.kind);
} }
if (arg->expr->ts.type == BT_CHARACTER) /* Obtain the destination word length. */
switch (arg->expr->ts.type)
{ {
case BT_CHARACTER:
tmp = size_of_string_in_bytes (arg->expr->ts.kind, argse.string_length); tmp = size_of_string_in_bytes (arg->expr->ts.kind, argse.string_length);
mold_type = gfc_get_character_type_len (arg->expr->ts.kind, tmp); mold_type = gfc_get_character_type_len (arg->expr->ts.kind, tmp);
break;
case BT_CLASS:
tmp = gfc_vtable_size_get (argse.expr);
break;
default:
tmp = fold_convert (gfc_array_index_type, size_in_bytes (mold_type));
break;
} }
else
tmp = fold_convert (gfc_array_index_type,
size_in_bytes (mold_type));
dest_word_len = gfc_create_var (gfc_array_index_type, NULL); dest_word_len = gfc_create_var (gfc_array_index_type, NULL);
gfc_add_modify (&se->pre, dest_word_len, tmp); gfc_add_modify (&se->pre, dest_word_len, tmp);
...@@ -5650,8 +5668,21 @@ scalar_transfer: ...@@ -5650,8 +5668,21 @@ scalar_transfer:
ptr = convert (build_pointer_type (mold_type), source); ptr = convert (build_pointer_type (mold_type), source);
/* For CLASS results, allocate the needed memory first. */
if (mold_expr->ts.type == BT_CLASS)
{
tree cdata;
cdata = gfc_class_data_get (tmpdecl);
tmp = gfc_call_malloc (&se->pre, TREE_TYPE (cdata), dest_word_len);
gfc_add_modify (&se->pre, cdata, tmp);
}
/* Use memcpy to do the transfer. */ /* Use memcpy to do the transfer. */
if (mold_expr->ts.type == BT_CLASS)
tmp = gfc_class_data_get (tmpdecl);
else
tmp = gfc_build_addr_expr (NULL_TREE, tmpdecl); tmp = gfc_build_addr_expr (NULL_TREE, tmpdecl);
tmp = build_call_expr_loc (input_location, tmp = build_call_expr_loc (input_location,
builtin_decl_explicit (BUILT_IN_MEMCPY), 3, builtin_decl_explicit (BUILT_IN_MEMCPY), 3,
fold_convert (pvoid_type_node, tmp), fold_convert (pvoid_type_node, tmp),
...@@ -5659,6 +5690,18 @@ scalar_transfer: ...@@ -5659,6 +5690,18 @@ scalar_transfer:
extent); extent);
gfc_add_expr_to_block (&se->pre, tmp); gfc_add_expr_to_block (&se->pre, tmp);
/* For CLASS results, set the _vptr. */
if (mold_expr->ts.type == BT_CLASS)
{
tree vptr;
gfc_symbol *vtab;
vptr = gfc_class_vptr_get (tmpdecl);
vtab = gfc_find_derived_vtab (source_expr->ts.u.derived);
gcc_assert (vtab);
tmp = gfc_build_addr_expr (NULL_TREE, gfc_get_symbol_decl (vtab));
gfc_add_modify (&se->pre, vptr, fold_convert (TREE_TYPE (vptr), tmp));
}
se->expr = tmpdecl; se->expr = tmpdecl;
} }
} }
......
2012-11-06 Janus Weil <janus@gcc.gnu.org>
PR fortran/54917
* gfortran.dg/transfer_class_1.f90: New.
* gfortran.dg/transfer_class_2.f90: New.
2012-11-05 Sriraman Tallam <tmsriram@google.com> 2012-11-05 Sriraman Tallam <tmsriram@google.com>
* testsuite/g++.dg/mv1.C: New test. * testsuite/g++.dg/mv1.C: New test.
......
! { dg-do compile }
! { dg-options "-Wsurprising" }
!
! PR 54917: [4.7/4.8 Regression] [OOP] TRANSFER on polymorphic variable causes ICE
!
! Contributed by Sean Santos <quantheory@gmail.com>
subroutine test_routine1(arg)
implicit none
type test_type
integer :: test_comp
end type
class(test_type) :: arg
integer :: i
i = transfer(arg, 1)
end subroutine
! { dg-do run }
!
! PR 54917: [OOP] TRANSFER on polymorphic variable causes ICE
!
! Contributed by Janus Weil <janus@gcc.gnu.org>
module m
implicit none
type test_type
integer :: i = 0
contains
procedure :: ass
generic :: assignment(=) => ass
end type
contains
subroutine ass (a, b)
class(test_type), intent(out) :: a
class(test_type), intent(in) :: b
a%i = b%i
end subroutine
end module
program p
use m
implicit none
class(test_type), allocatable :: c
type(test_type) :: t
allocate(c)
! (1) check CLASS-to-TYPE transfer
c%i=3
t = transfer(c, t)
if (t%i /= 3) call abort()
! (2) check TYPE-to-CLASS transfer
t%i=4
c = transfer(t, c)
if (c%i /= 4) call abort()
end
! { dg-final { cleanup-modules "m" } }
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