Skip to content

Commit 666d224

Browse files
authored
[clang-tidy] Fix modernize-use-std-print/format for fmt (#99021)
When fixing #92896 in 0e62d5c (#94104) I failed to spot that I'd broken converting from fmt::printf, fmt::fprintf and fmt::sprintf in these checks since the format parameter of those functions is not a simple character pointer. The first part of the previous fix to avoid the assert and instead produce an error message was sufficient. It was only the second part that required the format parameter of the called function to be a simple character pointer that was problematic. Let's remove that second part and add the now-expected error messages to the lit tests along with fixing the prototype for the fmt functions to more accurately reflect the ones used by the fmt library so they are actually useful. Fixes #92896
1 parent 3ad7108 commit 666d224

File tree

5 files changed

+34
-17
lines changed

5 files changed

+34
-17
lines changed

clang-tools-extra/clang-tidy/modernize/UseStdFormatCheck.cpp

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -47,15 +47,13 @@ void UseStdFormatCheck::registerPPCallbacks(const SourceManager &SM,
4747
}
4848

4949
void UseStdFormatCheck::registerMatchers(MatchFinder *Finder) {
50-
auto CharPointerType =
51-
hasType(pointerType(pointee(matchers::isSimpleChar())));
5250
Finder->addMatcher(
53-
callExpr(
54-
argumentCountAtLeast(1), hasArgument(0, stringLiteral(isOrdinary())),
55-
callee(functionDecl(
56-
unless(cxxMethodDecl()), hasParameter(0, CharPointerType),
57-
matchers::matchesAnyListedName(StrFormatLikeFunctions))
58-
.bind("func_decl")))
51+
callExpr(argumentCountAtLeast(1),
52+
hasArgument(0, stringLiteral(isOrdinary())),
53+
callee(functionDecl(unless(cxxMethodDecl()),
54+
matchers::matchesAnyListedName(
55+
StrFormatLikeFunctions))
56+
.bind("func_decl")))
5957
.bind("strformat"),
6058
this);
6159
}

clang-tools-extra/clang-tidy/modernize/UseStdPrintCheck.cpp

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -95,15 +95,12 @@ unusedReturnValue(clang::ast_matchers::StatementMatcher MatchedCallExpr) {
9595
}
9696

9797
void UseStdPrintCheck::registerMatchers(MatchFinder *Finder) {
98-
auto CharPointerType =
99-
hasType(pointerType(pointee(matchers::isSimpleChar())));
10098
if (!PrintfLikeFunctions.empty())
10199
Finder->addMatcher(
102100
unusedReturnValue(
103101
callExpr(argumentCountAtLeast(1),
104102
hasArgument(0, stringLiteral(isOrdinary())),
105103
callee(functionDecl(unless(cxxMethodDecl()),
106-
hasParameter(0, CharPointerType),
107104
matchers::matchesAnyListedName(
108105
PrintfLikeFunctions))
109106
.bind("func_decl")))
@@ -116,7 +113,6 @@ void UseStdPrintCheck::registerMatchers(MatchFinder *Finder) {
116113
callExpr(argumentCountAtLeast(2),
117114
hasArgument(1, stringLiteral(isOrdinary())),
118115
callee(functionDecl(unless(cxxMethodDecl()),
119-
hasParameter(1, CharPointerType),
120116
matchers::matchesAnyListedName(
121117
FprintfLikeFunctions))
122118
.bind("func_decl")))

clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-format-custom.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,4 +63,5 @@ std::string unsupported_format_parameter_type()
6363
// No fixes here because the format parameter of the function called is not a
6464
// string.
6565
return bad_format_type_strprintf("");
66+
// CHECK-MESSAGES: [[@LINE-1]]:10: warning: unable to use 'fmt::format' instead of 'bad_format_type_strprintf' because first argument is not a narrow string literal [modernize-use-std-format]
6667
}

clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-format-fmt.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@
1212

1313
namespace fmt
1414
{
15-
// Use const char * for the format since the real type is hard to mock up.
16-
template <typename... Args>
17-
std::string sprintf(const char *format, const Args&... args);
15+
template <typename S, typename... T,
16+
typename Char = char>
17+
std::basic_string<Char> sprintf(const S& fmt, const T&... args);
1818
} // namespace fmt
1919

2020
std::string fmt_sprintf_simple() {

clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print-custom.cpp

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
// RUN: %check_clang_tidy -std=c++23 %s modernize-use-std-print %t -- \
22
// RUN: -config="{CheckOptions: \
33
// RUN: { \
4-
// RUN: modernize-use-std-print.PrintfLikeFunctions: 'unqualified_printf;::myprintf; mynamespace::myprintf2; bad_format_type_printf', \
5-
// RUN: modernize-use-std-print.FprintfLikeFunctions: '::myfprintf; mynamespace::myfprintf2; bad_format_type_fprintf' \
4+
// RUN: modernize-use-std-print.PrintfLikeFunctions: 'unqualified_printf;::myprintf; mynamespace::myprintf2; bad_format_type_printf; fmt::printf', \
5+
// RUN: modernize-use-std-print.FprintfLikeFunctions: '::myfprintf; mynamespace::myfprintf2; bad_format_type_fprintf; fmt::fprintf' \
66
// RUN: } \
77
// RUN: }" \
88
// RUN: -- -isystem %clang_tidy_headers
@@ -106,5 +106,27 @@ void unsupported_format_parameter_type()
106106
// No fixes here because the format parameter of the function called is not a
107107
// string.
108108
bad_format_type_printf("Hello %s", "world");
109+
// CHECK-MESSAGES: [[@LINE-1]]:3: warning: unable to use 'std::print' instead of 'bad_format_type_printf' because first argument is not a narrow string literal [modernize-use-std-print]
110+
109111
bad_format_type_fprintf(stderr, "Hello %s", "world");
112+
// CHECK-MESSAGES: [[@LINE-1]]:3: warning: unable to use 'std::print' instead of 'bad_format_type_fprintf' because first argument is not a narrow string literal [modernize-use-std-print]
113+
}
114+
115+
namespace fmt {
116+
template <typename S, typename... T>
117+
inline int printf(const S& fmt, const T&... args);
118+
119+
template <typename S, typename... T>
120+
inline int fprintf(std::FILE* f, const S& fmt, const T&... args);
121+
}
122+
123+
void fmt_printf()
124+
{
125+
fmt::printf("fmt::printf templated %s argument %d\n", "format", 424);
126+
// CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
127+
// CHECK-FIXES: std::println("fmt::printf templated {} argument {}", "format", 424);
128+
129+
fmt::fprintf(stderr, "fmt::fprintf templated %s argument %d\n", "format", 425);
130+
// CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'fprintf' [modernize-use-std-print]
131+
// CHECK-FIXES: std::println(stderr, "fmt::fprintf templated {} argument {}", "format", 425);
110132
}

0 commit comments

Comments
 (0)