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
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to