https://gcc.gnu.org/bugzilla/show_bug.cgi?id=27100
Patrick Palka <ppalka at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- Status|NEW |ASSIGNED CC| |ppalka at gcc dot gnu.org Assignee|unassigned at gcc dot gnu.org |ppalka at gcc dot gnu.org --- Comment #7 from Patrick Palka <ppalka at gcc dot gnu.org> --- This ICE is ultimately caused by duplicate_decls not retaining the DECL_PENDING_INLINE_P flag of the old declaration in the new declaration. Here's a test case that illustrates the same problem, and that does not depend on when garbage collection takes place: // { dg-do run } struct A { friend int foo (const A&) { return 7; } friend int foo (const A&); }; int main () { return foo (A ()) != 7; } Since the DECL_PENDING_INLINE_P flag does not get retained in the new declaration, cp_parser_late_parsing_for_member never processes the body of foo and so this test case fails at link time with an "undefined reference to 'foo'" error. Here's an untested patch that makes deplicate_decls retain DECL_PENDING_INLINE_P as well as DECL_PENDING_INLINE_INFO (which the old code only accidentally did, since DECL_SAVED_FUNCTION_DATA points to the same memory location as DECL_PENDING_INLINE_INFO). --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -2322,8 +2322,16 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend) } else { - if (DECL_PENDING_INLINE_INFO (newdecl) == 0) - DECL_PENDING_INLINE_INFO (newdecl) = DECL_PENDING_INLINE_INFO (olddecl); + DECL_PENDING_INLINE_P (newdecl) |= DECL_PENDING_INLINE_P (olddecl); + + if (DECL_PENDING_INLINE_P (newdecl) + && DECL_PENDING_INLINE_INFO (newdecl) == NULL) + DECL_PENDING_INLINE_INFO (newdecl) + = DECL_PENDING_INLINE_INFO (olddecl); + else if (!DECL_PENDING_INLINE_P (newdecl) + && DECL_SAVED_FUNCTION_DATA (newdecl) == NULL) + DECL_SAVED_FUNCTION_DATA (newdecl) + = DECL_SAVED_FUNCTION_DATA (olddecl); DECL_DECLARED_INLINE_P (newdecl) |= DECL_DECLARED_INLINE_P (olddecl);