]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
backport: re PR fortran/90786 (ICE on procedure pointer assignment to function with...
authorThomas Koenig <tkoenig@gcc.gnu.org>
Tue, 30 Jul 2019 19:11:03 +0000 (19:11 +0000)
committerThomas Koenig <tkoenig@gcc.gnu.org>
Tue, 30 Jul 2019 19:11:03 +0000 (19:11 +0000)
2019-07-29  Thomas Koenig  <tkoenig@gcc.gnu.org>
Paul Thomas <pault@gcc.gnu.org>

Backport from trunk
PR fortran/90786
PR fortran/90813
* trans-expr.c (pointer_assignment_is_proc_pointer) Remove as
it is very simple and only called from one place.
(gfc_trans_pointer_assignment): Rename non_proc_pointer_assign
as non_proc_ptr_assign. Assign to it directly, rather than call
to above, deleted function and use gfc_expr_attr instead of
only checking the reference chain.
* dump-parse-tree.c (show_global_symbol): New function.
(gfc_dump_global_symbols): New function.
* gfortran.h (gfc_traverse_gsymbol): Add prototype.
(gfc_dump_global_symbols): Likewise.
* invoke.texi: Document -fdump-fortran-global.
* lang.opt: Add -fdump-fortran-global.
* parse.c (gfc_parse_file): Handle flag_dump_fortran_global.
* symbol.c (gfc_traverse_gsymbol): New function.
* trans-decl.c (sym_identifier): New function.
(mangled_identifier): New function, doing most of the work
of gfc_sym_mangled_identifier.
(gfc_sym_mangled_identifier): Use mangled_identifier.  Add mangled
identifier to global symbol table.
(get_proc_pointer_decl): Use backend decl from global identifier
if present.

2019-07-29  Thomas Koenig  <tkoenig@gcc.gnu.org>
Paul Thomas <pault@gcc.gnu.org>

Backport from trunk
PR fortran/90786
PR fortran/90813
* gfortran.dg/proc_ptr_51.f90: New test.

Co-Authored-By: Paul Thomas <pault@gcc.gnu.org>
From-SVN: r273913

gcc/fortran/ChangeLog
gcc/fortran/dump-parse-tree.c
gcc/fortran/gfortran.h
gcc/fortran/invoke.texi
gcc/fortran/lang.opt
gcc/fortran/parse.c
gcc/fortran/symbol.c
gcc/fortran/trans-decl.c
gcc/fortran/trans-expr.c
gcc/testsuite/ChangeLog
gcc/testsuite/gfortran.dg/proc_ptr_51.f90 [new file with mode: 0644]

index 7901430a1945a66f72cc272458e7f5e04ee2d72e..c7a3df6bc590903fbf509105f1481a8b2a24c256 100644 (file)
@@ -1,3 +1,31 @@
+2019-07-29  Thomas Koenig  <tkoenig@gcc.gnu.org>
+       Paul Thomas <pault@gcc.gnu.org>
+
+       Backport from trunk
+       PR fortran/90786
+       PR fortran/90813
+       * trans-expr.c (pointer_assignment_is_proc_pointer) Remove as
+       it is very simple and only called from one place.
+       (gfc_trans_pointer_assignment): Rename non_proc_pointer_assign
+       as non_proc_ptr_assign. Assign to it directly, rather than call
+       to above, deleted function and use gfc_expr_attr instead of
+       only checking the reference chain.
+       * dump-parse-tree.c (show_global_symbol): New function.
+       (gfc_dump_global_symbols): New function.
+       * gfortran.h (gfc_traverse_gsymbol): Add prototype.
+       (gfc_dump_global_symbols): Likewise.
+       * invoke.texi: Document -fdump-fortran-global.
+       * lang.opt: Add -fdump-fortran-global.
+       * parse.c (gfc_parse_file): Handle flag_dump_fortran_global.
+       * symbol.c (gfc_traverse_gsymbol): New function.
+       * trans-decl.c (sym_identifier): New function.
+       (mangled_identifier): New function, doing most of the work
+       of gfc_sym_mangled_identifier.
+       (gfc_sym_mangled_identifier): Use mangled_identifier.  Add mangled
+       identifier to global symbol table.
+       (get_proc_pointer_decl): Use backend decl from global identifier
+       if present.
+
 2019-07-23  Thomas König  <tkoenig@gcc.gnu.org>
 
        Backport from trunk
index 41b2c88265c18872241c3105c9d66837b8f5df4a..ebd73110e2de1b27ca092a04ab561ba59560be02 100644 (file)
@@ -3443,3 +3443,36 @@ write_interop_decl (gfc_symbol *sym)
   else if (sym->attr.flavor == FL_PROCEDURE)
     write_proc (sym, true);
 }
+
+/* This section deals with dumping the global symbol tree.  */
+
+/* Callback function for printing out the contents of the tree.  */
+
+static void
+show_global_symbol (gfc_gsymbol *gsym, void *f_data)
+{
+  FILE *out;
+  out = (FILE *) f_data;
+
+  if (gsym->name)
+    fprintf (out, "name=%s", gsym->name);
+
+  if (gsym->sym_name)
+    fprintf (out, ", sym_name=%s", gsym->sym_name);
+
+  if (gsym->mod_name)
+    fprintf (out, ", mod_name=%s", gsym->mod_name);
+
+  if (gsym->binding_label)
+    fprintf (out, ", binding_label=%s", gsym->binding_label);
+
+  fputc ('\n', out);
+}
+
+/* Show all global symbols.  */
+
+void
+gfc_dump_global_symbols (FILE *f)
+{
+  gfc_traverse_gsymbol (gfc_gsym_root, show_global_symbol, (void *) f);
+}
index 54987ac878b6446147cb01234c496e03b9502c46..2bb82980e8efba038a3ab5c397471c3cb6e9a1d9 100644 (file)
@@ -3123,6 +3123,7 @@ void gfc_free_dt_list (void);
 gfc_gsymbol *gfc_get_gsymbol (const char *, bool bind_c);
 gfc_gsymbol *gfc_find_gsymbol (gfc_gsymbol *, const char *);
 gfc_gsymbol *gfc_find_case_gsymbol (gfc_gsymbol *, const char *);
+void gfc_traverse_gsymbol (gfc_gsymbol *, void (*)(gfc_gsymbol *, void *), void *);
 
 gfc_typebound_proc* gfc_get_typebound_proc (gfc_typebound_proc*);
 gfc_symbol* gfc_get_derived_super_type (gfc_symbol*);
@@ -3466,6 +3467,7 @@ void gfc_delete_bbt (void *, void *, compare_fn);
 void gfc_dump_parse_tree (gfc_namespace *, FILE *);
 void gfc_dump_c_prototypes (gfc_namespace *, FILE *);
 void gfc_dump_external_c_prototypes (FILE *);
+void gfc_dump_global_symbols (FILE *);
 
 /* parse.c */
 bool gfc_parse_file (void);
index d53be69646af8a99af6d8155729f47a127811672..cf18a23d84d4b090b52fd843ecc401fba6b8166c 100644 (file)
@@ -157,7 +157,8 @@ and warnings}.
 @item Debugging Options
 @xref{Debugging Options,,Options for debugging your program or GNU Fortran}.
 @gccoptlist{-fbacktrace -fdump-fortran-optimized -fdump-fortran-original @gol
--fdump-parse-tree -ffpe-trap=@var{list} -ffpe-summary=@var{list}
+-fdump-fortran-global -fdump-parse-tree -ffpe-trap=@var{list} @gol
+-ffpe-summary=@var{list}
 }
 
 @item Directory Options
@@ -1182,6 +1183,14 @@ change between releases. This option may also generate internal
 compiler errors for features which have only recently been added. This
 option is deprecated; use @code{-fdump-fortran-original} instead.
 
+@item -fdump-fortran-global
+@opindex @code{fdump-fortran-global}
+Output a list of the global identifiers after translating into
+middle-end representation. Mostly useful for debugging the GNU Fortran
+compiler itself. The output generated by this option might change
+between releases.  This option may also generate internal compiler
+errors for features which have only recently been added.
+
 @item -ffpe-trap=@var{list}
 @opindex @code{ffpe-trap=}@var{list}
 Specify a list of floating point exception traps to enable.  On most
index cc5c217e70b55be3ff4bc79509dbcee62a5df0cc..90b09f99f72e189fb1dc915d82e29b46809d201a 100644 (file)
@@ -500,6 +500,10 @@ fdump-fortran-optimized
 Fortran Var(flag_dump_fortran_optimized)
 Display the code tree after front end optimization.
 
+fdump-fortran-global
+Fortran Var(flag_dump_fortran_global)
+Display the global symbol table after parsing.
+
 fdump-parse-tree
 Fortran Alias(fdump-fortran-original)
 Display the code tree after parsing; deprecated option.
index 8947299bc1f461c496d7e3a8f7fcbc545e5380f4..66d84b4118fb868a42d642d0ef995f6fdd944fe7 100644 (file)
@@ -6366,6 +6366,13 @@ done:
   /* Do the translation.  */
   translate_all_program_units (gfc_global_ns_list);
 
+  /* Dump the global symbol ist.  We only do this here because part
+     of it is generated after mangling the identifiers in
+     trans-decl.c.  */
+
+  if (flag_dump_fortran_global)
+    gfc_dump_global_symbols (stdout);
+  
   gfc_end_source_files ();
   return true;
 
index f4273633db74ef12d287c40185d4edf6fde09036..2b8f86e0881f30bd1334c32655b33903a971eee0 100644 (file)
@@ -4357,6 +4357,19 @@ gfc_get_gsymbol (const char *name, bool bind_c)
   return s;
 }
 
+void
+gfc_traverse_gsymbol (gfc_gsymbol *gsym,
+                     void (*do_something) (gfc_gsymbol *, void *),
+                     void *data)
+{
+  if (gsym->left)
+    gfc_traverse_gsymbol (gsym->left, do_something, data);
+
+  (*do_something) (gsym, data);
+
+  if (gsym->right)
+    gfc_traverse_gsymbol (gsym->right, do_something, data);
+}
 
 static gfc_symbol *
 get_iso_c_binding_dt (int sym_id)
index 14fa6462bd9305b6371d5b9b4b114b27d2a7ad6b..9538dee5733ab8b837704b747bbc57326015961e 100644 (file)
@@ -345,39 +345,45 @@ gfc_get_label_decl (gfc_st_label * lp)
     }
 }
 
+/* Return the name of an identifier.  */
 
-/* Convert a gfc_symbol to an identifier of the same name.  */
-
-static tree
-gfc_sym_identifier (gfc_symbol * sym)
+static const char *
+sym_identifier (gfc_symbol *sym)
 {
   if (sym->attr.is_main_program && strcmp (sym->name, "main") == 0)
-    return (get_identifier ("MAIN__"));
+    return "MAIN__";
   else
-    return (get_identifier (sym->name));
+    return sym->name;
 }
 
-
-/* Construct mangled name from symbol name.  */
+/* Convert a gfc_symbol to an identifier of the same name.  */
 
 static tree
-gfc_sym_mangled_identifier (gfc_symbol * sym)
+gfc_sym_identifier (gfc_symbol * sym)
 {
-  char name[GFC_MAX_MANGLED_SYMBOL_LEN + 1];
+  return get_identifier (sym_identifier (sym));
+}
 
+/* Construct mangled name from symbol name.   */
+
+static const char *
+mangled_identifier (gfc_symbol *sym)
+{
+  static char name[GFC_MAX_MANGLED_SYMBOL_LEN + 1];
   /* Prevent the mangling of identifiers that have an assigned
      binding label (mainly those that are bind(c)).  */
+
   if (sym->attr.is_bind_c == 1 && sym->binding_label)
-    return get_identifier (sym->binding_label);
+    return sym->binding_label;
 
   if (!sym->fn_result_spec)
     {
       if (sym->module == NULL)
-       return gfc_sym_identifier (sym);
+       return sym_identifier (sym);
       else
        {
          snprintf (name, sizeof name, "__%s_MOD_%s", sym->module, sym->name);
-         return get_identifier (name);
+         return name;
        }
     }
   else
@@ -392,17 +398,40 @@ gfc_sym_mangled_identifier (gfc_symbol * sym)
                    sym->ns->proc_name->module,
                    sym->ns->proc_name->name,
                    sym->name);
-         return get_identifier (name);
+         return name;
        }
       else
        {
          snprintf (name, sizeof name, "__%s_PROC_%s",
                    sym->ns->proc_name->name, sym->name);
-         return get_identifier (name);
+         return name;
        }
     }
 }
 
+/* Get mangled identifier, adding the symbol to the global table if
+   it is not yet already there.  */
+
+static tree
+gfc_sym_mangled_identifier (gfc_symbol * sym)
+{
+  tree result;
+  gfc_gsymbol *gsym;
+  const char *name;
+
+  name = mangled_identifier (sym);
+  result = get_identifier (name);
+
+  gsym = gfc_find_gsymbol (gfc_gsym_root, name);
+  if (gsym == NULL)
+    {
+      gsym = gfc_get_gsymbol (name, false);
+      gsym->ns = sym->ns;
+      gsym->sym_name = sym->name;
+    }
+
+  return result;
+}
 
 /* Construct mangled function name from symbol name.  */
 
@@ -1905,6 +1934,22 @@ get_proc_pointer_decl (gfc_symbol *sym)
   tree decl;
   tree attributes;
 
+  if (sym->module || sym->fn_result_spec)
+    {
+      const char *name;
+      gfc_gsymbol *gsym;
+
+      name = mangled_identifier (sym);
+      gsym = gfc_find_gsymbol (gfc_gsym_root, name);
+      if (gsym != NULL)
+       {
+         gfc_symbol *s;
+         gfc_find_symbol (sym->name, gsym->ns, 0, &s);
+         if (s && s->backend_decl)
+           return s->backend_decl;
+       }
+    }
+
   decl = sym->backend_decl;
   if (decl)
     return decl;
index 3711c38b2f237addd465870137920a254d775481..afe08fc266818049b53f2c4e266a3c9d4471d66e 100644 (file)
@@ -8785,23 +8785,6 @@ trans_caf_token_assign (gfc_se *lse, gfc_se *rse, gfc_expr *expr1,
     }
 }
 
-/* Indentify class valued proc_pointer assignments.  */
-
-static bool
-pointer_assignment_is_proc_pointer (gfc_expr * expr1, gfc_expr * expr2)
-{
-  gfc_ref * ref;
-
-  ref = expr1->ref;
-  while (ref && ref->next)
-     ref = ref->next;
-
-  return ref && ref->type == REF_COMPONENT
-      && ref->u.c.component->attr.proc_pointer
-      && expr2->expr_type == EXPR_VARIABLE
-      && expr2->symtree->n.sym->attr.flavor == FL_PROCEDURE;
-}
-
 
 /* Do everything that is needed for a CLASS function expr2.  */
 
@@ -8854,7 +8837,7 @@ gfc_trans_pointer_assignment (gfc_expr * expr1, gfc_expr * expr2)
   tree desc;
   tree tmp;
   tree expr1_vptr = NULL_TREE;
-  bool scalar, non_proc_pointer_assign;
+  bool scalar, non_proc_ptr_assign;
   gfc_ss *ss;
 
   gfc_start_block (&block);
@@ -8862,7 +8845,9 @@ gfc_trans_pointer_assignment (gfc_expr * expr1, gfc_expr * expr2)
   gfc_init_se (&lse, NULL);
 
   /* Usually testing whether this is not a proc pointer assignment.  */
-  non_proc_pointer_assign = !pointer_assignment_is_proc_pointer (expr1, expr2);
+  non_proc_ptr_assign = !(gfc_expr_attr (expr1).proc_pointer
+                       && expr2->expr_type == EXPR_VARIABLE
+                       && expr2->symtree->n.sym->attr.flavor == FL_PROCEDURE);
 
   /* Check whether the expression is a scalar or not; we cannot use
      expr1->rank as it can be nonzero for proc pointers.  */
@@ -8872,7 +8857,7 @@ gfc_trans_pointer_assignment (gfc_expr * expr1, gfc_expr * expr2)
     gfc_free_ss_chain (ss);
 
   if (expr1->ts.type == BT_DERIVED && expr2->ts.type == BT_CLASS
-      && expr2->expr_type != EXPR_FUNCTION && non_proc_pointer_assign)
+      && expr2->expr_type != EXPR_FUNCTION && non_proc_ptr_assign)
     {
       gfc_add_data_component (expr2);
       /* The following is required as gfc_add_data_component doesn't
@@ -8892,7 +8877,7 @@ gfc_trans_pointer_assignment (gfc_expr * expr1, gfc_expr * expr2)
       else
        gfc_conv_expr (&rse, expr2);
 
-      if (non_proc_pointer_assign && expr1->ts.type == BT_CLASS)
+      if (non_proc_ptr_assign && expr1->ts.type == BT_CLASS)
        {
          trans_class_vptr_len_assignment (&block, expr1, expr2, &rse, NULL,
                                           NULL);
index 0f2bda5dd0ec9708af30d5b5e85cff7ba4f82c4d..643e3e5a5cdad82de78b23b9a0711034e651d60e 100644 (file)
@@ -1,3 +1,11 @@
+2019-07-29  Thomas Koenig  <tkoenig@gcc.gnu.org>
+       Paul Thomas <pault@gcc.gnu.org>
+
+       Backport from trunk
+       PR fortran/90786
+       PR fortran/90813
+       * gfortran.dg/proc_ptr_51.f90: New test.
+
 2019-07-24  Bin Cheng  <bin.cheng@linux.alibaba.com>
 
        Backport from mainline
diff --git a/gcc/testsuite/gfortran.dg/proc_ptr_51.f90 b/gcc/testsuite/gfortran.dg/proc_ptr_51.f90
new file mode 100644 (file)
index 0000000..62b5d71
--- /dev/null
@@ -0,0 +1,38 @@
+! { dg-do run }
+!
+! Test the fix for PR90786.
+!
+! Contributed by Andrew benson  <abensonca@gmail.com>
+!
+module f
+procedure(c), pointer :: c_
+
+ type :: s
+   integer :: i = 42
+ end type s
+ class(s), pointer :: res, tgt
+
+contains
+
+ function c()
+   implicit none
+   class(s), pointer ::  c
+   c => tgt
+   return
+ end function c
+
+ subroutine fs()
+   implicit none
+   c_ => c  ! This used to ICE
+   return
+ end subroutine fs
+
+end module f
+
+  use f
+  allocate (tgt, source = s(99))
+  call fs()
+  res => c_()
+  if (res%i .ne. 99) stop 1
+  deallocate (tgt)
+end