Index: clang-tidy/misc/CMakeLists.txt =================================================================== --- clang-tidy/misc/CMakeLists.txt +++ clang-tidy/misc/CMakeLists.txt @@ -22,6 +22,7 @@ SizeofContainerCheck.cpp StaticAssertCheck.cpp StringIntegerAssignmentCheck.cpp + StringViewOfTemporaryCheck.cpp SuspiciousSemicolonCheck.cpp SwappedArgumentsCheck.cpp ThrowByValueCatchByReferenceCheck.cpp Index: clang-tidy/misc/MiscTidyModule.cpp =================================================================== --- clang-tidy/misc/MiscTidyModule.cpp +++ clang-tidy/misc/MiscTidyModule.cpp @@ -30,6 +30,7 @@ #include "SizeofContainerCheck.h" #include "StaticAssertCheck.h" #include "StringIntegerAssignmentCheck.h" +#include "StringViewOfTemporaryCheck.h" #include "SuspiciousSemicolonCheck.h" #include "SwappedArgumentsCheck.h" #include "ThrowByValueCatchByReferenceCheck.h" @@ -85,6 +86,8 @@ "misc-static-assert"); CheckFactories.registerCheck( "misc-string-integer-assignment"); + CheckFactories.registerCheck( + "misc-string_view-of-temporary"); CheckFactories.registerCheck( "misc-suspicious-semicolon"); CheckFactories.registerCheck( Index: clang-tidy/misc/StringViewOfTemporaryCheck.h =================================================================== --- /dev/null +++ clang-tidy/misc/StringViewOfTemporaryCheck.h @@ -0,0 +1,35 @@ +//===--- String_viewOfTemporaryCheck.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_MISC_STRING_VIEW_OF_TEMPORARY_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_STRING_VIEW_OF_TEMPORARY_H + +#include "../ClangTidy.h" + +namespace clang { +namespace tidy { +namespace misc { + +/// Find non-temporary string_views constructed from temporary strings. +/// +/// For the user-facing documentation see: +/// http://clang.llvm.org/extra/clang-tidy/checks/misc-string_view-of-temporary.html +class String_viewOfTemporaryCheck : public ClangTidyCheck { +public: + String_viewOfTemporaryCheck(StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context) {} + void registerMatchers(ast_matchers::MatchFinder *Finder) override; + void check(const ast_matchers::MatchFinder::MatchResult &Result) override; +}; + +} // namespace misc +} // namespace tidy +} // namespace clang + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_STRING_VIEW_OF_TEMPORARY_H Index: clang-tidy/misc/StringViewOfTemporaryCheck.cpp =================================================================== --- /dev/null +++ clang-tidy/misc/StringViewOfTemporaryCheck.cpp @@ -0,0 +1,55 @@ +//===--- StringViewOfTemporaryCheck.cpp - clang-tidy----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "StringViewOfTemporaryCheck.h" +#include "clang/AST/ASTContext.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" + +using namespace clang::ast_matchers; + +namespace clang { +namespace tidy { +namespace misc { + +namespace { + +AST_MATCHER(RecordDecl, isStdString) { + return Node.isInStdNamespace() && (Node.getName() == "string"); +} + +AST_MATCHER(RecordDecl, isStdStringView) { + return Node.isInStdNamespace() && (Node.getName() == "string_view"); +} + +} // end namespace + +void String_viewOfTemporaryCheck::registerMatchers(MatchFinder *Finder) { + Finder->addMatcher( + varDecl(has(cxxConstructExpr(hasDescendant(materializeTemporaryExpr( + hasType(recordDecl(isStdString())))))), + hasType(recordDecl(isStdStringView()))) + .bind("sv-temp"), + this); +} + +void String_viewOfTemporaryCheck::check( + const MatchFinder::MatchResult &Result) { + const auto *MatchedDecl = Result.Nodes.getNodeAs("sv-temp"); + + const auto TypeLoc = + MatchedDecl->getTypeSourceInfo()->getTypeLoc().getSourceRange(); + + diag(MatchedDecl->getLocation(), + "string_view %0 is constructed from a temporary string") + << MatchedDecl << FixItHint::CreateReplacement(TypeLoc, "std::string"); +} + +} // namespace misc +} // namespace tidy +} // namespace clang Index: docs/clang-tidy/checks/list.rst =================================================================== --- docs/clang-tidy/checks/list.rst +++ docs/clang-tidy/checks/list.rst @@ -65,6 +65,7 @@ misc-sizeof-container misc-static-assert misc-string-integer-assignment + misc-string_view-of-temporary misc-suspicious-semicolon misc-swapped-arguments misc-throw-by-value-catch-by-reference Index: docs/clang-tidy/checks/misc-string_view-of-temporary.rst =================================================================== --- /dev/null +++ docs/clang-tidy/checks/misc-string_view-of-temporary.rst @@ -0,0 +1,25 @@ +.. title:: clang-tidy - misc-string_view-of-temporary + +misc-string_view-of-temporary +============================= + +Find non-temporary ``string_view``s constructed from temporary strings and +replace them with ``std::string``s. + +The following construction of a ``string_view`` constructs a view of a +temporary object: + +.. code:: c++ + + std::string f(); + + std::string_view s(f()); + +The fix replaces the ``std::string_view`` with an ``std::string``: + +.. code:: c++ + + std::string f(); + + std::string s(f()); + Index: test/clang-tidy/misc-string_view-of-temporary.cpp =================================================================== --- /dev/null +++ test/clang-tidy/misc-string_view-of-temporary.cpp @@ -0,0 +1,33 @@ +// RUN: %check_clang_tidy %s misc-string_view-of-temporary %t + +namespace std { +inline namespace implementation { +class string { +public: + string(const char *); +}; + +class string_view { +public: + string_view(const string &); + string_view(const char*); +}; +} +} + +using std::string; +using std::string_view; + +string f(); +void g(string_view); +void h() +{ + string_view sv(f()); +// CHECK-MESSAGES: :[[@LINE-1]]:15: warning: string_view 'sv' is constructed from a temporary string [misc-string_view-of-temporary] +// CHECK-FIXES: std::string sv(f()); + g(f()); + auto s = f(); + string_view sv2(s); + string_view sv3("char[] construction"); +} +