This fixes PR55660 where a different setting of -f[un-]signed-char at compile vs. link-time lead to ICEs. This is because the not preloading of char_type_node isn't working on i?86 as char_type_node is reached via its va_list_type_node type (which is char *, not unsigned char * or signed char * and not void * either).
Short of rejecting different -f[un-]signed-char at link time (without a good means to detect the default) this avoids ICEing as designed. LTO bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk. Richard. 2012-12-13 Richard Biener <rguent...@suse.de> PR lto/55660 * tree-streamer.c (record_common_node): Check that we are not recursively pre-loading nodes we want to skip. Handle char_type_node appearing as part of va_list_type_node. * gcc.dg/lto/pr55660_0.c: New testcase. * gcc.dg/lto/pr55660_1.c: Likewise. Index: gcc/tree-streamer.c =================================================================== *** gcc/tree-streamer.c (revision 194444) --- gcc/tree-streamer.c (working copy) *************** streamer_tree_cache_lookup (struct strea *** 237,242 **** --- 237,252 ---- static void record_common_node (struct streamer_tree_cache_d *cache, tree node) { + /* If we recursively end up at nodes we do not want to preload simply don't. + ??? We'd want to verify that this doesn't happen, or alternatively + do not recurse at all. */ + if (node == char_type_node) + return; + + gcc_checking_assert (node != boolean_type_node + && node != boolean_true_node + && node != boolean_false_node); + /* We have to make sure to fill exactly the same number of elements for all frontends. That can include NULL trees. As our hash table can't deal with zero entries we'll simply stream Index: gcc/testsuite/gcc.dg/lto/pr55660_0.c =================================================================== *** gcc/testsuite/gcc.dg/lto/pr55660_0.c (revision 0) --- gcc/testsuite/gcc.dg/lto/pr55660_0.c (working copy) *************** *** 0 **** --- 1,11 ---- + /* { dg-lto-do run } */ + /* { dg-extra-ld-options { -funsigned-char } } */ + + char n[3] = {'a','b','c'}; + int foo(char *x) + { + if (*x == 'b') + return (int)*x; + *x = 'y'; + return 0; + } Index: gcc/testsuite/gcc.dg/lto/pr55660_1.c =================================================================== *** gcc/testsuite/gcc.dg/lto/pr55660_1.c (revision 0) --- gcc/testsuite/gcc.dg/lto/pr55660_1.c (working copy) *************** *** 0 **** --- 1,15 ---- + extern int foo (char*); + extern void abort (void); + + extern char n[3]; + + int main () + { + int i, m = 0; + for (i = 0; i < 3; i++) + m += foo(&n[i]); + + if (m != 'b') + abort (); + return 0; + }