Created attachment 15196 [details] test case foo.c On Linux/alpha, the function fesetexceptflag() clears some exception flags that are outside the EXCEPTS argument. This violates ISO C 23 ยง 7.6.4.5, which says: "The fesetexceptflag function attempts to set the floating-point status flags indicated by the argument excepts to the states stored in the object pointed to by flagp." How to reproduce: Compile and run the attached program. $ gcc -Wall foo.c -lm $ ./a.out Expected: It terminates with exit code 0. Actual: a.out: foo.c:58: main: Assertion `fetestexcept (FE_DIVBYZERO) == FE_DIVBYZERO' failed. Aborted When you compare the program's lines 49 and 58, you see that the invocation fesetexceptflag (&saved_flags_2, FE_OVERFLOW) not only modified the FE_OVERFLOW flag bit, but also cleared the FE_DIVBYZERO flag bit.
Seen on Debian 12.0/alpha.
Created attachment 15197 [details] proposed fix Find attached a proposed fix. The bug is obviously in glibc/sysdeps/alpha/fpu/fsetexcptflg.c . The line tmp = (tmp & ~SWCR_STATUS_MASK) | (*flagp & excepts & SWCR_STATUS_MASK); needs to be changed to tmp = (tmp & ~(excepts & SWCR_STATUS_MASK)) | (*flagp & excepts & SWCR_STATUS_MASK); A optimized expression (produces one less instruction when compiled by "alpha-linux-gnu-gcc -O2") is: tmp ^= (tmp ^ *flagp) & excepts & SWCR_STATUS_MASK;
Fixed on 2.39 (80a40a9e14d9a01e3f70c5b37ecd1da83033b6de).