A post-release update to VS 2017 was the first version which supported a useful subset of C99. But support isn't a binary thing; I was tangentially involved in diagnosing a critical bug in their implementation of C99 lvalue literals just a few months ago. Minimal repro: https://godbolt.org/z/7rTv1M
Minor nitpick: Most C99 features were "already" in a VS2015 update (initialization features like designated init and compound literals, and a standard compliant snprintf()).
The big missing features were VLAs (those will never be implemented) and _Generic (implemented now in VS2019).
Thanks, I was confusing the VS 2015 update with VS 2017 as the one that got the big pieces like designated initializers and compound literals. I don't think anyone cares about VLAs, but I look forward to being able to rely on _Generic in another 5 years when VS 2019 can be assumed available. :)
MSVC only supported a somewhat usable C99 subset since a VS2015 update, but it never implemented VLAs, so it can't be called a standard C99 compiler.
_Generic has only been added very recently in VS2019, and MS recently has pledged C11 and C17 support (but it will never be a C99 compiler because VLAs will not be implemented, that's fine though, VLAs should never have made it into the standard).
...also important to note in that context: unlike gcc and clang, the MSVC C++ compiler is stuck at a "sort-of-C95". GCC and clang support most modern C features in C++ as non-standard extensions, but MSVC doesn't.