On Wed, May 3, 2017 at 3:22 PM, Jason Merrill <ja...@redhat.com> wrote: > On Tue, Mar 14, 2017 at 8:24 AM, Pierre-Marie de Rodat > <dero...@adacore.com> wrote: >> 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. > > That seems like a bug; if gen_typedef_die is going to generate a DIE > for a cloned typedef, it needs to associate the type with the 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. > > This soundsn good; the DWARF standard says that we don't need to have > a die at all for the cloned typedef. > >> @@ -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)); > > This is unnecessarily complicated; at this point we already know that > TYPE_NAME (qualified_type) is non-null and in the variable "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 > > gen_typedef_die does create a DIE for them, it just doesn't do it > properly. But we could change gen_typedef_die to abort in that case, > making this comment correct.
Something like this, which also avoids routinely creating DIEs for local typedefs that will only be pruned away later; this patch doesn't change the size of .debug_info in cc1plus.
commit 56cce11181d1296e43cb4d603fc8efc6ac2570fa Author: Jason Merrill <ja...@redhat.com> Date: Thu May 4 15:00:51 2017 -0400 inline-static diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index 6caf598..bf6a65b 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -24355,7 +24355,7 @@ gen_typedef_die (tree decl, dw_die_ref context_die) 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); + gcc_unreachable (), add_abstract_origin_attribute (type_die, origin); else { tree type = TREE_TYPE (decl); @@ -24858,6 +24858,16 @@ process_scope_var (tree stmt, tree decl, tree origin, dw_die_ref context_die) else die = NULL; + if ((origin || DECL_ABSTRACT_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)) + equate_decl_number_to_die (decl, lookup_decl_die (origin)); + return; + } + if (die != NULL && die->die_parent == NULL) add_child_die (context_die, die); else if (TREE_CODE (decl_or_origin) == IMPORTED_DECL)