Index: clang-tidy/performance/ForRangeCopyCheck.cpp =================================================================== --- clang-tidy/performance/ForRangeCopyCheck.cpp +++ clang-tidy/performance/ForRangeCopyCheck.cpp @@ -32,7 +32,10 @@ // initialized through MaterializeTemporaryExpr which indicates a type // conversion. auto LoopVar = varDecl( - hasType(hasCanonicalType(unless(anyOf(referenceType(), pointerType())))), + hasType(hasCanonicalType( + unless(anyOf(referenceType(), pointerType(), + hasDeclaration(namedDecl(matchesName( + "[Pp]ointer$|[Pp]tr$|[Rr]ef(erence)?$"))))))), unless(hasInitializer(expr(hasDescendant(materializeTemporaryExpr()))))); Finder->addMatcher(cxxForRangeStmt(hasLoopVariable(LoopVar.bind("loopVar"))) .bind("forRange"), Index: clang-tidy/performance/UnnecessaryCopyInitialization.cpp =================================================================== --- clang-tidy/performance/UnnecessaryCopyInitialization.cpp +++ clang-tidy/performance/UnnecessaryCopyInitialization.cpp @@ -55,7 +55,11 @@ forEachDescendant( declStmt( has(varDecl(hasLocalStorage(), - hasType(matchers::isExpensiveToCopy()), + hasType(hasCanonicalType(allOf( + matchers::isExpensiveToCopy(), + unless(hasDeclaration(namedDecl( + matchesName("[Pp]ointer$|[Pp]tr$|[" + "Rr]ef(erence)?$"))))))), unless(isImplicit()), hasInitializer( cxxConstructExpr( Index: clang-tidy/performance/UnnecessaryValueParamCheck.cpp =================================================================== --- clang-tidy/performance/UnnecessaryValueParamCheck.cpp +++ clang-tidy/performance/UnnecessaryValueParamCheck.cpp @@ -75,10 +75,13 @@ // Objective-C. if (!getLangOpts().CPlusPlus) return; - const auto ExpensiveValueParamDecl = - parmVarDecl(hasType(hasCanonicalType(allOf( - unless(referenceType()), matchers::isExpensiveToCopy()))), - decl().bind("param")); + const auto ExpensiveValueParamDecl = parmVarDecl( + hasType(hasCanonicalType( + allOf(unless(anyOf(referenceType(), + hasDeclaration(namedDecl(matchesName( + "[Pp]ointer$|[Pp]tr$|[Rr]ef(erence)?$"))))), + matchers::isExpensiveToCopy()))), + decl().bind("param")); Finder->addMatcher( functionDecl(hasBody(stmt()), isDefinition(), unless(isImplicit()), unless(cxxMethodDecl(anyOf(isOverride(), isFinal()))), Index: docs/clang-tidy/checks/performance-for-range-copy.rst =================================================================== --- docs/clang-tidy/checks/performance-for-range-copy.rst +++ docs/clang-tidy/checks/performance-for-range-copy.rst @@ -10,6 +10,11 @@ which means they are not trivially copyable or have a non-trivial copy constructor or destructor. +To avoid too many false-positives the check ignores types considered as pointer +or reference types (e.g. smart pointers) based on their name. The name of these +types must end to either `Pointer`, `pointer`, `Ptr`, `ptr`, `Reference`, +`reference`, `Ref`, `ref`. + To ensure that it is safe to replace the copy with a const reference the following heuristic is employed: Index: docs/clang-tidy/checks/performance-unnecessary-copy-initialization.rst =================================================================== --- docs/clang-tidy/checks/performance-unnecessary-copy-initialization.rst +++ docs/clang-tidy/checks/performance-unnecessary-copy-initialization.rst @@ -7,6 +7,11 @@ constructor of a non-trivially-copyable type but it would suffice to obtain a const reference. +To avoid too many false-positives the check ignores types considered as pointer +or reference types (e.g. smart pointers) based on their name. The name of these +types must end to either `Pointer`, `pointer`, `Ptr`, `ptr`, `Reference`, +`reference`, `Ref`, `ref`. + The check is only applied if it is safe to replace the copy by a const reference. This is the case when the variable is const qualified or when it is only used as a const, i.e. only const methods or operators are invoked on it, or Index: docs/clang-tidy/checks/performance-unnecessary-value-param.rst =================================================================== --- docs/clang-tidy/checks/performance-unnecessary-value-param.rst +++ docs/clang-tidy/checks/performance-unnecessary-value-param.rst @@ -10,6 +10,11 @@ which means they are not trivially copyable or have a non-trivial copy constructor or destructor. +To avoid too many false-positives the check ignores types considered as pointer +or reference types (e.g. smart pointers) based on their name. The name of these +types must end to either `Pointer`, `pointer`, `Ptr`, `ptr`, `Reference`, +`reference`, `Ref`, `ref`. + To ensure that it is safe to replace the value parameter with a const reference the following heuristic is employed: Index: test/clang-tidy/performance-for-range-copy.cpp =================================================================== --- test/clang-tidy/performance-for-range-copy.cpp +++ test/clang-tidy/performance-for-range-copy.cpp @@ -52,6 +52,38 @@ } }; +struct SmartPointer { + ~SmartPointer(); +}; + +struct smart_pointer { + ~smart_pointer(); +}; + +struct SmartPtr { + ~SmartPtr(); +}; + +struct smart_ptr { + ~smart_ptr(); +}; + +struct SmartReference { + ~SmartReference(); +}; + +struct smart_reference { + ~smart_reference(); +}; + +struct SmartRef { + ~SmartRef(); +}; + +struct smart_ref { + ~smart_ref(); +}; + void negativeConstReference() { for (const S &S1 : View>()) { } @@ -270,3 +302,51 @@ for (auto _ : View>()) { } } + +void negativeSmartPointer() { + for (auto P : View>()) { + auto P2 = P; + } +} + +void negative_smart_pointer() { + for (auto p : View>()) { + auto p2 = p; + } +} + +void negativeSmartPtr() { + for (auto P : View>()) { + auto P2 = P; + } +} + +void negative_smart_ptr() { + for (auto p : View>()) { + auto p2 = p; + } +} + +void negativeSmartReference() { + for (auto R : View>()) { + auto R2 = R; + } +} + +void negative_smart_reference() { + for (auto r : View>()) { + auto r2 = r; + } +} + +void negativeSmartRef() { + for (auto R : View>()) { + auto R2 = R; + } +} + +void negative_smart_ref() { + for (auto r : View>()) { + auto r2 = r; + } +} Index: test/clang-tidy/performance-unnecessary-copy-initialization.cpp =================================================================== --- test/clang-tidy/performance-unnecessary-copy-initialization.cpp +++ test/clang-tidy/performance-unnecessary-copy-initialization.cpp @@ -20,11 +20,52 @@ bool constMethod() const; }; +struct SmartPointer { + ~SmartPointer(); +}; + +struct smart_pointer { + ~smart_pointer(); +}; + +struct SmartPtr { + ~SmartPtr(); +}; + +struct smart_ptr { + ~smart_ptr(); +}; + +struct SmartReference { + ~SmartReference(); +}; + +struct smart_reference { + ~smart_reference(); +}; + +struct SmartRef { + ~SmartRef(); +}; + +struct smart_ref { + ~smart_ref(); +}; + ExpensiveToCopyType global_expensive_to_copy_type; const ExpensiveToCopyType &ExpensiveTypeReference(); const TrivialToCopyType &TrivialTypeReference(); +const SmartPointer &getSmartPointer(); +const smart_pointer &get_smart_pointer(); +const SmartPtr &getSmartPtr(); +const smart_ptr &get_smart_ptr(); +const SmartReference &getSmartReference(); +const smart_reference &get_smart_reference(); +const SmartRef &getSmartRef(); +const smart_ref &get_smart_ref(); + void mutate(ExpensiveToCopyType &); void mutate(ExpensiveToCopyType *); void useAsConstPointer(const ExpensiveToCopyType *); @@ -387,3 +428,35 @@ for (const Element &E : Container()) { } } + +void negativeSmartPointer() { + const auto P = getSmartPointer(); +} + +void negative_smart_pointer() { + const auto p = get_smart_pointer(); +} + +void negativeSmartPtr() { + const auto P = getSmartPtr(); +} + +void negative_smart_ptr() { + const auto p = get_smart_ptr(); +} + +void negativeSmartReference() { + const auto R = getSmartReference(); +} + +void negative_smart_reference() { + const auto r = get_smart_reference(); +} + +void negativeSmartRef() { + const auto R = getSmartRef(); +} + +void negative_smart_ref() { + const auto r = get_smart_ref(); +} Index: test/clang-tidy/performance-unnecessary-value-param.cpp =================================================================== --- test/clang-tidy/performance-unnecessary-value-param.cpp +++ test/clang-tidy/performance-unnecessary-value-param.cpp @@ -55,6 +55,38 @@ ~ExpensiveMovableType(); }; +struct SmartPointer { + ~SmartPointer(); +}; + +struct smart_pointer { + ~smart_pointer(); +}; + +struct SmartPtr { + ~SmartPtr(); +}; + +struct smart_ptr { + ~smart_ptr(); +}; + +struct SmartReference { + ~SmartReference(); +}; + +struct smart_reference { + ~smart_reference(); +}; + +struct SmartRef { + ~SmartRef(); +}; + +struct smart_ref { + ~smart_ref(); +}; + void positiveExpensiveConstValue(const ExpensiveToCopyType Obj); // CHECK-FIXES: void positiveExpensiveConstValue(const ExpensiveToCopyType& Obj); void positiveExpensiveConstValue(const ExpensiveToCopyType Obj) { @@ -381,3 +413,27 @@ // CHECK-FIXES: void templateFunction(ExpensiveToCopyType E) { E.constReference(); } + +void negativeSmartPointer(SmartPointer P) { +} + +void negative_smart_pointer(smart_pointer p) { +} + +void negativeSmartPtr(SmartPtr P) { +} + +void negative_smart_ptr(smart_ptr p) { +} + +void negativeSmartReference(SmartReference R) { +} + +void negative_smart_reference(smart_reference r) { +} + +void negativeSmartRef(SmartRef R) { +} + +void negative_smart_ref(smart_ref r) { +}