[gcc r15-1704] Add gfc_class_set_vptr.
Andre Vehreschild
vehre@gcc.gnu.org
Fri Jun 28 09:09:39 GMT 2024
https://gcc.gnu.org/g:aa3599a10cab34104c0b9bd6951c5f0c420795d8
commit r15-1704-gaa3599a10cab34104c0b9bd6951c5f0c420795d8
Author: Andre Vehreschild <vehre@gcc.gnu.org>
Date: Tue Jun 11 12:52:26 2024 +0200
Add gfc_class_set_vptr.
First step to adding a general assign all class type's data members
routine. Having a general routine prevents forgetting to tackle the
edge cases, e.g. setting _len.
gcc/fortran/ChangeLog:
* trans-expr.cc (gfc_class_set_vptr): Add setting of _vptr
member.
* trans-intrinsic.cc (conv_intrinsic_move_alloc): First use
of gfc_class_set_vptr and refactor very similar code.
* trans.h (gfc_class_set_vptr): Declare the new function.
gcc/testsuite/ChangeLog:
* gfortran.dg/unlimited_polymorphic_11.f90: Remove unnecessary
casts in gd-final expression.
Diff:
---
gcc/fortran/trans-expr.cc | 48 +++++
gcc/fortran/trans-intrinsic.cc | 203 ++++++---------------
gcc/fortran/trans.h | 6 +-
.../gfortran.dg/unlimited_polymorphic_11.f90 | 2 +-
4 files changed, 111 insertions(+), 148 deletions(-)
diff --git a/gcc/fortran/trans-expr.cc b/gcc/fortran/trans-expr.cc
index 454b87581f5..477c2720187 100644
--- a/gcc/fortran/trans-expr.cc
+++ b/gcc/fortran/trans-expr.cc
@@ -599,6 +599,54 @@ gfc_reset_vptr (stmtblock_t *block, gfc_expr *e, tree class_container,
}
+/* Set the vptr of a class in to from the type given in from. If from is NULL,
+ then reset the vptr to the default or to. */
+
+void
+gfc_class_set_vptr (stmtblock_t *block, tree to, tree from)
+{
+ tree tmp, vptr_ref;
+
+ vptr_ref = gfc_get_vptr_from_expr (to);
+ if (POINTER_TYPE_P (TREE_TYPE (from))
+ && GFC_CLASS_TYPE_P (TREE_TYPE (TREE_TYPE (from))))
+ {
+ gfc_add_modify (block, vptr_ref,
+ fold_convert (TREE_TYPE (vptr_ref),
+ gfc_get_vptr_from_expr (from)));
+ }
+ else if (VAR_P (from)
+ && strncmp (IDENTIFIER_POINTER (DECL_NAME (from)), "__vtab", 6) == 0)
+ {
+ gfc_add_modify (block, vptr_ref,
+ gfc_build_addr_expr (TREE_TYPE (vptr_ref), from));
+ }
+ else if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (TREE_TYPE (from)))
+ && GFC_CLASS_TYPE_P (
+ TREE_TYPE (TREE_OPERAND (TREE_OPERAND (from, 0), 0))))
+ {
+ gfc_add_modify (block, vptr_ref,
+ fold_convert (TREE_TYPE (vptr_ref),
+ gfc_get_vptr_from_expr (TREE_OPERAND (
+ TREE_OPERAND (from, 0), 0))));
+ }
+ else
+ {
+ tree vtab;
+ gfc_symbol *type;
+ tmp = TREE_TYPE (from);
+ if (POINTER_TYPE_P (tmp))
+ tmp = TREE_TYPE (tmp);
+ gfc_find_symbol (IDENTIFIER_POINTER (TYPE_NAME (tmp)), gfc_current_ns, 1,
+ &type);
+ vtab = gfc_find_derived_vtab (type)->backend_decl;
+ gcc_assert (vtab);
+ gfc_add_modify (block, vptr_ref,
+ gfc_build_addr_expr (TREE_TYPE (vptr_ref), vtab));
+ }
+}
+
+
/* Reset the len for unlimited polymorphic objects. */
void
diff --git a/gcc/fortran/trans-intrinsic.cc b/gcc/fortran/trans-intrinsic.cc
index ac7fcd250d3..5ea10e84060 100644
--- a/gcc/fortran/trans-intrinsic.cc
+++ b/gcc/fortran/trans-intrinsic.cc
@@ -12667,10 +12667,9 @@ conv_intrinsic_move_alloc (gfc_code *code)
{
stmtblock_t block;
gfc_expr *from_expr, *to_expr;
- gfc_expr *to_expr2, *from_expr2 = NULL;
gfc_se from_se, to_se;
- tree tmp;
- bool coarray;
+ tree tmp, to_tree, from_tree;
+ bool coarray, from_is_class, from_is_scalar;
gfc_start_block (&block);
@@ -12680,178 +12679,94 @@ conv_intrinsic_move_alloc (gfc_code *code)
gfc_init_se (&from_se, NULL);
gfc_init_se (&to_se, NULL);
- gcc_assert (from_expr->ts.type != BT_CLASS
- || to_expr->ts.type == BT_CLASS);
+ gcc_assert (from_expr->ts.type != BT_CLASS || to_expr->ts.type == BT_CLASS);
coarray = gfc_get_corank (from_expr) != 0;
- if (from_expr->rank == 0 && !coarray)
+ from_is_class = from_expr->ts.type == BT_CLASS;
+ from_is_scalar = from_expr->rank == 0 && !coarray;
+ if (to_expr->ts.type == BT_CLASS || from_is_scalar)
{
- if (from_expr->ts.type != BT_CLASS)
- from_expr2 = from_expr;
+ from_se.want_pointer = 1;
+ if (from_is_scalar)
+ gfc_conv_expr (&from_se, from_expr);
else
- {
- from_expr2 = gfc_copy_expr (from_expr);
- gfc_add_data_component (from_expr2);
- }
-
- if (to_expr->ts.type != BT_CLASS)
- to_expr2 = to_expr;
+ gfc_conv_expr_descriptor (&from_se, from_expr);
+ if (from_is_class)
+ from_tree = gfc_class_data_get (from_se.expr);
else
{
- to_expr2 = gfc_copy_expr (to_expr);
- gfc_add_data_component (to_expr2);
+ gfc_symbol *vtab;
+ from_tree = from_se.expr;
+
+ vtab = gfc_find_vtab (&from_expr->ts);
+ gcc_assert (vtab);
+ from_se.expr = gfc_get_symbol_decl (vtab);
}
+ gfc_add_block_to_block (&block, &from_se.pre);
- from_se.want_pointer = 1;
to_se.want_pointer = 1;
- gfc_conv_expr (&from_se, from_expr2);
- gfc_conv_expr (&to_se, to_expr2);
- gfc_add_block_to_block (&block, &from_se.pre);
+ if (to_expr->rank == 0)
+ gfc_conv_expr (&to_se, to_expr);
+ else
+ gfc_conv_expr_descriptor (&to_se, to_expr);
+ if (to_expr->ts.type == BT_CLASS)
+ to_tree = gfc_class_data_get (to_se.expr);
+ else
+ to_tree = to_se.expr;
gfc_add_block_to_block (&block, &to_se.pre);
/* Deallocate "to". */
- tmp = gfc_deallocate_scalar_with_status (to_se.expr, NULL_TREE, NULL_TREE,
- true, to_expr, to_expr->ts);
- gfc_add_expr_to_block (&block, tmp);
+ if (to_expr->rank == 0)
+ {
+ tmp
+ = gfc_deallocate_scalar_with_status (to_tree, NULL_TREE, NULL_TREE,
+ true, to_expr, to_expr->ts);
+ gfc_add_expr_to_block (&block, tmp);
+ }
- /* Assign (_data) pointers. */
- gfc_add_modify_loc (input_location, &block, to_se.expr,
- fold_convert (TREE_TYPE (to_se.expr), from_se.expr));
+ if (from_is_scalar)
+ {
+ /* Assign (_data) pointers. */
+ gfc_add_modify_loc (input_location, &block, to_tree,
+ fold_convert (TREE_TYPE (to_tree), from_tree));
- /* Set "from" to NULL. */
- gfc_add_modify_loc (input_location, &block, from_se.expr,
- fold_convert (TREE_TYPE (from_se.expr), null_pointer_node));
+ /* Set "from" to NULL. */
+ gfc_add_modify_loc (input_location, &block, from_tree,
+ fold_convert (TREE_TYPE (from_tree),
+ null_pointer_node));
- gfc_add_block_to_block (&block, &from_se.post);
+ gfc_add_block_to_block (&block, &from_se.post);
+ }
gfc_add_block_to_block (&block, &to_se.post);
/* Set _vptr. */
if (to_expr->ts.type == BT_CLASS)
{
- gfc_symbol *vtab;
-
- gfc_free_expr (to_expr2);
- gfc_init_se (&to_se, NULL);
- to_se.want_pointer = 1;
- gfc_add_vptr_component (to_expr);
- gfc_conv_expr (&to_se, to_expr);
-
- if (from_expr->ts.type == BT_CLASS)
- {
- if (UNLIMITED_POLY (from_expr))
- vtab = NULL;
- else
- {
- vtab = gfc_find_derived_vtab (from_expr->ts.u.derived);
- gcc_assert (vtab);
- }
-
- gfc_free_expr (from_expr2);
- gfc_init_se (&from_se, NULL);
- from_se.want_pointer = 1;
- gfc_add_vptr_component (from_expr);
- gfc_conv_expr (&from_se, from_expr);
- gfc_add_modify_loc (input_location, &block, to_se.expr,
- fold_convert (TREE_TYPE (to_se.expr),
- from_se.expr));
-
- /* Reset _vptr component to declared type. */
- if (vtab == NULL)
- /* Unlimited polymorphic. */
- gfc_add_modify_loc (input_location, &block, from_se.expr,
- fold_convert (TREE_TYPE (from_se.expr),
- null_pointer_node));
- else
- {
- tmp = gfc_build_addr_expr (NULL_TREE, gfc_get_symbol_decl (vtab));
- gfc_add_modify_loc (input_location, &block, from_se.expr,
- fold_convert (TREE_TYPE (from_se.expr), tmp));
- }
- }
- else
- {
- vtab = gfc_find_vtab (&from_expr->ts);
- gcc_assert (vtab);
- tmp = gfc_build_addr_expr (NULL_TREE, gfc_get_symbol_decl (vtab));
- gfc_add_modify_loc (input_location, &block, to_se.expr,
- fold_convert (TREE_TYPE (to_se.expr), tmp));
- }
- }
-
- if (to_expr->ts.type == BT_CHARACTER && to_expr->ts.deferred)
- {
- gfc_add_modify_loc (input_location, &block, to_se.string_length,
- fold_convert (TREE_TYPE (to_se.string_length),
- from_se.string_length));
- if (from_expr->ts.deferred)
- gfc_add_modify_loc (input_location, &block, from_se.string_length,
- build_int_cst (TREE_TYPE (from_se.string_length), 0));
+ gfc_class_set_vptr (&block, to_se.expr, from_se.expr);
+ if (from_is_class)
+ gfc_reset_vptr (&block, from_expr);
}
- return gfc_finish_block (&block);
- }
-
- /* Update _vptr component. */
- if (to_expr->ts.type == BT_CLASS)
- {
- gfc_symbol *vtab;
-
- to_se.want_pointer = 1;
- to_expr2 = gfc_copy_expr (to_expr);
- gfc_add_vptr_component (to_expr2);
- gfc_conv_expr (&to_se, to_expr2);
-
- if (from_expr->ts.type == BT_CLASS)
+ if (from_is_scalar)
{
- if (UNLIMITED_POLY (from_expr))
- vtab = NULL;
- else
+ if (to_expr->ts.type == BT_CHARACTER && to_expr->ts.deferred)
{
- vtab = gfc_find_derived_vtab (from_expr->ts.u.derived);
- gcc_assert (vtab);
+ gfc_add_modify_loc (input_location, &block, to_se.string_length,
+ fold_convert (TREE_TYPE (to_se.string_length),
+ from_se.string_length));
+ if (from_expr->ts.deferred)
+ gfc_add_modify_loc (
+ input_location, &block, from_se.string_length,
+ build_int_cst (TREE_TYPE (from_se.string_length), 0));
}
- from_se.want_pointer = 1;
- from_expr2 = gfc_copy_expr (from_expr);
- gfc_add_vptr_component (from_expr2);
- gfc_conv_expr (&from_se, from_expr2);
- gfc_add_modify_loc (input_location, &block, to_se.expr,
- fold_convert (TREE_TYPE (to_se.expr),
- from_se.expr));
-
- /* Reset _vptr component to declared type. */
- if (vtab == NULL)
- /* Unlimited polymorphic. */
- gfc_add_modify_loc (input_location, &block, from_se.expr,
- fold_convert (TREE_TYPE (from_se.expr),
- null_pointer_node));
- else
- {
- tmp = gfc_build_addr_expr (NULL_TREE, gfc_get_symbol_decl (vtab));
- gfc_add_modify_loc (input_location, &block, from_se.expr,
- fold_convert (TREE_TYPE (from_se.expr), tmp));
- }
- }
- else
- {
- vtab = gfc_find_vtab (&from_expr->ts);
- gcc_assert (vtab);
- tmp = gfc_build_addr_expr (NULL_TREE, gfc_get_symbol_decl (vtab));
- gfc_add_modify_loc (input_location, &block, to_se.expr,
- fold_convert (TREE_TYPE (to_se.expr), tmp));
+ return gfc_finish_block (&block);
}
- gfc_free_expr (to_expr2);
gfc_init_se (&to_se, NULL);
-
- if (from_expr->ts.type == BT_CLASS)
- {
- gfc_free_expr (from_expr2);
- gfc_init_se (&from_se, NULL);
- }
+ gfc_init_se (&from_se, NULL);
}
-
/* Deallocate "to". */
if (from_expr->rank == 0)
{
diff --git a/gcc/fortran/trans.h b/gcc/fortran/trans.h
index f019c89edf2..ec04aede0fd 100644
--- a/gcc/fortran/trans.h
+++ b/gcc/fortran/trans.h
@@ -451,9 +451,9 @@ tree gfc_vptr_def_init_get (tree);
tree gfc_vptr_copy_get (tree);
tree gfc_vptr_final_get (tree);
tree gfc_vptr_deallocate_get (tree);
-void
-gfc_reset_vptr (stmtblock_t *, gfc_expr *, tree = NULL_TREE,
- gfc_symbol * = nullptr);
+void gfc_reset_vptr (stmtblock_t *, gfc_expr *, tree = NULL_TREE,
+ gfc_symbol * = nullptr);
+void gfc_class_set_vptr (stmtblock_t *, tree, tree);
void gfc_reset_len (stmtblock_t *, gfc_expr *);
tree gfc_get_class_from_gfc_expr (gfc_expr *);
tree gfc_get_class_from_expr (tree);
diff --git a/gcc/testsuite/gfortran.dg/unlimited_polymorphic_11.f90 b/gcc/testsuite/gfortran.dg/unlimited_polymorphic_11.f90
index bbd3d067f3f..653992f40eb 100644
--- a/gcc/testsuite/gfortran.dg/unlimited_polymorphic_11.f90
+++ b/gcc/testsuite/gfortran.dg/unlimited_polymorphic_11.f90
@@ -10,4 +10,4 @@
call move_alloc(a,c)
end
-! { dg-final { scan-tree-dump "\\(struct __vtype__STAR \\*\\) c._vptr = \\(struct __vtype__STAR \\*\\) a._vptr;" "original" } }
+! { dg-final { scan-tree-dump "c._vptr = a._vptr;" "original" } }
More information about the Gcc-cvs
mailing list