Pourquoi ce code se comporte-t-il différemment si l’optimisation (-O2, -O3) est utilisée?

J’ai dû coder certaines routines de vérification et elles semblent se comporter différemment si l’on utilise -O0, -O1, -O2 ou -O3.

Ci-dessous, j’ai créé un exemple minimal qui fonctionne bien pour -O0 et -O1. Mais en utilisant -O2 ou -O3, le comportement a changé. Dans les cas -O0 et -O1, la boucle for incrémente l’entier et la première fois qu’elle atteint le maximum, le débordement se produit et la routine de vérification se déclenche. Dans l’autre cas, la boucle for ne se rompt jamais, même si le nombre entier devient négatif.

Code

#include  inline bool check(const int i) { if (i < 0) return false; else return true; } int main() { for (int i = 0;; i += 50000000) { std::cout << i << std::endl; const bool succ = check(i); if (succ == false) { std::cout << "Overflow: " << i << std::endl; break; } } return 0; } 

Pourquoi le compilateur est-il autorisé à l’optimiser?

En essayant avec gcc, clang et icc, seul l’icc le corrige dans toutes les variantes d’optimisation que les deux autres n’ont pas.

Le dépassement d’entier signé donne un comportement non défini . Ainsi, le compilateur a toute latitude pour implémenter ce cas à sa guise.