Back in 2007 glibc gained some logic to implement "error" and "error_at_line" by splitting into zero and non-zero cases, with the nonzero case calling a "noreturn" function [1].
This doesn't seem to work. I tested back to 4.8.1 with Compiler Explorer [2], which seems to be the earliest GCC that supports -fdump- tree-original=stderr. What happens is that glibc's __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 ()); } comes out of GCC's C frontend as: { if (0) { __error_noreturn (__status, __errnum, __format, __builtin_va_arg_pack ()); } else { __error_alias (__status, __errnum, __format, __builtin_va_arg_pack ()); } } since __status is not a builtin constant, and this rapidly gets optimized down to just: __error_alias (__status, __errnum, __format, __builtin_va_arg_pack ()); and so by the time GCC gets to try inlining calls to error (EXIT_FAILURE, ...etc we just have a call to __error_alias, and any "noreturn" logic is lost. glib'c attempt to specialize the cases is causing false positives from GCC's -fanalyzer, which is how I spotted this [3]. It's probably trivial to workaround the issue within -fanalyzer, but I wonder to what extent glibc has further such specializations being thwarted by gcc optimizing away the __builtin_constant_p, and if gcc should be doing this (e.g. keep it around for __always_inline__ functions???), hence I thought it worth sharing this to both mailing lists. Thoughts? Dave [1] ("Specializations of error functions" https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=fae56ce808e36e8112d15189bf4337b3a39ee683 [2] https://godbolt.org/z/WsvqxP6hY [3] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115724