https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115724
--- Comment #5 from David Malcolm <dmalcolm at gcc dot gnu.org> --- glib'c bits/error.h has: /* If we know the function will never return make sure the compiler realizes that, too. */ __extern_always_inline void error (int __status, int __errnum, const char *__format, ...) { if (__builtin_constant_p (__status) && __status != 0) __error_noreturn (__status, __errnum, __format, __va_arg_pack ()); else __error_alias (__status, __errnum, __format, __va_arg_pack ()); } and similar for error_at_line. However, looking at GENERIC (via -fdump-tree-original=stderr) https://godbolt.org/z/dqWr1G97s I see that this is coming out of the C front end as: ;; Function error (null) ;; enabled by -tree-original { if (0) { __error_noreturn (__status, __errnum, __format, __builtin_va_arg_pack ()); } else { __error_alias (__status, __errnum, __format, __builtin_va_arg_pack ()); } } before any of GCC's inlining logic gets to work on it. Hence "test" quickly gets optimized down to just: __error_alias (__status_2(D), __errnum_3(D), __format_4(D), __builtin_va_arg_pack ()); and this is what is inlined into the callsite of "error". Hence by the time the analyzer sees it we have a call to "__error_alias" which the analyzer/kf.cc doesn't recognize, and conservatively assumes could return. So there are arguably three issues here: (a) should gcc keep the __builtin_constant_p around longer so that it's still around when the inliner gets a chance to work on it? (I don't know if this is a good idea or not) (b) should glibc's header be rewritten (perhaps losing the __builtin_constant_p?) (c) the analyzer's special-casing for error and error_at_line should also recognize __error_alias and __error_at_line_alias (probably an easy workaround)