[RFC] Format attribute: `__attribute__((format_like(...)))`

Thanks. Enumerating the differences: eliminate pretty much all leniency with length modifiers, eliminate leniency for signedness changes, rejecting ordering modifiers.

I’m not attached enough to the leniency on length modifiers to make a serious argument for it. This creates some differences with how -Wformat works, but they are not very serious differences, and it’s usually an easy fix on the project side (except the %i%c case).

I would like to see if you would be open to changing your mind on the other two. Specifically:

  • Diagnostics on specifier signedness are currently controlled by -Wformat-signedness for attribute((format)). This is respected by my patch. Would you be open to keep it this way? The complexity cost is about 9 lines (see lines 7158-7166).
  • What should the user experience be when developers try to use order modifiers? Should we emit incorrect diagnostics, cross-referencing specifiers in the order they appear instead of in the specified order? Should there be a diagnostic saying “order modifiers are not currently supported by format_matches” or equivalent? Should we allow the format string without checking? None of these options seem very good to me, so I would like to see if you would be OK keeping it working. The complexity cost is a little bit more spread out but still not very much (we just record the specifier position and std::sort the specifiers by it before comparing).

What’s causing changes all over the file is that I need an extra argument to CheckFormatString, and this reverberates somewhat deeply. About 13 of about 45 change blocks are just piping through the argument, and those are made worse by the fact these haven’t been changed since clang-format became enforced. If you’re able to mostly tune out argument list changes to functions that sound like CheckFormatString, the change will look about one-third smaller.