格式错误,无需诊断 (NDR):C++14 中的 ConstExpr 函数抛出

Ill-Formed, No Diagnostic Required (NDR): ConstExpr Function Throw in C++14

#include <iostream>
using namespace std;

constexpr int f(bool b){ return b ? throw 0 : 0; } // OK 

constexpr int f() { return f(true); } // Ill-Formed, No Diagnostic Required

int main(){

    try{
        f();
    }catch( int x ){
        cout << "x = " << x << endl;
    }

    return 0;
}

此代码是 C++14 标准 (ISO/IEC 14882:2014) 第 7.1.5 节第 5 段的示例:

For a non-template, non-defaulted constexpr function or a non-template, non-defaulted, non-inheriting constexpr constructor, if no argument values exist such that an invocation of the function or constructor could be an evaluated subexpression of a core constant expression (5.19), the program is ill-formed; no diagnostic required.

它被描述为“格式错误,不需要诊断”因为抛出表达式不是核心常量表达式 (5.19/2)。但是,Clang 和 GCC 都成功编译了它 (Ideone)。

我还发现了这些关于标准措辞的有趣讨论:

是否有可能 a/this 程序“格式错误,不需要诊断”并且允许编译器成功编译它?

Is this code correct (and there is a mistake in the Standard)

标准决定了程序是否 "correct",即 well-formed。该标准明确表示程序是 ill-formed.

or is it incorrect (and there is a bug in both Clang and GCC)?

程序是 ill-formed(不正确)。 clang 和 gcc 的观察行为都符合标准。

Is it possible that a/this program is "ill-formed, no diagnostic required" and that the compilers are allowed to compile it successfully?

是的。该标准不要求 ill-formed 程序必须编译失败。如果程序违反规则,它仅要求实现发出至少一条诊断消息。有些规则是不可诊断的,如果违反了这些规则,则不需要诊断。

事实上,该规则被认为是 "not diagnosable",因为编译器很难(通常)证明违反了该规则。 "no diagnostic required" 规则违规编译成功是很典型的。

如果 ill-formed 程序确实可以编译,则标准没有指定此类程序的行为方式。