On 09/28/2016 09:48 AM, Richard Biener wrote:
Hmm, interesting approach.  It might work reliably at this point of
the compilation
but we do actually recycle cgraph nodes.

Arf, what a pity. ;-)

So I wonder if given we do have
->origin / ->next_nested in the cgraph if we can simply perform a walk in the
appropriate order.

But then OTOH in my early LTO debug patchset I have
[…]
which is not 100% equivalent (looking at the abstract origin) but it
sounds like a
similar issue.  So I wonder if doing the same for DECL_CONTEXT being a function
makes sense here and would also fix your particular issue in a more
reliable way.

I think it makes sense, and it seems to work, so many thanks for the suggestion! Bootstrapped and regtested successfuly on x86_64-linux. And this time, I did not forgot to attach the new testcase!

--
Pierre-Marie de Rodat
>From ad9eeef49da48786caabe9ef529127d6f93ea766 Mon Sep 17 00:00:00 2001
From: Pierre-Marie de Rodat <dero...@adacore.com>
Date: Fri, 23 Sep 2016 18:16:07 +0200
Subject: [PATCH] DWARF: fix scoping for descriptions of local types

In Ada, it is possible to have nested subprograms in the following
configuration:

    procedure Parent is
       type T;
       [...]
       procedure Child (Value : T) is
       begin
          [...]
       end Child;
    begin
       [...]
    end Parent;

As we currently generate debugging information for Child first before
Parent, the debug info for T appears in global scope since the DIE for
Parent does not exist yet.

This patch makes sure that when we generate early debug info for a
nested function, we trigger generation for the parent function first.

gcc/ChangeLog:

	* dwarf2out.c (dwarf2out_early_global_decl): For nested
	functions, call dwarf2out_decl on the parent function first.

gcc/testsuite/

	* gcc/testsuite/gnat.dg/debug9.adb: New testcase.
---
 gcc/dwarf2out.c                  | 10 ++++++++
 gcc/testsuite/gnat.dg/debug9.adb | 53 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 63 insertions(+)
 create mode 100644 gcc/testsuite/gnat.dg/debug9.adb

diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index 4a3df33..413106d 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -23867,6 +23867,16 @@ dwarf2out_early_global_decl (tree decl)
 	  if (!DECL_STRUCT_FUNCTION (decl))
 	    goto early_decl_exit;
 
+	  /* For nested functions, emit DIEs for the parents first so that all
+	     nested DIEs are generated at the proper scope in the first
+	     shot.  */
+	  tree context = decl_function_context (decl);
+	  if (context != NULL)
+	    {
+	      current_function_decl = context;
+	      dwarf2out_decl (context);
+	    }
+
 	  current_function_decl = decl;
 	}
       dwarf2out_decl (decl);
diff --git a/gcc/testsuite/gnat.dg/debug9.adb b/gcc/testsuite/gnat.dg/debug9.adb
new file mode 100644
index 0000000..dd14210
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/debug9.adb
@@ -0,0 +1,53 @@
+--  The aim of this test is to check that Ada types appear in the proper
+--  context in the debug info.
+-- 
+--  Checking this directly would be really tedious just scanning for assembly
+--  lines, so instead we rely on DWARFv4's .debug_types sections, which must be
+--  created only for global-scope types. Checking the number of .debug_types is
+--  some hackish way to check that types are output in the proper context (i.e.
+--  at global or local scope).
+--
+--  { dg-options "-g -gdwarf-4 -cargs -fdebug-types-section -dA" }
+--  { dg-final { scan-assembler-times "\\(DIE \\(0x\[a-f0-9\]*\\) DW_TAG_type_unit\\)" 0 } }
+
+procedure Debug9 is
+   type Array_Type is array (Natural range <>) of Integer;
+   type Record_Type (L1, L2 : Natural) is record
+      I1 : Integer;
+      A1 : Array_Type (1 .. L1);
+      I2 : Integer;
+      A2 : Array_Type (1 .. L2);
+      I3 : Integer;
+   end record;
+
+   function Get (L1, L2 : Natural) return Record_Type is
+      Result : Record_Type (L1, L2);
+   begin
+      Result.I1 := 1;
+      for I in Result.A1'Range loop
+         Result.A1 (I) := I;
+      end loop;
+      Result.I2 := 2;
+      for I in Result.A2'Range loop
+         Result.A2 (I) := I;
+      end loop;
+      Result.I3 := 3;
+      return Result;
+   end Get;
+
+   R1 : Record_Type := Get (0, 0);
+   R2 : Record_Type := Get (1, 0);
+   R3 : Record_Type := Get (0, 1);
+   R4 : Record_Type := Get (2, 2);
+
+   procedure Process (R : Record_Type) is
+   begin
+      null;
+   end Process;
+
+begin
+   Process (R1);
+   Process (R2);
+   Process (R3);
+   Process (R4);
+end Debug9;
-- 
2.10.0

Reply via email to