tree size;
tree size_in_bytes;
tree lhs_cl_size = NULL_TREE;
+ gfc_se se;
if (!comp)
return;
}
else if (cm->ts.type == BT_CLASS)
{
- gcc_assert (expr2->ts.type == BT_CLASS || expr2->ts.type == BT_DERIVED);
- if (expr2->ts.type == BT_DERIVED)
+ if (expr2->ts.type != BT_CLASS)
{
- tmp = gfc_get_symbol_decl (expr2->ts.u.derived);
- size = TYPE_SIZE_UNIT (tmp);
+ if (expr2->ts.type == BT_CHARACTER)
+ {
+ gfc_init_se (&se, NULL);
+ gfc_conv_expr (&se, expr2);
+ size = build_int_cst (gfc_charlen_type_node, expr2->ts.kind);
+ size = fold_build2_loc (input_location, MULT_EXPR,
+ gfc_charlen_type_node,
+ se.string_length, size);
+ size = fold_convert (size_type_node, size);
+ }
+ else
+ {
+ if (expr2->ts.type == BT_DERIVED)
+ tmp = gfc_get_symbol_decl (expr2->ts.u.derived);
+ else
+ tmp = gfc_typenode_for_spec (&expr2->ts);
+ size = TYPE_SIZE_UNIT (tmp);
+ }
}
else
{
gfc_expr *e2vtab;
- gfc_se se;
e2vtab = gfc_find_and_cut_at_last_class_ref (expr2);
gfc_add_vptr_component (e2vtab);
gfc_add_size_component (e2vtab);
{
gfc_init_se (&se, NULL);
gfc_conv_expr (&se, expr);
+ tree size;
/* Take care about non-array allocatable components here. The alloc_*
routine below is motivated by the alloc_scalar_allocatable_for_
&& expr->symtree->n.sym->attr.dummy)
se.expr = build_fold_indirect_ref_loc (input_location, se.expr);
- if (cm->ts.type == BT_CLASS && expr->ts.type == BT_DERIVED)
+ if (cm->ts.type == BT_CLASS)
{
tmp = gfc_class_data_get (dest);
tmp = build_fold_indirect_ref_loc (input_location, tmp);
/* For deferred strings insert a memcpy. */
if (cm->ts.type == BT_CHARACTER && cm->ts.deferred)
{
- tree size;
gcc_assert (se.string_length || expr->ts.u.cl->backend_decl);
size = size_of_string_in_bytes (cm->ts.kind, se.string_length
? se.string_length
tmp = gfc_build_memcpy_call (tmp, se.expr, size);
gfc_add_expr_to_block (&block, tmp);
}
+ else if (cm->ts.type == BT_CLASS)
+ {
+ /* Fix the expression for memcpy. */
+ if (expr->expr_type != EXPR_VARIABLE)
+ se.expr = gfc_evaluate_now (se.expr, &block);
+
+ if (expr->ts.type == BT_CHARACTER)
+ {
+ size = build_int_cst (gfc_charlen_type_node, expr->ts.kind);
+ size = fold_build2_loc (input_location, MULT_EXPR,
+ gfc_charlen_type_node,
+ se.string_length, size);
+ size = fold_convert (size_type_node, size);
+ }
+ else
+ size = TYPE_SIZE_UNIT (gfc_typenode_for_spec (&expr->ts));
+
+ /* Now copy the expression to the constructor component _data. */
+ gfc_add_expr_to_block (&block,
+ gfc_build_memcpy_call (tmp, se.expr, size));
+
+ /* Fill the unlimited polymorphic _len field. */
+ if (UNLIMITED_POLY (cm) && expr->ts.type == BT_CHARACTER)
+ {
+ tmp = gfc_class_len_get (gfc_get_class_from_expr (tmp));
+ gfc_add_modify (&block, tmp,
+ fold_convert (TREE_TYPE (tmp),
+ se.string_length));
+ }
+ }
else
gfc_add_modify (&block, tmp,
fold_convert (TREE_TYPE (tmp), se.expr));
--- /dev/null
+! { dg-do run }
+!
+! Contributed by Neil Carlson <neil.n.carlson@gmail.com>
+!
+program main
+ character(2) :: c
+
+ type :: S
+ integer :: n
+ end type
+ type(S) :: Sobj
+
+ type, extends(S) :: S2
+ integer :: m
+ end type
+ type(S2) :: S2obj
+
+ type :: T
+ class(S), allocatable :: x
+ end type
+
+ type tContainer
+ class(*), allocatable :: x
+ end type
+
+ type(T) :: Tobj
+
+ Sobj = S(1)
+ Tobj = T(Sobj)
+
+ S2obj = S2(1,2)
+ Tobj = T(S2obj) ! Failed here
+ select type (x => Tobj%x)
+ type is (S2)
+ if ((x%n .ne. 1) .or. (x%m .ne. 2)) stop 1
+ class default
+ stop 2
+ end select
+
+ c = " "
+ call pass_it (T(Sobj))
+ if (c .ne. "S ") stop 3
+ call pass_it (T(S2obj)) ! and here
+ if (c .ne. "S2") stop 4
+
+ call bar
+
+contains
+
+ subroutine pass_it (foo)
+ type(T), intent(in) :: foo
+ select type (x => foo%x)
+ type is (S)
+ c = "S "
+ if (x%n .ne. 1) stop 5
+ type is (S2)
+ c = "S2"
+ if ((x%n .ne. 1) .or. (x%m .ne. 2)) stop 6
+ class default
+ stop 7
+ end select
+ end subroutine
+
+ subroutine check_it (t, errno)
+ type(tContainer) :: t
+ integer :: errno
+ select type (x => t%x)
+ type is (integer)
+ if (x .ne. 42) stop errno
+ type is (integer(8))
+ if (x .ne. 42_8) stop errno
+ type is (real(8))
+ if (int(x**2) .ne. 2) stop errno
+ type is (character(*, kind=1))
+ if (x .ne. "end of tests") stop errno
+ type is (character(*, kind=4))
+ if ((x .ne. 4_"hello!") .and. (x .ne. 4_"goodbye")) stop errno
+ class default
+ stop errno
+ end select
+ end subroutine
+
+ subroutine bar
+ ! Test from comment #29 extended by Harald Anlauf to check kinds /= default
+ integer(8), parameter :: i = 0_8
+ integer :: j = 42
+ character(7,kind=4) :: chr4 = 4_"goodbye"
+ type(tContainer) :: cont
+
+ cont%x = j
+ call check_it (cont, 8)
+
+ cont = tContainer(i+42_8)
+ call check_it (cont, 9)
+
+ cont = tContainer(sqrt (2.0_8))
+ call check_it (cont, 10)
+
+ cont = tContainer(4_"hello!")
+ call check_it (cont, 11)
+
+ cont = tContainer(chr4)
+ call check_it (cont, 12)
+
+ cont = tContainer("end of tests")
+ call check_it (cont, 13)
+
+ end subroutine bar
+end program