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

Reply via email to