xref: /llvm-project/clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print-custom.cpp (revision 0e62d5cf55479981da5e05e406bbca4afb3cdc4f)
183f875dcSMike Crowe // RUN: %check_clang_tidy -std=c++23 %s modernize-use-std-print %t -- \
283f875dcSMike Crowe // RUN:   -config="{CheckOptions: \
383f875dcSMike Crowe // RUN:             { \
4*0e62d5cfSMike Crowe // RUN:               modernize-use-std-print.PrintfLikeFunctions: 'unqualified_printf;::myprintf; mynamespace::myprintf2; bad_format_type_printf', \
5*0e62d5cfSMike Crowe // RUN:               modernize-use-std-print.FprintfLikeFunctions: '::myfprintf; mynamespace::myfprintf2; bad_format_type_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 }
89*0e62d5cfSMike Crowe 
90*0e62d5cfSMike Crowe int myprintf(const wchar_t *, ...);
91*0e62d5cfSMike Crowe 
92*0e62d5cfSMike Crowe void wide_string_not_supported() {
93*0e62d5cfSMike Crowe   myprintf(L"wide string %s", L"string");
94*0e62d5cfSMike Crowe }
95*0e62d5cfSMike Crowe 
96*0e62d5cfSMike Crowe // Issue #92896: Ensure that the check doesn't assert if the argument is
97*0e62d5cfSMike Crowe // promoted to something that isn't a string.
98*0e62d5cfSMike Crowe struct S {
99*0e62d5cfSMike Crowe   S(...) {}
100*0e62d5cfSMike Crowe };
101*0e62d5cfSMike Crowe int bad_format_type_printf(const S &, ...);
102*0e62d5cfSMike Crowe int bad_format_type_fprintf(FILE *, const S &, ...);
103*0e62d5cfSMike Crowe 
104*0e62d5cfSMike Crowe void unsupported_format_parameter_type()
105*0e62d5cfSMike Crowe {
106*0e62d5cfSMike Crowe   // No fixes here because the format parameter of the function called is not a
107*0e62d5cfSMike Crowe   // string.
108*0e62d5cfSMike Crowe   bad_format_type_printf("Hello %s", "world");
109*0e62d5cfSMike Crowe   bad_format_type_fprintf(stderr, "Hello %s", "world");
110*0e62d5cfSMike Crowe }
111