Warning g++ non expliqué

Le
jz
Bonjour

J'ai extrait d'un programme le code minimal suivant :
--
#include <iostream>
class truc {
int Ni;
void print ();
int test (int i);
};
void truc::print () {
std::cout << test (Ni-2);
}
int truc::test (int i) {
return (i<Ni) ? 1 : 2;
}
--

Avec g++ version 4.4.1 :
g++ -c -O2 -Wall truc.cpp
truc.cpp: In member function ‘void truc::print()’:
truc.cpp:11: warning: assuming signed overflow does not occur when
assuming that (X - c) <= X is always true

Ici le test (i<Ni) est toujours vrai, ce qui semble déranger g++.

Il n'y a plus de warning sans le -O2, ou avec des unsigned int (mais
j'ai besoin de int dans le vrai prog).

Je ne me vois pas écrire une fonction test() spécialisée pour les cas où
le test est inutile, d'autant plus que ces cas ne sautent pas aux yeux
dans le vrai prog comme ici (constantes et macros réparties dans
plusieurs fichiers), ou alors autant jeter la machine et tout calculer à
la main si elle ne veut plus bosser pour nous.

Fais-je une ânerie que je ne vois pas, ou bien est-ce g++ ?

Merci,
A+
Jacques
Vidéos High-Tech et Jeu Vidéo
Téléchargements
Vos réponses
Gagnez chaque mois un abonnement Premium avec GNT : Inscrivez-vous !
Trier par : date / pertinence
Fabien LE LEZ
Le #20967981
On Thu, 14 Jan 2010 00:07:56 +0100, jz
Fais-je une ânerie que je ne vois pas, ou bien est-ce g++ ?



Apparemment c'est g++ :
http://www.airs.com/blog/archives/120
Jean-Marc Bourguet
Le #20969811
jz
Ici le test (i<Ni) est toujours vrai, ce qui semble déranger g++.



Ca ne le derange pas. J'ai pas verifie exactement ce qu'il fait -- et
encore moins cherche a le faire version par version -- mais voici ma
comprehension des choses.

Le test "i < i - 2" (qui est en cause ici apres inlining) est un
comportement indefini. Face a de tels comportements, il y a -- au moins --
deux ecoles.

Celle qui dit "le compilateur peut faire n'importe quoi et il faut en
profiter pour optimiser le cas defini". Donc supprimer le test.

La deuxieme dit "C est un langage de base niveau, il faut faire ce qui est
naturel pour la machine cible, c'est a dire que le test doit etre vrai en
cas d'overflow; d'autant plus que c'est le comportement historique des
compilateurs C. Le comportement est formellement indefini mais c'est pour
permettre une implementation naturelle du C sur des machines exotiques, pas
pour laisser faire n'importe quoi sous pretexte d'optimisations".

Par defaut, g++ se comporte suivant la premiere ecole, mais donne un
warning. Il y a un flag (-fwrapv si j'ai bonne memoire) qui le fait se
comporter suivant la deuxieme.

A+

--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org
Jean-Marc Bourguet
Le #20969801
Jean-Marc Bourguet
jz
> Ici le test (i<Ni) est toujours vrai, ce qui semble déranger g++.

Ca ne le derange pas. J'ai pas verifie exactement ce qu'il fait -- et
encore moins cherche a le faire version par version -- mais voici ma
comprehension des choses.

Le test "i < i - 2" (qui est en cause ici apres inlining) est un
comportement indefini. Face a de tels comportements, il y a -- au moins --
deux ecoles.

Celle qui dit "le compilateur peut faire n'importe quoi et il faut en
profiter pour optimiser le cas defini". Donc supprimer le test.

La deuxieme dit "C est un langage de base niveau, il faut faire ce qui est
naturel pour la machine cible, c'est a dire que le test doit etre vrai en
cas d'overflow; d'autant plus que c'est le comportement historique des
compilateurs C. Le comportement est formellement indefini mais c'est pour
permettre une implementation naturelle du C sur des machines exotiques, pas
pour laisser faire n'importe quoi sous pretexte d'optimisations".

Par defaut, g++ se comporte suivant la premiere ecole, mais donne un
warning. Il y a un flag (-fwrapv si j'ai bonne memoire) qui le fait se
comporter suivant la deuxieme.



En passant, si tu utilises des unsigned, le test est vrai en cas
d'overflow et tout le monde est d'accord la dessus.

A+

--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org
jz
Le #20974531
Fabien LE LEZ a écrit :
On Thu, 14 Jan 2010 00:07:56 +0100, jz
Fais-je une ânerie que je ne vois pas, ou bien est-ce g++ ?



Apparemment c'est g++ :



ouf ;)
merci

a+
Jacques
jz
Le #20974691
Jean-Marc Bourguet a écrit :

Merci pour la réponse détaillée.

Le test "i < i - 2" (qui est en cause ici apres inlining) est un
comportement indefini. Face a de tels comportements, il y a -- au moins --
deux ecoles.



En fait ici c'est dans le sens i-2<i que le warning apparaît. Par contre
là où ça devient vraiment surprenant, c'est que en remplaçant -2 par -1
le warning disparaît.

Donc "i-2<i" risquerait d'être indéfini en cas de débordement (ça je
conçois), mais pas "i-1<i" ?

J'ai du mal à percevoir la logique.

A+
Jacques
Jean-Marc Bourguet
Le #20976741
jz
Jean-Marc Bourguet a écrit :

Merci pour la réponse détaillée.

> Le test "i < i - 2" (qui est en cause ici apres inlining) est un
> comportement indefini. Face a de tels comportements, il y a -- au moins --
> deux ecoles.

En fait ici c'est dans le sens i-2<i que le warning apparaît. Par contre là
où ça devient vraiment surprenant, c'est que en remplaçant -2 par -1
le warning disparaît.

Donc "i-2<i" risquerait d'être indéfini en cas de débordement (ça je
conçois), mais pas "i-1<i" ?



Je ne connais pas leur raisonnement. Une possibilite est qu'ils ne donnent
pas de warnings parce que le cas avec -1 est trop commum de maniere
legitime -- et un warning donne trop souvent quand le code est legitime
perds beaucoup de son interet. Une autre est que le cas avec -1 est traite
de maniere particuliere pour d'autres raisons et que personne n'a pense a
mettre le warning dans ce chemin d'execution la.

A+

--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org
Jean-Marc Desperrier
Le #21000861
Jean-Marc Bourguet wrote:
En passant, si tu utilises des unsigned, le test est vrai en cas
d'overflow et tout le monde est d'accord la dessus.



Euh, pourquoi ? Pour les unsigned, le fait de boucler sur UINT_MAX en
cas d'overflow est un comportement défini ?
espie
Le #21000851
In article Jean-Marc Desperrier
Jean-Marc Bourguet wrote:
En passant, si tu utilises des unsigned, le test est vrai en cas
d'overflow et tout le monde est d'accord la dessus.



Euh, pourquoi ? Pour les unsigned, le fait de boucler sur UINT_MAX en
cas d'overflow est un comportement défini ?



Les unsigned, c'est de l'arithmetique dans Z/nZ, avec n qui vaut la puissance
de 2 adequate. Et c'est un comportement garanti:

unsigned int i = UINT_MAX;
i+=3;
assert(i == 2);
Jean-Marc Desperrier
Le #21119441
Marc Espie wrote:
Les unsigned, c'est de l'arithmetique dans Z/nZ,
[...] c'est un comportement garanti:



OK, merci
Publicité
Poster une réponse
Anonyme