llvm/Support/Format.h provides format(), a variadic template function that accepts a printf-style format string and the corresponding fixed format arguments. While this function does forward its arguments to snprintf, which is type-checked thanks to the gnu::format attribute on platforms where that attribute is supported, it cannot itself have that attribute because GCC does not allow the format attribute on non-variadic functions (variadic template functions not excepted).
Regardless, we can change the implementation of format() so that it would be more amenable to this attribute. Recently, clang did gain support for gnu::format on non-variadic functions. We still can't use it because GCC would reject the code. However, this does allow vendors who never build LLVM with GCC themselves to maintain a patch which has that attribute enabled, catching a few errors in the process. The changes to the format_object class allow us to attribute its constructor with gnu::format (which, in turns, allows us to attribute format() with gnu::format as well).
In addition, we create a new function, format_chk(Expected, Fmt, T...), for the case where Fmt isn't known at compile-time. At runtime, Fmt is verified to have specifiers which are compatible with Expected's.
There will be another PR fixing any eventual format specifier mistakes found. In warning flags parlance, this would allow LLVM to build with -Wformat -Wformat-nonliteral.
Can you use char as the underlying type for enums?