140 lines · cpp
1// RUN: %check_clang_tidy -std=c++23 %s modernize-use-std-print %t -- \2// RUN: -config="{CheckOptions: \3// RUN: { \4// RUN: modernize-use-std-print.PrintfLikeFunctions: 'unqualified_printf;::myprintf; mynamespace::myprintf2; any_format_type_printf; fmt::printf', \5// RUN: modernize-use-std-print.FprintfLikeFunctions: '::myfprintf; mynamespace::myfprintf2; any_format_type_fprintf; fmt::fprintf' \6// RUN: } \7// RUN: }" \8// RUN: -- -isystem %clang_tidy_headers9 10#include <cstdio>11#include <string>12 13int myprintf(const char *, ...);14int myfprintf(FILE *fp, const char *, ...);15 16namespace mynamespace {17int myprintf2(const char *, ...);18int myfprintf2(FILE *fp, const char *, ...);19}20 21void printf_simple() {22 myprintf("Hello %s %d", "world", 42);23 // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'myprintf' [modernize-use-std-print]24 // CHECK-FIXES: std::print("Hello {} {}", "world", 42);25}26 27void printf_newline() {28 myprintf("Hello %s %d\n", "world", 42);29 // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'myprintf' [modernize-use-std-print]30 // CHECK-FIXES: std::println("Hello {} {}", "world", 42);31 32 mynamespace::myprintf2("Hello %s %d\n", "world", 42);33 // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'myprintf2' [modernize-use-std-print]34 // CHECK-FIXES: std::println("Hello {} {}", "world", 42);35 36 using mynamespace::myprintf2;37 myprintf2("Hello %s %d\n", "world", 42);38 // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'myprintf2' [modernize-use-std-print]39 // CHECK-FIXES: std::println("Hello {} {}", "world", 42);40 41 // When using custom options leave printf alone42 printf("Hello %s %d\n", "world", 42);43}44 45int printf_uses_return_value(int i) {46 return myprintf("return value %d\n", i);47 // CHECK-MESSAGES-NOT: [[@LINE-1]]:10: warning: use 'std::println' instead of 'myprintf' [modernize-use-std-print]48 // CHECK-FIXES-NOT: std::println("return value {}", i);49}50 51void fprintf_simple(FILE *fp)52{53 myfprintf(stderr, "Hello %s %d", "world", 42);54 // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'myfprintf' [modernize-use-std-print]55 // CHECK-FIXES: std::print(stderr, "Hello {} {}", "world", 42);56}57 58void fprintf_newline(FILE *fp)59{60 myfprintf(stderr, "Hello %s %d\n", "world", 42);61 // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'myfprintf' [modernize-use-std-print]62 // CHECK-FIXES: std::println(stderr, "Hello {} {}", "world", 42);63 64 mynamespace::myfprintf2(stderr, "Hello %s %d\n", "world", 42);65 // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'myfprintf2' [modernize-use-std-print]66 // CHECK-FIXES: std::println(stderr, "Hello {} {}", "world", 42);67 68 using mynamespace::myfprintf2;69 myfprintf2(stderr, "Hello %s %d\n", "world", 42);70 // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'myfprintf2' [modernize-use-std-print]71 // CHECK-FIXES: std::println(stderr, "Hello {} {}", "world", 42);72 73 // When using custom options leave fprintf alone74 fprintf(stderr, "Hello %s %d\n", "world", 42);75}76 77int fprintf_uses_return_value(int i) {78 return myfprintf(stderr, "return value %d\n", i);79 // CHECK-MESSAGES-NOT: [[@LINE-1]]:10: warning: use 'std::println' instead of 'myprintf' [modernize-use-std-print]80 // CHECK-FIXES-NOT: std::println(stderr, "return value {}", i);81}82 83// Ensure that MatchesAnyListedNameMatcher::NameMatcher::match() can cope with a84// NamedDecl that has no name when we're trying to match unqualified_printf.85void no_name(const std::string &in)86{87 "A" + in;88}89 90int myprintf(const wchar_t *, ...);91 92void wide_string_not_supported() {93 myprintf(L"wide string %s", L"string");94}95 96// Issue #92896: Ensure that the check doesn't assert if the argument is97// promoted to something that isn't a string.98struct S {99 S(...) {}100};101int any_format_type_printf(const S &, ...);102int any_format_type_fprintf(FILE *, const S &, ...);103 104void unsupported_format_parameter_type()105{106 // No fixes here because the format parameter of the function called is not a107 // string.108 any_format_type_printf(L"Hello %s", "world");109 any_format_type_fprintf(stderr, L"Hello %s", "world");110 any_format_type_printf(42);111 any_format_type_fprintf(stderr, 42L);112 113 // But if we do pass a character string then that ought to be acceptable.114 any_format_type_printf("Hello %s\n", "world");115 // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'any_format_type_printf' [modernize-use-std-print]116 // CHECK-FIXES: std::println("Hello {}", "world");117 any_format_type_fprintf(stderr, "Hello %s\n", "world");118 // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'any_format_type_fprintf' [modernize-use-std-print]119 // CHECK-FIXES: std::println(stderr, "Hello {}", "world");120}121 122namespace fmt {123 template <typename S, typename... T>124 inline int printf(const S& fmt, const T&... args);125 126 template <typename S, typename... T>127 inline int fprintf(std::FILE* f, const S& fmt, const T&... args);128}129 130void fmt_printf()131{132 fmt::printf("fmt::printf templated %s argument %d\n", "format", 424);133 // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]134 // CHECK-FIXES: std::println("fmt::printf templated {} argument {}", "format", 424);135 136 fmt::fprintf(stderr, "fmt::fprintf templated %s argument %d\n", "format", 425);137 // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'fprintf' [modernize-use-std-print]138 // CHECK-FIXES: std::println(stderr, "fmt::fprintf templated {} argument {}", "format", 425);139}140