The devil is in the details. The "almost" and "mostly" parts are really important here, especially given that the entire topic is safety.
If you compile "C code" with your C++ compiler (as C++), you're no longer compiling C code; you're now compiling C++ code that looks like C.
It would be fine if C code, when compiled as C++ had one of two outcomes:
1. Behaved identically to C code compiled as C. 2. Refused to compile
Unfortunately, there are things that exist in both languages but have different semantics such as the type of character literals, e.g. 'a' (int in C, char in C++).
As for the superset thing, there's been quite significant divergence especially since C99 (e.g. variable length arrays)
Other subtly different things include:
the bool type (C++ has a bool type, C99 has _Bool with a macro for bool as bool isn't a reserved word in C).
designated initializers (C99 had them first then C++20 introduced them to C++ but with more restrictions)