| .. title:: clang-tidy - modernize-use-std-print |
| |
| modernize-use-std-print |
| ======================= |
| |
| Converts calls to ``printf``, ``fprintf``, ``absl::PrintF`` and |
| ``absl::FPrintf`` to equivalent calls to C++23's ``std::print`` or |
| ``std::println`` as appropriate, modifying the format string appropriately. |
| The replaced and replacement functions can be customised by configuration |
| options. Each argument that is the result of a call to ``std::string::c_str()`` and |
| ``std::string::data()`` will have that now-unnecessary call removed in a |
| similar manner to the `readability-redundant-string-cstr` check. |
| |
| In other words, it turns lines like: |
| |
| .. code-block:: c++ |
| |
| fprintf(stderr, "The %s is %3d\n", description.c_str(), value); |
| |
| into: |
| |
| .. code-block:: c++ |
| |
| std::println(stderr, "The {} is {:3}", description, value); |
| |
| If the `ReplacementPrintFunction` or `ReplacementPrintlnFunction` options |
| are left, or assigned to their default values then this check is only |
| enabled with `-std=c++23` or later. |
| |
| The check doesn't do a bad job, but it's not perfect. In particular: |
| |
| - It assumes that the format string is correct for the arguments. If you |
| get any warnings when compiling with `-Wformat` then misbehaviour is |
| possible. |
| |
| - At the point that the check runs, the AST contains a single |
| ``StringLiteral`` for the format string and any macro expansion, token |
| pasting, adjacent string literal concatenation and escaping has been |
| handled. Although it's possible for the check to automatically put the |
| escapes back, they may not be exactly as they were written (e.g. |
| ``"\x0a"`` will become ``"\n"`` and ``"ab" "cd"`` will become |
| ``"abcd"``.) This is helpful since it means that the ``PRIx`` macros from |
| ``<inttypes.h>`` are removed correctly. |
| |
| - It supports field widths, precision, positional arguments, leading zeros, |
| leading ``+``, alignment and alternative forms. |
| |
| - Use of any unsupported flags or specifiers will cause the entire |
| statement to be left alone and a warning to be emitted. Particular |
| unsupported features are: |
| |
| - The ``%'`` flag for thousands separators. |
| |
| - The glibc extension ``%m``. |
| |
| - ``printf`` and similar functions return the number of characters printed. |
| ``std::print`` does not. This means that any invocations that use the |
| return value will not be converted. Unfortunately this currently includes |
| explicitly-casting to ``void``. Deficiencies in this check mean that any |
| invocations inside ``GCC`` compound statements cannot be converted even |
| if the resulting value is not used. |
| |
| If conversion would be incomplete or unsafe then the entire invocation will |
| be left unchanged. |
| |
| If the call is deemed suitable for conversion then: |
| |
| - ``printf``, ``fprintf``, ``absl::PrintF``, ``absl::FPrintF`` and any |
| functions specified by the `PrintfLikeFunctions` option or |
| `FprintfLikeFunctions` are replaced with the function specified by the |
| `ReplacementPrintlnFunction` option if the format string ends with ``\n`` |
| or `ReplacementPrintFunction` otherwise. |
| - the format string is rewritten to use the ``std::formatter`` language. If |
| a ``\n`` is found at the end of the format string not preceded by ``r`` |
| then it is removed and `ReplacementPrintlnFunction` is used rather than |
| `ReplacementPrintFunction`. |
| - any arguments that corresponded to ``%p`` specifiers that |
| ``std::formatter`` wouldn't accept are wrapped in a ``static_cast`` |
| to ``const void *``. |
| - any arguments that corresponded to ``%s`` specifiers where the argument |
| is of ``signed char`` or ``unsigned char`` type are wrapped in a |
| ``reinterpret_cast<const char *>``. |
| - any arguments where the format string and the parameter differ in |
| signedness will be wrapped in an appropriate ``static_cast`` if `StrictMode` |
| is enabled. |
| - any arguments that end in a call to ``std::string::c_str()`` or |
| ``std::string::data()`` will have that call removed. |
| |
| Options |
| ------- |
| |
| .. option:: StrictMode |
| |
| When `true`, the check will add casts when converting from variadic |
| functions like ``printf`` and printing signed or unsigned integer types |
| (including fixed-width integer types from ``<cstdint>``, ``ptrdiff_t``, |
| ``size_t`` and ``ssize_t``) as the opposite signedness to ensure that |
| the output matches that of ``printf``. This does not apply when |
| converting from non-variadic functions such as ``absl::PrintF`` and |
| ``fmt::printf``. For example, with `StrictMode` enabled: |
| |
| .. code-block:: c++ |
| |
| int i = -42; |
| unsigned int u = 0xffffffff; |
| printf("%d %u\n", i, u); |
| |
| would be converted to: |
| |
| .. code-block:: c++ |
| |
| std::print("{} {}\n", static_cast<unsigned int>(i), static_cast<int>(u)); |
| |
| to ensure that the output will continue to be the unsigned representation |
| of `-42` and the signed representation of `0xffffffff` (often |
| `4294967254` and `-1` respectively.) When `false` (which is the default), |
| these casts will not be added which may cause a change in the output. |
| |
| .. option:: PrintfLikeFunctions |
| |
| A semicolon-separated list of (fully qualified) function names to |
| replace, with the requirement that the first parameter contains the |
| printf-style format string and the arguments to be formatted follow |
| immediately afterwards. If neither this option nor |
| `FprintfLikeFunctions` are set then the default value for this option |
| is `printf; absl::PrintF`, otherwise it is empty. |
| |
| |
| .. option:: FprintfLikeFunctions |
| |
| A semicolon-separated list of (fully qualified) function names to |
| replace, with the requirement that the first parameter is retained, the |
| second parameter contains the printf-style format string and the |
| arguments to be formatted follow immediately afterwards. If neither this |
| option nor `PrintfLikeFunctions` are set then the default value for |
| this option is `fprintf; absl::FPrintF`, otherwise it is empty. |
| |
| .. option:: ReplacementPrintFunction |
| |
| The function that will be used to replace ``printf``, ``fprintf`` etc. |
| during conversion rather than the default ``std::print`` when the |
| originalformat string does not end with ``\n``. It is expected that the |
| function provides an interface that is compatible with ``std::print``. A |
| suitable candidate would be ``fmt::print``. |
| |
| .. option:: ReplacementPrintlnFunction |
| |
| The function that will be used to replace ``printf``, ``fprintf`` etc. |
| during conversion rather than the default ``std::println`` when the |
| original format string ends with ``\n``. It is expected that the |
| function provides an interface that is compatible with ``std::println``. |
| A suitable candidate would be ``fmt::println``. |
| |
| .. option:: PrintHeader |
| |
| The header that must be included for the declaration of |
| `ReplacementPrintFunction` so that a ``#include`` directive can be |
| added if required. If `ReplacementPrintFunction` is ``std::print`` |
| then this option will default to ``<print>``, otherwise this option will |
| default to nothing and no ``#include`` directive will be added. |