[clang-tools-extra] r250897 - Add modernize-use-default check to clang-tidy.

Angel Garcia Gomez via cfe-commits cfe-commits at lists.llvm.org
Wed Oct 21 05:58:16 PDT 2015


Author: angelgarcia
Date: Wed Oct 21 07:58:15 2015
New Revision: 250897

URL: http://llvm.org/viewvc/llvm-project?rev=250897&view=rev
Log:
Add modernize-use-default check to clang-tidy.

Summary:
Add a check that replaces empty bodies of special member functions with '= default;'.
For now, it is only implemented for the default constructor and the destructor, which are the easier cases.
The copy-constructor and the copy-assignment operator cases will be implemented later.

I applied this check to the llvm code base and found 627 warnings (385 in llvm, 9 in compiler-rt, 220 in clang and 13 in clang-tools-extra).
Applying the fixes didn't break any build or test, it only caused a -Wpedantic warning in lib/Target/Mips/MipsOptionRecord.h:33 becaused it replaced
virtual ~MipsOptionRecord(){}; to virtual ~MipsOptionRecord()= default;;

Reviewers: klimek

Subscribers: george.burgess.iv, Eugene.Zelenko, alexfh, cfe-commits

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

Added:
    clang-tools-extra/trunk/clang-tidy/modernize/UseDefaultCheck.cpp
    clang-tools-extra/trunk/clang-tidy/modernize/UseDefaultCheck.h
    clang-tools-extra/trunk/docs/clang-tidy/checks/modernize-use-default.rst
    clang-tools-extra/trunk/test/clang-tidy/modernize-use-default.cpp
Modified:
    clang-tools-extra/trunk/clang-tidy/modernize/CMakeLists.txt
    clang-tools-extra/trunk/clang-tidy/modernize/ModernizeTidyModule.cpp
    clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst

Modified: clang-tools-extra/trunk/clang-tidy/modernize/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/modernize/CMakeLists.txt?rev=250897&r1=250896&r2=250897&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/modernize/CMakeLists.txt (original)
+++ clang-tools-extra/trunk/clang-tidy/modernize/CMakeLists.txt Wed Oct 21 07:58:15 2015
@@ -9,6 +9,7 @@ add_clang_library(clangTidyModernizeModu
   ReplaceAutoPtrCheck.cpp
   ShrinkToFitCheck.cpp
   UseAutoCheck.cpp
+  UseDefaultCheck.cpp
   UseNullptrCheck.cpp
   UseOverrideCheck.cpp
 

Modified: clang-tools-extra/trunk/clang-tidy/modernize/ModernizeTidyModule.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/modernize/ModernizeTidyModule.cpp?rev=250897&r1=250896&r2=250897&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/modernize/ModernizeTidyModule.cpp (original)
+++ clang-tools-extra/trunk/clang-tidy/modernize/ModernizeTidyModule.cpp Wed Oct 21 07:58:15 2015
@@ -16,6 +16,7 @@
 #include "ReplaceAutoPtrCheck.h"
 #include "ShrinkToFitCheck.h"
 #include "UseAutoCheck.h"
+#include "UseDefaultCheck.h"
 #include "UseNullptrCheck.h"
 #include "UseOverrideCheck.h"
 
@@ -29,13 +30,13 @@ class ModernizeModule : public ClangTidy
 public:
   void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
     CheckFactories.registerCheck<LoopConvertCheck>("modernize-loop-convert");
-    CheckFactories.registerCheck<MakeUniqueCheck>(
-        "modernize-make-unique");
+    CheckFactories.registerCheck<MakeUniqueCheck>("modernize-make-unique");
     CheckFactories.registerCheck<PassByValueCheck>("modernize-pass-by-value");
     CheckFactories.registerCheck<ReplaceAutoPtrCheck>(
         "modernize-replace-auto-ptr");
     CheckFactories.registerCheck<ShrinkToFitCheck>("modernize-shrink-to-fit");
     CheckFactories.registerCheck<UseAutoCheck>("modernize-use-auto");
+    CheckFactories.registerCheck<UseDefaultCheck>("modernize-use-default");
     CheckFactories.registerCheck<UseNullptrCheck>("modernize-use-nullptr");
     CheckFactories.registerCheck<UseOverrideCheck>("modernize-use-override");
   }
@@ -45,7 +46,7 @@ public:
     auto &Opts = Options.CheckOptions;
     Opts["modernize-loop-convert.MinConfidence"] = "reasonable";
     Opts["modernize-loop-convert.NamingStyle"] = "CamelCase";
-    Opts["modernize-pass-by-value.IncludeStyle"] = "llvm"; // Also: "google".
+    Opts["modernize-pass-by-value.IncludeStyle"] = "llvm";    // Also: "google".
     Opts["modernize-replace-auto-ptr.IncludeStyle"] = "llvm"; // Also: "google".
 
     // Comma-separated list of macros that behave like NULL.

Added: clang-tools-extra/trunk/clang-tidy/modernize/UseDefaultCheck.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/modernize/UseDefaultCheck.cpp?rev=250897&view=auto
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/modernize/UseDefaultCheck.cpp (added)
+++ clang-tools-extra/trunk/clang-tidy/modernize/UseDefaultCheck.cpp Wed Oct 21 07:58:15 2015
@@ -0,0 +1,63 @@
+//===--- UseDefaultCheck.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 "UseDefaultCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace modernize {
+
+static const char CtorDtor[] = "CtorDtorDecl";
+
+void UseDefaultCheck::registerMatchers(MatchFinder *Finder) {
+  if (getLangOpts().CPlusPlus) {
+    Finder->addMatcher(
+        cxxConstructorDecl(isDefinition(),
+                           unless(hasAnyConstructorInitializer(anything())),
+                           parameterCountIs(0))
+            .bind(CtorDtor),
+        this);
+    Finder->addMatcher(cxxDestructorDecl(isDefinition()).bind(CtorDtor), this);
+  }
+}
+
+void UseDefaultCheck::check(const MatchFinder::MatchResult &Result) {
+  // Both CXXConstructorDecl and CXXDestructorDecl inherit from CXXMethodDecl.
+  const auto *CtorDtorDecl = Result.Nodes.getNodeAs<CXXMethodDecl>(CtorDtor);
+
+  // Discard explicitly deleted/defaulted constructors/destructors, those that
+  // are not user-provided (automatically generated constructor/destructor), and
+  // those with non-empty bodies.
+  if (CtorDtorDecl->isDeleted() || CtorDtorDecl->isExplicitlyDefaulted() ||
+      !CtorDtorDecl->isUserProvided() || !CtorDtorDecl->hasTrivialBody())
+    return;
+
+  const auto *Body = dyn_cast<CompoundStmt>(CtorDtorDecl->getBody());
+  // This should never happen, since 'hasTrivialBody' checks that this is
+  // actually a CompoundStmt.
+  assert(Body && "Definition body is not a CompoundStmt");
+
+  diag(CtorDtorDecl->getLocStart(),
+       "use '= default' to define a trivial " +
+           std::string(dyn_cast<CXXConstructorDecl>(CtorDtorDecl)
+                           ? "default constructor"
+                           : "destructor"))
+      << FixItHint::CreateReplacement(
+          CharSourceRange::getTokenRange(Body->getLBracLoc(),
+                                         Body->getRBracLoc()),
+          "= default;");
+}
+
+} // namespace modernize
+} // namespace tidy
+} // namespace clang

Added: clang-tools-extra/trunk/clang-tidy/modernize/UseDefaultCheck.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/modernize/UseDefaultCheck.h?rev=250897&view=auto
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/modernize/UseDefaultCheck.h (added)
+++ clang-tools-extra/trunk/clang-tidy/modernize/UseDefaultCheck.h Wed Oct 21 07:58:15 2015
@@ -0,0 +1,51 @@
+//===--- UseDefaultCheck.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_MODERNIZE_USE_DEFAULT_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_USE_DEFAULT_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace modernize {
+
+/// \brief Replace default bodies of special member functions with '= default;'.
+/// \code
+///   struct A {
+///     A() {}
+///     ~A();
+///   };
+///   A::~A() {}
+/// \endcode
+/// Is converted to:
+/// \code
+///   struct A {
+///     A() = default;
+///     ~A();
+///   };
+///   A::~A() = default;
+/// \endcode
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/modernize-use-default.html
+class UseDefaultCheck : public ClangTidyCheck {
+public:
+  UseDefaultCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace modernize
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_USE_DEFAULT_H
+

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=250897&r1=250896&r2=250897&view=diff
==============================================================================
--- clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst (original)
+++ clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst Wed Oct 21 07:58:15 2015
@@ -55,6 +55,7 @@ List of clang-tidy Checks
    modernize-replace-auto-ptr
    modernize-shrink-to-fit
    modernize-use-auto
+   modernize-use-default
    modernize-use-nullptr
    modernize-use-override
    readability-braces-around-statements

Added: clang-tools-extra/trunk/docs/clang-tidy/checks/modernize-use-default.rst
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/docs/clang-tidy/checks/modernize-use-default.rst?rev=250897&view=auto
==============================================================================
--- clang-tools-extra/trunk/docs/clang-tidy/checks/modernize-use-default.rst (added)
+++ clang-tools-extra/trunk/docs/clang-tidy/checks/modernize-use-default.rst Wed Oct 21 07:58:15 2015
@@ -0,0 +1,27 @@
+modernize-use-default
+=====================
+
+This check replaces default bodies of special member functions with ``=
+default;``.  The explicitly defaulted function declarations enable more
+opportunities in optimization, because the compiler might treat explicitly
+defaulted functions as trivial.
+
+.. code-block:: c++
+
+  struct A {
+    A() {}
+    ~A();
+  };
+  A::~A() {}
+
+  // becomes
+
+  struct A {
+    A() = default;
+    ~A();
+  };
+  A::~A() = default;
+
+.. note::
+  Copy-constructor, copy-assignment operator, move-constructor and
+  move-assignment operator are not supported yet.

Added: clang-tools-extra/trunk/test/clang-tidy/modernize-use-default.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clang-tidy/modernize-use-default.cpp?rev=250897&view=auto
==============================================================================
--- clang-tools-extra/trunk/test/clang-tidy/modernize-use-default.cpp (added)
+++ clang-tools-extra/trunk/test/clang-tidy/modernize-use-default.cpp Wed Oct 21 07:58:15 2015
@@ -0,0 +1,137 @@
+// RUN: %python %S/check_clang_tidy.py %s modernize-use-default %t
+
+class A {
+public:
+  A();
+  ~A();
+};
+
+A::A() {}
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use '= default' to define a trivial default constructor [modernize-use-default]
+// CHECK-FIXES: A::A() = default;
+A::~A() {}
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use '= default' to define a trivial destructor [modernize-use-default]
+// CHECK-FIXES: A::~A() = default;
+
+// Inline definitions.
+class B {
+public:
+  B() {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'
+  // CHECK-FIXES: B() = default;
+  ~B() {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'
+  // CHECK-FIXES: ~B() = default;
+};
+
+void f();
+
+class C {
+public:
+  // Non-empty constructor body.
+  C() { f(); }
+  // Non-empty destructor body.
+  ~C() { f(); }
+};
+
+class D {
+public:
+  // Constructor with initializer.
+  D() : Field(5) {}
+  // Constructor with arguments.
+  D(int Arg1, int Arg2) {}
+  int Field;
+};
+
+// Private constructor/destructor.
+class E {
+  E() {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'
+  // CHECK-FIXES: E() = default;
+  ~E() {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'
+  // CHECK-FIXES: ~E() = default;
+};
+
+// struct.
+struct F {
+  F() {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'
+  // CHECK-FIXES: F() = default;
+  ~F() {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'
+  // CHECK-FIXES: F() = default;
+};
+
+// Deleted constructor/destructor.
+class G {
+public:
+  G() = delete;
+  ~G() = delete;
+};
+
+// Do not remove other keywords.
+class H {
+public:
+  explicit H() {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'
+  // CHECK-FIXES: explicit H() = default;
+  virtual ~H() {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'
+  // CHECK-FIXES: virtual ~H() = default;
+};
+
+// Nested class.
+struct I {
+  struct II {
+    II() {}
+    // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use '= default'
+    // CHECK-FIXES: II() = default;
+    ~II() {}
+    // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use '= default'
+    // CHECK-FIXES: ~II() = default;
+  };
+  int Int;
+};
+
+// Class template.
+template <class T>
+class J {
+public:
+  J() {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'
+  // CHECK-FIXES: J() = default;
+  ~J() {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'
+  // CHECK-FIXES: ~J() = default;
+};
+
+// Non user-provided constructor/destructor.
+struct K {
+  int Int;
+};
+void g() {
+  K *PtrK = new K();
+  PtrK->~K();
+  delete PtrK;
+}
+
+// Already using default.
+struct L {
+  L() = default;
+  ~L() = default;
+};
+struct M {
+  M();
+  ~M();
+};
+M::M() = default;
+M::~M() = default;
+
+// Delegating constructor and overriden destructor.
+struct N : H {
+  N() : H() {}
+  ~N() override {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'
+  // CHECK-FIXES: ~N() override = default;
+};




More information about the cfe-commits mailing list