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; +}; _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits