For global variables (and functions), const void* is a reasonable default in
many cases. In cases where writing to a value is necessary (and known to be
safe, such as global initialization in ExecutionEngine), const_cast<> gets back
the mutable value.
A reproducible case where this matters is building against musl-libc. Under
musl, the type of stdin, stdout, and stderr is 'FILE *const'.
From lib/Support/DynamicLibrary.cpp:
// On linux we have a weird situation. The stderr/out/in symbols are both // macros and global variables because of standards requirements. So, we // boldly use the EXPLICIT_SYMBOL macro without checking for a #define first. EXPLICIT_SYMBOL(stderr); EXPLICIT_SYMBOL(stdout); EXPLICIT_SYMBOL(stdin);
In this case, EXPLICIT_SYMBOL takes the address of variables of type 'extern
FILE *const', which can be converted to 'const void*', but not to 'void*'. So,
in other words, a global 'T *' is stored by pointer (a 'T **') cast to 'void*',
but a global 'T *const' stored by pointer is a 'T *const *', which can be
converted to 'const void *' (but not 'void *').
The ExecutionEngine changes might be separable, but it seems slightly better to
keep consistent const-correctness. That means pushing const_cast down to where
it is known to be safe, as opposed of casting away const from variables early,
when we know it is not generally safe to do so.