Mengapa fungsi konsteval memungkinkan perilaku tidak terdefinisi?


16

Ada properti yang sangat rapi dari ekspresi konstan dalam C ++: evaluasi mereka tidak dapat memiliki perilaku yang tidak terdefinisi ( 7.7.4.7 ):

Ekspresi e adalah ekspresi konstanta inti kecuali evaluasi e, mengikuti aturan mesin abstrak ([intro.execution]), akan mengevaluasi salah satu dari yang berikut:

  • ...

  • sebuah operasi yang akan memiliki perilaku yang tidak ditentukan sebagaimana ditentukan dalam [intro] melalui [cpp] dokumen ini [Catatan: termasuk, misalnya, menandatangani integer overflow ([expr.prop]), aritmatika pointer tertentu ([expr.add]), pembagian dengan nol, atau operasi shift tertentu - catatan akhir];

Mencoba menyimpan nilai 13!dalam constexpr intmemang menghasilkan kesalahan kompilasi yang bagus :

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

Keluaran:

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 mengapa kesalahan mengatakan "panggil ke 'f (3)'", sementara itu adalah panggilan ke f (13)? ..)

Kemudian, saya menghapus constexprdari x, tetapi membuat fsebuah consteval. Menurut dokumen :

consteval - menetapkan bahwa fungsi adalah fungsi langsung, yaitu, setiap panggilan ke fungsi harus menghasilkan konstanta waktu kompilasi

Saya berharap bahwa program seperti itu lagi akan menyebabkan kesalahan kompilasi. Tetapi sebaliknya, program ini mengkompilasi dan berjalan dengan UB .

Mengapa demikian?

UPD: Komentator menyarankan bahwa ini adalah bug penyusun. Saya melaporkannya: https://bugs.llvm.org/show_bug.cgi?id=43714


2
in call to 'f(3)'- ini aneh! Ex. Jika Anda menaruh f(123)dentang memperingatkan in call to 'f(119)'.
KamilCuk

Saya pikir ini hanya bug. Standarnya jelas bahwa "doa segera akan menjadi ekspresi yang konstan". Namun, ada juga kemungkinan bahwa ada sesuatu yang lebih rumit sedang terjadi (yaitu, mungkin persyaratan itu akan dihapus dan Dentang menerapkan perilaku baru).
Brian

3
Bug penyusun. Tidak ada yang bisa dilihat di sini, bergeraklah.
TC

1
@JesperJuhl Selesai.
Mikhail

4
@StoryTeller Integers adalah pelengkap dua, tetapi overflow masih belum ditentukan.
Barry

Jawaban:


Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.