From: Mikael Morin <morin-mikael@orange.fr>
To: Harald Anlauf <anlauf@gmx.de>, fortran <fortran@gcc.gnu.org>,
gcc-patches <gcc-patches@gcc.gnu.org>
Subject: Re: [PATCH] Fortran: fixes for procedures with ALLOCATABLE,INTENT(OUT) arguments [PR92178]
Date: Sat, 8 Jul 2023 14:07:08 +0200 [thread overview]
Message-ID: <077e5274-b366-8587-1599-a414e1269862@orange.fr> (raw)
In-Reply-To: <e815fde6-abf7-15c8-153e-a1ffc6f9656d@gmx.de>
[-- Attachment #1: Type: text/plain, Size: 727 bytes --]
Hello,
Le 07/07/2023 à 20:23, Harald Anlauf a écrit :
> Hi Mikael,
>
> Am 07.07.23 um 14:21 schrieb Mikael Morin:
>> I'm attaching what I have (lightly) tested so far, which doesn't work.
>> It seems gfc_conv_class_to_class reevaluates part of the original
>> expression, which is not correct after deallocation.
>
> this looks much more elegant than my attempt that passed an additional
> argument to gfc_conv_class_to_class, to achieve what your patch does.
>
>> Will have a look again tonight.
>
> Great.
>
> Harald
>
here is what I'm finally coming to. This patch fixes my example, but is
otherwise untested.
The patch has grown enough that I'm tempted to fix my example
separately, in its own commit.
Mikael
[-- Attachment #2: pr92178_tmp2.diff --]
[-- Type: text/x-patch, Size: 7052 bytes --]
diff --git a/gcc/fortran/trans-array.cc b/gcc/fortran/trans-array.cc
index e7c51bae052..1c2af55d436 100644
--- a/gcc/fortran/trans-array.cc
+++ b/gcc/fortran/trans-array.cc
@@ -3271,6 +3271,7 @@ gfc_conv_ss_descriptor (stmtblock_t * block, gfc_ss * ss, int base)
gfc_add_block_to_block (block, &se.pre);
info->descriptor = se.expr;
ss_info->string_length = se.string_length;
+ ss_info->class_container = se.class_container;
if (base)
{
@@ -7687,6 +7688,8 @@ gfc_conv_expr_descriptor (gfc_se *se, gfc_expr *expr)
else if (deferred_array_component)
se->string_length = ss_info->string_length;
+ se->class_container = ss_info->class_container;
+
gfc_free_ss_chain (ss);
return;
}
diff --git a/gcc/fortran/trans-expr.cc b/gcc/fortran/trans-expr.cc
index ebef1a36577..01386bceaeb 100644
--- a/gcc/fortran/trans-expr.cc
+++ b/gcc/fortran/trans-expr.cc
@@ -529,24 +529,10 @@ gfc_find_and_cut_at_last_class_ref (gfc_expr *e, bool is_mold,
}
-/* Reset the vptr to the declared type, e.g. after deallocation. */
-
-void
-gfc_reset_vptr (stmtblock_t *block, gfc_expr *e)
+static void
+reset_vptr (stmtblock_t *block, gfc_expr *e, tree class_expr)
{
- gfc_symbol *vtab;
- tree vptr;
- tree vtable;
- gfc_se se;
-
- /* Evaluate the expression and obtain the vptr from it. */
- gfc_init_se (&se, NULL);
- if (e->rank)
- gfc_conv_expr_descriptor (&se, e);
- else
- gfc_conv_expr (&se, e);
- gfc_add_block_to_block (block, &se.pre);
- vptr = gfc_get_vptr_from_expr (se.expr);
+ tree vptr = gfc_get_vptr_from_expr (class_expr);
/* If a vptr is not found, we can do nothing more. */
if (vptr == NULL_TREE)
@@ -556,6 +542,9 @@ gfc_reset_vptr (stmtblock_t *block, gfc_expr *e)
gfc_add_modify (block, vptr, build_int_cst (TREE_TYPE (vptr), 0));
else
{
+ gfc_symbol *vtab;
+ tree vtable;
+
/* Return the vptr to the address of the declared type. */
vtab = gfc_find_derived_vtab (e->ts.u.derived);
vtable = vtab->backend_decl;
@@ -568,6 +557,24 @@ gfc_reset_vptr (stmtblock_t *block, gfc_expr *e)
}
+/* Reset the vptr to the declared type, e.g. after deallocation. */
+
+void
+gfc_reset_vptr (stmtblock_t *block, gfc_expr *e)
+{
+ gfc_se se;
+
+ /* Evaluate the expression and obtain the vptr from it. */
+ gfc_init_se (&se, NULL);
+ if (e->rank)
+ gfc_conv_expr_descriptor (&se, e);
+ else
+ gfc_conv_expr (&se, e);
+ gfc_add_block_to_block (block, &se.pre);
+ reset_vptr (block, e, se.expr);
+}
+
+
/* Reset the len for unlimited polymorphic objects. */
void
@@ -1266,6 +1273,8 @@ gfc_conv_class_to_class (gfc_se *parmse, gfc_expr *e, gfc_typespec class_ts,
slen = build_zero_cst (size_type_node);
}
+ else if (parmse->class_container != NULL_TREE)
+ tmp = parmse->class_container;
else
{
/* Remove everything after the last class reference, convert the
@@ -3078,6 +3087,11 @@ gfc_conv_variable (gfc_se * se, gfc_expr * expr)
return;
}
+ if (sym->ts.type == BT_CLASS
+ && sym->attr.class_ok
+ && sym->ts.u.derived->attr.is_class)
+ se->class_container = se->expr;
+
/* Dereference the expression, where needed. */
se->expr = gfc_maybe_dereference_var (sym, se->expr, se->descriptor_only,
is_classarray);
@@ -3135,6 +3149,15 @@ gfc_conv_variable (gfc_se * se, gfc_expr * expr)
conv_parent_component_references (se, ref);
gfc_conv_component_ref (se, ref);
+
+ if (ref->u.c.component->ts.type == BT_CLASS
+ && ref->u.c.component->attr.class_ok
+ && ref->u.c.component->ts.u.derived->attr.is_class)
+ se->class_container = se->expr;
+ else if (!(ref->u.c.sym->attr.flavor == FL_DERIVED
+ && ref->u.c.sym->attr.is_class))
+ se->class_container = NULL_TREE;
+
if (!ref->next && ref->u.c.sym->attr.codimension
&& se->want_pointer && se->descriptor_only)
return;
@@ -6784,6 +6807,21 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
stmtblock_t block;
tree ptr;
+ /* In case the data reference to deallocate is dependent on
+ its own content, save the resulting pointer to a variable
+ and only use that variable from now on, before the
+ expression becomes invalid. */
+ tree t = gfc_build_addr_expr (NULL_TREE, parmse.expr);
+ t = gfc_evaluate_now (t, &parmse.pre);
+ parmse.expr = build_fold_indirect_ref_loc (input_location, t);
+
+ if (parmse.class_container != NULL_TREE)
+ {
+ t = gfc_build_addr_expr (NULL_TREE, parmse.class_container);
+ t = gfc_evaluate_now (t, &parmse.pre);
+ parmse.class_container = build_fold_indirect_ref_loc (input_location, t);
+ }
+
gfc_init_block (&block);
ptr = parmse.expr;
ptr = gfc_class_data_get (ptr);
@@ -6797,7 +6835,10 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
void_type_node, ptr,
null_pointer_node);
gfc_add_expr_to_block (&block, tmp);
- gfc_reset_vptr (&block, e);
+ if (parmse.class_container == NULL_TREE)
+ gfc_reset_vptr (&block, e);
+ else
+ reset_vptr (&block, e, parmse.class_container);
if (fsym->attr.optional
&& e->expr_type == EXPR_VARIABLE
@@ -6819,9 +6860,13 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
defer_to_dealloc_blk = true;
}
+ gfc_se class_se = parmse;
+ gfc_init_block (&class_se.pre);
+ gfc_init_block (&class_se.post);
+
/* The conversion does not repackage the reference to a class
array - _data descriptor. */
- gfc_conv_class_to_class (&parmse, e, fsym->ts, false,
+ gfc_conv_class_to_class (&class_se, e, fsym->ts, false,
fsym->attr.intent != INTENT_IN
&& (CLASS_DATA (fsym)->attr.class_pointer
|| CLASS_DATA (fsym)->attr.allocatable),
@@ -6831,9 +6876,10 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
CLASS_DATA (fsym)->attr.class_pointer
|| CLASS_DATA (fsym)->attr.allocatable);
- /* Defer repackaging after deallocation. */
- if (defer_to_dealloc_blk)
- gfc_add_block_to_block (&dealloc_blk, &parmse.pre);
+ parmse.expr = class_se.expr;
+ stmtblock_t *class_pre_block = defer_to_dealloc_blk ? &dealloc_blk : &parmse.pre;
+ gfc_add_block_to_block (class_pre_block, &class_se.pre);
+ gfc_add_block_to_block (&parmse.post, &class_se.post);
}
else
{
diff --git a/gcc/fortran/trans.h b/gcc/fortran/trans.h
index 0c8d004736d..9254de733de 100644
--- a/gcc/fortran/trans.h
+++ b/gcc/fortran/trans.h
@@ -57,6 +57,10 @@ typedef struct gfc_se
here. */
tree class_vptr;
+ /* When expr is a reference to class subobject, store the class object
+ here. */
+ tree class_container;
+
/* Whether expr is a reference to an unlimited polymorphic object. */
unsigned unlimited_polymorphic:1;
@@ -263,6 +267,7 @@ typedef struct gfc_ss_info
gfc_ss_type type;
gfc_expr *expr;
tree string_length;
+ tree class_container;
union
{
next prev parent reply other threads:[~2023-07-08 12:07 UTC|newest]
Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-07-02 20:38 Harald Anlauf
2023-07-03 11:46 ` Mikael Morin
2023-07-03 20:49 ` Harald Anlauf
2023-07-03 20:49 ` Harald Anlauf
2023-07-03 23:56 ` Steve Kargl
2023-07-04 9:26 ` Mikael Morin
2023-07-04 15:50 ` Steve Kargl
2023-07-04 13:35 ` Mikael Morin
2023-07-04 19:00 ` Harald Anlauf
2023-07-04 19:00 ` Harald Anlauf
2023-07-04 19:37 ` Mikael Morin
2023-07-05 14:54 ` Mikael Morin
2023-07-05 20:36 ` Harald Anlauf
2023-07-05 20:36 ` Harald Anlauf
2023-07-07 12:21 ` Mikael Morin
2023-07-07 18:23 ` Harald Anlauf
2023-07-07 18:23 ` Harald Anlauf
2023-07-08 12:07 ` Mikael Morin [this message]
2023-07-08 14:20 ` Harald Anlauf
2023-07-08 14:20 ` Harald Anlauf
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=077e5274-b366-8587-1599-a414e1269862@orange.fr \
--to=morin-mikael@orange.fr \
--cc=anlauf@gmx.de \
--cc=fortran@gcc.gnu.org \
--cc=gcc-patches@gcc.gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).