[clang-tools-extra] r266190 - [clang-tidy] Add a readability-deleted-default clang-tidy check.

Alexander Kornienko via cfe-commits cfe-commits at lists.llvm.org
Wed Apr 13 04:33:41 PDT 2016


Author: alexfh
Date: Wed Apr 13 06:33:40 2016
New Revision: 266190

URL: http://llvm.org/viewvc/llvm-project?rev=266190&view=rev
Log:
[clang-tidy] Add a readability-deleted-default clang-tidy check.

Checks if constructors and assignment operators that are marked '= default' are
actually deleted by the compiler.

Patch by Alex Pilkiewicz!

Differential Revision: http://reviews.llvm.org/D18961

Added:
    clang-tools-extra/trunk/clang-tidy/readability/DeletedDefaultCheck.cpp
    clang-tools-extra/trunk/clang-tidy/readability/DeletedDefaultCheck.h
    clang-tools-extra/trunk/docs/clang-tidy/checks/readability-deleted-default.rst
    clang-tools-extra/trunk/test/clang-tidy/readability-deleted-default.cpp
Modified:
    clang-tools-extra/trunk/clang-tidy/readability/CMakeLists.txt
    clang-tools-extra/trunk/clang-tidy/readability/ReadabilityTidyModule.cpp
    clang-tools-extra/trunk/docs/ReleaseNotes.rst
    clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst

Modified: clang-tools-extra/trunk/clang-tidy/readability/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/readability/CMakeLists.txt?rev=266190&r1=266189&r2=266190&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/readability/CMakeLists.txt (original)
+++ clang-tools-extra/trunk/clang-tidy/readability/CMakeLists.txt Wed Apr 13 06:33:40 2016
@@ -4,6 +4,7 @@ add_clang_library(clangTidyReadabilityMo
   AvoidConstParamsInDecls.cpp
   BracesAroundStatementsCheck.cpp
   ContainerSizeEmptyCheck.cpp
+  DeletedDefaultCheck.cpp
   ElseAfterReturnCheck.cpp
   FunctionSizeCheck.cpp
   IdentifierNamingCheck.cpp

Added: clang-tools-extra/trunk/clang-tidy/readability/DeletedDefaultCheck.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/readability/DeletedDefaultCheck.cpp?rev=266190&view=auto
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/readability/DeletedDefaultCheck.cpp (added)
+++ clang-tools-extra/trunk/clang-tidy/readability/DeletedDefaultCheck.cpp Wed Apr 13 06:33:40 2016
@@ -0,0 +1,69 @@
+//===--- DeletedDefaultCheck.cpp - clang-tidy------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DeletedDefaultCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace readability {
+
+void DeletedDefaultCheck::registerMatchers(MatchFinder *Finder) {
+  // We match constructors/assignment operators that are:
+  //   - explicitly marked '= default'
+  //   - actually deleted
+  //   - not in template instantiation.
+  // We bind the declaration to "method-decl" and also to "constructor" when
+  // it is a constructor.
+
+  Finder->addMatcher(
+      cxxMethodDecl(anyOf(cxxConstructorDecl().bind("constructor"),
+                          isCopyAssignmentOperator(),
+                          isMoveAssignmentOperator()),
+                    isDefaulted(), unless(isImplicit()), isDeleted(),
+                    unless(isInstantiated()))
+          .bind("method-decl"),
+      this);
+}
+
+void DeletedDefaultCheck::check(const MatchFinder::MatchResult &Result) {
+  const StringRef Message = "%0 is explicitly defaulted but implicitly "
+                            "deleted, probably because %1; definition can "
+                            "either be removed or explicitly deleted";
+  if (const auto *Constructor =
+          Result.Nodes.getNodeAs<CXXConstructorDecl>("constructor")) {
+    auto Diag = diag(Constructor->getLocStart(), Message);
+    if (Constructor->isDefaultConstructor()) {
+      Diag << "default constructor"
+           << "a non-static data member or a base class is lacking a default "
+              "constructor";
+    } else if (Constructor->isCopyConstructor()) {
+      Diag << "copy constructor"
+           << "a non-static data member or a base class is not copyable";
+    } else if (Constructor->isMoveConstructor()) {
+      Diag << "move constructor"
+           << "a non-static data member or a base class is neither copyable "
+              "nor movable";
+    }
+  } else if (const auto *Assignment =
+                 Result.Nodes.getNodeAs<CXXMethodDecl>("method-decl")) {
+    diag(Assignment->getLocStart(), Message)
+        << (Assignment->isCopyAssignmentOperator() ? "copy assignment operator"
+                                                   : "move assignment operator")
+        << "a base class or a non-static data member is not assignable, e.g. "
+           "because the latter is marked 'const'";
+  }
+}
+
+} // namespace readability
+} // namespace tidy
+} // namespace clang

Added: clang-tools-extra/trunk/clang-tidy/readability/DeletedDefaultCheck.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/readability/DeletedDefaultCheck.h?rev=266190&view=auto
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/readability/DeletedDefaultCheck.h (added)
+++ clang-tools-extra/trunk/clang-tidy/readability/DeletedDefaultCheck.h Wed Apr 13 06:33:40 2016
@@ -0,0 +1,36 @@
+//===--- DeletedDefaultCheck.h - clang-tidy----------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_DELETED_DEFAULT_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_DELETED_DEFAULT_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace readability {
+
+/// Checks when a constructor or an assignment operator is marked as '= default'
+/// but is actually deleted by the compiler.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/readability-deleted-default.html
+class DeletedDefaultCheck : public ClangTidyCheck {
+public:
+  DeletedDefaultCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace readability
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_DELETED_DEFAULT_H

Modified: clang-tools-extra/trunk/clang-tidy/readability/ReadabilityTidyModule.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/readability/ReadabilityTidyModule.cpp?rev=266190&r1=266189&r2=266190&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/readability/ReadabilityTidyModule.cpp (original)
+++ clang-tools-extra/trunk/clang-tidy/readability/ReadabilityTidyModule.cpp Wed Apr 13 06:33:40 2016
@@ -13,6 +13,7 @@
 #include "AvoidConstParamsInDecls.h"
 #include "BracesAroundStatementsCheck.h"
 #include "ContainerSizeEmptyCheck.h"
+#include "DeletedDefaultCheck.h"
 #include "ElseAfterReturnCheck.h"
 #include "FunctionSizeCheck.h"
 #include "IdentifierNamingCheck.h"
@@ -40,6 +41,8 @@ public:
         "readability-braces-around-statements");
     CheckFactories.registerCheck<ContainerSizeEmptyCheck>(
         "readability-container-size-empty");
+    CheckFactories.registerCheck<DeletedDefaultCheck>(
+        "readability-deleted-default");
     CheckFactories.registerCheck<ElseAfterReturnCheck>(
         "readability-else-after-return");
     CheckFactories.registerCheck<FunctionSizeCheck>(

Modified: clang-tools-extra/trunk/docs/ReleaseNotes.rst
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/docs/ReleaseNotes.rst?rev=266190&r1=266189&r2=266190&view=diff
==============================================================================
--- clang-tools-extra/trunk/docs/ReleaseNotes.rst (original)
+++ clang-tools-extra/trunk/docs/ReleaseNotes.rst Wed Apr 13 06:33:40 2016
@@ -154,6 +154,12 @@ identified.  The improvements since the
 
   Warns about top-level const parameters in function declarations.
 
+- New `readability-deleted-default
+  <http://clang.llvm.org/extra/clang-tidy/checks/readability-deleted-default.html>`_ check
+
+  Warns about defaulted constructors and assignment operators that are actually
+  deleted.
+
 - New `readability-redundant-control-flow
   <http://clang.llvm.org/extra/clang-tidy/checks/readability-redundant-control-flow.html>`_ check
 

Modified: clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst?rev=266190&r1=266189&r2=266190&view=diff
==============================================================================
--- clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst (original)
+++ clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst Wed Apr 13 06:33:40 2016
@@ -98,6 +98,7 @@ Clang-Tidy Checks
    readability-avoid-const-params-in-decls
    readability-braces-around-statements
    readability-container-size-empty
+   readability-deleted-default
    readability-else-after-return
    readability-function-size
    readability-identifier-naming

Added: clang-tools-extra/trunk/docs/clang-tidy/checks/readability-deleted-default.rst
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/docs/clang-tidy/checks/readability-deleted-default.rst?rev=266190&view=auto
==============================================================================
--- clang-tools-extra/trunk/docs/clang-tidy/checks/readability-deleted-default.rst (added)
+++ clang-tools-extra/trunk/docs/clang-tidy/checks/readability-deleted-default.rst Wed Apr 13 06:33:40 2016
@@ -0,0 +1,21 @@
+.. title:: clang-tidy - readability-deleted-default
+
+readability-deleted-default
+===========================
+
+Checks that constructors and assignment operators marked as ``= default`` are
+not actually deleted by the compiler.
+
+.. code:: c++
+  class Example {
+  public:
+    // This constructor is deleted because I is missing a default value.
+    Example() = default;
+    // This is fine.
+    Example(const Example& Other) = default;
+    // This operator is deleted because I cannot be assigned (it is const).
+    Example& operator=(const Example& Other) = default;
+  private:
+    const int I;
+  };
+

Added: clang-tools-extra/trunk/test/clang-tidy/readability-deleted-default.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clang-tidy/readability-deleted-default.cpp?rev=266190&view=auto
==============================================================================
--- clang-tools-extra/trunk/test/clang-tidy/readability-deleted-default.cpp (added)
+++ clang-tools-extra/trunk/test/clang-tidy/readability-deleted-default.cpp Wed Apr 13 06:33:40 2016
@@ -0,0 +1,127 @@
+// RUN: %check_clang_tidy %s readability-deleted-default %t
+
+class NoDefault {
+public:
+  NoDefault() = delete;
+  NoDefault(NoDefault &&Other) = delete;
+  NoDefault(const NoDefault &Other) = delete;
+};
+
+class MissingEverything {
+public:
+  MissingEverything() = default;
+  // CHECK-MESSAGES: warning: default constructor is explicitly defaulted but implicitly deleted, probably because a non-static data member or a base class is lacking a default constructor; definition can either be removed or explicitly deleted [readability-deleted-default]
+  MissingEverything(MissingEverything &&Other) = default;
+  // CHECK-MESSAGES: warning: move constructor is explicitly defaulted but implicitly deleted, probably because a non-static data member or a base class is neither copyable nor movable; definition can either be removed or explicitly deleted [readability-deleted-default]
+  MissingEverything(const MissingEverything &Other) = default;
+  // CHECK-MESSAGES: warning: copy constructor is explicitly defaulted but implicitly deleted, probably because a non-static data member or a base class is not copyable; definition can either be removed or explicitly deleted [readability-deleted-default]
+  MissingEverything &operator=(MissingEverything &&Other) = default;
+  // CHECK-MESSAGES: warning: move assignment operator is explicitly defaulted but implicitly deleted, probably because a base class or a non-static data member is not assignable, e.g. because the latter is marked 'const'; definition can either be removed or explicitly deleted [readability-deleted-default]
+  MissingEverything &operator=(const MissingEverything &Other) = default;
+  // CHECK-MESSAGES: warning: copy assignment operator is explicitly defaulted but implicitly deleted, probably because a base class or a non-static data member is not assignable, e.g. because the latter is marked 'const'; definition can either be removed or explicitly deleted [readability-deleted-default]
+
+private:
+  NoDefault ND;
+};
+
+class NotAssignable {
+public:
+  NotAssignable(NotAssignable &&Other) = default;
+  NotAssignable(const NotAssignable &Other) = default;
+  NotAssignable &operator=(NotAssignable &&Other) = default;
+  // CHECK-MESSAGES: warning: move assignment operator is explicitly defaulted but implicitly deleted
+  NotAssignable &operator=(const NotAssignable &Other) = default;
+  // CHECK-MESSAGES: warning: copy assignment operator is explicitly defaulted but implicitly deleted
+
+private:
+  const int I = 0;
+};
+
+class Movable {
+public:
+  Movable() = default;
+  Movable(Movable &&Other) = default;
+  Movable(const Movable &Other) = delete;
+  Movable &operator=(Movable &&Other) = default;
+  Movable &operator=(const Movable &Other) = delete;
+};
+
+class NotCopyable {
+public:
+  NotCopyable(NotCopyable &&Other) = default;
+  NotCopyable(const NotCopyable &Other) = default;
+  // CHECK-MESSAGES: warning: copy constructor is explicitly defaulted but implicitly deleted
+  NotCopyable &operator=(NotCopyable &&Other) = default;
+  NotCopyable &operator=(const NotCopyable &Other) = default;
+  // CHECK-MESSAGES: warning: copy assignment operator is explicitly defaulted but implicitly deleted
+private:
+  Movable M;
+};
+
+template <typename T> class Templated {
+public:
+  // No warning here, it is a templated class.
+  Templated() = default;
+  Templated(Templated &&Other) = default;
+  Templated(const Templated &Other) = default;
+  Templated &operator=(Templated &&Other) = default;
+  Templated &operator=(const Templated &Other) = default;
+
+  class InnerTemplated {
+  public:
+    // This class is not in itself templated, but we still don't have warning.
+    InnerTemplated() = default;
+    InnerTemplated(InnerTemplated &&Other) = default;
+    InnerTemplated(const InnerTemplated &Other) = default;
+    InnerTemplated &operator=(InnerTemplated &&Other) = default;
+    InnerTemplated &operator=(const InnerTemplated &Other) = default;
+
+  private:
+    T TVar;
+  };
+
+  class InnerNotTemplated {
+  public:
+    // This one could technically have warnings, but currently doesn't.
+    InnerNotTemplated() = default;
+    InnerNotTemplated(InnerNotTemplated &&Other) = default;
+    InnerNotTemplated(const InnerNotTemplated &Other) = default;
+    InnerNotTemplated &operator=(InnerNotTemplated &&Other) = default;
+    InnerNotTemplated &operator=(const InnerNotTemplated &Other) = default;
+
+  private:
+    int I;
+  };
+
+private:
+  const T TVar{};
+};
+
+int FunctionWithInnerClass() {
+  class InnerNotAssignable {
+  public:
+    InnerNotAssignable &operator=(InnerNotAssignable &&Other) = default;
+    // CHECK-MESSAGES: warning: move assignment operator is explicitly defaulted but implicitly deleted
+  private:
+    const int I = 0;
+  };
+  return 1;
+};
+
+template <typename T>
+int TemplateFunctionWithInnerClass() {
+  class InnerNotAssignable {
+  public:
+    InnerNotAssignable &operator=(InnerNotAssignable &&Other) = default;
+  private:
+    const T TVar{};
+  };
+  return 1;
+};
+
+void Foo() {
+  Templated<const int> V1;
+  Templated<int>::InnerTemplated V2;
+  Templated<float>::InnerNotTemplated V3;
+  TemplateFunctionWithInnerClass<int>();
+}




More information about the cfe-commits mailing list