Perché una funzione consteval consente un comportamento indefinito?


16

Esiste una proprietà molto accurata delle espressioni costanti in C ++: la loro valutazione non può avere un comportamento indefinito ( 7.7.4.7 ):

Un'espressione e è un'espressione costante centrale a meno che la valutazione di e, seguendo le regole della macchina astratta ([intro.execution]), valuti una delle seguenti:

  • ...

  • un'operazione che avrebbe un comportamento indefinito come specificato da [introduzione] a [cpp] di questo documento [Nota: tra cui, ad esempio, overflow di interi con segno ([prop.espr.]), aritmetica di alcuni puntatori ([expr.add]), divisione per zero, o determinate operazioni di spostamento - nota finale];

Cercare di memorizzare il valore di 13!in a produce inconstexpr int effetti un buon errore di compilazione :

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;
}

Produzione:

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.

(A proposito, perché l'errore dice "call to 'f (3)'", mentre è una chiamata a f (13)? ..)

Quindi, rimuovo constexprda x, ma crea fun consteval. Secondo i documenti :

consteval: specifica che una funzione è una funzione immediata, ovvero ogni chiamata alla funzione deve produrre una costante di tempo di compilazione

Mi aspetto che un tale programma provochi di nuovo un errore di compilazione. Invece, il programma viene compilato ed eseguito con UB .

Perché?

UPD: i commentatori hanno suggerito che si tratta di un bug del compilatore. L'ho segnalato: https://bugs.llvm.org/show_bug.cgi?id=43714


2
in call to 'f(3)'- Questo è strano! Ex. Se metti f(123)clang avverte in call to 'f(119)'.
KamilCuk,

Penso che questo sia solo un bug. Lo standard è chiaro che "un'invocazione immediata deve essere un'espressione costante". Tuttavia, è anche possibile che ci sia qualcosa di più complicato in corso (cioè, forse quel requisito verrà rimosso e Clang sta implementando il nuovo comportamento).
Brian,

3
Bug del compilatore. Niente da vedere qui, vai avanti.
TC

1
@JesperJuhl Done.
Mikhail,

4
@StoryTeller Gli interi sono il complemento di due, ma l'overflow è ancora indefinito.
Barry,

Risposte:


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.