_HAS_EXCEPTIONS=0 allows disabling the exception parts of the MS STL
and vcruntime, and e.g. compiler-rt/lib/fuzzer sets this define (to
work around issues with MS STL). If using libc++ instead of MS STL,
this define previously broke the libc++ headers.
If _HAS_EXCEPTIONS is set to 0, the vcruntime_exception.h header
doesn't define the ABI base class std::exception. If no exceptions
are going to be thrown, this probably is fine (although it also
breaks using subclasses of it as regular objects that aren't thrown),
but it requires ifdeffing out all subclasses of all exception/error
derived objects (which are sprinkled throughout the headers).
Instead, libc++ will supply an ABI compatible definition when
_HAS_EXCEPTIONS is set to 0, which will make the class hierarchies
complete.
In this build configuration, one can still create instances of
exception subclasses, and those objects will be ABI incompatible
with the ones from when _HAS_EXCEPTIONS isn't defined to 0 - but
one may argue that's a pathological/self-imposed problem in that case.
Is this condition strictly necessary? Isn't it the case that if we include the header, under these circumstances, it doesn't provide the definitions we need? I.e. we could still keep including the header even if it doesn't give us anything of value.
(OTOH I guess the condition can be good for clarity?)
Are we sure that vcruntime.h which sets the default _HAS_EXCEPTIONS == 1 has been included at this point? (I guess cstddef and cstdlib boil down to including that transitively?) Or would we need to make this into #if defined(_LIBCPP_ABI_VCRUNTIME) && (!defined(_HAS_EXCEPTIONS) || _HAS_EXCEPTIONS != 0)?