This fixes PR48354 by streaming DECL_ORIGINAL_TYPE. LTO bootstrapped and tested on x86_64-unknown-linux-gnu, applied.
Richard. 2011-12-13 Richard Guenther <rguent...@suse.de> PR lto/48354 * tree.c (find_decls_types_r): Also walk DECL_ORIGINAL_TYPE. * tree-streamer-in.c (lto_input_ts_decl_non_common_tree_pointers): Stream DECL_ORIGINAL_TYPE. * tree-streamer-out.c (write_ts_decl_non_common_tree_pointers): Likewise. lto/ * lto.c (lto_ft_decl_non_common): When we merged DECL_ORIGINAL_TYPE with the type of the TYPE_DECL clear DECL_ORIGINAL_TYPE. * g++.dg/lto/pr48354-1_0.C: New testcase. Index: gcc/tree.c =================================================================== *** gcc/tree.c.orig 2011-12-13 13:36:34.000000000 +0100 --- gcc/tree.c 2011-12-13 13:41:24.000000000 +0100 *************** find_decls_types_r (tree *tp, int *ws, v *** 4796,4801 **** --- 4796,4802 ---- { fld_worklist_push (DECL_ARGUMENT_FLD (t), fld); fld_worklist_push (DECL_VINDEX (t), fld); + fld_worklist_push (DECL_ORIGINAL_TYPE (t), fld); } else if (TREE_CODE (t) == FIELD_DECL) { Index: gcc/testsuite/g++.dg/lto/pr48354-1_0.C =================================================================== *** /dev/null 1970-01-01 00:00:00.000000000 +0000 --- gcc/testsuite/g++.dg/lto/pr48354-1_0.C 2011-12-13 13:41:24.000000000 +0100 *************** *** 0 **** --- 1,16 ---- + // { dg-lto-do link } + // { dg-lto-options { { -g -flto } } } + // { dg-extra-ld-options "-r -nostdlib" } + + template<typename T> struct Identity { typedef T type; }; + struct S { + typedef void (S::*FP)(); + FP fp; + }; + void g(); + void f() { + typedef Identity<S>::type Dummy; + S s; + g(); + } + Index: gcc/tree-streamer-in.c =================================================================== *** gcc/tree-streamer-in.c.orig 2011-12-13 13:36:34.000000000 +0100 --- gcc/tree-streamer-in.c 2011-12-13 13:41:24.000000000 +0100 *************** lto_input_ts_decl_non_common_tree_pointe *** 602,607 **** --- 602,609 ---- DECL_ARGUMENTS (expr) = stream_read_tree (ib, data_in); DECL_RESULT (expr) = stream_read_tree (ib, data_in); } + else if (TREE_CODE (expr) == TYPE_DECL) + DECL_ORIGINAL_TYPE (expr) = stream_read_tree (ib, data_in); DECL_VINDEX (expr) = stream_read_tree (ib, data_in); } Index: gcc/tree-streamer-out.c =================================================================== *** gcc/tree-streamer-out.c.orig 2011-12-13 13:36:34.000000000 +0100 --- gcc/tree-streamer-out.c 2011-12-13 13:41:24.000000000 +0100 *************** write_ts_decl_non_common_tree_pointers ( *** 508,513 **** --- 508,515 ---- stream_write_tree (ob, DECL_ARGUMENTS (expr), ref_p); stream_write_tree (ob, DECL_RESULT (expr), ref_p); } + else if (TREE_CODE (expr) == TYPE_DECL) + stream_write_tree (ob, DECL_ORIGINAL_TYPE (expr), ref_p); stream_write_tree (ob, DECL_VINDEX (expr), ref_p); } Index: gcc/lto/lto.c =================================================================== *** gcc/lto/lto.c.orig 2011-12-12 16:55:19.000000000 +0100 --- gcc/lto/lto.c 2011-12-13 13:48:19.000000000 +0100 *************** lto_ft_decl_non_common (tree t) *** 381,386 **** --- 381,393 ---- LTO_FIXUP_TREE (DECL_ARGUMENT_FLD (t)); LTO_FIXUP_TREE (DECL_RESULT_FLD (t)); LTO_FIXUP_TREE (DECL_VINDEX (t)); + /* The C frontends may create exact duplicates for DECL_ORIGINAL_TYPE + like for 'typedef enum foo foo'. We have no way of avoiding to + merge them and dwarf2out.c cannot deal with this, + so fix this up by clearing DECL_ORIGINAL_TYPE in this case. */ + if (TREE_CODE (t) == TYPE_DECL + && DECL_ORIGINAL_TYPE (t) == TREE_TYPE (t)) + DECL_ORIGINAL_TYPE (t) = NULL_TREE; } /* Fix up fields of a decl_non_common T. */