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