diff --git a/clang-tools-extra/clang-tidy/readability/RedundantStringCStrCheck.cpp b/clang-tools-extra/clang-tidy/readability/RedundantStringCStrCheck.cpp --- a/clang-tools-extra/clang-tidy/readability/RedundantStringCStrCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/RedundantStringCStrCheck.cpp @@ -11,6 +11,8 @@ //===----------------------------------------------------------------------===// #include "RedundantStringCStrCheck.h" +#include "clang/AST/DeclCXX.h" +#include "clang/AST/ExprCXX.h" #include "clang/Lex/Lexer.h" #include "clang/Tooling/FixIt.h" @@ -65,6 +67,12 @@ return Node.isBoundToLvalueReference(); } +AST_MATCHER_P(CXXConstructExpr, forClass, + ast_matchers::internal::Matcher, InnerMatcher) { + const CXXRecordDecl *Parent = Node.getConstructor()->getParent(); + return Parent && InnerMatcher.matches(*Parent, Finder, Builder); +} + } // end namespace void RedundantStringCStrCheck::registerMatchers( @@ -157,22 +165,21 @@ // Detect redundant 'c_str()' calls through a StringRef constructor. Finder->addMatcher( - traverse( - TK_AsIs, - cxxConstructExpr( - // Implicit constructors of these classes are overloaded - // wrt. string types and they internally make a StringRef - // referring to the argument. Passing a string directly to - // them is preferred to passing a char pointer. - hasDeclaration(cxxMethodDecl(hasAnyName( - "::llvm::StringRef::StringRef", "::llvm::Twine::Twine"))), - argumentCountIs(1), - // The only argument must have the form x.c_str() or p->c_str() - // where the method is string::c_str(). StringRef also has - // a constructor from string which is more efficient (avoids - // strlen), so we can construct StringRef from the string - // directly. - hasArgument(0, StringCStrCallExpr))), + traverse(TK_AsIs, + cxxConstructExpr( + // Implicit constructors of these classes are overloaded + // wrt. string types and they internally make a StringRef + // referring to the argument. Passing a string directly to + // them is preferred to passing a char pointer. + forClass(hasAnyName("::std::basic_string_view", + "::llvm::StringRef", "::llvm::Twine")), + argumentCountIs(1), + // The only argument must have the form x.c_str() or + // p->c_str() where the method is string::c_str(). StringRef + // also has a constructor from string which is more efficient + // (avoids strlen), so we can construct StringRef from the + // string directly. + hasArgument(0, StringCStrCallExpr))), this); } diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-string-cstr.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-string-cstr.cpp --- a/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-string-cstr.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-string-cstr.cpp @@ -48,6 +48,16 @@ typedef basic_string, std::allocator> wstring; typedef basic_string, std::allocator> u16string; typedef basic_string, std::allocator> u32string; + +template +struct basic_string_view { + basic_string_view(const C*); +}; + +typedef basic_string_view> string_view; +typedef basic_string_view> wstring_voew; +typedef basic_string_view> u16string_view; +typedef basic_string_view> u32string_view; } std::string operator+(const std::string&, const std::string&); @@ -170,6 +180,14 @@ tmp.insert(1, s.c_str(), 2); } +void f7(const std::string_view&) { + std::string S; + f7(S.c_str()); + // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: redundant call {{.*}} + // CHECK-FIXES: {{^ }}std::string S;{{$}} + // CHECK-FIXES-NEXT: {{^ }}f7(S);{{$}} +} + // Tests for std::wstring. void g1(const std::wstring &s) {