https://gcc.gnu.org/bugzilla/show_bug.cgi?id=116388

--- Comment #1 from Tomáš Trnka <trnka at scm dot com> ---
Diagnosing this further, the "comp_byte_stride" temporary created by
finalize_component() is never initialized because it is marked .artificial=1,
and resolve_symbol() bails out early for artificial symbols instead of calling
apply_default_init() normally.

The temporary is never actually used in generated code, because it's only an
argument to storage_size(), which is then replaced by an integer constant.

However, the temporary is then finalized as if it was a normal variable,
because gfc_trans_deferred_array() skips finalization (via
gfc_deallocate_alloc_comp()) only if !(sym->attr.artificial && sym->name[0] ==
'_'). Being artificial is thus not sufficient; as long as the symbol doesn't
start with an underscore, it will be finalized. This discrepancy causes the bug
by calling finalization on uninitialized data.

One hacky "fix" is to give the temporary a leading underscore, thus avoiding
finalization altogether:
--- a/gcc/fortran/class.cc
+++ b/gcc/fortran/class.cc
@@ -1152,7 +1152,7 @@ finalize_component (gfc_expr *expr, gfc_symbol *derived,
gfc_component *comp,
       gcc_assert (c);

       /* Set scalar argument for storage_size.  */
-      gfc_get_symbol ("comp_byte_stride", sub_ns, &byte_stride);
+      gfc_get_symbol ("_comp_byte_stride", sub_ns, &byte_stride);
       byte_stride->ts = e->ts;
       byte_stride->attr.flavor = FL_VARIABLE;
       byte_stride->attr.value = 1;

This regtests cleanly on current trunk and seems to fix the issue. However,
since I'm only taking first baby steps in gfortran development, I have no clue
what the significance of the leading underscore is and what sort of other side
effects this change could have.

Could someone (Paul?) comment on this?

I have also tested the alternative of making comp_byte_stride not artificial:

--- a/gcc/fortran/class.cc
+++ b/gcc/fortran/class.cc
@@ -1088,8 +1088,8 @@ finalize_component (gfc_expr *expr, gfc_symbol *derived,
gfc_component *comp,
       gfc_get_symbol ("comp_byte_stride", sub_ns, &byte_stride);
       byte_stride->ts = e->ts;
       byte_stride->attr.flavor = FL_VARIABLE;
-      byte_stride->attr.value = 1;
-      byte_stride->attr.artificial = 1;
+      byte_stride->attr.value = 0;
+      byte_stride->attr.artificial = 0;
       gfc_set_sym_referenced (byte_stride);
       gfc_commit_symbol (byte_stride);
       scalar = gfc_lval_expr_from_sym (byte_stride);

Although this seems to fix the issue in this PR (according to the tree dump,
the variable is then fully initialized and finalized afterwards), it causes
crashes in several tests (which I have not investigated further):

FAIL: gfortran.dg/finalize_25.f90
FAIL: gfortran.dg/finalize_37.f90
FAIL: gfortran.dg/finalize_44.f90
FAIL: gfortran.dg/finalize_46.f90
(snipped all the different optimization levels)

Reply via email to