I have attached the updated and rather simpler patch.

Thanks for the prod, Mikael!

Paul

Fortran: Fix ICE with structure constructor in data statement [PR79685]

2024-07-28  Paul Thomas  <pa...@gcc.gnu.org>

gcc/fortran
PR fortran/79685
* decl.cc (match_data_constant): Find the symtree instead of
the symbol so the use renamed symbols are found. Pass this and
the derived type to gfc_match_structure_constructor.
* match.h: Update prototype of gfc_match_structure_contructor.
* primary.cc (gfc_match_structure_constructor): Remove call to
gfc_get_ha_sym_tree and use caller supplied symtree instead.

gcc/testsuite/
PR fortran/79685
* gfortran.dg/use_rename_12.f90: New test.


On Sat, 27 Jul 2024 at 22:04, Paul Richard Thomas <
paul.richard.tho...@gmail.com> wrote:

> Hi Mikael,
>
> You were absolutely right. I looked at the caller and "just didn't get
> it". Thanks. I will resubmit when I get back from a business trip.
>
> Cordialement
>
> Paul
>
>
>
> On Sat, 27 Jul 2024 at 12:35, Mikael Morin <morin-mik...@orange.fr> wrote:
>
>> Hello,
>>
>> Le 27/07/2024 à 11:25, Paul Richard Thomas a écrit :
>> > This patch is straightforward but I am still puzzled as to why it is
>> > necessary for the particular case. Having looked at all the other
>> chunks
>> > of frontend code involving use renaming, it seems that the process just
>> > works everywhere else. I tried putting the new code in gfc_find_symtree
>> > but it caused some regressions unless I pinned it down to the specific
>> > case of a structure constructor.
>> >
>> I think it works as expected, symtrees have the local names, and symbols
>> the original name, so if all that is available is the symbol, name
>> lookup may not work correctly with renaming.  And I think that there are
>> other places where it happens.
>>
>> In this case, it seems the caller can provide the local name, which
>> would avoid processing the use statements.  Did you try that?
>>
>> Mikael
>>
>
diff --git a/gcc/fortran/decl.cc b/gcc/fortran/decl.cc
index b8308aeee55..119c9dffa03 100644
--- a/gcc/fortran/decl.cc
+++ b/gcc/fortran/decl.cc
@@ -376,6 +376,7 @@ match_data_constant (gfc_expr **result)
   gfc_expr *expr;
   match m;
   locus old_loc;
+  gfc_symtree *symtree;
 
   m = gfc_match_literal_constant (&expr, 1);
   if (m == MATCH_YES)
@@ -436,9 +437,11 @@ match_data_constant (gfc_expr **result)
   if (m != MATCH_YES)
     return m;
 
-  if (gfc_find_symbol (name, NULL, 1, &sym))
+  if (gfc_find_sym_tree (name, NULL, 1, &symtree))
     return MATCH_ERROR;
 
+  sym = symtree->n.sym;
+
   if (sym && sym->attr.generic)
     dt_sym = gfc_find_dt_in_generic (sym);
 
@@ -452,7 +455,7 @@ match_data_constant (gfc_expr **result)
       return MATCH_ERROR;
     }
   else if (dt_sym && gfc_fl_struct (dt_sym->attr.flavor))
-    return gfc_match_structure_constructor (dt_sym, result);
+    return gfc_match_structure_constructor (dt_sym, symtree, result);
 
   /* Check to see if the value is an initialization array expression.  */
   if (sym->value->expr_type == EXPR_ARRAY)
diff --git a/gcc/fortran/match.h b/gcc/fortran/match.h
index c2b7d69c37c..519ad194a15 100644
--- a/gcc/fortran/match.h
+++ b/gcc/fortran/match.h
@@ -101,7 +101,7 @@ match gfc_match_call (void);
 /* We want to use this function to check for a common-block-name
    that can exist in a bind statement, so removed the "static"
    declaration of the function in match.cc. */
- 
+
 match gfc_match_common_name (char *name);
 
 match gfc_match_common (void);
@@ -302,7 +302,7 @@ match gfc_match_bind_c_stmt (void);
 match gfc_match_bind_c (gfc_symbol *, bool);
 
 /* primary.cc.  */
-match gfc_match_structure_constructor (gfc_symbol *, gfc_expr **);
+match gfc_match_structure_constructor (gfc_symbol *, gfc_symtree *, gfc_expr **);
 match gfc_match_variable (gfc_expr **, int);
 match gfc_match_equiv_variable (gfc_expr **);
 match gfc_match_actual_arglist (int, gfc_actual_arglist **, bool = false);
diff --git a/gcc/fortran/primary.cc b/gcc/fortran/primary.cc
index 76f6bcb8a78..9000b9cbbbc 100644
--- a/gcc/fortran/primary.cc
+++ b/gcc/fortran/primary.cc
@@ -3520,18 +3520,16 @@ gfc_convert_to_structure_constructor (gfc_expr *e, gfc_symbol *sym, gfc_expr **c
 
 
 match
-gfc_match_structure_constructor (gfc_symbol *sym, gfc_expr **result)
+gfc_match_structure_constructor (gfc_symbol *sym, gfc_symtree *symtree,
+				 gfc_expr **result)
 {
   match m;
   gfc_expr *e;
-  gfc_symtree *symtree;
   bool t = true;
 
-  gfc_get_ha_sym_tree (sym->name, &symtree);
-
   e = gfc_get_expr ();
-  e->symtree = symtree;
   e->expr_type = EXPR_FUNCTION;
+  e->symtree = symtree;
   e->where = gfc_current_locus;
 
   gcc_assert (gfc_fl_struct (sym->attr.flavor)
diff --git a/gcc/testsuite/gfortran.dg/use_rename_12.f90 b/gcc/testsuite/gfortran.dg/use_rename_12.f90
new file mode 100644
index 00000000000..97f26f42f76
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/use_rename_12.f90
@@ -0,0 +1,37 @@
+! { dg-do compile }
+!
+! Test the fix for pr79685, which failed as in the comments below.
+!
+! Contributed by Juergen Reuter  <juergen.reu...@desy.de>
+!
+module omega_color
+  implicit none
+
+  type omega_color_factor
+     integer :: i
+  end type
+
+  type(omega_color_factor), parameter :: op = omega_color_factor (199)
+
+end module
+
+module foo
+  use omega_color, ocf => omega_color_factor, ocfp => op
+  implicit none
+
+  type(ocf) :: table_color_factors1 = ocf(42)
+  type(ocf) :: table_color_factors2
+  type(ocf) :: table_color_factors3 (2)
+  type(ocf) :: table_color_factors4
+  data table_color_factors2 / ocf(99) /        ! This failed in gfc_match_structure_constructor.
+  data table_color_factors3 / ocf(1), ocf(2) / ! ditto.
+  data table_color_factors4 / ocfp /
+end module
+
+  use foo
+  if (table_color_factors1%i .ne. 42) stop 1
+  if (table_color_factors2%i .ne. 99) stop 2
+  if (any (table_color_factors3%i .ne. [1,2])) stop 3
+  if (table_color_factors4%i .ne. 199) stop 4
+end
+

Reply via email to