This is a regression present on all active branches.  The compiler segfaults 
on a function returning an array variable declared locally and used in a 
grandchild function but not in its parent function (which is a child of the 
first function).

Tested on x86_64-suse-linux, applied on all active branches.


2019-05-28  Eric Botcazou  <ebotca...@adacore.com>

        * gcc-interface/trans.c (walk_nesting_tree): New static function.
        (finalize_nrv): Use it to walk the entire nesting tree.


2019-05-28  Eric Botcazou  <ebotca...@adacore.com>

        * gnat.dg/opt79.ad[sb]: New test.

-- 
Eric Botcazou
package Opt79 is

  type Arr is array (1 .. 8) of Integer;

  function F (I : Integer) return Arr;

end Opt79;
-- { dg-do compile }
-- { dg-options "-O" }

package body Opt79 is

  function F (I : Integer) return Arr is
    A : Arr;

    procedure Nested is

      procedure Inner is
      begin
        A (1) := 0;
      end;

    begin
       Inner;
    end;

  begin
    Nested;
    for J in A'Range loop
      A (J) := I;
    end loop;
    return A;
  end;

end Opt79;
Index: gcc-interface/trans.c
===================================================================
--- gcc-interface/trans.c	(revision 271659)
+++ gcc-interface/trans.c	(working copy)
@@ -4280,6 +4280,20 @@ finalize_nrv_unc_r (tree *tp, int *walk_
   return NULL_TREE;
 }
 
+/* Apply FUNC to all the sub-trees of nested functions in NODE.  FUNC is called
+   with the DATA and the address of each sub-tree.  If FUNC returns a non-NULL
+   value, the traversal is stopped.  */
+
+static void
+walk_nesting_tree (struct cgraph_node *node, walk_tree_fn func, void *data)
+{
+  for (node = node->nested; node; node = node->next_nested)
+    {
+      walk_tree_without_duplicates (&DECL_SAVED_TREE (node->decl), func, data);
+      walk_nesting_tree (node, func, data);
+    }
+}
+
 /* Finalize the Named Return Value optimization for FNDECL.  The NRV bitmap
    contains the candidates for Named Return Value and OTHER is a list of
    the other return values.  GNAT_RET is a representative return node.  */
@@ -4287,7 +4301,6 @@ finalize_nrv_unc_r (tree *tp, int *walk_
 static void
 finalize_nrv (tree fndecl, bitmap nrv, vec<tree, va_gc> *other, Node_Id gnat_ret)
 {
-  struct cgraph_node *node;
   struct nrv_data data;
   walk_tree_fn func;
   unsigned int i;
@@ -4308,10 +4321,7 @@ finalize_nrv (tree fndecl, bitmap nrv, v
     return;
 
   /* Prune also the candidates that are referenced by nested functions.  */
-  node = cgraph_node::get_create (fndecl);
-  for (node = node->nested; node; node = node->next_nested)
-    walk_tree_without_duplicates (&DECL_SAVED_TREE (node->decl), prune_nrv_r,
-				  &data);
+  walk_nesting_tree (cgraph_node::get_create (fndecl), prune_nrv_r, &data);
   if (bitmap_empty_p (nrv))
     return;
 

Reply via email to