Since C++17 (via P0012R1), except specifications have became part of the type system, and a noexcept function is implicitly convertible to a pointer to a non-noexcept function. However,
it seems that calling a noexcept function through a pointer to a non-noexcept function is UB, as
[expr.call]/6 remains unchanged (known compilers accept such call in constant evaluation in C++17 and later modes).
In the other hand, the definition “int main() noexcept {}” was guaranteed to be supported in C++11/14 (as noexcept was not part of the function type), but the guarantee is removed
by P0012R1, because [basic.start.main]/2 says about the type of main and remains unchanged.
These cases should be addressed as CWG issue(s) IMO.
I don't consider the second case here to be a defect; it's more of a feature that you're not allowed to declare `main` to be `noexcept`. To declare a function to be `noexcept` means that it does not emit an exception to its caller (and if you try, the program will terminate). Well, `main` has no "caller" as far as the C++ standard is concerned, so who would it be emitting exceptions to? And if someone tries to emit an exception from `main`, the program terminates.
Which brings us to the next question: what exactly would `noexcept` `main` mean?
If an appropriate `catch` clause is not found (either before reaching past `main` or a thread function), `std::terminate` is called. However, whether the stack is unwound is implementation defined. And this is basically the same as what happens if you try to throw past a `noexcept` function; whether the stack is unwound is still implementation-defined.
So what's the point?