aboutsummaryrefslogtreecommitdiff
path: root/gcc/fortran/interface.cc
diff options
context:
space:
mode:
authorMikael Morin <mikael@gcc.gnu.org>2022-04-24 15:05:41 +0200
committerMikael Morin <mikael@gcc.gnu.org>2022-04-24 15:05:41 +0200
commitfa5cd7102da676dcb1757b1288421f5f3439ae0e (patch)
treead25ead238ade82a8702219169912630b4b39bb4 /gcc/fortran/interface.cc
parentafe0b5b7ce597641f02d47f0384610fb078a2cb7 (diff)
downloadgcc-fa5cd7102da676dcb1757b1288421f5f3439ae0e.zip
gcc-fa5cd7102da676dcb1757b1288421f5f3439ae0e.tar.gz
gcc-fa5cd7102da676dcb1757b1288421f5f3439ae0e.tar.bz2
fortran: Detect duplicate unlimited polymorphic types [PR103662]
This fixes a type-based alias analysis issue with unlimited polymorphic class descriptors (types behind class(*)) causing data initialisation to be removed by optimization. The fortran front-end may create multiple declarations for types, for example if a type is redeclared in each program unit it is used in. To avoid optimization seeing them as non-aliasing, a list of derived types is created at resolution time, and used at translation to set the same TYPE_CANONICAL type for each duplicate type declaration. This mechanism didn’t work for unlimited polymorphic descriptors types, as there is a short-circuit return skipping all the resolution handling for them, including the type registration. This change adds type registration at the short-circuit return, and updates type comparison to handle specifically unlimited polymorphic fake symbols, class descriptor types and virtual table types. The test, which exhibited mismatching dynamic types had to be fixed as well. PR fortran/103662 gcc/fortran/ChangeLog: * interface.cc (gfc_compare_derived_types): Support comparing unlimited polymorphic fake symbols. Recursively compare class descriptor types and virtual table types. * resolve.cc (resolve_fl_derived): Add type to the types list on unlimited polymorphic short-circuit return. gcc/testsuite/ChangeLog: * gfortran.dg/unlimited_polymorphic_3.f03 (foo): Separate bind(c) and sequence checks to... (foo_bc, foo_sq): ... two different procedures. (main, foo*): Change type declarations so that type name, component name, and either bind(c) or sequence attribute match between the main type declarations and the procedure type declarations. (toplevel): Add optimization dump checks. Co-Authored-By: Jakub Jelinek <jakub@redhat.com>
Diffstat (limited to 'gcc/fortran/interface.cc')
-rw-r--r--gcc/fortran/interface.cc19
1 files changed, 15 insertions, 4 deletions
diff --git a/gcc/fortran/interface.cc b/gcc/fortran/interface.cc
index 000a530..7ed6e13 100644
--- a/gcc/fortran/interface.cc
+++ b/gcc/fortran/interface.cc
@@ -618,6 +618,14 @@ gfc_compare_derived_types (gfc_symbol *derived1, gfc_symbol *derived2)
if (!derived1 || !derived2)
gfc_internal_error ("gfc_compare_derived_types: invalid derived type");
+ if (derived1->attr.unlimited_polymorphic
+ && derived2->attr.unlimited_polymorphic)
+ return true;
+
+ if (derived1->attr.unlimited_polymorphic
+ != derived2->attr.unlimited_polymorphic)
+ return false;
+
/* Compare UNION types specially. */
if (derived1->attr.flavor == FL_UNION || derived2->attr.flavor == FL_UNION)
return compare_union_types (derived1, derived2);
@@ -630,10 +638,11 @@ gfc_compare_derived_types (gfc_symbol *derived1, gfc_symbol *derived2)
&& strcmp (derived1->module, derived2->module) == 0)
return true;
- /* Compare type via the rules of the standard. Both types must have
- the SEQUENCE or BIND(C) attribute to be equal. STRUCTUREs are special
- because they can be anonymous; therefore two structures with different
- names may be equal. */
+ /* Compare type via the rules of the standard. Both types must have the
+ SEQUENCE or BIND(C) attribute to be equal. We also compare types
+ recursively if they are class descriptors types or virtual tables types.
+ STRUCTUREs are special because they can be anonymous; therefore two
+ structures with different names may be equal. */
/* Compare names, but not for anonymous types such as UNION or MAP. */
if (!is_anonymous_dt (derived1) && !is_anonymous_dt (derived2)
@@ -646,6 +655,8 @@ gfc_compare_derived_types (gfc_symbol *derived1, gfc_symbol *derived2)
if (!(derived1->attr.sequence && derived2->attr.sequence)
&& !(derived1->attr.is_bind_c && derived2->attr.is_bind_c)
+ && !(derived1->attr.is_class && derived2->attr.is_class)
+ && !(derived1->attr.vtype && derived2->attr.vtype)
&& !(derived1->attr.pdt_type && derived2->attr.pdt_type))
return false;