Il existe une propriété très soignée d'expressions constantes en C ++: leur évaluation ne peut pas avoir un comportement indéfini ( 7.7.4.7 ):
Une expression e est une expression constante de base à moins que l'évaluation de e, suivant les règles de la machine abstraite ([intro.execution]), n'évalue l'un des éléments suivants:
...
une opération qui aurait un comportement non défini comme spécifié dans [intro] à [cpp] de ce document [Remarque: y compris, par exemple, un débordement d'entier signé ([expr.prop]), une certaine arithmétique de pointeur ([expr.add]), division par zéro, ou certaines opérations de décalage - note de fin];
Essayer de stocker la valeur de 13!
dans un produit enconstexpr int
effet une belle erreur de compilation :
constexpr int f(int n)
{
int r = n--;
for (; n > 1; --n) r *= n;
return r;
}
int main()
{
constexpr int x = f(13);
return x;
}
Production:
9:19: error: constexpr variable 'x' must be initialized by a constant expression
constexpr int x = f(13);
^ ~~~~~
4:26: note: value 3113510400 is outside the range of representable values of type 'int'
for (; n > 1; --n) r *= n;
^
9:23: note: in call to 'f(3)'
constexpr int x = f(13);
^
1 error generated.
(BTW pourquoi l'erreur dit "appel à 'f (3)'", alors qu'il s'agit d'un appel à f (13)? ..)
Ensuite, je retire constexpr
de x
, mais faire f
un consteval
. Selon les documents :
consteval - spécifie qu'une fonction est une fonction immédiate, c'est-à-dire que chaque appel à la fonction doit produire une constante de compilation
Je m'attends à ce qu'un tel programme provoque à nouveau une erreur de compilation. Mais à la place, le programme se compile et s'exécute avec UB .
Pourquoi donc?
UPD: Les commentateurs ont suggéré qu'il s'agissait d'un bogue du compilateur. Je l'ai signalé: https://bugs.llvm.org/show_bug.cgi?id=43714
in call to 'f(3)'
- cela est étrange! Ex. Si vous mettezf(123)
clang met en gardein call to 'f(119)'
.