Index: clang-tools-extra/clang-tidy/readability/RedundantStringInitCheck.h =================================================================== --- clang-tools-extra/clang-tidy/readability/RedundantStringInitCheck.h +++ clang-tools-extra/clang-tidy/readability/RedundantStringInitCheck.h @@ -10,6 +10,8 @@ #define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_REDUNDANT_STRING_INIT_H #include "../ClangTidyCheck.h" +#include +#include namespace clang { namespace tidy { @@ -18,10 +20,13 @@ /// Finds unnecessary string initializations. class RedundantStringInitCheck : public ClangTidyCheck { public: - RedundantStringInitCheck(StringRef Name, ClangTidyContext *Context) - : ClangTidyCheck(Name, Context) {} + RedundantStringInitCheck(StringRef Name, ClangTidyContext *Context); + void storeOptions(ClangTidyOptions::OptionMap &Opts) override; void registerMatchers(ast_matchers::MatchFinder *Finder) override; void check(const ast_matchers::MatchFinder::MatchResult &Result) override; + +private: + std::vector StringNames; }; } // namespace readability Index: clang-tools-extra/clang-tidy/readability/RedundantStringInitCheck.cpp =================================================================== --- clang-tools-extra/clang-tidy/readability/RedundantStringInitCheck.cpp +++ clang-tools-extra/clang-tidy/readability/RedundantStringInitCheck.cpp @@ -8,6 +8,7 @@ #include "RedundantStringInitCheck.h" #include "../utils/Matchers.h" +#include "../utils/OptionsUtils.h" #include "clang/ASTMatchers/ASTMatchers.h" using namespace clang::ast_matchers; @@ -17,19 +18,32 @@ namespace tidy { namespace readability { +const char DefaultStringNames[] = "basic_string"; + +RedundantStringInitCheck::RedundantStringInitCheck(StringRef Name, + ClangTidyContext *Context) + : ClangTidyCheck(Name, Context), + StringNames(utils::options::parseStringList( + Options.get("StringNames", DefaultStringNames))) {} + +void RedundantStringInitCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { + Options.store(Opts, "StringNames", DefaultStringNames); +} + void RedundantStringInitCheck::registerMatchers(MatchFinder *Finder) { if (!getLangOpts().CPlusPlus) return; - + const auto hasStringName = hasAnyName( + SmallVector(StringNames.begin(), StringNames.end())); // Match string constructor. - const auto StringConstructorExpr = expr(anyOf( - cxxConstructExpr(argumentCountIs(1), - hasDeclaration(cxxMethodDecl(hasName("basic_string")))), - // If present, the second argument is the alloc object which must not - // be present explicitly. - cxxConstructExpr(argumentCountIs(2), - hasDeclaration(cxxMethodDecl(hasName("basic_string"))), - hasArgument(1, cxxDefaultArgExpr())))); + const auto StringConstructorExpr = + expr(anyOf(cxxConstructExpr(argumentCountIs(1), + hasDeclaration(cxxMethodDecl(hasStringName))), + // If present, the second argument is the alloc object which + // must not be present explicitly. + cxxConstructExpr(argumentCountIs(2), + hasDeclaration(cxxMethodDecl(hasStringName)), + hasArgument(1, cxxDefaultArgExpr())))); // Match a string constructor expression with an empty string literal. const auto EmptyStringCtorExpr = cxxConstructExpr( @@ -47,7 +61,7 @@ Finder->addMatcher( namedDecl( varDecl(hasType(hasUnqualifiedDesugaredType(recordType( - hasDeclaration(cxxRecordDecl(hasName("basic_string")))))), + hasDeclaration(cxxRecordDecl(hasStringName))))), hasInitializer(expr(ignoringImplicit(anyOf( EmptyStringCtorExpr, EmptyStringCtorExprWithTemporaries))) Index: clang-tools-extra/docs/ReleaseNotes.rst =================================================================== --- clang-tools-extra/docs/ReleaseNotes.rst +++ clang-tools-extra/docs/ReleaseNotes.rst @@ -130,6 +130,10 @@ - The 'objc-avoid-spinlock' check was renamed to :doc:`darwin-avoid-spinlock ` +- The :doc:`readability-redundant-string-init + ` check now supports a + `StringNames` option enabling its application to custom string classes. + Improvements to include-fixer ----------------------------- Index: clang-tools-extra/docs/clang-tidy/checks/readability-redundant-string-init.rst =================================================================== --- clang-tools-extra/docs/clang-tidy/checks/readability-redundant-string-init.rst +++ clang-tools-extra/docs/clang-tidy/checks/readability-redundant-string-init.rst @@ -5,7 +5,8 @@ Finds unnecessary string initializations. -Examples: +Examples +-------- .. code-block:: c++ @@ -17,3 +18,16 @@ std::string a; std::string b; + +Options +------- + +.. option:: StringNames + + Default is `basic_string`. + + Semicolon-delimited list of base class names to apply this check to. + By default `basic_string` applies to std::string and std::wstring. + Set to e.g. `basic_string;StringRef;QString` to perform this check on + custom classes as well. + Index: clang-tools-extra/test/clang-tidy/checkers/readability-redundant-string-init.cpp =================================================================== --- clang-tools-extra/test/clang-tidy/checkers/readability-redundant-string-init.cpp +++ clang-tools-extra/test/clang-tidy/checkers/readability-redundant-string-init.cpp @@ -1,4 +1,8 @@ // RUN: %check_clang_tidy %s readability-redundant-string-init %t +// RUN: -config="{CheckOptions: \ +// RUN: [{key: readability-redundant-string-init.StringNames, \ +// RUN: value: "basic_string;OurTestString"}] \ +// RUN: }" namespace std { template @@ -139,3 +143,31 @@ void Param3(std::string param = "") {} void Param4(STRING param = "") {} +struct OurTestString { + OurTestString(); + OurTestString(const OurTestString &); + // MSVC headers define two constructors instead of using optional arguments. + OurTestString(const char *); + ~OurTestString(); +}; + +void OurTestStringTests() { + OurTestString a = ""; + // CHECK-MESSAGES: [[@LINE-1]]:17: warning: redundant string initialization + // CHECK-FIXES: OurTestString a; + OurTestString b(""); + // CHECK-MESSAGES: [[@LINE-1]]:17: warning: redundant string initialization + // CHECK-FIXES: OurTestString b; + OurTestString c = R"()"; + // CHECK-MESSAGES: [[@LINE-1]]:17: warning: redundant string initialization + // CHECK-FIXES: OurTestString c; + OurTestString d(R"()"); + // CHECK-MESSAGES: [[@LINE-1]]:17: warning: redundant string initialization + // CHECK-FIXES: OurTestString d; + + OurTestString u = "u"; + OurTestString w("w"); + OurTestString x = R"(x)"; + OurTestString y(R"(y)"); + OurTestString z; +}