title: Why does integer overflow on x86 with GCC cause an infinite loop?
body: <p><strong>The following code goes into an infinite loop on GCC:</strong></p>
  
  <pre><code>#include &lt;iostream&gt;
  using namespace std;
  
  int main(){
      int i = 0x10000000;
  
      int c = 0;
      do{
          c++;
          i += i;
          cout &lt;&lt; i &lt;&lt; endl;
      }while (i &gt; 0);
  
      cout &lt;&lt; c &lt;&lt; endl;
      return 0;
  }
  </code></pre>
  
  <p><strong>So here's the deal:</strong> Signed integer overflow is technically undefined behavior. But GCC on x86 implements integer arithmetic using x86 integer instructions - which wrap on overflow.</p>
  
  <p>Therefore, I would have expected it to wrap on overflow - despite the fact that it is undefined behavior. But that's clearly not the case. So what did I miss?</p>
  
  <p><strong>I compiled this using:</strong></p>
  
  <pre><code>~/Desktop$ g++ main.cpp -O2
  </code></pre>
  
  <p><strong>GCC Output:</strong></p>
  
  <pre><code>~/Desktop$ ./a.out
  536870912
  1073741824
  -2147483648
  0
  0
  0
  
  ... (infinite loop)
  </code></pre>
  
  <p>With optimizations disabled, there is no infinite loop and the output is correct. Visual Studio also correctly compiles this and gives the following result:</p>
  
  <p><strong>Correct Output:</strong></p>
  
  <pre><code>~/Desktop$ g++ main.cpp
  ~/Desktop$ ./a.out
  536870912
  1073741824
  -2147483648
  3
  </code></pre>
  
  <p><strong>Here are some other variations:</strong></p>
  
  <pre><code>i *= 2;   //  Also fails and goes into infinite loop.
  i &lt;&lt;= 1;  //  This seems okay. It does not enter infinite loop.
  </code></pre>
  
  <p><strong>Here's all the relevant version information:</strong></p>
  
  <pre><code>~/Desktop$ g++ -v
  Using built-in specs.
  COLLECT_GCC=g++
  COLLECT_LTO_WRAPPER=/usr/lib/x86_64-linux-gnu/gcc/x86_64-linux-gnu/4.5.2/lto-wrapper
  Target: x86_64-linux-gnu
  Configured with: ..
  
  ...
  
  Thread model: posix
  gcc version 4.5.2 (Ubuntu/Linaro 4.5.2-8ubuntu4) 
  ~/Desktop$ 
  </code></pre>
  
  <p><strong>So the question is:</strong> Is this a bug in GCC? Or did I misunderstand something about how GCC handles integer arithmetic?</p>
  
  <p>*I'm tagging this C as well, because I assume this bug will reproduce in C. (I haven't verified it yet.)</p>
  
  <p>EDIT:</p>
  
  <p>Here's the assembly of the loop: (if I recognized it properly)</p>
  
  <pre><code>.L5:
  addl    %ebp, %ebp
  movl    $_ZSt4cout, %edi
  movl    %ebp, %esi
  .cfi_offset 3, -40
  call    _ZNSolsEi
  movq    %rax, %rbx
  movq    (%rax), %rax
  movq    -24(%rax), %rax
  movq    240(%rbx,%rax), %r13
  testq   %r13, %r13
  je  .L10
  cmpb    $0, 56(%r13)
  je  .L3
  movzbl  67(%r13), %eax
  .L4:
  movsbl  %al, %esi
  movq    %rbx, %rdi
  addl    $1, %r12d
  call    _ZNSo3putEc
  movq    %rax, %rdi
  call    _ZNSo5flushEv
  cmpl    $3, %r12d
  jne .L5
  </code></pre>