1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
|
// RUN: %check_clang_tidy %s readability-redundant-string-cstr %t -- \
// RUN: -config="{CheckOptions: \
// RUN: [{key: readability-redundant-string-cstr.StringParameterFunctions, \
// RUN: value: '::fmt::format; ::fmt::print; ::BaseLogger::operator(); ::BaseLogger::Log'}] \
// RUN: }" \
// RUN: -- -isystem %clang_tidy_headers
#include <string>
namespace fmt {
inline namespace v8 {
template<typename ...Args>
void print(const char *, Args &&...);
template<typename ...Args>
std::string format(const char *, Args &&...);
}
}
namespace notfmt {
inline namespace v8 {
template<typename ...Args>
void print(const char *, Args &&...);
template<typename ...Args>
std::string format(const char *, Args &&...);
}
}
void fmt_print(const std::string &s1, const std::string &s2, const std::string &s3) {
fmt::print("One:{}\n", s1.c_str());
// CHECK-MESSAGES: :[[@LINE-1]]:26: warning: redundant call to 'c_str' [readability-redundant-string-cstr]
// CHECK-FIXES: {{^ }}fmt::print("One:{}\n", s1);
fmt::print("One:{} Two:{} Three:{}\n", s1.c_str(), s2, s3.c_str());
// CHECK-MESSAGES: :[[@LINE-1]]:42: warning: redundant call to 'c_str' [readability-redundant-string-cstr]
// CHECK-MESSAGES: :[[@LINE-2]]:58: warning: redundant call to 'c_str' [readability-redundant-string-cstr]
// CHECK-FIXES: {{^ }}fmt::print("One:{} Two:{} Three:{}\n", s1, s2, s3);
}
// There's no c_str() call here, so it shouldn't be touched
void fmt_print_no_cstr(const std::string &s1, const std::string &s2) {
fmt::print("One: {}, Two: {}\n", s1, s2);
}
// This isn't fmt::print, so it shouldn't be fixed.
void not_fmt_print(const std::string &s1) {
notfmt::print("One: {}\n", s1.c_str());
}
void fmt_format(const std::string &s1, const std::string &s2, const std::string &s3) {
auto r1 = fmt::format("One:{}\n", s1.c_str());
// CHECK-MESSAGES: :[[@LINE-1]]:37: warning: redundant call to 'c_str' [readability-redundant-string-cstr]
// CHECK-FIXES: {{^ }}auto r1 = fmt::format("One:{}\n", s1);
auto r2 = fmt::format("One:{} Two:{} Three:{}\n", s1.c_str(), s2, s3.c_str());
// CHECK-MESSAGES: :[[@LINE-1]]:53: warning: redundant call to 'c_str' [readability-redundant-string-cstr]
// CHECK-MESSAGES: :[[@LINE-2]]:69: warning: redundant call to 'c_str' [readability-redundant-string-cstr]
// CHECK-FIXES: {{^ }}auto r2 = fmt::format("One:{} Two:{} Three:{}\n", s1, s2, s3);
}
// There's are c_str() calls here, so it shouldn't be touched
void fmt_format_no_cstr(const std::string &s1, const std::string &s2) {
fmt::format("One: {}, Two: {}\n", s1, s2);
}
// This is not fmt::format, so it shouldn't be fixed
std::string not_fmt_format(const std::string &s1) {
return notfmt::format("One: {}\n", s1.c_str());
}
class BaseLogger {
public:
template <typename... Args>
void operator()(const char *fmt, Args &&...args) {
}
template <typename... Args>
void Log(const char *fmt, Args &&...args) {
}
};
class DerivedLogger : public BaseLogger {};
class DoubleDerivedLogger : public DerivedLogger {};
typedef DerivedLogger TypedefDerivedLogger;
void logger1(const std::string &s1, const std::string &s2, const std::string &s3) {
BaseLogger LOGGER;
LOGGER("%s\n", s1.c_str(), s2, s3.c_str());
// CHECK-MESSAGES: :[[@LINE-1]]:18: warning: redundant call to 'c_str' [readability-redundant-string-cstr]
// CHECK-MESSAGES: :[[@LINE-2]]:34: warning: redundant call to 'c_str' [readability-redundant-string-cstr]
// CHECK-FIXES: {{^ }}LOGGER("%s\n", s1, s2, s3);
DerivedLogger LOGGER2;
LOGGER2("%d %s\n", 42, s1.c_str(), s2.c_str(), s3);
// CHECK-MESSAGES: :[[@LINE-1]]:26: warning: redundant call to 'c_str' [readability-redundant-string-cstr]
// CHECK-MESSAGES: :[[@LINE-2]]:38: warning: redundant call to 'c_str' [readability-redundant-string-cstr]
// CHECK-FIXES: {{^ }}LOGGER2("%d %s\n", 42, s1, s2, s3);
DoubleDerivedLogger LOGGERD;
LOGGERD("%d %s\n", 42, s1.c_str(), s2, s3.c_str());
// CHECK-MESSAGES: :[[@LINE-1]]:26: warning: redundant call to 'c_str' [readability-redundant-string-cstr]
// CHECK-MESSAGES: :[[@LINE-2]]:42: warning: redundant call to 'c_str' [readability-redundant-string-cstr]
// CHECK-FIXES: {{^ }}LOGGERD("%d %s\n", 42, s1, s2, s3);
TypedefDerivedLogger LOGGERT;
LOGGERT("%d %s\n", 42, s1.c_str(), s2, s3.c_str());
// CHECK-MESSAGES: :[[@LINE-1]]:26: warning: redundant call to 'c_str' [readability-redundant-string-cstr]
// CHECK-MESSAGES: :[[@LINE-2]]:42: warning: redundant call to 'c_str' [readability-redundant-string-cstr]
// CHECK-FIXES: {{^ }}LOGGERT("%d %s\n", 42, s1, s2, s3);
}
void logger2(const std::string &s1, const std::string &s2) {
BaseLogger LOGGER3;
LOGGER3.Log("%s\n", s1.c_str(), s2.c_str());
// CHECK-MESSAGES: :[[@LINE-1]]:23: warning: redundant call to 'c_str' [readability-redundant-string-cstr]
// CHECK-MESSAGES: :[[@LINE-2]]:35: warning: redundant call to 'c_str' [readability-redundant-string-cstr]
// CHECK-FIXES: {{^ }}LOGGER3.Log("%s\n", s1, s2);
DerivedLogger LOGGER4;
LOGGER4.Log("%d %s\n", 42, s1.c_str(), s2.c_str());
// CHECK-MESSAGES: :[[@LINE-1]]:30: warning: redundant call to 'c_str' [readability-redundant-string-cstr]
// CHECK-MESSAGES: :[[@LINE-2]]:42: warning: redundant call to 'c_str' [readability-redundant-string-cstr]
// CHECK-FIXES: {{^ }}LOGGER4.Log("%d %s\n", 42, s1, s2);
}
class NotLogger {
public:
template <typename... Args>
void operator()(const char *fmt, Args &&...args) {
}
template <typename... Args>
void Log(const char *fmt, Args &&...args) {
}
};
void Log(const char *fmt, ...);
void logger3(const std::string &s1)
{
// Not BaseLogger or something derived from it
NotLogger LOGGER;
LOGGER("%s\n", s1.c_str());
LOGGER.Log("%s\n", s1.c_str());
// Free function not in StringParameterFunctions list
Log("%s\n", s1.c_str());
}
|