Author: Zeyi Xu Date: 2026-07-08T15:17:29+08:00 New Revision: e6525149c347a4787dd82ce5d2663bc577afd4a3
URL: https://github.com/llvm/llvm-project/commit/e6525149c347a4787dd82ce5d2663bc577afd4a3 DIFF: https://github.com/llvm/llvm-project/commit/e6525149c347a4787dd82ce5d2663bc577afd4a3.diff LOG: [clang-tidy] Fix AllowImplicitlyDeletedCopyOrMove missing-move false positive (#207586) The documentation for `cppcoreguidelines-special-member-functions` says that `AllowImplicitlyDeletedCopyOrMove` suppresses diagnostics for classes which implicitly delete copy or move operations. In practice, the move operations are missing because the user-declared destructor prevents their implicit declaration. This commit suppresses that missing-move diagnostic when both copy operations are implicitly deleted and no move operation is user-declared. Godbolt: https://clang-tidy.godbolt.org/z/h1nT84Tee Closes https://github.com/llvm/llvm-project/issues/196615 Added: clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/special-member-functions-implicit-delete.cpp Modified: clang-tools-extra/clang-tidy/cppcoreguidelines/SpecialMemberFunctionsCheck.cpp clang-tools-extra/docs/ReleaseNotes.rst Removed: ################################################################################ diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/SpecialMemberFunctionsCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/SpecialMemberFunctionsCheck.cpp index 1ef64b702cd66..6f2ab250e441b 100644 --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/SpecialMemberFunctionsCheck.cpp +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/SpecialMemberFunctionsCheck.cpp @@ -224,10 +224,19 @@ void SpecialMemberFunctionsCheck::checkForMissingMembers( SpecialMemberFunctionKind::CopyAssignment); } + const bool CopyImplicitlyDeleted = + HasImplicitDeletedMember(SpecialMemberFunctionKind::CopyConstructor) && + HasImplicitDeletedMember(SpecialMemberFunctionKind::CopyAssignment); + const bool MoveMissing = + !HasMember(SpecialMemberFunctionKind::MoveConstructor) && + !HasMember(SpecialMemberFunctionKind::MoveAssignment); + if (RequireFive && !(AllowMissingMoveFunctionsWhenCopyIsDeleted && (IsDeleted(SpecialMemberFunctionKind::CopyConstructor) && - IsDeleted(SpecialMemberFunctionKind::CopyAssignment)))) { + IsDeleted(SpecialMemberFunctionKind::CopyAssignment))) && + !(AllowImplicitlyDeletedCopyOrMove && CopyImplicitlyDeleted && + MoveMissing)) { assert(RequireThree); RequireMembers(SpecialMemberFunctionKind::MoveConstructor, SpecialMemberFunctionKind::MoveAssignment); diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index b85ece288881e..79885902ab079 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -541,6 +541,12 @@ Changes in existing checks by fixing a false positive on implicitly generated functions such as inherited constructors. +- Improved :doc:`cppcoreguidelines-special-member-functions + <clang-tidy/checks/cppcoreguidelines/special-member-functions>` check by + fixing a false positive with the `AllowImplicitlyDeletedCopyOrMove` option + for classes whose copy operations are implicitly deleted by a non-copyable + base class. + - Improved :doc:`cppcoreguidelines-use-enum-class <clang-tidy/checks/cppcoreguidelines/use-enum-class>` check by adding the `IgnoreMacros` option. When enabled, unscoped ``enum`` declarations within diff --git a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/special-member-functions-implicit-delete.cpp b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/special-member-functions-implicit-delete.cpp new file mode 100644 index 0000000000000..45137a30c807c --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/special-member-functions-implicit-delete.cpp @@ -0,0 +1,31 @@ +// RUN: %check_clang_tidy %s cppcoreguidelines-special-member-functions %t -- \ +// RUN: -config="{CheckOptions: {cppcoreguidelines-special-member-functions.AllowImplicitlyDeletedCopyOrMove: true}}" + +struct Base { + Base(const Base &) = delete; + Base &operator=(const Base &) = delete; + Base(Base &&) = delete; + Base &operator=(Base &&) = delete; + ~Base(); +}; + +struct A : Base { + ~A() {} +}; + +struct Member { + Base B; + ~Member() {} +}; + +// CHECK-MESSAGES: [[@LINE+1]]:8: warning: class 'B' defines a non-default destructor and a move constructor but does not define a move assignment operator +struct B : Base { + ~B() {} + B(B &&); +}; + +// CHECK-MESSAGES: [[@LINE+1]]:8: warning: class 'C' defines a non-default destructor and a move assignment operator but does not define a move constructor +struct C : Base { + ~C() {} + C &operator=(C &&); +}; _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
