Skip to content

[clang-tidy] Peculiar behaviour of modernize-use-std-format #160991

@asakovets

Description

@asakovets

Hi,

I’ve encountered unexpected behavior with the modernize-use-std-format check in clang-tidy. Consider the following code:

#include <format>

namespace foo {
void info__ (const char * s, ...) {}

template <typename... Args> 
void info_fmt (std::format_string<Args...> fmt, Args &&... args) {}
}

int main ()
{
    foo::info__ ("hello, %s!", "world");
}

My .clang-tidy configuration is

Checks: 'modernize-use-std-format'
CheckOptions:
  - key: modernize-use-std-format.StrFormatLikeFunctions
    value: "foo::info"
  - key: modernize-use-std-format.ReplacementFormatFunction
    value: foo::info_fmt

Running clang-tidy:

clang-tidy -checks=-clang-analyzer-* fmt.cc

1 warning generated.
~/fmt.cc:12:5: warning: use 'foo::info_fmt' instead of 'info__' [modernize-use-std-format]
   12 |     foo::info__ ("hello, %s!", "world");
      |     ^~~~~~~~~~~  ~~~~~~~~~~~~
      |     foo::info_fmt"hello, {}!"

The warning suggests replacing info__ with info_fmt, even though StrFormatLikeFunctions only includes foo::info—not foo::info__. It appears that clang-tidy matches function names by prefix rather than requiring an exact match.

After applying the suggested fix and running clang-tidy again, it then suggests replacing foo::info_fmt with foo::info_fmt, creating a “diagnostics loop”:

clang-tidy -checks=-clang-analyzer-* fmt.cc
1 warning generated.
~/fmt.cc:12:5: warning: use 'foo::info_fmt' instead of 'info_fmt' [modernize-use-std-format]
   12 |     foo::info_fmt ("hello, {}!", "world");
      |     ^~~~~~~~~~~~~  ~~~~~~~~~~~~
      |     foo::info_fmt  "hello, {{}}!"

Is it intentional?

clang-tidy version: 21.1.2
Platform: Windows

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions