[clang-tools-extra] aa56e66 - [clang-tidy] Tweak 'rule of 3/5' checks to allow defaulting a destructor outside the class.
Roy Jacobson via cfe-commits
cfe-commits at lists.llvm.org
Sun Feb 26 03:58:11 PST 2023
Author: Roy Jacobson
Date: 2023-02-26T15:55:54+02:00
New Revision: aa56e66bf7520512fd1209cbb7d099604a5f6277
URL: https://github.com/llvm/llvm-project/commit/aa56e66bf7520512fd1209cbb7d099604a5f6277
DIFF: https://github.com/llvm/llvm-project/commit/aa56e66bf7520512fd1209cbb7d099604a5f6277.diff
LOG: [clang-tidy] Tweak 'rule of 3/5' checks to allow defaulting a destructor outside the class.
A somewhat common code-pattern is to default a destructor in the source file and not in the header.
For example, this is the way to use smart pointers with forward-declared classes:
```c++
struct Impl;
struct A {
~A(); // Can't be defaulted in the header.
private:
std::unique_ptr<Impl> impl;
};
```
To be able to use this check with this pattern, I modified the behavior with `AllowSoleDefaultDtor`
to not trigger on destructors if they aren't defined yet.
Since a declared destructor should still be defined somewhere in the program, this
won't miss bad classes, just diagnose on less translation units.
Reviewed By: carlosgalvezp
Differential Revision: https://reviews.llvm.org/D143851
Added:
Modified:
clang-tools-extra/clang-tidy/cppcoreguidelines/SpecialMemberFunctionsCheck.cpp
clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/special-member-functions.rst
clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/special-member-functions-cxx-03.cpp
clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/special-member-functions-relaxed.cpp
clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/special-member-functions.cpp
Removed:
################################################################################
diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/SpecialMemberFunctionsCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/SpecialMemberFunctionsCheck.cpp
index 9bea2a78fa953..d2117c67a76d0 100644
--- a/clang-tools-extra/clang-tidy/cppcoreguidelines/SpecialMemberFunctionsCheck.cpp
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/SpecialMemberFunctionsCheck.cpp
@@ -108,10 +108,14 @@ void SpecialMemberFunctionsCheck::check(
};
if (const auto *Dtor = Result.Nodes.getNodeAs<CXXMethodDecl>("dtor")) {
- StoreMember({Dtor->isDefaulted()
- ? SpecialMemberFunctionKind::DefaultDestructor
- : SpecialMemberFunctionKind::NonDefaultDestructor,
- Dtor->isDeleted()});
+ SpecialMemberFunctionKind DestructorType =
+ SpecialMemberFunctionKind::Destructor;
+ if (Dtor->isDefined()) {
+ DestructorType = Dtor->getDefinition()->isDefaulted()
+ ? SpecialMemberFunctionKind::DefaultDestructor
+ : SpecialMemberFunctionKind::NonDefaultDestructor;
+ }
+ StoreMember({DestructorType, Dtor->isDeleted()});
}
std::initializer_list<std::pair<std::string, SpecialMemberFunctionKind>>
@@ -158,7 +162,8 @@ void SpecialMemberFunctionsCheck::checkForMissingMembers(
bool RequireThree =
HasMember(SpecialMemberFunctionKind::NonDefaultDestructor) ||
(!AllowSoleDefaultDtor &&
- HasMember(SpecialMemberFunctionKind::DefaultDestructor)) ||
+ (HasMember(SpecialMemberFunctionKind::Destructor) ||
+ HasMember(SpecialMemberFunctionKind::DefaultDestructor))) ||
HasMember(SpecialMemberFunctionKind::CopyConstructor) ||
HasMember(SpecialMemberFunctionKind::CopyAssignment) ||
HasMember(SpecialMemberFunctionKind::MoveConstructor) ||
@@ -170,7 +175,8 @@ void SpecialMemberFunctionsCheck::checkForMissingMembers(
HasMember(SpecialMemberFunctionKind::MoveAssignment);
if (RequireThree) {
- if (!HasMember(SpecialMemberFunctionKind::DefaultDestructor) &&
+ if (!HasMember(SpecialMemberFunctionKind::Destructor) &&
+ !HasMember(SpecialMemberFunctionKind::DefaultDestructor) &&
!HasMember(SpecialMemberFunctionKind::NonDefaultDestructor))
MissingMembers.push_back(SpecialMemberFunctionKind::Destructor);
diff --git a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/special-member-functions.rst b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/special-member-functions.rst
index 92815e216242c..2d8b842be5942 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/special-member-functions.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/special-member-functions.rst
@@ -25,15 +25,25 @@ Options
.. option:: AllowSoleDefaultDtor
- When set to `true` (default is `false`), this check doesn't flag classes with a sole, explicitly
- defaulted destructor. An example for such a class is:
+ When set to `true` (default is `false`), this check will only trigger on
+ destructors if they are defined and not defaulted.
.. code-block:: c++
- struct A {
+ struct A { // This is fine.
virtual ~A() = default;
};
+ struct B { // This is not fine.
+ ~B() {}
+ };
+
+ struct C {
+ // This is not checked, because the destructor might be defaulted in
+ // another translation unit.
+ ~C();
+ };
+
.. option:: AllowMissingMoveFunctions
When set to `true` (default is `false`), this check doesn't flag classes which define no move
diff --git a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/special-member-functions-cxx-03.cpp b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/special-member-functions-cxx-03.cpp
index 10f3955846d71..272adff32677a 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/special-member-functions-cxx-03.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/special-member-functions-cxx-03.cpp
@@ -3,7 +3,7 @@
class DefinesDestructor {
~DefinesDestructor();
};
-// CHECK-MESSAGES: [[@LINE-3]]:7: warning: class 'DefinesDestructor' defines a non-default destructor but does not define a copy constructor or a copy assignment operator [cppcoreguidelines-special-member-functions]
+// CHECK-MESSAGES: [[@LINE-3]]:7: warning: class 'DefinesDestructor' defines a destructor but does not define a copy constructor or a copy assignment operator [cppcoreguidelines-special-member-functions]
class DefinesCopyConstructor {
DefinesCopyConstructor(const DefinesCopyConstructor &);
diff --git a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/special-member-functions-relaxed.cpp b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/special-member-functions-relaxed.cpp
index 72248d3e05feb..4bdaff5a7cb26 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/special-member-functions-relaxed.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/special-member-functions-relaxed.cpp
@@ -1,14 +1,26 @@
// RUN: %check_clang_tidy %s cppcoreguidelines-special-member-functions %t -- -config="{CheckOptions: [{key: cppcoreguidelines-special-member-functions.AllowMissingMoveFunctions, value: true}, {key: cppcoreguidelines-special-member-functions.AllowSoleDefaultDtor, value: true}]}" --
+// Don't warn on destructors without definitions, they might be defaulted in another TU.
+class DeclaresDestructor {
+ ~DeclaresDestructor();
+};
+
class DefinesDestructor {
~DefinesDestructor();
};
-// CHECK-MESSAGES: [[@LINE-3]]:7: warning: class 'DefinesDestructor' defines a non-default destructor but does not define a copy constructor or a copy assignment operator [cppcoreguidelines-special-member-functions]
+DefinesDestructor::~DefinesDestructor() {}
+// CHECK-MESSAGES: [[@LINE-4]]:7: warning: class 'DefinesDestructor' defines a non-default destructor but does not define a copy constructor or a copy assignment operator [cppcoreguidelines-special-member-functions]
class DefinesDefaultedDestructor {
~DefinesDefaultedDestructor() = default;
};
+class DefinesDefaultedDestructorOutside {
+ ~DefinesDefaultedDestructorOutside();
+};
+
+DefinesDefaultedDestructorOutside::~DefinesDefaultedDestructorOutside() = default;
+
class DefinesCopyConstructor {
DefinesCopyConstructor(const DefinesCopyConstructor &);
};
diff --git a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/special-member-functions.cpp b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/special-member-functions.cpp
index 013ba8623a62b..60c945c8e20c3 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/special-member-functions.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/special-member-functions.cpp
@@ -3,7 +3,7 @@
class DefinesDestructor {
~DefinesDestructor();
};
-// CHECK-MESSAGES: [[@LINE-3]]:7: warning: class 'DefinesDestructor' defines a non-default destructor but does not define a copy constructor, a copy assignment operator, a move constructor or a move assignment operator [cppcoreguidelines-special-member-functions]
+// CHECK-MESSAGES: [[@LINE-3]]:7: warning: class 'DefinesDestructor' defines a destructor but does not define a copy constructor, a copy assignment operator, a move constructor or a move assignment operator [cppcoreguidelines-special-member-functions]
class DefinesDefaultedDestructor {
~DefinesDefaultedDestructor() = default;
More information about the cfe-commits
mailing list