#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?
throw
, compile and raise a warning and it will be conformant, a third one can choose to silently compile after removing the offending expression, or to compile the program in a run time error and all will be conformant. – Rimola