You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[Clang] On GCC, C23 typeof strips noreturn attribute on function pointers #176070
[[gnu::noreturn]]
externvoid(*fptr)(void);
inttypeof_ext(inti, __typeof(fptr) p) {
p();
returni; // not emitted because p is noreturn
}
inttypeof_std(inti, typeof(fptr) p) {
p();
returni; // emitted on GCC C23
}
When under C23 and using the standard (not underscored) spelling of typeof, GCC would remove the noreturn attribute from the function pointer type.
From GCC's commit message (gcc-mirror/gcc@fa258f6) this seems to be intentional.
Could be dangerous if someone rely on this behavior and only test with GCC.
int typeof_ext(int i, __typeof(fptr) p) {
p();
return i; // not emitted because p is noreturn
}
int typeof_std(int i, typeof(fptr) p) {
p();
return i; // emitted on GCC C23
}
When under C23 and using the standard (not underscored) spelling of `typeof`, GCC would remove the `noreturn` attribute from the function pointer type.
From GCC's commit message (https://github.com/gcc-mirror/gcc/commit/fa258f6894801aef6785f0327594dc803da63fbd) this seems to be intentional.
Could be dangerous if someone rely on this behavior and only test with GCC.
</details>
I think this requires more thought; I'm not currently comfortable with the approach GCC took for several reasons. 1) users don't expect a difference between __typeof__ and typeof so this introduces a fun new footgun for them to reason about, 2) typeof should not be stripping type information; that creates an arms race where we then will find a need for typeof_but_for_real_this_time in cases where you actually want the real type as the type system sees it.
Note, Clang and GCC are already divergent in how we handle noreturn attributes; Clang treats __attribute__((noreturn)) and [[gnu::noreturn]] as being a fundamental part of the type. So you can do things like: typedef void func(void) __attribute__((noreturn)); in Clang and func has the expected type annotation effects; the same is not true in GCC where they ignore the attribute despite treating it as part of the function type in other scenarios: https://godbolt.org/z/d7xsT5Exq
Activity
shafik commentedon Jan 15, 2026
CC @AaronBallman
llvmbot commentedon Jan 15, 2026
@llvm/issue-subscribers-clang-frontend
Author: Hsiang-Ying Fu (fuhsnn)
Details
https://godbolt.org/z/e8M18778s ```C [[gnu::noreturn]] extern void(*fptr)(void);int typeof_ext(int i, __typeof(fptr) p) {
p();
return i; // not emitted because p is noreturn
}
int typeof_std(int i, typeof(fptr) p) {
p();
return i; // emitted on GCC C23
}
AaronBallman commentedon Jan 16, 2026
I think this requires more thought; I'm not currently comfortable with the approach GCC took for several reasons. 1) users don't expect a difference between
__typeof__andtypeofso this introduces a fun new footgun for them to reason about, 2) typeof should not be stripping type information; that creates an arms race where we then will find a need fortypeof_but_for_real_this_timein cases where you actually want the real type as the type system sees it.Note, Clang and GCC are already divergent in how we handle noreturn attributes; Clang treats
__attribute__((noreturn))and[[gnu::noreturn]]as being a fundamental part of the type. So you can do things like:typedef void func(void) __attribute__((noreturn));in Clang andfunchas the expected type annotation effects; the same is not true in GCC where they ignore the attribute despite treating it as part of the function type in other scenarios: https://godbolt.org/z/d7xsT5Exq