------- Comment #6 from hjl dot tools at gmail dot com 2008-08-06 13:51 ------- >From Xuepeng:
__attribute__((noinline, used)) void foo (int a, ...) { va_list arg; char *p; int size; va_start (arg, a); size = va_arg (arg, int); if (size != 2) /*A*/ abort (); p = (char *) __builtin_alloca (size + 1); va_end (arg); if (v < 0) /*B*/ abort (); } This bug is caused by label optimization. Function compute_barrier_args_size intends to walk the whole function rtl and compute args_size on BARRIERS. When it reached the first if statement (size != 2), it will compute the destination of this if statement, the destination was supposed to be at /*A*/ and then set barrier_args_size[/*A*/]=cur_args_size. Unfortunately the destination /*A*/ was optimized to /*B*/, so the actual result is barrier_args_size[/*B*/] was set to cur_args_size. And at this point the cur_args_size was still zero, so the barrier_args_size[/*B*/]=0. The __builtin_alloca will adjust stack pointer and make cur_args_size=32. The function compute_barrier_args_size continued and reached label /*B*/. According to the author's comment that barrier_args_size[/*B*/] != -1 means that the insns starting with this label have been already scanned or are in the worklist, so the author thought barrier_args_size[/*B*/] should be cur_args_size which is 32 now. But in fact the insns starting with this label havn't been scanned, the barrier_args_size[/*B*/] was set to 0 just because of label optimization. So the assert (barrier_args_size[/*B*/]== cur_args_size) was generated. If change label /*A*/ to something like v=0 rather than abort (), there will be no compiler errors. -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=37022