https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67857
Bug ID: 67857 Summary: noreturn + volatile results in wrong code Product: gcc Version: 5.2.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: middle-end Assignee: unassigned at gcc dot gnu.org Reporter: karl at skomski dot com Target Milestone: --- On Linux/x86-64, GCC 5.2 (g++ -m32 -O1) optimizes this test into wrong code: Important is the volatile argument to Increment and __noreturn__ function in the if clause. ``` #include <stdlib.h> #include <stdio.h> int Increment(volatile int* ptr, int increment) { // volatile int temp = *ptr; *ptr += increment; return temp + increment; } int main() { // Test at rollover boundary between int_max and int_min. int test_val = 1 << (sizeof(int) * 8 - 1); int value = -1 ^ test_val; int new_value = Increment(&value, 1); if (test_val != value) exit(100); if (value != new_value) exit(200); return 0; } ``` produces ``` Fatal 200 [1] 3789 exit 200 ``` ``` .cfi_startproc lea ecx, [esp+4] .cfi_def_cfa 1, 0 and esp, -16 push DWORD PTR [ecx-4] push ebp .cfi_escape 0x10,0x5,0x2,0x75,0 mov ebp, esp push ecx .cfi_escape 0xf,0x3,0x75,0x7c,0x6 sub esp, 20 mov DWORD PTR [ebp-12], 2147483647 mov eax, DWORD PTR [ebp-12] mov eax, DWORD PTR [ebp-12] add eax, 1 mov DWORD PTR [ebp-12], eax cmp DWORD PTR [ebp-12], -2147483648 je .L4 sub esp, 12 push 100 call exit .L4: sub esp, 12 push 200 call exit .cfi_endproc ```