diff --git a/clang-tools-extra/clang-tidy/modernize/UseEmplaceCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseEmplaceCheck.cpp --- a/clang-tools-extra/clang-tidy/modernize/UseEmplaceCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/UseEmplaceCheck.cpp @@ -130,27 +130,35 @@ // because this requires special treatment (it could cause performance // regression) // + match for emplace calls that should be replaced with insertion + + auto PushBackTypes = hasCanonicalType( + hasDeclaration(cxxRecordDecl(hasAnyName(ContainersWithPushBack)))); auto CallPushBack = cxxMemberCallExpr( hasDeclaration(functionDecl(hasName("push_back"))), - on(hasType(hasCanonicalType( - hasDeclaration(cxxRecordDecl(hasAnyName(ContainersWithPushBack))))))); + on(anyOf(hasType(PushBackTypes), + hasType(pointerType(pointee(PushBackTypes)))))); - auto CallPush = - cxxMemberCallExpr(hasDeclaration(functionDecl(hasName("push"))), - on(hasType(hasCanonicalType(hasDeclaration( - cxxRecordDecl(hasAnyName(ContainersWithPush))))))); + auto PushTypes = hasCanonicalType( + hasDeclaration(cxxRecordDecl(hasAnyName(ContainersWithPush)))); + auto CallPush = cxxMemberCallExpr( + hasDeclaration(functionDecl(hasName("push"))), + on(anyOf(hasType(PushTypes), hasType(pointerType(pointee(PushTypes)))))); + auto PushFrontTypes = hasCanonicalType( + hasDeclaration(cxxRecordDecl(hasAnyName(ContainersWithPushFront)))); auto CallPushFront = cxxMemberCallExpr( hasDeclaration(functionDecl(hasName("push_front"))), - on(hasType(hasCanonicalType(hasDeclaration( - cxxRecordDecl(hasAnyName(ContainersWithPushFront))))))); - - auto CallEmplacy = cxxMemberCallExpr( - hasDeclaration( - functionDecl(hasAnyNameIgnoringTemplates(EmplacyFunctions))), - on(hasType(hasCanonicalType(hasDeclaration(has(typedefNameDecl( - hasName("value_type"), hasType(type(hasUnqualifiedDesugaredType( - recordType().bind("value_type"))))))))))); + on(anyOf(hasType(PushFrontTypes), + hasType(pointerType(pointee(PushFrontTypes)))))); + + auto EmplacyTypes = hasCanonicalType(hasDeclaration(has(typedefNameDecl( + hasName("value_type"), hasType(type(hasUnqualifiedDesugaredType( + recordType().bind("value_type")))))))); + auto CallEmplacy = + cxxMemberCallExpr(hasDeclaration(functionDecl( + hasAnyNameIgnoringTemplates(EmplacyFunctions))), + on(anyOf(hasType(EmplacyTypes), + hasType(pointerType(pointee(EmplacyTypes)))))); // We can't replace push_backs of smart pointer because // if emplacement fails (f.e. bad_alloc in vector) we will have leak of diff --git a/clang-tools-extra/test/clang-tidy/checkers/modernize/use-emplace.cpp b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-emplace.cpp --- a/clang-tools-extra/test/clang-tidy/checkers/modernize/use-emplace.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-emplace.cpp @@ -1334,3 +1334,40 @@ v3.push_back({{0}}); v3.push_back({{}}); } + +void testWithPointerTypes() { + std::vector v; + std::vector* vp = &v; + + vp->push_back(Something(1, 2)); + // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use emplace_back instead of push_back [modernize-use-emplace] + // CHECK-FIXES: vp->emplace_back(1, 2); + + vp->push_back(Something{1, 2}); + // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use emplace_back instead of push_back [modernize-use-emplace] + // CHECK-FIXES: vp->emplace_back(1, 2); + + vp->push_back(Something()); + // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use emplace_back instead of push_back [modernize-use-emplace] + // CHECK-FIXES: vp->emplace_back(); + + vp->push_back(Something{}); + // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use emplace_back instead of push_back [modernize-use-emplace] + // CHECK-FIXES: vp->emplace_back(); + + vp->emplace_back(Something(1, 2)); + // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: unnecessary temporary object created while calling emplace_back + // CHECK-FIXES: vp->emplace_back(1, 2); + + vp->emplace_back(Something{1, 2}); + // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: unnecessary temporary object created while calling emplace_back + // CHECK-FIXES: vp->emplace_back(1, 2); + + vp->emplace_back(Something()); + // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: unnecessary temporary object created while calling emplace_back + // CHECK-FIXES: vp->emplace_back(); + + vp->emplace_back(Something{}); + // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: unnecessary temporary object created while calling emplace_back + // CHECK-FIXES: vp->emplace_back(); +}