|
I agree that testing this is great idea. I think we might as well hardcode the sizes of all the exception classes for each known compiler into the test itself:
#ifdef __VACPP__
assert (sizeof (std::bad_alloc)) == 2 * sizeof (char*));
assert (sizeof (std::bad_cast)) == 2 * sizeof (char*));
assert (sizeof (std::bad_exception)) == 2 * sizeof (char*));
assert (sizeof (std::bad_typeid)) == 2 * sizeof (char*));
assert (sizeof (std::exception)) == 2 * sizeof (char*));
#elif defined (__HP_aCC)
assert (sizeof (std::bad_alloc)) == sizeof (char*));
assert (sizeof (std::bad_cast)) == sizeof (char*));
assert (sizeof (std::bad_exception)) == sizeof (char*));
assert (sizeof (std::bad_typeid)) == sizeof (char*));
assert (sizeof (std::exception)) == sizeof (char*));
#elif defined __GNUC__
assert (sizeof (std::bad_alloc)) == sizeof (char*));
assert (sizeof (std::bad_cast)) == sizeof (char*));
assert (sizeof (std::bad_exception)) == sizeof (char*));
assert (sizeof (std::bad_typeid)) == sizeof (char*));
assert (sizeof (std::exception)) == sizeof (char*));
#else
// ...
#endif
I'm assuming that you are talking about asserting the size of the runtime library exceptions in a configuration test, is that right? If so, what happens if the config test fails? Without something else, nobody will notice unless they are actually looking for the failure message in the configuration spew. I guess that we could use the configuration test to set a macro like _RWSTD_NO_EXCEPTION_BROKEN, and then in the library we could assert at compile time that the macro is defined. That way the library will fail to build if we don't know the proper sizes for the exception classes. The problem with this is that we have to hardcode the correct values for all compilers we know. This config test, and the implementation, would need to be ported for any new environment that we wanted to support or that our users would want to use.
I think an ideal solution would be to do something to guarantee that these objects are of the correct size, even for compilers that we don't officially support. We already do it for things like struct lconv and struct tm, why not std::exception? I meant in a regular test (not a config one). But you're right, that may not be enough. Similarly, asserting the same conditions in a config test wouldn't be enough unless the test's failure caused the whole configuration process to fail. We don't have a mechanism like that in place but we've had the need for it in the past so enhancing the config infrastructure might be the way to go. The other approach you suggest – to #define a macro like _RWSTD_NO_EXCEPTION_BROKEN and then asserting that it's #defined (or preferably the other way around so as not to introduce unnecessary macros) would also work.
That said, if as you say we already have a solution in place for other types (I forgot about struct lconv and struct tm), we might as well use it. This issue is specific to IBM XLC++ on AIX (as opposed to Linux).
Added a platform tag to Summary and updated Environment. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// looking for runtime library exceptions #include <exception> #include <typeinfo> #include <stdio.h> template <class T> void run_test (const char* s) { printf ("#define %-18s %u\n", s, sizeof (T)); } int main () { #define TEST(s,t) run_test<t>(#s) TEST (_RWSTD_EXCEPTION_SIZE , std::exception); TEST (_RWSTD_BAD_ALLOC_SIZE , std::bad_alloc); TEST (_RWSTD_BAD_CAST_SIZE , std::bad_cast); TEST (_RWSTD_BAD_EXCDEPTION_SIZE, std::bad_exception); TEST (_RWSTD_BAD_TYPEID_SIZE , std::bad_typeid); return 0; }Then we would put something like this near the top of exception.cpp
_RWSTD_NAMESPACE (__rw) { static void __rw_exception_compile_asserts () { #define TEST(s,t) _RWSTD_COMPILE_ASSERT (s == sizeof (t)) TEST (_RWSTD_EXCEPTION_SIZE , std::exception); TEST (_RWSTD_BAD_ALLOC_SIZE , std::bad_alloc); TEST (_RWSTD_BAD_CAST_SIZE , std::bad_cast); TEST (_RWSTD_BAD_EXCDEPTION_SIZE, std::bad_exception); TEST (_RWSTD_BAD_TYPEID_SIZE , std::bad_typeid); #undef TEST } } // namespace rw