diff --git a/clang-tools-extra/clang-tidy/utils/DeclRefExprUtils.cpp b/clang-tools-extra/clang-tidy/utils/DeclRefExprUtils.cpp --- a/clang-tools-extra/clang-tidy/utils/DeclRefExprUtils.cpp +++ b/clang-tools-extra/clang-tidy/utils/DeclRefExprUtils.cpp @@ -59,7 +59,11 @@ extractNodesByIdTo(Matches, "declRef", DeclRefs); auto ConstReferenceOrValue = qualType(anyOf(referenceType(pointee(qualType(isConstQualified()))), - unless(anyOf(referenceType(), pointerType())))); + unless(anyOf(referenceType(), pointerType(), + substTemplateTypeParmType())))); + auto ConstReferenceOrValueOrReplaced = qualType(anyOf( + ConstReferenceOrValue, + substTemplateTypeParmType(hasReplacementType(ConstReferenceOrValue)))); auto UsedAsConstRefOrValueArg = forEachArgumentWithParam( DeclRefToVar, parmVarDecl(hasType(ConstReferenceOrValue))); Matches = match(findAll(callExpr(UsedAsConstRefOrValueArg)), Stmt, Context); diff --git a/clang-tools-extra/test/clang-tidy/checkers/performance-unnecessary-copy-initialization.cpp b/clang-tools-extra/test/clang-tidy/checkers/performance-unnecessary-copy-initialization.cpp --- a/clang-tools-extra/test/clang-tidy/checkers/performance-unnecessary-copy-initialization.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/performance-unnecessary-copy-initialization.cpp @@ -411,14 +411,37 @@ template class function; -template -class function { +template +class function { public: function(); - function(const function &other); - R operator()(Args &&...args) const; + function(const function &Other); + R operator()(ArgTypes &&...Args) const; +}; + +template +struct remove_reference; + +template +struct remove_reference { + typedef _Tp type; +}; + +template +struct remove_reference<_Tp &> { + typedef _Tp type; +}; + +template +struct remove_reference<_Tp &&> { + typedef _Tp type; }; +template +constexpr _Tp &&forward(typename remove_reference<_Tp>::type &__t) noexcept { + return static_cast<_Tp &&>(__t); +} + } // namespace __1 } // namespace std @@ -460,3 +483,24 @@ } } // namespace fake + +void positiveInvokedOnStdFunction( + std::function Update, + const ExpensiveToCopyType Orig) { + auto Copy = Orig.reference(); + // CHECK-MESSAGES: [[@LINE-1]]:8: warning: the variable 'Copy' is copy-constructed from a const reference + // CHECK-FIXES: const auto& Copy = Orig.reference(); + Update(Copy); +} + +template +void foo(Type &&T) { + std::forward(T).nonConstMethod(); +} + +void negativeInvokedOnStdFunction( + std::function Update, + const ExpensiveToCopyType Orig) { + auto Copy = Orig.reference(); + foo(Copy); +}