clang-tidy-modernize-use-std-format
Clang 19 has recently been released.
It includes my new modernize-use-std-format
check and fixes a bug in the
modernize-use-std-print
check that I added
in Clang 17. (I also fixed another bug in the
intervening Clang 18 release.)
The new modernise-use-std-format check by default turns
calls to absl::StrFormat
into calls to std::format.
For example,
it turns:
return absl::StrFormat("The %s is %d", description.c_str(), value);
into
return std::format("The {} is {}", description, value);
The full
documentation for the check is available on the clang-tidy web
site.
Although the default behaviour of the check is to replace calls to
absl::StrFormat, many codebases have their own “wrap snprintf
to return a std::string” function. Ours was called
strprintf.
Given a file named example.cpp containing:
#include <string>
extern std::string strprintf(const char *format, ...);
std::string format_row(int quantity, const std::string &name, double mass, const std::string &description)
{
return strprintf("| %3d | %10s | %6.3fkg | %-30s |\n", quantity, name.c_str(), mass, description.c_str());
}
int main()
{
puts(format_row(4, "carrots", 0.25, "Long orange things").c_str());
puts(format_row(9, "sprouts", 0.1, "Roundish green things").c_str());
}
then running
clang-tidy '-checks=-*,modernize-use-std-format' \
-config="{CheckOptions: { modernize-use-std-format.StrFormatLikeFunctions: '::strprintf;' }}" \
-fix example.cpp -- -std=c++20
will result in the file being rewritten to:
#include <format>
#include <string> 'format' file not found [pp_file_not_found]
extern std::string strprintf(const char *format, ...);
std::string format_row(int quantity, const std::string &name, double mass, const std::string &description)
{
return std::format("| {:3} | {:>10} | {:6.3f}kg | {:30} |\n", quantity, name, mass, description);
}
int main()
{
puts(format_row(4, "carrots", 0.25, "Long orange things").c_str());
puts(format_row(9, "sprouts", 0.1, "Roundish green things").c_str());
}
The check has done several things:
- The
<format> header is now included. (The
declaration of strprintf has not been removed since it may
still be used in ways that could not be converted.)
- The
strprintf call has been replaced with
std::format.
- The format string has been rewritten to use the new C++ format
language.
- The now-unnecessary calls to
std::string::c_str() for
name and description have been removed.
If you aren’t able to use C++20 yet then the check can be told to use
fmt::format from the {fmt}
library instead with something like:
clang-tidy '-checks=-*,modernize-use-std-format' \
-config="{CheckOptions: { \
modernize-use-std-format.StrFormatLikeFunctions: '::strprintf;', \
modernize-use-std-format.ReplacementFormatFunction: 'fmt::format', \
modernize-use-std-format.FormatHeader: '<fmt/core.h>' }}" \
-fix example.cpp
You can play with the modernize-use-std-format
and modernize-use-std-print
checks using the excellent Compiler Explorer.
Thanks to everyone who reviewed and made suggestions for the new check and
bug fixes.
I have several further improvements to these checks in development that I hope will land in time for Clang 20.