Ethin wrote:I know what your saying, but your still overthinking the problem.
Don't judge my thinking process just because you disagree with my ideas
Ethin wrote:You don't want to change the ABI for something like noexcept.
That is a subjective statement. Clearly, there is a high price for changing the ABI and I understand why compiler engineers preferred not to, but, ultimately, everything is arbitrary. There are no "laws" of computer science that would force one decision or another. It's about making trade-offs. It's possible that, if I was in the position to decide, I would have taken the same decision (to not include it in the ABI), but because of cost effectiveness, not because it wouldn't be useful.
Ethin wrote:I'm not even sure how you even could, especially since the ABI (if I'm not mistaken) does not specify how exceptions are passed over the ABI boundary. Why do you think dealing with C++ exceptions over FFI is so hard?
The ABI for exceptions and anything else in C++ is
well defined for pairs <compiler, platform> but the problem is that it's not officially documented and multiple compilers couldn't agree to commit to a specific ABI for a specific platform. For C, we have cdecl, stdcall, fastcall etc. We also have Microsoft x64 and System V AMD64 for x86_64 and who knows how many ABIs for other architectures. For C++, because compiler engineers wanted to have more flexibility, couldn't agree on anything particular. Other compiled languages don't have a standard documented ABI too. Not having a formally-specified ABI, means more flexibility for future changes. That's why FFI means using the C ABI for that platform, because is the common denominator. Therefore, with FFI we cannot throw exceptions, because in C there is no such thing.
Ethin wrote:When it comes to attributes or specifiers within C++, your focus should solely be on the language. The noexcept-specifier, just like the nodiscard-attribute, is internal to the language.
That is subjective. Nodiscard cannot change the control flow, nor allocate special objects on the stack: it just triggers a warning if you ignore the return value. While a noexcept(false) attribute means that this function might throw an exception. That changes everything, like changing the return type of a function. No matter how carefully you called it and prepared to check it's return value, it might not be enough. You have to call that function from exception-safe code which won't be called from a destructor or be prepared to catch an exception with try/catch. This is a more serious requirement than nodiscard but I acknowledge that the comparison makes sense. Choosing what to include in the ABI is arbitrary and goes from exclusively the strictly necessary (the simplest path) to every possible attribute (hell).
Ethin wrote:As such, you have a lot more freedom: the compiler could very trivially enforce noexcept-specifier contracts. The only reason that compilers don't do this is because the standard says that implementations shouldn't reject violaters of the noexcept-specifier, even though that's the logical thing to do.
We agree here: the ISO standard is weird. I guess it was another trade-off to facilitate the conversion from throw() to noexcept().
Ethin wrote:Claiming that the ABI needs to be changed just to enforce noexcept is like claiming that the ABI should be changed to enforce the nodiscard attribute: this is a language-level item, not an ABI item. The ABI could care less that your function is marked nodiscard; attributes such as nodiscard or noexcept attributes have no meaning on the ABI level.
What has meaning at ABI level and what doesn't is
arbitrary: there are no "laws of CS for writing ABIs" that forbid that. Simply, compiler engineers prefer to keep the ABI to the minimum possible and avoid changes at all costs (this is a trade-off, not a law!). Changing the ABI was not mandatory to support noexcept and would have caused quite some pain. Why go through all of that, just to add some extra safety for developers? That would have been too expensive.
Let me argue more about that: making a breaking change in the ABI, even for a specific compiler on a specific platform, would mean having to re-compile all the libraries (and their dependencies) before being able to compile applications, unless the change is somehow backwards-compatible. If that happened with noexcept, we would have likely had many C++ libraries distributed in two binary forms, regular and "-ex" ABI (e.g. "gcc-ex"). Gradually, we would have moved to the -ex version. But, yeah, unless the change was 100% backwards compatible somehow, it would have been a mess for quite some time. That's why I believe nobody even considered going down that road.
Just, don't think all the decisions made by committees and compiler engineers are driven by "what is better, on the absolute scale". Most of the time, it's all about: how to maximize the benefits of a given feature with
minimal effort?