Ill-Formed, No Diagnostic Required (NDR): ConstExp

2019-02-25 21:05发布

问题:

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

This code is an example from the C++14 Standard (ISO/IEC 14882:2014), Section 7.1.5, Paragraph 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.

It is described as "ill-formed, no diagnostic required" because a throw-expression is not a core constant expression (5.19/2). However, both Clang and GCC compile it successfully (Ideone).

  • Is this code correct (and there is a mistake in the Standard) or is it incorrect (and there is a bug in both Clang and GCC)?

I also found these interesting discussions about the Standard wording:

  • Difference between Undefined Behavior and Ill-formed, no diagnostic message required
  • What is the rationale to "no diagnostic required"?
  • What is the C++ compiler required to do with ill-formed programs according to the Standard?

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

回答1:

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

The standard is what decides if a program is "correct" i.e. well-formed. The standard explicitly says that the program is ill-formed.

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

The program is ill-formed (incorrect). Both clang and gcc are standard compliant in their observed behaviour.

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

Yes. The standard doesn't require that an ill-formed program must fail to compile. It merely requires that the implementation issues at least one diagnostic message, if the program violates the rules. Some rules are not diagnosable, and diagnostic is not required if such rules are violated.

In fact, the rule is considered "not diagnosable" because it would be very difficult for the compiler to prove (in general) that the rule is violated. It is quite typical that "no diagnostic required" rule violations compile successfully.

If an ill-formed program does compile, the standard does not specify how such program should behave.