Строка i = i + foo();
в вашей программе не определена, но не определена.
Компиляторы пытаются выдавать предупреждения без ложных срабатываний (каждый раз, когда компилятор предупреждает, есть дефект, который должен исправить программист) или, по крайней мере, с очень низким уровнем ложных срабатываний. Это значит, что взамен у них немало ложных негативов. В соответствии с той же философией, компиляторы обычно не предупреждают о неопределенном поведении.
Чтобы получить предупреждение о вашей программе, вы должны изучить статические анализаторы, которые более агрессивны в отношении предупреждений, за счет чуть большего количества ложных срабатываний. Статические анализаторы могут очень хорошо решить, чтобы предупредить о неопределенном поведении. Некоторые из них даже предупреждают об определенных поведениях, которые, хотя и определены, указывают на то, что программист, вероятно, был сбит с толку.