Fil-C is a fork of clang that explicitly defines all these things to have bounded behavior, so ignoring exactly this - the whole point of Fil-C - makes no sense.
I spent a few minutes poking just to see if my gut is right here, and already, here's an example of UB being used in an optimization by the compiler that leaves a fil safety check at on -O0 but drops it at higher optimization levels. I find it difficult to believe that all of the complex interactions of every optimization pass in the presence of even this subset of UB are guaranteed not to violate these memory safety promises.
#include <stdio.h>
#include <stdlib.h>
__attribute__((noinline)) static void poke(int *p, int k)
{
int n = 32 + (k & 15); /* always >= 32: shifting an int by >= 32 is UB */
p[(1 << n) * 20] = 0x41414141; /* on x86 the CPU computes index 40, out of bounds */
}
int main(int argc, char **argv)
{
int *p = calloc(16, sizeof(int));
poke(p, argc);
puts("after poke");
return 0;
}I also do not believe that all complex interactions are guaranteed to not violate all safety promises. I also know that this is not true for Rust, so what is your point?