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);

Reply via email to