xref: /llvm-project/clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print-custom.cpp (revision 666d224248707f373577b5b049b5b0229100006c)
183f875dcSMike Crowe // RUN: %check_clang_tidy -std=c++23 %s modernize-use-std-print %t -- \
283f875dcSMike Crowe // RUN:   -config="{CheckOptions: \
383f875dcSMike Crowe // RUN:             { \
4*666d2242SMike Crowe // RUN:               modernize-use-std-print.PrintfLikeFunctions: 'unqualified_printf;::myprintf; mynamespace::myprintf2; bad_format_type_printf; fmt::printf', \
5*666d2242SMike Crowe // RUN:               modernize-use-std-print.FprintfLikeFunctions: '::myfprintf; mynamespace::myfprintf2; bad_format_type_fprintf; fmt::fprintf' \
683f875dcSMike Crowe // RUN:             } \
783f875dcSMike Crowe // RUN:            }" \
883f875dcSMike Crowe // RUN:   -- -isystem %clang_tidy_headers
983f875dcSMike Crowe 
1083f875dcSMike Crowe #include <cstdio>
11b389a625SMike Crowe #include <string>
1283f875dcSMike Crowe 
1383f875dcSMike Crowe int myprintf(const char *, ...);
1483f875dcSMike Crowe int myfprintf(FILE *fp, const char *, ...);
1583f875dcSMike Crowe 
1683f875dcSMike Crowe namespace mynamespace {
1783f875dcSMike Crowe int myprintf2(const char *, ...);
1883f875dcSMike Crowe int myfprintf2(FILE *fp, const char *, ...);
1983f875dcSMike Crowe }
2083f875dcSMike Crowe 
2183f875dcSMike Crowe void printf_simple() {
2283f875dcSMike Crowe   myprintf("Hello %s %d", "world", 42);
2383f875dcSMike Crowe   // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'myprintf' [modernize-use-std-print]
2483f875dcSMike Crowe   // CHECK-FIXES: std::print("Hello {} {}", "world", 42);
2583f875dcSMike Crowe }
2683f875dcSMike Crowe 
2783f875dcSMike Crowe void printf_newline() {
2883f875dcSMike Crowe   myprintf("Hello %s %d\n", "world", 42);
2983f875dcSMike Crowe   // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'myprintf' [modernize-use-std-print]
3083f875dcSMike Crowe   // CHECK-FIXES: std::println("Hello {} {}", "world", 42);
3183f875dcSMike Crowe 
3283f875dcSMike Crowe   mynamespace::myprintf2("Hello %s %d\n", "world", 42);
3383f875dcSMike Crowe   // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'myprintf2' [modernize-use-std-print]
3483f875dcSMike Crowe   // CHECK-FIXES: std::println("Hello {} {}", "world", 42);
3583f875dcSMike Crowe 
3683f875dcSMike Crowe   using mynamespace::myprintf2;
3783f875dcSMike Crowe   myprintf2("Hello %s %d\n", "world", 42);
3883f875dcSMike Crowe   // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'myprintf2' [modernize-use-std-print]
3983f875dcSMike Crowe   // CHECK-FIXES: std::println("Hello {} {}", "world", 42);
4083f875dcSMike Crowe 
4183f875dcSMike Crowe   // When using custom options leave printf alone
4283f875dcSMike Crowe   printf("Hello %s %d\n", "world", 42);
4383f875dcSMike Crowe }
4483f875dcSMike Crowe 
4509ed2102SMike Crowe int printf_uses_return_value(int i) {
4609ed2102SMike Crowe   return myprintf("return value %d\n", i);
4709ed2102SMike Crowe   // CHECK-MESSAGES-NOT: [[@LINE-1]]:10: warning: use 'std::println' instead of 'myprintf' [modernize-use-std-print]
4809ed2102SMike Crowe   // CHECK-FIXES-NOT: std::println("return value {}", i);
4909ed2102SMike Crowe }
5009ed2102SMike Crowe 
5183f875dcSMike Crowe void fprintf_simple(FILE *fp)
5283f875dcSMike Crowe {
5383f875dcSMike Crowe   myfprintf(stderr, "Hello %s %d", "world", 42);
5483f875dcSMike Crowe   // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'myfprintf' [modernize-use-std-print]
5583f875dcSMike Crowe   // CHECK-FIXES: std::print(stderr, "Hello {} {}", "world", 42);
5683f875dcSMike Crowe }
5783f875dcSMike Crowe 
5883f875dcSMike Crowe void fprintf_newline(FILE *fp)
5983f875dcSMike Crowe {
6083f875dcSMike Crowe   myfprintf(stderr, "Hello %s %d\n", "world", 42);
6183f875dcSMike Crowe   // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'myfprintf' [modernize-use-std-print]
6283f875dcSMike Crowe   // CHECK-FIXES: std::println(stderr, "Hello {} {}", "world", 42);
6383f875dcSMike Crowe 
6483f875dcSMike Crowe   mynamespace::myfprintf2(stderr, "Hello %s %d\n", "world", 42);
6583f875dcSMike Crowe   // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'myfprintf2' [modernize-use-std-print]
6683f875dcSMike Crowe   // CHECK-FIXES: std::println(stderr, "Hello {} {}", "world", 42);
6783f875dcSMike Crowe 
6883f875dcSMike Crowe   using mynamespace::myfprintf2;
6983f875dcSMike Crowe   myfprintf2(stderr, "Hello %s %d\n", "world", 42);
7083f875dcSMike Crowe   // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'myfprintf2' [modernize-use-std-print]
7183f875dcSMike Crowe   // CHECK-FIXES: std::println(stderr, "Hello {} {}", "world", 42);
7283f875dcSMike Crowe 
7383f875dcSMike Crowe   // When using custom options leave fprintf alone
7483f875dcSMike Crowe   fprintf(stderr, "Hello %s %d\n", "world", 42);
7583f875dcSMike Crowe }
7609ed2102SMike Crowe 
7709ed2102SMike Crowe int fprintf_uses_return_value(int i) {
7809ed2102SMike Crowe   return myfprintf(stderr, "return value %d\n", i);
7909ed2102SMike Crowe   // CHECK-MESSAGES-NOT: [[@LINE-1]]:10: warning: use 'std::println' instead of 'myprintf' [modernize-use-std-print]
8009ed2102SMike Crowe   // CHECK-FIXES-NOT: std::println(stderr, "return value {}", i);
8109ed2102SMike Crowe }
82b389a625SMike Crowe 
83b389a625SMike Crowe // Ensure that MatchesAnyListedNameMatcher::NameMatcher::match() can cope with a
84b389a625SMike Crowe // NamedDecl that has no name when we're trying to match unqualified_printf.
85b389a625SMike Crowe void no_name(const std::string &in)
86b389a625SMike Crowe {
87b389a625SMike Crowe   "A" + in;
88b389a625SMike Crowe }
890e62d5cfSMike Crowe 
900e62d5cfSMike Crowe int myprintf(const wchar_t *, ...);
910e62d5cfSMike Crowe 
920e62d5cfSMike Crowe void wide_string_not_supported() {
930e62d5cfSMike Crowe   myprintf(L"wide string %s", L"string");
940e62d5cfSMike Crowe }
950e62d5cfSMike Crowe 
960e62d5cfSMike Crowe // Issue #92896: Ensure that the check doesn't assert if the argument is
970e62d5cfSMike Crowe // promoted to something that isn't a string.
980e62d5cfSMike Crowe struct S {
990e62d5cfSMike Crowe   S(...) {}
1000e62d5cfSMike Crowe };
1010e62d5cfSMike Crowe int bad_format_type_printf(const S &, ...);
1020e62d5cfSMike Crowe int bad_format_type_fprintf(FILE *, const S &, ...);
1030e62d5cfSMike Crowe 
1040e62d5cfSMike Crowe void unsupported_format_parameter_type()
1050e62d5cfSMike Crowe {
1060e62d5cfSMike Crowe   // No fixes here because the format parameter of the function called is not a
1070e62d5cfSMike Crowe   // string.
1080e62d5cfSMike Crowe   bad_format_type_printf("Hello %s", "world");
109*666d2242SMike Crowe // 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*666d2242SMike Crowe 
1110e62d5cfSMike Crowe   bad_format_type_fprintf(stderr, "Hello %s", "world");
112*666d2242SMike Crowe // 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*666d2242SMike Crowe }
114*666d2242SMike Crowe 
115*666d2242SMike Crowe namespace fmt {
116*666d2242SMike Crowe   template <typename S, typename... T>
117*666d2242SMike Crowe   inline int printf(const S& fmt, const T&... args);
118*666d2242SMike Crowe 
119*666d2242SMike Crowe   template <typename S, typename... T>
120*666d2242SMike Crowe   inline int fprintf(std::FILE* f, const S& fmt, const T&... args);
121*666d2242SMike Crowe }
122*666d2242SMike Crowe 
123*666d2242SMike Crowe void fmt_printf()
124*666d2242SMike Crowe {
125*666d2242SMike Crowe   fmt::printf("fmt::printf templated %s argument %d\n", "format", 424);
126*666d2242SMike Crowe   // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
127*666d2242SMike Crowe   // CHECK-FIXES: std::println("fmt::printf templated {} argument {}", "format", 424);
128*666d2242SMike Crowe 
129*666d2242SMike Crowe   fmt::fprintf(stderr, "fmt::fprintf templated %s argument %d\n", "format", 425);
130*666d2242SMike Crowe   // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'fprintf' [modernize-use-std-print]
131*666d2242SMike Crowe   // CHECK-FIXES: std::println(stderr, "fmt::fprintf templated {} argument {}", "format", 425);
1320e62d5cfSMike Crowe }
133