Index: clang-tidy/ClangTidyDiagnosticConsumer.h =================================================================== --- clang-tidy/ClangTidyDiagnosticConsumer.h +++ clang-tidy/ClangTidyDiagnosticConsumer.h @@ -151,7 +151,7 @@ void setASTContext(ASTContext *Context); /// \brief Gets the language options from the AST context. - LangOptions getLangOpts() const { return LangOpts; } + const LangOptions &getLangOpts() const { return LangOpts; } /// \brief Returns the name of the clang-tidy check which produced this /// diagnostic ID. Index: clang-tidy/ClangTidyDiagnosticConsumer.cpp =================================================================== --- clang-tidy/ClangTidyDiagnosticConsumer.cpp +++ clang-tidy/ClangTidyDiagnosticConsumer.cpp @@ -338,10 +338,9 @@ Errors.push_back(ClangTidyError(CheckName, Level, IsWarningAsError)); } - // FIXME: Provide correct LangOptions for each file. - LangOptions LangOpts; ClangTidyDiagnosticRenderer Converter( - LangOpts, &Context.DiagEngine->getDiagnosticOptions(), Errors.back()); + Context.getLangOpts(), &Context.DiagEngine->getDiagnosticOptions(), + Errors.back()); SmallString<100> Message; Info.FormatDiagnostic(Message); SourceManager *Sources = nullptr; Index: clang-tidy/readability/CMakeLists.txt =================================================================== --- clang-tidy/readability/CMakeLists.txt +++ clang-tidy/readability/CMakeLists.txt @@ -14,6 +14,7 @@ RedundantControlFlowCheck.cpp RedundantStringCStrCheck.cpp RedundantSmartptrGetCheck.cpp + RedundantStringInitCheck.cpp SimplifyBooleanExprCheck.cpp UniqueptrDeleteReleaseCheck.cpp Index: clang-tidy/readability/ReadabilityTidyModule.cpp =================================================================== --- clang-tidy/readability/ReadabilityTidyModule.cpp +++ clang-tidy/readability/ReadabilityTidyModule.cpp @@ -21,6 +21,7 @@ #include "RedundantControlFlowCheck.h" #include "RedundantSmartptrGetCheck.h" #include "RedundantStringCStrCheck.h" +#include "RedundantStringInitCheck.h" #include "SimplifyBooleanExprCheck.h" #include "UniqueptrDeleteReleaseCheck.h" @@ -53,6 +54,8 @@ "readability-redundant-smartptr-get"); CheckFactories.registerCheck( "readability-redundant-string-cstr"); + CheckFactories.registerCheck( + "readability-redundant-string-init"); CheckFactories.registerCheck( "readability-simplify-boolean-expr"); CheckFactories.registerCheck( Index: clang-tidy/readability/RedundantStringInitCheck.h =================================================================== --- /dev/null +++ clang-tidy/readability/RedundantStringInitCheck.h @@ -0,0 +1,32 @@ +//===- RedundantStringInitCheck.h - clang-tidy ------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_REDUNDANT_STRING_INIT_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_REDUNDANT_STRING_INIT_H + +#include "../ClangTidy.h" + +namespace clang { +namespace tidy { +namespace readability { + +/// Finds unnecessary string initializations. +class RedundantStringInitCheck : public ClangTidyCheck { +public: + RedundantStringInitCheck(StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context) {} + void registerMatchers(ast_matchers::MatchFinder *Finder) override; + void check(const ast_matchers::MatchFinder::MatchResult &Result) override; +}; + +} // namespace readability +} // namespace tidy +} // namespace clang + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_REDUNDANT_STRING_INIT_H Index: clang-tidy/readability/RedundantStringInitCheck.cpp =================================================================== --- /dev/null +++ clang-tidy/readability/RedundantStringInitCheck.cpp @@ -0,0 +1,64 @@ +//===- RedundantStringInitCheck.cpp - clang-tidy ----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "RedundantStringInitCheck.h" +#include "clang/ASTMatchers/ASTMatchers.h" + +using namespace clang::ast_matchers; + +namespace clang { +namespace tidy { +namespace readability { + +namespace { + +AST_MATCHER(StringLiteral, lengthIsZero) { return Node.getLength() == 0; } + +} // namespace + +void RedundantStringInitCheck::registerMatchers( + ast_matchers::MatchFinder *Finder) { + if (!getLangOpts().CPlusPlus) + return; + + const auto StringCtorExpr = cxxConstructExpr( + hasDeclaration(cxxMethodDecl(hasName("basic_string"))), + argumentCountIs(2), + hasArgument(0, ignoringParenImpCasts(stringLiteral(lengthIsZero()))), + hasArgument(1, cxxDefaultArgExpr())); + + // string foo = ""; + // OR + // string bar(""); + Finder->addMatcher( + namedDecl(varDecl(hasType(cxxRecordDecl(hasName("basic_string"))), + hasInitializer( + expr(anyOf(StringCtorExpr, + exprWithCleanups(has(expr(anyOf( + StringCtorExpr, + cxxConstructExpr(hasArgument( + 0, cxxBindTemporaryExpr(has( + StringCtorExpr)))))))))) + .bind("expr")))) + .bind("decl"), + this); +} + +void RedundantStringInitCheck::check( + const ast_matchers::MatchFinder::MatchResult &Result) { + const auto *CtorExpr = Result.Nodes.getNodeAs("expr"); + const auto *Decl = Result.Nodes.getNodeAs("decl"); + diag(CtorExpr->getExprLoc(), "redundant string initialization") + << FixItHint::CreateReplacement(CtorExpr->getSourceRange(), + Decl->getName()); +} + +} // namespace readability +} // namespace tidy +} // namespace clang Index: docs/clang-tidy/checks/list.rst =================================================================== --- docs/clang-tidy/checks/list.rst +++ docs/clang-tidy/checks/list.rst @@ -97,5 +97,6 @@ readability-redundant-control-flow readability-redundant-smartptr-get readability-redundant-string-cstr + readability-redundant-string-init readability-simplify-boolean-expr readability-uniqueptr-delete-release Index: docs/clang-tidy/checks/readability-redundant-string-init.rst =================================================================== --- /dev/null +++ docs/clang-tidy/checks/readability-redundant-string-init.rst @@ -0,0 +1,16 @@ +.. title:: clang-tidy - readability-redundant-string-init + +readability-redundant-string-init +================================= + + +Finds unnecessary string initializations. + +Examples: + +.. code:: c++ + + // Initializing string with empty string literal is unnecessary. + std::string a = ""; + std::string b(""); + Index: test/clang-tidy/readability-redundant-string-init.cpp =================================================================== --- /dev/null +++ test/clang-tidy/readability-redundant-string-init.cpp @@ -0,0 +1,59 @@ +// RUN: %check_clang_tidy %s readability-redundant-string-init %t + +namespace std { +template +class allocator {}; +template +class char_traits {}; +template , typename A = std::allocator> +struct basic_string { + basic_string(); + basic_string(const basic_string&); + basic_string(const C *, const A &a = A()); + ~basic_string(); +}; +typedef basic_string string; +typedef basic_string wstring; +} + +void f() { + std::string a = ""; + // CHECK-MESSAGES: [[@LINE-1]]:15: warning: redundant string initialization [readability-redundant-string-init] + // CHECK-FIXES: std::string a; + std::string b(""); + // CHECK-MESSAGES: [[@LINE-1]]:15: warning: redundant string initialization + // CHECK-FIXES: std::string b; + std::string c = R"()"; + // CHECK-MESSAGES: [[@LINE-1]]:15: warning: redundant string initialization + // CHECK-FIXES: std::string c; + std::string d(R"()"); + // CHECK-MESSAGES: [[@LINE-1]]:15: warning: redundant string initialization + // CHECK-FIXES: std::string d; + + std::string u = "u"; + std::string w("w"); + std::string x = R"(x)"; + std::string y(R"(y)"); + std::string z; +} + +void g() { + std::wstring a = L""; + // CHECK-MESSAGES: [[@LINE-1]]:16: warning: redundant string initialization + // CHECK-FIXES: std::wstring a; + std::wstring b(L""); + // CHECK-MESSAGES: [[@LINE-1]]:16: warning: redundant string initialization + // CHECK-FIXES: std::wstring b; + std::wstring c = LR"()"; + // CHECK-MESSAGES: [[@LINE-1]]:16: warning: redundant string initialization + // CHECK-FIXES: std::wstring c; + std::wstring d(LR"()"); + // CHECK-MESSAGES: [[@LINE-1]]:16: warning: redundant string initialization + // CHECK-FIXES: std::wstring d; + + std::wstring u = L"u"; + std::wstring w(L"w"); + std::wstring x = LR"(x)"; + std::wstring y(LR"(y)"); + std::wstring z; +}