Dear Dominique,
The attached fixes the problem withPR51218 and bootstraps and regtests
on FC23/x86_64 - OK for trunk?
Cheers
Paul
2017-04-13 Paul Thomas <[email protected]>
PR fortran/34640
* expr.c (gfc_check_pointer_assign): Exclude pointer array
components in test for 'subref_array_pointer' attribute.
(gfc_hidden_length_field): New function.
* gfortran.h : Prototype for the above.
* resolve.c (resolve_component): Call the above for deferred
character and pointer array components to provide the hidden
field for the character length or span.
* trans-array.c (gfc_conv_scalarized_array_ref); Use the hidden
span field provided by 'gfc_pointer_array_comp_ref' in the call
to 'gfc_build_array_ref'.
(build_array_ref): Add the new argument 'passed_span' and pass
its to 'gfc_build_array_ref'.
(gfc_conv_array_ref): Same as 'gfc_conv_scalarized_array_ref'.
(gfc_array_allocate): Set the hidden span field if it is passed
by 'gfc_pointer_array_comp_ref'.
(gfc_get_dataptr_offset): Pass a null to the 'passed_span' arg.
trans-expr.c (gfc_trans_pointer_assignment): Obtain the 'span'
for pointer array components and use if applicable.
* trans-io.c (gfc_trans_transfer): Scalarize if this is a
pointer array component, rather than using the library.
trans.c (gfc_build_addr_expr): Use the 'passed_span' arg.
(gfc_pointer_array_comp_ref): New function.
(hidden_length_field): New function.
(gfc_deferred_strlen): Now just calls previous.
(gfc_span_field): New function.
* trans.h : Add prototypes for 'gfc_pointer_array_comp_ref' and
'gfc_span_field'.
2017-04-13 Paul Thomas <[email protected]>
PR fortran/34640
* gfortran.dg/pointer_array_component_1.f90: New test.
* gfortran.dg/pointer_array_component_2.f90: New test.
On 9 April 2017 at 17:14, Dominique d'Humières <[email protected]> wrote:
> The original test in pr51218 is also miscomputed with the patch:
>
> Before t:
>
> Program received signal SIGSEGV: Segmentation fault - invalid memory
> reference.
>
> Dominique
>
>> Le 9 avr. 2017 à 16:41, Dominique d'Humières <[email protected]> a écrit :
>>
>> Dear Paul,
>>
>> Your patch fixes the tests in pr34640 comments 20 and 28 (I didn’t test the
>> variants in comment 27) and in pr57733.
>> The tests in pr34640 in comments 0, 3, and 5, as well in all the other
>> duplicates still fail.
>>
>> Thanks for working on the issue,
>>
>> Dominique
>>
>
--
"If you can't explain it simply, you don't understand it well enough"
- Albert Einstein
Index: gcc/fortran/expr.c
===================================================================
*** gcc/fortran/expr.c (revision 246903)
--- gcc/fortran/expr.c (working copy)
*************** gfc_check_pointer_assign (gfc_expr *lval
*** 3733,3739 ****
return false;
}
! if (rvalue->expr_type == EXPR_VARIABLE && is_subref_array (rvalue))
lvalue->symtree->n.sym->attr.subref_array_pointer = 1;
attr = gfc_expr_attr (rvalue);
--- 3733,3742 ----
return false;
}
! /* Pointer array components are taken care of using the hidden 'span'
! component. */
! if (rvalue->expr_type == EXPR_VARIABLE && is_subref_array (rvalue)
! && lvalue->symtree->n.sym->ts.type != BT_DERIVED)
lvalue->symtree->n.sym->attr.subref_array_pointer = 1;
attr = gfc_expr_attr (rvalue);
*************** gfc_check_vardef_context (gfc_expr* e, b
*** 5504,5506 ****
--- 5507,5530 ----
return true;
}
+
+
+ gfc_component *
+ gfc_hidden_length_field (gfc_symbol *sym, gfc_component *c,
+ bool add_if_missing, const char *postfix)
+ {
+ char name[GFC_MAX_SYMBOL_LEN+9];
+ gfc_component *strlen;
+ sprintf (name, "_%s_%s", c->name, postfix);
+ strlen = gfc_find_component (sym, name, true, true, NULL);
+ if (strlen == NULL && add_if_missing)
+ {
+ if (!gfc_add_component (sym, name, &strlen))
+ return NULL;
+ strlen->ts.type = BT_INTEGER;
+ strlen->ts.kind = gfc_charlen_int_kind;
+ strlen->attr.access = ACCESS_PRIVATE;
+ strlen->attr.artificial = 1;
+ }
+ return strlen;
+ }
Index: gcc/fortran/gfortran.h
===================================================================
*** gcc/fortran/gfortran.h (revision 246903)
--- gcc/fortran/gfortran.h (working copy)
*************** gfc_expr* gfc_find_stat_co (gfc_expr *);
*** 3157,3162 ****
--- 3157,3164 ----
gfc_expr* gfc_build_intrinsic_call (gfc_namespace *, gfc_isym_id, const char*,
locus, unsigned, ...);
bool gfc_check_vardef_context (gfc_expr*, bool, bool, bool, const char*);
+ gfc_component* gfc_hidden_length_field (gfc_symbol *, gfc_component *,
+ bool, const char *);
/* st.c */
Index: gcc/fortran/resolve.c
===================================================================
*** gcc/fortran/resolve.c (revision 246903)
--- gcc/fortran/resolve.c (working copy)
*************** resolve_component (gfc_component *c, gfc
*** 13551,13571 ****
/* Add the hidden deferred length field. */
if (c->ts.type == BT_CHARACTER && c->ts.deferred && !c->attr.function
! && !sym->attr.is_class)
{
! char name[GFC_MAX_SYMBOL_LEN+9];
! gfc_component *strlen;
! sprintf (name, "_%s_length", c->name);
! strlen = gfc_find_component (sym, name, true, true, NULL);
! if (strlen == NULL)
! {
! if (!gfc_add_component (sym, name, &strlen))
! return false;
! strlen->ts.type = BT_INTEGER;
! strlen->ts.kind = gfc_charlen_int_kind;
! strlen->attr.access = ACCESS_PRIVATE;
! strlen->attr.artificial = 1;
! }
}
if (c->ts.type == BT_DERIVED
--- 13551,13567 ----
/* Add the hidden deferred length field. */
if (c->ts.type == BT_CHARACTER && c->ts.deferred && !c->attr.function
! && !sym->attr.is_class)
{
! if (gfc_hidden_length_field (sym, c, true, "length") == NULL)
! return false;
! }
!
! /* Add the hidden pointer array span field. */
! if (c->attr.pointer && c->attr.dimension && !sym->attr.is_class)
! {
! if (gfc_hidden_length_field (sym, c, true, "span") == NULL)
! return false;
}
if (c->ts.type == BT_DERIVED
Index: gcc/fortran/trans-array.c
===================================================================
*** gcc/fortran/trans-array.c (revision 246903)
--- gcc/fortran/trans-array.c (working copy)
*************** gfc_conv_scalarized_array_ref (gfc_se *
*** 3218,3223 ****
--- 3218,3224 ----
{
gfc_array_info *info;
tree decl = NULL_TREE;
+ tree passed_span = NULL_TREE;
tree index;
tree tmp;
gfc_ss *ss;
*************** gfc_conv_scalarized_array_ref (gfc_se *
*** 3244,3249 ****
--- 3245,3262 ----
|| expr->expr_type == EXPR_FUNCTION))))
decl = expr->symtree->n.sym->backend_decl;
+ /* Use the hidden 'span' field to address the elements of a pointer
+ array component. */
+ if (info->descriptor != NULL_TREE
+ && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (info->descriptor))
+ && expr && gfc_pointer_array_comp_ref (expr, ar ? ar->as : NULL,
&passed_span))
+ {
+ tmp = TREE_OPERAND (info->descriptor, 0);
+ passed_span = fold_build3_loc (input_location, COMPONENT_REF,
+ TREE_TYPE (passed_span), tmp,
+ passed_span, NULL_TREE);
+ }
+
tmp = build_fold_indirect_ref_loc (input_location, info->data);
/* Use the vptr 'size' field to access a class the element of a class
*************** gfc_conv_scalarized_array_ref (gfc_se *
*** 3251,3257 ****
if (build_class_array_ref (se, tmp, index))
return;
! se->expr = gfc_build_array_ref (tmp, index, decl);
}
--- 3264,3270 ----
if (build_class_array_ref (se, tmp, index))
return;
! se->expr = gfc_build_array_ref (tmp, index, decl, NULL, passed_span);
}
*************** add_to_offset (tree *cst_offset, tree *o
*** 3284,3290 ****
static tree
! build_array_ref (tree desc, tree offset, tree decl, tree vptr)
{
tree tmp;
tree type;
--- 3297,3304 ----
static tree
! build_array_ref (tree desc, tree offset, tree decl, tree vptr,
! tree passed_span)
{
tree tmp;
tree type;
*************** build_array_ref (tree desc, tree offset,
*** 3331,3337 ****
tmp = gfc_conv_array_data (desc);
tmp = build_fold_indirect_ref_loc (input_location, tmp);
! tmp = gfc_build_array_ref (tmp, offset, decl, vptr);
return tmp;
}
--- 3345,3351 ----
tmp = gfc_conv_array_data (desc);
tmp = build_fold_indirect_ref_loc (input_location, tmp);
! tmp = gfc_build_array_ref (tmp, offset, decl, vptr, passed_span);
return tmp;
}
*************** gfc_conv_array_ref (gfc_se * se, gfc_arr
*** 3350,3355 ****
--- 3364,3370 ----
tree offset, cst_offset;
tree tmp;
tree stride;
+ tree passed_span = NULL_TREE;
gfc_se indexse;
gfc_se tmpse;
gfc_symbol * sym = expr->symtree->n.sym;
*************** gfc_conv_array_ref (gfc_se * se, gfc_arr
*** 3494,3501 ****
offset = fold_build2_loc (input_location, PLUS_EXPR,
gfc_array_index_type, offset, cst_offset);
se->expr = build_array_ref (se->expr, offset, sym->ts.type == BT_CLASS ?
! NULL_TREE : sym->backend_decl, se->class_vptr);
}
--- 3509,3533 ----
offset = fold_build2_loc (input_location, PLUS_EXPR,
gfc_array_index_type, offset, cst_offset);
+ /* Use the hidden 'span' field to address the elements of a pointer
+ array component. */
+ if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (se->expr))
+ && expr && gfc_pointer_array_comp_ref (expr, ar ? ar->as : NULL,
&passed_span))
+ {
+ if (TREE_CODE (se->expr) != VAR_DECL)
+ {
+ tmp = TREE_OPERAND (se->expr, 0);
+ passed_span = fold_build3_loc (input_location, COMPONENT_REF,
+ TREE_TYPE (passed_span), tmp,
+ passed_span, NULL_TREE);
+ }
+ else
+ passed_span = NULL_TREE;
+ }
+
se->expr = build_array_ref (se->expr, offset, sym->ts.type == BT_CLASS ?
! NULL_TREE : sym->backend_decl, se->class_vptr,
! passed_span);
}
*************** gfc_array_allocate (gfc_se * se, gfc_exp
*** 5464,5469 ****
--- 5496,5502 ----
tree var_overflow = NULL_TREE;
tree cond;
tree set_descriptor;
+ tree span;
stmtblock_t set_descriptor_block;
stmtblock_t elseblock;
gfc_expr **lower;
*************** gfc_array_allocate (gfc_se * se, gfc_exp
*** 5471,5476 ****
--- 5504,5510 ----
gfc_ref *ref, *prev_ref = NULL, *coref;
bool allocatable, coarray, dimension, alloc_w_e3_arr_spec = false,
non_ulimate_coarray_ptr_comp;
+ bool is_pointer_array_comp_ref;
ref = expr->ref;
*************** gfc_array_allocate (gfc_se * se, gfc_exp
*** 5478,5483 ****
--- 5512,5520 ----
if (!retrieve_last_ref (&ref, &prev_ref))
return false;
+ is_pointer_array_comp_ref = gfc_pointer_array_comp_ref (expr, ref->u.ar.as,
+ &span);
+
/* Take the allocatable and coarray properties solely from the expr-ref's
attributes and not from source=-expression. */
if (!prev_ref)
*************** gfc_array_allocate (gfc_se * se, gfc_exp
*** 5648,5654 ****
--- 5685,5708 ----
if (dimension)
gfc_conv_descriptor_offset_set (&set_descriptor_block, se->expr, offset);
+ /* Set the hidden 'span' field used to address the elements of a pointer
+ array component. */
+ if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (se->expr))
+ && is_pointer_array_comp_ref
+ && TREE_CODE (se->expr) != VAR_DECL)
+ {
+ tmp = se->expr;
+ tmp = TREE_OPERAND (tmp, 0);
+ span = fold_build3_loc (input_location, COMPONENT_REF,
+ TREE_TYPE (span), tmp,
+ span, NULL_TREE);
+ tmp = TYPE_SIZE_UNIT (gfc_get_element_type (TREE_TYPE (se->expr)));
+ gfc_add_modify (&set_descriptor_block, span,
+ fold_convert (TREE_TYPE (span), tmp));
+ }
+
set_descriptor = gfc_finish_block (&set_descriptor_block);
+
if (status != NULL_TREE)
{
cond = fold_build2_loc (input_location, EQ_EXPR,
*************** gfc_get_dataptr_offset (stmtblock_t *blo
*** 6492,6498 ****
return;
}
! tmp = build_array_ref (desc, offset, NULL, NULL);
/* Offset the data pointer for pointer assignments from arrays with
subreferences; e.g. my_integer => my_type(:)%integer_component. */
--- 6546,6552 ----
return;
}
! tmp = build_array_ref (desc, offset, NULL, NULL, NULL);
/* Offset the data pointer for pointer assignments from arrays with
subreferences; e.g. my_integer => my_type(:)%integer_component. */
Index: gcc/fortran/trans-expr.c
===================================================================
*** gcc/fortran/trans-expr.c (revision 246903)
--- gcc/fortran/trans-expr.c (working copy)
*************** gfc_trans_pointer_assignment (gfc_expr *
*** 8395,8411 ****
}
else if (expr2->expr_type == EXPR_VARIABLE)
{
/* Assign directly to the LHS's descriptor. */
lse.descriptor_only = 0;
lse.direct_byref = 1;
gfc_conv_expr_descriptor (&lse, expr2);
strlen_rhs = lse.string_length;
! /* If this is a subreference array pointer assignment, use the rhs
! descriptor element size for the lhs span. */
! if (expr1->symtree->n.sym->attr.subref_array_pointer)
{
- decl = expr1->symtree->n.sym->backend_decl;
gfc_init_se (&rse, NULL);
rse.descriptor_only = 1;
gfc_conv_expr (&rse, expr2);
--- 8395,8413 ----
}
else if (expr2->expr_type == EXPR_VARIABLE)
{
+ tree span = NULL_TREE;
+
/* Assign directly to the LHS's descriptor. */
lse.descriptor_only = 0;
lse.direct_byref = 1;
gfc_conv_expr_descriptor (&lse, expr2);
strlen_rhs = lse.string_length;
! /* If this is a subreference array or component pointer assignment,
! use the rhs descriptor element size for the lhs span. */
! if (expr1->symtree->n.sym->attr.subref_array_pointer
! || gfc_pointer_array_comp_ref (expr1, NULL, &span))
{
gfc_init_se (&rse, NULL);
rse.descriptor_only = 1;
gfc_conv_expr (&rse, expr2);
*************** gfc_trans_pointer_assignment (gfc_expr *
*** 8413,8422 ****
trans_class_vptr_len_assignment (&block, expr1, expr2, &rse,
NULL, NULL);
tmp = gfc_get_element_type (TREE_TYPE (rse.expr));
- tmp = fold_convert (gfc_array_index_type, size_in_bytes (tmp));
if (!INTEGER_CST_P (tmp))
gfc_add_block_to_block (&lse.post, &rse.pre);
! gfc_add_modify (&lse.post, GFC_DECL_SPAN(decl), tmp);
}
else if (expr1->ts.type == BT_CLASS)
{
--- 8415,8439 ----
trans_class_vptr_len_assignment (&block, expr1, expr2, &rse,
NULL, NULL);
tmp = gfc_get_element_type (TREE_TYPE (rse.expr));
if (!INTEGER_CST_P (tmp))
gfc_add_block_to_block (&lse.post, &rse.pre);
! if (span != NULL_TREE)
! {
! decl = TREE_OPERAND (lse.expr, 0);
! span = fold_build3_loc (input_location, COMPONENT_REF,
! TREE_TYPE (span), decl, span,
! NULL_TREE);
! tmp = fold_convert (TREE_TYPE (span),
! size_in_bytes (tmp));
! gfc_add_modify (&lse.post, span, tmp);
! }
! else
! {
! decl = expr1->symtree->n.sym->backend_decl;
! tmp = fold_convert (gfc_array_index_type,
! size_in_bytes (tmp));
! gfc_add_modify (&lse.post, GFC_DECL_SPAN(decl), tmp);
! }
}
else if (expr1->ts.type == BT_CLASS)
{
Index: gcc/fortran/trans-io.c
===================================================================
*** gcc/fortran/trans-io.c (revision 246903)
--- gcc/fortran/trans-io.c (working copy)
*************** gfc_trans_transfer (gfc_code * code)
*** 2555,2561 ****
if (!(gfc_bt_struct (expr->ts.type)
|| expr->ts.type == BT_CLASS)
&& ref && ref->next == NULL
! && !is_subref_array (expr))
{
bool seen_vector = false;
--- 2555,2562 ----
if (!(gfc_bt_struct (expr->ts.type)
|| expr->ts.type == BT_CLASS)
&& ref && ref->next == NULL
! && !is_subref_array (expr)
! && !gfc_pointer_array_comp_ref (expr, NULL, &tmp))
{
bool seen_vector = false;
Index: gcc/fortran/trans.c
===================================================================
*** gcc/fortran/trans.c (revision 246903)
--- gcc/fortran/trans.c (working copy)
*************** gfc_build_addr_expr (tree type, tree t)
*** 308,314 ****
/* Build an ARRAY_REF with its natural type. */
tree
! gfc_build_array_ref (tree base, tree offset, tree decl, tree vptr)
{
tree type = TREE_TYPE (base);
tree tmp;
--- 308,315 ----
/* Build an ARRAY_REF with its natural type. */
tree
! gfc_build_array_ref (tree base, tree offset, tree decl, tree vptr,
! tree passed_span)
{
tree type = TREE_TYPE (base);
tree tmp;
*************** gfc_build_array_ref (tree base, tree off
*** 343,348 ****
--- 344,351 ----
|| DECL_CONTEXT (TYPE_MAXVAL (TYPE_DOMAIN (type)))
== DECL_CONTEXT (decl)))
span = TYPE_MAXVAL (TYPE_DOMAIN (type));
+ else if (decl != NULL_TREE && passed_span != NULL_TREE)
+ span = passed_span;
else
span = NULL_TREE;
*************** gfc_build_array_ref (tree base, tree off
*** 362,368 ****
&& !integer_zerop (GFC_DECL_SPAN (decl)))
|| GFC_DECL_CLASS (decl)
|| span != NULL_TREE))
! || vptr != NULL_TREE)
{
if (decl)
{
--- 365,372 ----
&& !integer_zerop (GFC_DECL_SPAN (decl)))
|| GFC_DECL_CLASS (decl)
|| span != NULL_TREE))
! || vptr != NULL_TREE
! || passed_span != NULL_TREE)
{
if (decl)
{
*************** gfc_build_array_ref (tree base, tree off
*** 399,404 ****
--- 403,410 ----
}
else if (vptr)
span = gfc_vptr_size_get (vptr);
+ else if (passed_span)
+ span = fold_convert (gfc_array_index_type, passed_span);
else
gcc_unreachable ();
*************** gfc_likely (tree cond, enum br_predictor
*** 2295,2313 ****
}
! /* Get the string length for a deferred character length component. */
bool
! gfc_deferred_strlen (gfc_component *c, tree *decl)
{
! char name[GFC_MAX_SYMBOL_LEN+9];
! gfc_component *strlen;
! if (!(c->ts.type == BT_CHARACTER && c->ts.deferred))
return false;
! sprintf (name, "_%s_length", c->name);
! for (strlen = c; strlen; strlen = strlen->next)
! if (strcmp (strlen->name, name) == 0)
! break;
! *decl = strlen ? strlen->backend_decl : NULL_TREE;
return strlen != NULL;
}
--- 2301,2365 ----
}
! /* Returns true if the expression is a reference to a pointer array
! component. The second argument is the backend decl for the hidden
! span component. */
bool
! gfc_pointer_array_comp_ref (gfc_expr *e, gfc_array_spec *as, tree *decl)
{
! gfc_ref *ref;
!
! if (e->expr_type != EXPR_VARIABLE)
return false;
!
! if (e->symtree->n.sym->ts.type != BT_DERIVED)
! return false;
!
! for (ref = e->ref; ref; ref = ref->next)
! {
! if (ref->type == REF_COMPONENT
! && ref->u.c.component->attr.pointer
! && ref->u.c.component->attr.dimension
! && (ref->u.c.component->as == as
! || as == NULL)
! && gfc_span_field (ref->u.c.component, decl))
! return true;
! }
!
! return false;
! }
!
!
! /* Get the string length for a deferred character length component and
! the span of a pointer array component. */
!
! static bool
! hidden_length_field (gfc_component *c, tree *decl, const char *postfix)
! {
! char name[GFC_MAX_SYMBOL_LEN+9];
! gfc_component *strlen = NULL;
! if ((c->ts.type == BT_CHARACTER && c->ts.deferred)
! || (c->attr.pointer && c->attr.dimension))
! {
! sprintf (name, "_%s_%s", c->name, postfix);
! for (strlen = c; strlen; strlen = strlen->next)
! if (strcmp (strlen->name, name) == 0)
! break;
! *decl = strlen ? strlen->backend_decl : NULL_TREE;
! }
return strlen != NULL;
}
+
+ bool
+ gfc_deferred_strlen (gfc_component *c, tree *decl)
+ {
+ return hidden_length_field (c, decl, "length");
+ }
+
+ bool
+ gfc_span_field (gfc_component *c, tree *decl)
+ {
+ return hidden_length_field (c, decl, "span");
+ }
+
Index: gcc/fortran/trans.h
===================================================================
*** gcc/fortran/trans.h (revision 246903)
--- gcc/fortran/trans.h (working copy)
*************** tree gfc_get_function_decl (gfc_symbol *
*** 587,593 ****
tree gfc_build_addr_expr (tree, tree);
/* Build an ARRAY_REF. */
! tree gfc_build_array_ref (tree, tree, tree, tree vptr = NULL_TREE);
/* Creates a label. Decl is artificial if label_id == NULL_TREE. */
tree gfc_build_label_decl (tree);
--- 587,594 ----
tree gfc_build_addr_expr (tree, tree);
/* Build an ARRAY_REF. */
! tree gfc_build_array_ref (tree, tree, tree, tree vptr = NULL_TREE,
! tree passed_span = NULL_TREE);
/* Creates a label. Decl is artificial if label_id == NULL_TREE. */
tree gfc_build_label_decl (tree);
*************** bool get_array_ctor_strlen (stmtblock_t
*** 683,691 ****
--- 684,699 ----
tree gfc_likely (tree, enum br_predictor);
tree gfc_unlikely (tree, enum br_predictor);
+ /* Return the backend decl for the hidden span and true if this is a
+ pointer array component. */
+ bool gfc_pointer_array_comp_ref (gfc_expr *, gfc_array_spec *, tree *);
+
/* Return the string length of a deferred character length component. */
bool gfc_deferred_strlen (gfc_component *, tree *);
+ /* Return the span of a pointer array component. */
+ bool gfc_span_field (gfc_component *, tree *);
+
/* Generate a runtime error call. */
tree gfc_trans_runtime_error (bool, locus*, const char*, ...);
Index: gcc/testsuite/gfortran.dg/pointer_array_component_1.f90
===================================================================
*** gcc/testsuite/gfortran.dg/pointer_array_component_1.f90 (nonexistent)
--- gcc/testsuite/gfortran.dg/pointer_array_component_1.f90 (working copy)
***************
*** 0 ****
--- 1,47 ----
+ ! { dg-do run }
+ !
+ ! Check the fix for PR34640 comment 28.
+ !
+ ! This involves pointer array components that point to components of arrays
+ ! of derived types.
+ !
+ type var_tables
+ real, pointer :: rvar(:)
+ end type
+
+ type real_vars
+ real r
+ real :: index
+ end type
+
+ type(var_tables) :: vtab_r
+ type(real_vars), target :: x(2)
+ real, pointer :: z(:)
+ real :: y(2)
+
+ x = [real_vars (11.0, 1.0), real_vars (42.0, 2.0)]
+ vtab_r%rvar => x%r
+ if (any (abs (vtab_r%rvar - [11.0, 42.0]) > 1.0e-5)) call abort ! Check
skipping 'index; is OK.
+
+ y = vtab_r%rvar
+ if (any (abs (y - [11.0, 42.0]) > 1.0e-5)) call abort ! Check that the
component is usable in assignment.
+
+ call foobar (vtab_r, [11.0, 42.0])
+
+ vtab_r = barfoo ()
+
+ call foobar (vtab_r, [111.0, 142.0])
+
+ contains
+ subroutine foobar (vtab, array)
+ type(var_tables) :: vtab
+ real :: array (:)
+ if (any (abs (vtab%rvar - array) > 1.0e-5)) call abort ! Check passing
as a dummy.
+ if (abs (vtab%rvar(2) - array(2)) > 1.0e-5) call abort ! Check component
reference.
+ end subroutine
+
+ function barfoo () result(res)
+ type(var_tables) :: res
+ allocate (res%rvar(2), source = [111.0, 142.0]) ! Check allocation
+ end function
+ end
Index: gcc/testsuite/gfortran.dg/pointer_array_component_2.f90
===================================================================
*** gcc/testsuite/gfortran.dg/pointer_array_component_2.f90 (nonexistent)
--- gcc/testsuite/gfortran.dg/pointer_array_component_2.f90 (working copy)
***************
*** 0 ****
--- 1,43 ----
+ ! { dg-do run }
+ !
+ ! Test the fix for PR34640. In the first version of the fix, the first
+ ! testcase in PR51218 failed with a segfault. This test extracts the
+ ! failing part and checks that all is well.
+ !
+ type t_info_block
+ integer :: n = 0 ! number of elements
+ end type t_info_block
+ !
+ type t_dec_info
+ integer :: n = 0 ! number of elements
+ integer :: n_b = 0 ! number of blocks
+ type (t_info_block) ,pointer :: b (:) => NULL() ! info blocks
+ end type t_dec_info
+ !
+ type t_vector_segm
+ integer :: n = 0 ! number of elements
+ real ,pointer :: x(:) => NULL() ! coefficients
+ end type t_vector_segm
+ !
+ type t_vector
+ type (t_dec_info) ,pointer :: info => NULL() ! decomposition info
+ integer :: n = 0 ! number of elements
+ integer :: n_s = 0 ! number of segments
+ integer :: alloc_l = 0 ! allocation level
+ type (t_vector_segm) ,pointer :: s (:) => NULL() ! vector blocks
+ end type t_vector
+
+
+ type(t_vector) :: z
+ type(t_vector_segm), pointer :: ss
+
+ allocate (z%s(2))
+ do i = 1, 2
+ ss => z%s(i)
+ allocate (ss%x(2), source = [1.0, 2.0]*real(i))
+ end do
+
+ ! These lines would segfault.
+ if (int (sum (z%s(1)%x)) .ne. 3) call abort
+ if (int (sum (z%s(1)%x * z%s(2)%x)) .ne. 10) call abort
+ end