vrnithinkumar updated this revision to Diff 265921.
vrnithinkumar added a comment.
fixed the clang-tidy warnig
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D80490/new/
https://reviews.llvm.org/D80490
Files:
clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt
clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp
clang-tools-extra/clang-tidy/cppcoreguidelines/RuleOfFiveAndZeroCheck.cpp
clang-tools-extra/clang-tidy/cppcoreguidelines/RuleOfFiveAndZeroCheck.h
clang-tools-extra/docs/ReleaseNotes.rst
clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-rule-of-five-and-zero.rst
clang-tools-extra/docs/clang-tidy/checks/list.rst
clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-rule-of-five-and-zero-strict.cpp
clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-rule-of-five-and-zero.cpp
Index: clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-rule-of-five-and-zero.cpp
===================================================================
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-rule-of-five-and-zero.cpp
@@ -0,0 +1,122 @@
+// RUN: %check_clang_tidy %s cppcoreguidelines-rule-of-five-and-zero %t
+
+class DefinesNothing {
+};
+
+class DefinesEverything {
+ DefinesEverything(const DefinesEverything &);
+ DefinesEverything &operator=(const DefinesEverything &);
+ DefinesEverything(DefinesEverything &&);
+ DefinesEverything &operator=(DefinesEverything &&);
+ ~DefinesEverything();
+};
+
+class DeletesEverything {
+ DeletesEverything(const DeletesEverything &);
+ DeletesEverything &operator=(const DeletesEverything &);
+ DeletesEverything(DeletesEverything &&);
+ DeletesEverything &operator=(DeletesEverything &&);
+ ~DeletesEverything();
+};
+
+// Safe cases
+class DefinesAllExceptMoves {
+ ~DefinesAllExceptMoves();
+ DefinesAllExceptMoves(DefinesAllExceptMoves &);
+ DefinesAllExceptMoves &operator=(DefinesAllExceptMoves &);
+};
+
+class DefinesAllExceptMoveConstructor {
+ ~DefinesAllExceptMoveConstructor();
+ DefinesAllExceptMoveConstructor(DefinesAllExceptMoveConstructor &);
+ DefinesAllExceptMoveConstructor &operator=(DefinesAllExceptMoveConstructor &);
+ DefinesAllExceptMoveConstructor &operator=(DefinesAllExceptMoveConstructor &&);
+};
+
+class DefinesAllExceptMoveAssignment {
+ ~DefinesAllExceptMoveAssignment();
+ DefinesAllExceptMoveAssignment(DefinesAllExceptMoveAssignment &);
+ DefinesAllExceptMoveAssignment &operator=(DefinesAllExceptMoveAssignment &);
+ DefinesAllExceptMoveAssignment(DefinesAllExceptMoveAssignment &&);
+};
+
+class DefinesDestructorAndMoveConstructor {
+ ~DefinesDestructorAndMoveConstructor();
+ DefinesDestructorAndMoveConstructor(DefinesDestructorAndMoveConstructor &&);
+};
+
+class DefinesDestructorAndMoveAssignment {
+ ~DefinesDestructorAndMoveAssignment();
+ DefinesDestructorAndMoveAssignment &operator=(DefinesDestructorAndMoveAssignment &&);
+};
+
+// CHECK-MESSAGES: :[[@LINE+1]]:7: warning: class 'DefinesOnlyDestructor' defines a destructor but does not define all other 5, define all other 5 or delete all other special member functions [cppcoreguidelines-rule-of-five-and-zero]
+class DefinesOnlyDestructor {
+ ~DefinesOnlyDestructor();
+};
+
+// CHECK-MESSAGES: :[[@LINE+1]]:7: warning: class 'DefinesOnlyCopyConstructor' defines a copy constructor but does not define all other 5, define all other 5 or delete all other special member functions [cppcoreguidelines-rule-of-five-and-zero]
+class DefinesOnlyCopyConstructor {
+ DefinesOnlyCopyConstructor(const DefinesOnlyCopyConstructor &);
+};
+
+// CHECK-MESSAGES: :[[@LINE+1]]:7: warning: class 'DefinesOnlyMoveConstructor' defines a move constructor but does not define all other 5, define all other 5 or delete all other special member functions [cppcoreguidelines-rule-of-five-and-zero]
+class DefinesOnlyMoveConstructor {
+ DefinesOnlyMoveConstructor(DefinesOnlyMoveConstructor &&);
+};
+
+// CHECK-MESSAGES: :[[@LINE+1]]:7: warning: class 'DefinesOnlyCopyAssignment' defines a copy assignment operator but does not define all other 5, define all other 5 or delete all other special member functions [cppcoreguidelines-rule-of-five-and-zero]
+class DefinesOnlyCopyAssignment {
+ DefinesOnlyCopyAssignment &operator=(const DefinesOnlyCopyAssignment &);
+};
+
+// CHECK-MESSAGES: :[[@LINE+1]]:7: warning: class 'DefinesOnlyMoveAssignment' defines a move assignment operator but does not define all other 5, define all other 5 or delete all other special member functions [cppcoreguidelines-rule-of-five-and-zero]
+class DefinesOnlyMoveAssignment {
+ DefinesOnlyMoveAssignment &operator=(DefinesOnlyMoveAssignment &&);
+};
+
+// check inheritance
+class NoCopyBase {
+public:
+ ~NoCopyBase();
+ NoCopyBase(NoCopyBase &&);
+ NoCopyBase &operator=(NoCopyBase &&);
+
+private:
+ NoCopyBase(const NoCopyBase &) = delete;
+ NoCopyBase &operator=(const NoCopyBase &) = delete;
+};
+
+class NoMoveBase {
+public:
+ ~NoMoveBase();
+ NoMoveBase(const NoMoveBase &);
+ NoMoveBase &operator=(const NoMoveBase &);
+
+private:
+ NoMoveBase(NoMoveBase &&) = delete;
+ NoMoveBase &operator=(NoMoveBase &&) = delete;
+};
+
+class NoCopyNoMove : NoMoveBase, NoCopyBase {
+};
+
+class NoCopyViaBaseClass : NoCopyBase {
+ ~NoCopyViaBaseClass();
+ NoCopyViaBaseClass(NoCopyViaBaseClass &&);
+ NoCopyViaBaseClass &operator=(NoCopyViaBaseClass &&);
+};
+
+class NoMoveViaBaseClass : NoMoveBase {
+ ~NoMoveViaBaseClass();
+ NoMoveViaBaseClass(const NoMoveViaBaseClass &);
+ NoMoveViaBaseClass &operator=(const NoMoveViaBaseClass &);
+};
+
+class NoMoveNoCopyViaBaseClasses : NoCopyBase, NoMoveBase {
+ ~NoMoveNoCopyViaBaseClasses();
+};
+
+class NoMoveNoCopyViaBaseClass : NoCopyNoMove {
+ ~NoMoveNoCopyViaBaseClass();
+};
Index: clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-rule-of-five-and-zero-strict.cpp
===================================================================
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-rule-of-five-and-zero-strict.cpp
@@ -0,0 +1,139 @@
+// RUN: %check_clang_tidy %s cppcoreguidelines-rule-of-five-and-zero %t -- \
+// RUN: -config="{CheckOptions: \
+// RUN: [{key: cppcoreguidelines-rule-of-five-and-zero.StrictCheck, \
+// RUN: value: 1}]}"
+
+class DefinesNothing {
+};
+
+class DefinesEverything {
+ DefinesEverything(const DefinesEverything &);
+ DefinesEverything &operator=(const DefinesEverything &);
+ DefinesEverything(DefinesEverything &&);
+ DefinesEverything &operator=(DefinesEverything &&);
+ ~DefinesEverything();
+};
+
+class DeletesEverything {
+ DeletesEverything(const DeletesEverything &);
+ DeletesEverything &operator=(const DeletesEverything &);
+ DeletesEverything(DeletesEverything &&);
+ DeletesEverything &operator=(DeletesEverything &&);
+ ~DeletesEverything();
+};
+
+// CHECK-MESSAGES: :[[@LINE+3]]:7: warning: class 'DefinesAllExceptMoves' defines a copy assignment operator but does not define all other 5, define all other 5 or delete all other special member functions [cppcoreguidelines-rule-of-five-and-zero]
+// CHECK-MESSAGES: :[[@LINE+2]]:7: warning: class 'DefinesAllExceptMoves' defines a copy constructor but does not define all other 5, define all other 5 or delete all other special member functions [cppcoreguidelines-rule-of-five-and-zero]
+// CHECK-MESSAGES: :[[@LINE+1]]:7: warning: class 'DefinesAllExceptMoves' defines a destructor but does not define all other 5, define all other 5 or delete all other special member functions [cppcoreguidelines-rule-of-five-and-zero]
+class DefinesAllExceptMoves {
+ ~DefinesAllExceptMoves();
+ DefinesAllExceptMoves(const DefinesAllExceptMoves &);
+ DefinesAllExceptMoves &operator=(const DefinesAllExceptMoves &);
+};
+
+// CHECK-MESSAGES: :[[@LINE+4]]:7: warning: class 'DefinesAllExceptMoveConstructor' defines a copy assignment operator but does not define all other 5, define all other 5 or delete all other special member functions [cppcoreguidelines-rule-of-five-and-zero]
+// CHECK-MESSAGES: :[[@LINE+3]]:7: warning: class 'DefinesAllExceptMoveConstructor' defines a copy constructor but does not define all other 5, define all other 5 or delete all other special member functions [cppcoreguidelines-rule-of-five-and-zero]
+// CHECK-MESSAGES: :[[@LINE+2]]:7: warning: class 'DefinesAllExceptMoveConstructor' defines a destructor but does not define all other 5, define all other 5 or delete all other special member functions [cppcoreguidelines-rule-of-five-and-zero]
+// CHECK-MESSAGES: :[[@LINE+1]]:7: warning: class 'DefinesAllExceptMoveConstructor' defines a move assignment operator but does not define all other 5, define all other 5 or delete all other special member functions [cppcoreguidelines-rule-of-five-and-zero]
+class DefinesAllExceptMoveConstructor {
+ ~DefinesAllExceptMoveConstructor();
+ DefinesAllExceptMoveConstructor(const DefinesAllExceptMoveConstructor &);
+ DefinesAllExceptMoveConstructor &operator=(const DefinesAllExceptMoveConstructor &);
+ DefinesAllExceptMoveConstructor &operator=(DefinesAllExceptMoveConstructor &&);
+};
+
+// CHECK-MESSAGES: :[[@LINE+4]]:7: warning: class 'DefinesAllExceptMoveAssignment' defines a copy assignment operator but does not define all other 5, define all other 5 or delete all other special member functions [cppcoreguidelines-rule-of-five-and-zero]
+// CHECK-MESSAGES: :[[@LINE+3]]:7: warning: class 'DefinesAllExceptMoveAssignment' defines a copy constructor but does not define all other 5, define all other 5 or delete all other special member functions [cppcoreguidelines-rule-of-five-and-zero]
+// CHECK-MESSAGES: :[[@LINE+2]]:7: warning: class 'DefinesAllExceptMoveAssignment' defines a destructor but does not define all other 5, define all other 5 or delete all other special member functions [cppcoreguidelines-rule-of-five-and-zero]
+// CHECK-MESSAGES: :[[@LINE+1]]:7: warning: class 'DefinesAllExceptMoveAssignment' defines a move constructor but does not define all other 5, define all other 5 or delete all other special member functions [cppcoreguidelines-rule-of-five-and-zero]
+class DefinesAllExceptMoveAssignment {
+ ~DefinesAllExceptMoveAssignment();
+ DefinesAllExceptMoveAssignment(const DefinesAllExceptMoveAssignment &);
+ DefinesAllExceptMoveAssignment &operator=(const DefinesAllExceptMoveAssignment &);
+ DefinesAllExceptMoveAssignment(DefinesAllExceptMoveAssignment &&);
+};
+
+// CHECK-MESSAGES: :[[@LINE+2]]:7: warning: class 'DefinesDestructorAndMoveConstructor' defines a destructor but does not define all other 5, define all other 5 or delete all other special member functions [cppcoreguidelines-rule-of-five-and-zero]
+// CHECK-MESSAGES: :[[@LINE+1]]:7: warning: class 'DefinesDestructorAndMoveConstructor' defines a move constructor but does not define all other 5, define all other 5 or delete all other special member functions [cppcoreguidelines-rule-of-five-and-zero]
+class DefinesDestructorAndMoveConstructor {
+ ~DefinesDestructorAndMoveConstructor();
+ DefinesDestructorAndMoveConstructor(DefinesDestructorAndMoveConstructor &&);
+};
+
+// CHECK-MESSAGES: :[[@LINE+2]]:7: warning: class 'DefinesDestructorAndMoveAssignment' defines a destructor but does not define all other 5, define all other 5 or delete all other special member functions [cppcoreguidelines-rule-of-five-and-zero]
+// CHECK-MESSAGES: :[[@LINE+1]]:7: warning: class 'DefinesDestructorAndMoveAssignment' defines a move assignment operator but does not define all other 5, define all other 5 or delete all other special member functions [cppcoreguidelines-rule-of-five-and-zero]
+class DefinesDestructorAndMoveAssignment {
+ ~DefinesDestructorAndMoveAssignment();
+ DefinesDestructorAndMoveAssignment &operator=(DefinesDestructorAndMoveAssignment &&);
+};
+
+// CHECK-MESSAGES: :[[@LINE+1]]:7: warning: class 'DefinesOnlyDestructor' defines a destructor but does not define all other 5, define all other 5 or delete all other special member functions [cppcoreguidelines-rule-of-five-and-zero]
+class DefinesOnlyDestructor {
+ ~DefinesOnlyDestructor();
+};
+
+// CHECK-MESSAGES: :[[@LINE+1]]:7: warning: class 'DefinesOnlyCopyConstructor' defines a copy constructor but does not define all other 5, define all other 5 or delete all other special member functions [cppcoreguidelines-rule-of-five-and-zero]
+class DefinesOnlyCopyConstructor {
+ DefinesOnlyCopyConstructor(const DefinesOnlyCopyConstructor &);
+};
+
+// CHECK-MESSAGES: :[[@LINE+1]]:7: warning: class 'DefinesOnlyMoveConstructor' defines a move constructor but does not define all other 5, define all other 5 or delete all other special member functions [cppcoreguidelines-rule-of-five-and-zero]
+class DefinesOnlyMoveConstructor {
+ DefinesOnlyMoveConstructor(DefinesOnlyMoveConstructor &&);
+};
+
+// CHECK-MESSAGES: :[[@LINE+1]]:7: warning: class 'DefinesOnlyCopyAssignment' defines a copy assignment operator but does not define all other 5, define all other 5 or delete all other special member functions [cppcoreguidelines-rule-of-five-and-zero]
+class DefinesOnlyCopyAssignment {
+ DefinesOnlyCopyAssignment &operator=(const DefinesOnlyCopyAssignment &);
+};
+
+// CHECK-MESSAGES: :[[@LINE+1]]:7: warning: class 'DefinesOnlyMoveAssignment' defines a move assignment operator but does not define all other 5, define all other 5 or delete all other special member functions [cppcoreguidelines-rule-of-five-and-zero]
+class DefinesOnlyMoveAssignment {
+ DefinesOnlyMoveAssignment &operator=(DefinesOnlyMoveAssignment &&);
+};
+
+// check inheritance
+class NoCopyBase {
+public:
+ ~NoCopyBase();
+ NoCopyBase(NoCopyBase &&);
+ NoCopyBase &operator=(NoCopyBase &&);
+
+private:
+ NoCopyBase(const NoCopyBase &) = delete;
+ NoCopyBase &operator=(const NoCopyBase &) = delete;
+};
+
+class NoMoveBase {
+public:
+ ~NoMoveBase();
+ NoMoveBase(const NoMoveBase &);
+ NoMoveBase &operator=(const NoMoveBase &);
+
+private:
+ NoMoveBase(NoMoveBase &&) = delete;
+ NoMoveBase &operator=(NoMoveBase &&) = delete;
+};
+
+class NoCopyNoMove : NoMoveBase, NoCopyBase {
+};
+
+class NoCopyViaBaseClass : NoCopyBase {
+ ~NoCopyViaBaseClass();
+ NoCopyViaBaseClass(NoCopyViaBaseClass &&);
+ NoCopyViaBaseClass &operator=(NoCopyViaBaseClass &&);
+};
+
+class NoMoveViaBaseClass : NoMoveBase {
+ ~NoMoveViaBaseClass();
+ NoMoveViaBaseClass(const NoMoveViaBaseClass &);
+ NoMoveViaBaseClass &operator=(const NoMoveViaBaseClass &);
+};
+
+class NoMoveNoCopyViaBaseClasses : NoCopyBase, NoMoveBase {
+ ~NoMoveNoCopyViaBaseClasses();
+};
+
+class NoMoveNoCopyViaBaseClass : NoCopyNoMove {
+ ~NoMoveNoCopyViaBaseClass();
+};
Index: clang-tools-extra/docs/clang-tidy/checks/list.rst
===================================================================
--- clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -148,6 +148,7 @@
`cppcoreguidelines-pro-type-static-cast-downcast <cppcoreguidelines-pro-type-static-cast-downcast.html>`_, "Yes"
`cppcoreguidelines-pro-type-union-access <cppcoreguidelines-pro-type-union-access.html>`_,
`cppcoreguidelines-pro-type-vararg <cppcoreguidelines-pro-type-vararg.html>`_,
+ `cppcoreguidelines-rule-of-five-and-zero <cppcoreguidelines-rule-of-five-and-zero.html>`_, "Yes"
`cppcoreguidelines-slicing <cppcoreguidelines-slicing.html>`_,
`cppcoreguidelines-special-member-functions <cppcoreguidelines-special-member-functions.html>`_,
`darwin-avoid-spinlock <darwin-avoid-spinlock.html>`_,
@@ -421,4 +422,3 @@
`hicpp-use-override <hicpp-use-override.html>`_, `modernize-use-override <modernize-use-override.html>`_, "Yes"
`hicpp-vararg <hicpp-vararg.html>`_, `cppcoreguidelines-pro-type-vararg <cppcoreguidelines-pro-type-vararg.html>`_,
`llvm-qualified-auto <llvm-qualified-auto.html>`_, `readability-qualified-auto <readability-qualified-auto.html>`_, "Yes"
-
Index: clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-rule-of-five-and-zero.rst
===================================================================
--- /dev/null
+++ clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-rule-of-five-and-zero.rst
@@ -0,0 +1,37 @@
+.. title:: clang-tidy - cppcoreguidelines-rule-of-five-and-zero
+
+cppcoreguidelines-rule-of-five-and-zero
+=======================================
+
+The check finds classes where some but not all of the special member functions
+are defined. This rule is known as rule of five and zero.
+
+By default the compiler defines a copy constructor, copy assignment operator,
+move constructor, move assignment operator and destructor. The default can be
+suppressed by explicit user-definitions.``=default`` or ``=delete`` are
+considered to be a definition and will suppress the implicit declaration. The
+relationship between which functions will be suppressed by definitions of
+other functions is complicated and it is advised that all five are defaulted
+or explicitly defined.
+
+With ``strict-check`` flag the check has two modes. With the flag the rule
+checks whether the all special members or none of the special members are
+defined.
+
+But for some combination, compiler explicitly delete the special members or
+does not declare implicitly. In that case don'nt have to define all the special
+members. For example, in case of defining all members except move constructor
+and move assignment compiler will not implicitly declare the move constructor
+and move assignment.
+
+Without the flag the check will ignore special safe cases:
+* Defining all members except move constructor and move assignment
+* Defining all except move constructor
+* Defining all except move assignment
+* Defining only destructor and move constructor
+* Defining only destructor and move assignment
+
+This rule is part of the "Constructors, assignments, and destructors" profile of the C++ Core
+Guidelines, corresponding to rule C.21. See
+
+https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#c21-if-you-define-or-delete-any-default-operation-define-or-delete-them-all.
\ No newline at end of file
Index: clang-tools-extra/docs/ReleaseNotes.rst
===================================================================
--- clang-tools-extra/docs/ReleaseNotes.rst
+++ clang-tools-extra/docs/ReleaseNotes.rst
@@ -113,6 +113,13 @@
Flags use of the `C` standard library functions ``memset``, ``memcpy`` and
``memcmp`` and similar derivatives on non-trivial types.
+- New :doc:`cppcoreguidelines-rule-of-five-and-zero
+ <clang-tidy/checks/cppcoreguidelines-rule-of-five-and-zero>` check.
+
+ Check for rule of five and zero violations.
+ Finds the classes where some but not all of the special member functions
+ are defined.
+
- New :doc:`llvmlibc-callee-namespace
<clang-tidy/checks/llvmlibc-callee-namespace>` check.
Index: clang-tools-extra/clang-tidy/cppcoreguidelines/RuleOfFiveAndZeroCheck.h
===================================================================
--- /dev/null
+++ clang-tools-extra/clang-tidy/cppcoreguidelines/RuleOfFiveAndZeroCheck.h
@@ -0,0 +1,41 @@
+//===--- RuleOfFiveAndZeroCheck.h - clang-tidy ------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_RULE_OF_FIVE_AND_ZERO_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_RULE_OF_FIVE_AND_ZERO_H
+
+#include "../ClangTidyCheck.h"
+
+namespace clang {
+namespace tidy {
+namespace cppcoreguidelines {
+
+/// Rule of five and zero check
+/// Checks for classes where some, but not all, of the special member functions
+/// are defined.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/cppcoreguidelines-rule-of-five-and-zero.html
+class RuleOfFiveAndZeroCheck : public ClangTidyCheck {
+public:
+ RuleOfFiveAndZeroCheck(StringRef Name, ClangTidyContext *Context);
+ void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+ void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+
+private:
+ const bool StrictCheck;
+ void
+ checkRuleOfFiveViolation(const ast_matchers::MatchFinder::MatchResult &Result,
+ llvm::StringRef Match, llvm::StringRef FunctionName);
+};
+
+} // namespace cppcoreguidelines
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_RULEOFFIVEANDZEROCHECK_H
Index: clang-tools-extra/clang-tidy/cppcoreguidelines/RuleOfFiveAndZeroCheck.cpp
===================================================================
--- /dev/null
+++ clang-tools-extra/clang-tidy/cppcoreguidelines/RuleOfFiveAndZeroCheck.cpp
@@ -0,0 +1,152 @@
+//===--- RuleOfFiveAndZeroCheck.cpp - clang-tidy --------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "RuleOfFiveAndZeroCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace cppcoreguidelines {
+
+RuleOfFiveAndZeroCheck::RuleOfFiveAndZeroCheck(StringRef Name,
+ ClangTidyContext *Context)
+ : ClangTidyCheck(Name, Context),
+ StrictCheck(Options.get("StrictCheck", false)) {}
+
+void RuleOfFiveAndZeroCheck::registerMatchers(MatchFinder *Finder) {
+ if (!getLangOpts().CPlusPlus11)
+ return;
+
+ // Checks for user defined constructors and destructors
+ auto DefinesDestructor = has(cxxDestructorDecl(unless(isImplicit())));
+ auto UserDefinesCopyConstructor =
+ has(cxxConstructorDecl(isCopyConstructor(), unless(isImplicit())));
+ auto UserDefinesCopyAssignment =
+ has(cxxMethodDecl(isCopyAssignmentOperator(), unless(isImplicit())));
+ auto UserDefinesMoveConstructor =
+ has(cxxConstructorDecl(isMoveConstructor(), unless(isImplicit())));
+ auto UserDefinesMoveAssignment =
+ has(cxxMethodDecl(isMoveAssignmentOperator(), unless(isImplicit())));
+
+ // Checks for any derived class has deleted special members
+ auto DerivedFromBaseWithDeletedCopyConstructor =
+ isDerivedFrom(has(cxxConstructorDecl(isCopyConstructor(), isDeleted())));
+ auto DerivedFromBaseWithDeletedCopyAssignment = isDerivedFrom(
+ has(cxxMethodDecl(isCopyAssignmentOperator(), isDeleted())));
+ auto DerivedFromBaseWithDeletedMoveConstructor =
+ isDerivedFrom(has(cxxConstructorDecl(isMoveConstructor(), isDeleted())));
+ auto DerivedFromBaseWithDeletedMoveAssignment = isDerivedFrom(
+ has(cxxMethodDecl(isMoveAssignmentOperator(), isDeleted())));
+
+ auto DefinesCopyConstructor = anyOf(
+ UserDefinesCopyConstructor, DerivedFromBaseWithDeletedCopyConstructor);
+ auto DefinesCopyAssignment = anyOf(UserDefinesCopyAssignment,
+ DerivedFromBaseWithDeletedCopyAssignment);
+ auto DefinesMoveConstructor = anyOf(
+ UserDefinesMoveConstructor, DerivedFromBaseWithDeletedMoveConstructor);
+ auto DefinesMoveAssignment = anyOf(UserDefinesMoveAssignment,
+ DerivedFromBaseWithDeletedMoveAssignment);
+ auto DefinesAllSpecialMembers =
+ allOf(DefinesDestructor, DefinesCopyConstructor, DefinesCopyAssignment,
+ DefinesMoveConstructor, DefinesMoveAssignment);
+
+ // Safe cases
+ auto DefinesAllExceptMoves =
+ allOf(DefinesDestructor, DefinesCopyConstructor, DefinesCopyAssignment);
+ auto DefinesAllExceptMoveAssignment =
+ allOf(DefinesDestructor, DefinesCopyConstructor, DefinesCopyAssignment,
+ DefinesMoveConstructor);
+ auto DefinesAllExceptMoveConstructor =
+ allOf(DefinesDestructor, DefinesCopyConstructor, DefinesCopyAssignment,
+ DefinesMoveAssignment);
+ auto DefinesDestructorAndMoveAssignment =
+ allOf(DefinesDestructor, DefinesMoveAssignment);
+ auto DefinesDestructorAndMoveConstructor =
+ allOf(DefinesDestructor, DefinesMoveConstructor);
+
+ auto SafeSpecialMembers =
+ anyOf(DefinesAllExceptMoves, DefinesAllExceptMoveConstructor,
+ DefinesAllExceptMoveAssignment, DefinesDestructorAndMoveConstructor,
+ DefinesDestructorAndMoveAssignment);
+
+ if (StrictCheck) {
+ Finder->addMatcher(cxxRecordDecl(allOf(DefinesDestructor,
+ unless(DefinesAllSpecialMembers)))
+ .bind("dtor"),
+ this);
+ Finder->addMatcher(cxxRecordDecl(allOf(UserDefinesCopyConstructor,
+ unless(DefinesAllSpecialMembers)))
+ .bind("copy-ctor"),
+ this);
+ Finder->addMatcher(cxxRecordDecl(allOf(UserDefinesCopyAssignment,
+ unless(DefinesAllSpecialMembers)))
+ .bind("copy-assign"),
+ this);
+ Finder->addMatcher(cxxRecordDecl(allOf(UserDefinesMoveConstructor,
+ unless(DefinesAllSpecialMembers)))
+ .bind("move-ctor"),
+ this);
+ Finder->addMatcher(cxxRecordDecl(allOf(UserDefinesMoveAssignment,
+ unless(DefinesAllSpecialMembers)))
+ .bind("move-assign"),
+ this);
+ } else {
+ Finder->addMatcher(
+ cxxRecordDecl(allOf(DefinesDestructor, unless(DefinesAllSpecialMembers),
+ unless(SafeSpecialMembers)))
+ .bind("dtor"),
+ this);
+ Finder->addMatcher(cxxRecordDecl(allOf(UserDefinesCopyConstructor,
+ unless(DefinesAllSpecialMembers),
+ unless(SafeSpecialMembers)))
+ .bind("copy-ctor"),
+ this);
+ Finder->addMatcher(cxxRecordDecl(allOf(UserDefinesCopyAssignment,
+ unless(DefinesAllSpecialMembers),
+ unless(SafeSpecialMembers)))
+ .bind("copy-assign"),
+ this);
+ Finder->addMatcher(cxxRecordDecl(allOf(UserDefinesMoveConstructor,
+ unless(DefinesAllSpecialMembers),
+ unless(SafeSpecialMembers)))
+ .bind("move-ctor"),
+ this);
+ Finder->addMatcher(cxxRecordDecl(allOf(UserDefinesMoveAssignment,
+ unless(DefinesAllSpecialMembers),
+ unless(SafeSpecialMembers)))
+ .bind("move-assign"),
+ this);
+ }
+}
+
+void RuleOfFiveAndZeroCheck::checkRuleOfFiveViolation(
+ const MatchFinder::MatchResult &Result, llvm::StringRef Match,
+ llvm::StringRef FunctionName) {
+ if (const auto *MatchedDecl = Result.Nodes.getNodeAs<CXXRecordDecl>(Match)) {
+ diag(MatchedDecl->getLocation(),
+ "class %0 defines a %1 but does not define all other 5, "
+ "define all other 5 or delete all other special "
+ "member functions")
+ << MatchedDecl << FunctionName;
+ }
+}
+
+void RuleOfFiveAndZeroCheck::check(const MatchFinder::MatchResult &Result) {
+ checkRuleOfFiveViolation(Result, "dtor", "destructor");
+ checkRuleOfFiveViolation(Result, "copy-ctor", "copy constructor");
+ checkRuleOfFiveViolation(Result, "copy-assign", "copy assignment operator");
+ checkRuleOfFiveViolation(Result, "move-ctor", "move constructor");
+ checkRuleOfFiveViolation(Result, "move-assign", "move assignment operator");
+}
+
+} // namespace cppcoreguidelines
+} // namespace tidy
+} // namespace clang
Index: clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp
===================================================================
--- clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp
+++ clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp
@@ -32,6 +32,7 @@
#include "ProTypeStaticCastDowncastCheck.h"
#include "ProTypeUnionAccessCheck.h"
#include "ProTypeVarargCheck.h"
+#include "RuleOfFiveAndZeroCheck.h"
#include "SlicingCheck.h"
#include "SpecialMemberFunctionsCheck.h"
@@ -86,6 +87,8 @@
"cppcoreguidelines-pro-type-union-access");
CheckFactories.registerCheck<ProTypeVarargCheck>(
"cppcoreguidelines-pro-type-vararg");
+ CheckFactories.registerCheck<RuleOfFiveAndZeroCheck>(
+ "cppcoreguidelines-rule-of-five-and-zero");
CheckFactories.registerCheck<SpecialMemberFunctionsCheck>(
"cppcoreguidelines-special-member-functions");
CheckFactories.registerCheck<SlicingCheck>("cppcoreguidelines-slicing");
Index: clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt
===================================================================
--- clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt
+++ clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt
@@ -23,6 +23,7 @@
ProTypeStaticCastDowncastCheck.cpp
ProTypeUnionAccessCheck.cpp
ProTypeVarargCheck.cpp
+ RuleOfFiveAndZeroCheck.cpp
SlicingCheck.cpp
SpecialMemberFunctionsCheck.cpp
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits