Commit 7a7b545f by Pierre-Marie de Rodat Committed by Pierre-Marie de Rodat

[PR79542][Ada] Fix ICE in dwarf2out.c with nested func. inlining

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. It also updates
in a similar way gen_type_die_with_usage, assert that when
gen_typedef_die is called on nodes that have an ultimate origin, this
origin is themselves.

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.
	(gen_typedef_die): Assert that input DECLs have no ultimate
	origin.
	(gen_type_die_with_usage): For typedef variants that have an
	ultimate origin, just call gen_decl_die on the original DECL.
	(process_scope_var): Avoid creating DIEs for local typedefs and
	concrete static variables.

gcc/testsuite/

	PR ada/79542
	* gnat.dg/debug13.ads, gnat.dg/debug13.adb: New testcase.

From-SVN: r251066
parent ff97dd82
2017-08-12 Pierre-Marie de Rodat <derodat@adacore.com>
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.
(gen_typedef_die): Assert that input DECLs have no ultimate
origin.
(gen_type_die_with_usage): For typedef variants that have an
ultimate origin, just call gen_decl_die on the original DECL.
(process_scope_var): Avoid creating DIEs for local typedefs and
concrete static variables.
2017-08-12 Alan Modra <amodra@gmail.com>
PR target/81170
......
......@@ -12506,6 +12506,15 @@ modified_type_die (tree type, int cv_quals, bool reverse,
if (qualified_type == dtype)
{
tree origin = decl_ultimate_origin (name);
/* 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);
......@@ -24296,7 +24305,7 @@ static void
gen_typedef_die (tree decl, dw_die_ref context_die)
{
dw_die_ref type_die;
tree origin;
tree type;
if (TREE_ASM_WRITTEN (decl))
{
......@@ -24305,23 +24314,18 @@ gen_typedef_die (tree decl, dw_die_ref context_die)
return;
}
/* As we avoid creating DIEs for local typedefs (see decl_ultimate_origin
checks in process_scope_var and modified_type_die), this should be called
only for original types. */
gcc_assert (decl_ultimate_origin (decl) == NULL);
TREE_ASM_WRITTEN (decl) = 1;
type_die = new_die (DW_TAG_typedef, context_die, decl);
origin = decl_ultimate_origin (decl);
if (origin != NULL)
add_abstract_origin_attribute (type_die, origin);
else
{
tree type = TREE_TYPE (decl);
if (type == error_mark_node)
return;
add_name_and_src_coords_attributes (type_die, decl);
if (DECL_ORIGINAL_TYPE (decl))
{
type = DECL_ORIGINAL_TYPE (decl);
if (type == error_mark_node)
return;
......@@ -24330,6 +24334,10 @@ gen_typedef_die (tree decl, dw_die_ref context_die)
}
else
{
type = TREE_TYPE (decl);
if (type == error_mark_node)
return;
if (is_naming_typedef_decl (TYPE_NAME (type)))
{
/* Here, we are in the case of decl being a typedef naming
......@@ -24368,12 +24376,9 @@ gen_typedef_die (tree decl, dw_die_ref context_die)
created. */
equate_type_number_to_die (type, type_die);
type = TREE_TYPE (decl);
add_alignment_attribute (type_die, type);
add_alignment_attribute (type_die, TREE_TYPE (decl));
add_accessibility_attribute (type_die, decl);
}
if (DECL_ABSTRACT_P (decl))
equate_decl_number_to_die (decl, type_die);
......@@ -24485,15 +24490,23 @@ gen_type_die_with_usage (tree type, dw_die_ref context_die,
if (TREE_ASM_WRITTEN (type))
return;
tree name = TYPE_NAME (type);
tree origin = decl_ultimate_origin (name);
if (origin != NULL)
{
gen_decl_die (origin, NULL, NULL, context_die);
return;
}
/* Prevent broken recursion; we can't hand off to the same type. */
gcc_assert (DECL_ORIGINAL_TYPE (TYPE_NAME (type)) != type);
gcc_assert (DECL_ORIGINAL_TYPE (name) != type);
/* Give typedefs the right scope. */
context_die = scope_die_for (type, context_die);
TREE_ASM_WRITTEN (type) = 1;
gen_decl_die (TYPE_NAME (type), NULL, NULL, context_die);
gen_decl_die (name, NULL, NULL, context_die);
return;
}
......@@ -24812,6 +24825,22 @@ process_scope_var (tree stmt, tree decl, tree origin, dw_die_ref context_die)
else
die = NULL;
/* Avoid creating DIEs for local typedefs and concrete static variables that
will only be pruned later. */
if ((origin || decl_ultimate_origin (decl))
&& (TREE_CODE (decl_or_origin) == TYPE_DECL
|| (VAR_P (decl_or_origin) && TREE_STATIC (decl_or_origin))))
{
origin = decl_ultimate_origin (decl_or_origin);
if (decl && VAR_P (decl) && die != NULL)
{
die = lookup_decl_die (origin);
if (die != NULL)
equate_decl_number_to_die (decl, die);
}
return;
}
if (die != NULL && die->die_parent == NULL)
add_child_die (context_die, die);
else if (TREE_CODE (decl_or_origin) == IMPORTED_DECL)
......
2017-08-12 Pierre-Marie de Rodat <derodat@adacore.com>
PR ada/79542
* gnat.dg/debug13.ads, gnat.dg/debug13.adb: New testcase.
2017-08-11 Marek Polacek <polacek@redhat.com>
PR c/81795
......
-- { dg-options "-cargs -O2 -g -margs" }
package body Debug13 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 Debug13;
package Debug13 is
procedure Compile (P : Natural);
end Debug13;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment