https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77947

--- Comment #6 from rguenther at suse dot de <rguenther at suse dot de> ---
On Wed, 12 Oct 2016, marxin at gcc dot gnu.org wrote:

> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77947
> 
> --- Comment #5 from Martin Liška <marxin at gcc dot gnu.org> ---
> Created attachment 39791
>   --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=39791&action=edit
> Really reduced test-case

So we are properly creating a DIE for m_fn1 early but then end up
removing it via prune_unused_types.  It looks like this is because
the DIE for C has the CU as parent rather than B::m_fn2.  It
first gets created in limbo (via dwarf2out_type_decl) because:

      /* If we're a function-scope tag, initially use a parent of NULL;
         this will be fixed up in decls_for_scope.  */
      if (decl_function_context (decl))
        context_die = NULL;

but we never end up calling dwarf2out_early_global_decl for B::m_fn2
and thus the limbo gets re-parented to the CU DIE (as we record
the TREE_TYPE for DW_TAG_class_type DIEs, not the TYPE_DECL):

              if (DECL_P (node->created_for))
                origin = get_context_die (DECL_CONTEXT 
(node->created_for));
              else if (TYPE_P (node->created_for))
                origin = scope_die_for (node->created_for, comp_unit_die 
());

and scope_die_for simply doesn't handle FUNCTION_DECL as containing_scope.

B::m_fn2 has been optimized out as unreachable which is the reason we
are not ending up in decls_for_scope eventually.

IMHO optimizing C as unused is ok.  The question is why we end up
with inlining m_fn1 ...

looks like we devirtualize the call in fn1 to B::C::m_fn1:

t.ii:25:14: note: speculatively devirtualizing call in void fn1(A&)/8 to 
virtual bool B::m_fn2() const::C::m_fn1() const/0
Indirect call -> speculative call void fn1(A&)/8 => virtual bool 
B::m_fn2() const::C::m_fn1() const/0
1 polymorphic calls, 0 devirtualized, 1 speculatively devirtualized, 0 
cold
0 have multiple targets, 0 overwritable, 0 already speculated (0 agree, 0 
disagree), 0 external, 0 not defined, 0 artificial, 0 infos dropped
Symbol table:

and -fno-devirtualize fixes it.

-> we shouldn't reclaim B::m_fn2 when we later end up devirtualizing
to B::m_fn2::C::m_fn1 (or rather we should never devirtualize to
a local class method?)

Reply via email to