gcc/ 2011-06-02 Mikael Pettersson PR tree-optimization/49243 * calls.c (setjmp_call_p): Also check if fndecl has the returns_twice attribute. gcc/testsuite/ 2011-06-02 Mikael Pettersson PR tree-optimization/49243 * gcc.dg/pr49243.c: New. --- gcc-4.6.0/gcc/calls.c.~1~ 2011-03-03 22:56:58.000000000 +0100 +++ gcc-4.6.0/gcc/calls.c 2011-06-02 14:41:47.000000000 +0200 @@ -548,6 +548,8 @@ special_function_p (const_tree fndecl, i int setjmp_call_p (const_tree fndecl) { + if (DECL_IS_RETURNS_TWICE (fndecl)) + return ECF_RETURNS_TWICE; return special_function_p (fndecl, 0) & ECF_RETURNS_TWICE; } --- gcc-4.6.0/gcc/testsuite/gcc.dg/pr49243.c.~1~ 1970-01-01 01:00:00.000000000 +0100 +++ gcc-4.6.0/gcc/testsuite/gcc.dg/pr49243.c 2011-06-02 14:41:47.000000000 +0200 @@ -0,0 +1,25 @@ +/* PR tree-optimization/49243 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -Winline" } */ + +extern unsigned long jb[]; +extern int my_setjmp(unsigned long jb[]) __attribute__((returns_twice)); +extern int decode(const char*); + +static inline int wrapper(const char **s_ptr) /* { dg-warning "(inlining failed|function 'wrapper' can never be inlined because it uses setjmp)" } */ +{ + if (my_setjmp(jb) == 0) { + const char *s = *s_ptr; + while (decode(s) != 0) + *s_ptr = ++s; + return 0; + } else + return -1; +} + +void parse(const char *data) +{ + const char *s = data; + if (!(wrapper(&s) == -1 && (s - data) == 1)) /* { dg-warning "called from here" } */ + __builtin_abort(); +}