This fixes PR53470 - I for quite some time wanted to remove that conditional clearing of TYPE_CONTEXT from free_lang_data_in_type but failed to do so because we regress. I've debugged it down to the C frontend having sometimes BLOCK as TYPE_CONTEXT for a type. So, simply replace such BLOCK with the nearest non-BLOCK we can get at.
Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk. Richard. 2012-06-11 Richard Guenther <rguent...@suse.de> PR middle-end/53470 * tree.c (free_lang_data_in_type): Do not clear TYPE_CONTEXT but replace it with the first non-BLOCK context. * g++.dg/lto/pr53470_0.C: New testcase. * gcc.dg/lto/pr53470_0.c: Likewise. Index: gcc/tree.c =================================================================== --- gcc/tree.c (revision 188384) +++ gcc/tree.c (working copy) @@ -4575,11 +4575,17 @@ free_lang_data_in_type (tree type) free_lang_data_in_one_sizepos (&TYPE_SIZE (type)); free_lang_data_in_one_sizepos (&TYPE_SIZE_UNIT (type)); - if (debug_info_level < DINFO_LEVEL_TERSE - || (TYPE_CONTEXT (type) - && TREE_CODE (TYPE_CONTEXT (type)) != FUNCTION_DECL - && TREE_CODE (TYPE_CONTEXT (type)) != NAMESPACE_DECL)) - TYPE_CONTEXT (type) = NULL_TREE; + if (TYPE_CONTEXT (type) + && TREE_CODE (TYPE_CONTEXT (type)) == BLOCK) + { + tree ctx = TYPE_CONTEXT (type); + do + { + ctx = BLOCK_SUPERCONTEXT (ctx); + } + while (ctx && TREE_CODE (ctx) == BLOCK); + TYPE_CONTEXT (type) = ctx; + } } Index: gcc/testsuite/g++.dg/lto/pr53470_0.C =================================================================== --- gcc/testsuite/g++.dg/lto/pr53470_0.C (revision 0) +++ gcc/testsuite/g++.dg/lto/pr53470_0.C (revision 0) @@ -0,0 +1,26 @@ +// { dg-lto-do link } +// { dg-lto-options { { -g -flto } } } + +class sp_counted_base; +class shared_count { + sp_counted_base *pi_; +public: + template<class Y> shared_count(Y) : pi_() {} + ~shared_count() {} +}; +template<class T> struct shared_ptr { + T element_type; + template<class Y> shared_ptr(Y) : pn(0) {} + shared_count pn; +}; +template<class> class ECGetterBase; +template<class T> struct ExtensionCord { + struct Holder { + ECGetterBase<T> *getter_; + }; + ExtensionCord() : holder_(new Holder) {} + + shared_ptr<Holder> holder_; +}; +ExtensionCord<int> a; +int main() {} Index: gcc/testsuite/gcc.dg/lto/pr53470_0.c =================================================================== --- gcc/testsuite/gcc.dg/lto/pr53470_0.c (revision 0) +++ gcc/testsuite/gcc.dg/lto/pr53470_0.c (revision 0) @@ -0,0 +1,9 @@ +/* { dg-lto-do link } */ +/* { dg-lto-options { { -flto } { -flto -g } } } */ + +int main () +{ + { + union A { } v; + } +}