consteval関数が未定義の動作を許可するのはなぜですか?


16

C ++には定数式の非常にきちんとした特性があります。それらの評価に未定義の動作を含めることはできません(7.7.4.7):

抽象マシン([intro.execution])の規則に従ってeの評価が次のいずれかを評価しない限り、式eはコア定数式です。

  • ...

  • このドキュメントの[intro]から[cpp]で指定されている未定義の動作を持つ操作[注:たとえば、符号付き整数オーバーフロー([expr.prop])、特定のポインター演算([expr.add])、ゼロによる除算、または特定のシフト演算—後記];

値を格納しようとする13!中でconstexpr int実際には、素敵なコンパイルエラーを生成します

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

出力:

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.

(ところで、エラーがf(13)の呼び出しであるのに、「call to 'f(3)'」と表示されるのはなぜですか?)

次に、から削除constexprしますxが、を作成fconstevalます。ドキュメントによると:

consteval-関数が即時関数であることを指定します。つまり、関数を呼び出すたびにコンパイル時定数を生成する必要があります。

私はそのようなプログラムが再びコンパイルエラーを引き起こすことを期待しています。しかし代わりに、プログラムはUBでコンパイルおよび実行されます。

何故ですか?

UPD:コメンターは、これがコンパイラのバグであると提案しました。私はそれを報告しました:https//bugs.llvm.org/show_bug.cgi?id = 43714


2
in call to 'f(3)'- これは奇妙です!例 あなたがf(123)clang を置く場合について警告しin call to 'f(119)'ます。
KamilCuk

これは単なるバグだと思います。標準では、「即時呼び出しは定数式である」ことが明確になっています。ただし、さらに複雑な状況が発生している可能性もあります(つまり、その要件が削除され、Clangが新しい動作を実装している可能性があります)。
ブライアン、

3
コンパイラのバグ。ここで見るものは何もありません。
TC

1
@JesperJuhl完了。
ミハイル、

4
@StoryTeller整数は2の補数ですが、オーバーフローはまだ定義されていません。
バリー

回答:


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.