This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] [PR79542][Ada] Fix ICE in dwarf2out.c with nested func. inlining
- From: Pierre-Marie de Rodat <derodat at adacore dot com>
- To: gcc-patches at gcc dot gnu dot org
- Cc: Pierre-Marie de Rodat <derodat at adacore dot com>
- Date: Tue, 14 Mar 2017 13:24:10 +0100
- Subject: [PATCH] [PR79542][Ada] Fix ICE in dwarf2out.c with nested func. inlining
- Authentication-results: sourceware.org; auth=none
Hello,
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=79542 reports an ICE in
dwarf2out.c for an Ada testcase built with optimization.
This crash happens during the late generation pass because
add_gnat_descriptive_type cannot find the type DIE corresponding to some
descriptive type after having tried to generate it. This is because the
DIE was generated during the early generation pass, but then pruned by
the type pruning machinery. So why was it pruned?
We are in a situation where we have cloned types (because of inlining,
IIUC) whose TYPE_NAME have non-null DECL_ABSTRACT_ORIGIN attributes. As
a consequence:
* In modified_type_die, the "handle C typedef types" part calls
gen_type_die on the cloned type.
* gen_type_die matches a typedef variant, and then calls gen_decl_die
on its TYPE_NAME, which will end up calling gen_typedef_die.
* gen_typedef_die checks decl_ultimate_origin for this TYPE_DECL, and
finds one, so it only adds a DW_AT_abstract_origin attribute to the
DW_TAG_typedef DIE, but the cloned type itself does not get its own
DIE.
* Back in modified_type_die, the call to lookup_type_die on the type
passed to gen_type_die returns NULL.
In the end, whole type trees, i.e. the ones referenced by
DECL_ABSTRACT_ORIGIN attributes, are never referenced from type pruning
"roots" and are thus pruned. The descriptive type at stake here is one
of them, hence the assertion failure.
This patch attemps to fix that with what seems to be the most sensible
thing to do in my opinion: updating the "handle C typedef types" part in
modified_type_die to check decl_ultimate_origin before calling
gen_type_die: if that function returns something not null, then we know
that gen_type_die/gen_typedef_die will not generate a DIE for the input
type, so we try to process the ultimate origin instead.
I bootstrapped and regtested this successfully on x86_64-linux. I also
checked that there was no regression in GDB's testsuite and of course
the new testcase, which crashes with current trunk, passes with the
patch applied.
Is it ok to commit? Thank you in advance!
gcc/
PR ada/79542
* dwarf2out.c (modified_type_die): For C typedef types that have
an ultimate origin, process the ultimate origin instead of the
input type.
gcc/testsuite/
* gnat.dg/debug10.ads, gnat.dg/debug10.adb: New testcase.
---
gcc/dwarf2out.c | 12 ++++++++++++
gcc/testsuite/gnat.dg/debug10.adb | 38 ++++++++++++++++++++++++++++++++++++++
gcc/testsuite/gnat.dg/debug10.ads | 5 +++++
3 files changed, 55 insertions(+)
create mode 100644 gcc/testsuite/gnat.dg/debug10.adb
create mode 100644 gcc/testsuite/gnat.dg/debug10.ads
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index 0bbb90ed3aa..4088614fc18 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -12496,6 +12496,18 @@ modified_type_die (tree type, int cv_quals, bool reverse,
if (qualified_type == dtype)
{
+ tree origin
+ = TYPE_NAME (qualified_type) == NULL
+ ? NULL
+ : decl_ultimate_origin (TYPE_NAME (qualified_type));
+
+ /* Typedef variants that have an abstract origin don't get their own
+ type DIE (see gen_typedef_die), so fall back on the ultimate
+ abstract origin instead. */
+ if (origin != NULL)
+ return modified_type_die (TREE_TYPE (origin), cv_quals, reverse,
+ context_die);
+
/* For a named type, use the typedef. */
gen_type_die (qualified_type, context_die);
return lookup_type_die (qualified_type);
diff --git a/gcc/testsuite/gnat.dg/debug10.adb b/gcc/testsuite/gnat.dg/debug10.adb
new file mode 100644
index 00000000000..b85f3d36dd7
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/debug10.adb
@@ -0,0 +1,38 @@
+-- { dg-options "-cargs -O2 -g -margs" }
+
+package body Debug10 is
+
+ procedure Compile (P : Natural)
+ is
+ Max_Pos : constant Natural := P;
+ type Position_Set is array (1 .. Max_Pos) of Boolean;
+
+ Empty : constant Position_Set := (others => False);
+
+ type Position_Set_Array is array (1 .. Max_Pos) of Position_Set;
+
+ Follow : Position_Set_Array := (others => Empty);
+
+ function Get_Follows return Position_Set;
+
+ procedure Make_DFA;
+
+ function Get_Follows return Position_Set is
+ Result : Position_Set := Empty;
+ begin
+ Result := Result or Follow (1);
+
+ return Result;
+ end Get_Follows;
+
+ procedure Make_DFA is
+ Next : constant Position_Set := Get_Follows;
+ begin
+ null;
+ end Make_DFA;
+
+ begin
+ Make_DFA;
+ end Compile;
+
+end Debug10;
diff --git a/gcc/testsuite/gnat.dg/debug10.ads b/gcc/testsuite/gnat.dg/debug10.ads
new file mode 100644
index 00000000000..ecd3c8880ba
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/debug10.ads
@@ -0,0 +1,5 @@
+package Debug10 is
+
+ procedure Compile (P : Natural);
+
+end Debug10;
--
2.11.0