Index: clang-tools-extra/clang-tidy/readability/ContainerSizeEmptyCheck.cpp =================================================================== --- clang-tools-extra/clang-tidy/readability/ContainerSizeEmptyCheck.cpp +++ clang-tools-extra/clang-tidy/readability/ContainerSizeEmptyCheck.cpp @@ -191,10 +191,17 @@ std::string ReplacementText = std::string( Lexer::getSourceText(CharSourceRange::getTokenRange(E->getSourceRange()), *Result.SourceManager, getLangOpts())); - if (isBinaryOrTernary(E) || isa(E)) { + const auto *OpCallExpr = dyn_cast(E); + if (isBinaryOrTernary(E) || isa(E) || + (OpCallExpr && (OpCallExpr->getOperator() == OO_Star))) { ReplacementText = "(" + ReplacementText + ")"; } - if (E->getType()->isPointerType()) + if (OpCallExpr && + OpCallExpr->getOperator() == OverloadedOperatorKind::OO_Arrow) { + // This can happen if the object is a smart pointer. Don't add anything + // because a '->' is already there (PR#51776), just call the method. + ReplacementText += "empty()"; + } else if (E->getType()->isPointerType()) ReplacementText += "->empty()"; else ReplacementText += ".empty()"; Index: clang-tools-extra/docs/ReleaseNotes.rst =================================================================== --- clang-tools-extra/docs/ReleaseNotes.rst +++ clang-tools-extra/docs/ReleaseNotes.rst @@ -83,6 +83,9 @@ - Generalized the `modernize-use-default-member-init` check to handle non-default constructors. +- Fixed incorrect suggestions for `readability-container-size-empty` when + smart pointers are involved. + New checks ^^^^^^^^^^ Index: clang-tools-extra/test/clang-tidy/checkers/readability-container-size-empty.cpp =================================================================== --- clang-tools-extra/test/clang-tidy/checkers/readability-container-size-empty.cpp +++ clang-tools-extra/test/clang-tidy/checkers/readability-container-size-empty.cpp @@ -696,3 +696,25 @@ instantiatedTemplateWithSizeCall(); instantiatedTemplateWithSizeCall>(); } + +namespace std { +template +struct unique_ptr { + T *operator->() const; + T &operator*() const; +}; +} // namespace std + +bool call_through_unique_ptr(const std::unique_ptr> &ptr) { + return ptr->size() > 0; + // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: the 'empty' method should be used + // CHECK-MESSAGES: :9:8: note: method 'vector'::empty() defined here + // CHECK-FIXES: {{^ }}return !ptr->empty(); +} + +bool call_through_unique_ptr_deref(const std::unique_ptr> &ptr) { + return (*ptr).size() > 0; + // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: the 'empty' method should be used + // CHECK-MESSAGES: :9:8: note: method 'vector'::empty() defined here + // CHECK-FIXES: {{^ }}return !(*ptr).empty(); +}