jbcoe removed rL LLVM as the repository for this revision.
jbcoe updated this revision to Diff 48028.
jbcoe added a comment.
Minor fixes from review.
http://reviews.llvm.org/D16376
Files:
clang-tidy/misc/CMakeLists.txt
clang-tidy/misc/DeprecatedSpecialMemberGenerationCheck.cpp
clang-tidy/misc/DeprecatedSpecialMemberGenerationCheck.h
clang-tidy/misc/MiscTidyModule.cpp
docs/clang-tidy/checks/list.rst
docs/clang-tidy/checks/misc-deprecated-special-member-generation.rst
test/clang-tidy/misc-deprecated-special-member-generation.cpp
Index: test/clang-tidy/misc-deprecated-special-member-generation.cpp
===================================================================
--- /dev/null
+++ test/clang-tidy/misc-deprecated-special-member-generation.cpp
@@ -0,0 +1,122 @@
+// RUN: %check_clang_tidy %s misc-deprecated-special-member-generation %t
+
+//
+// User defined copy constructors
+//
+class DeclaresCopyConstructor {
+ DeclaresCopyConstructor(const DeclaresCopyConstructor &);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: class 'DeclaresCopyConstructor' defines a copy constructor but not a copy assignment operator [misc-deprecated-special-member-generation]
+};
+
+// CHECK-FIXES: DeclaresCopyConstructor & operator=(const DeclaresCopyConstructor &) = delete;
+
+class DefinesDefaultedCopyConstructor {
+ DefinesDefaultedCopyConstructor(const DefinesDefaultedCopyConstructor &) = default;
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: class 'DefinesDefaultedCopyConstructor' defines a copy constructor but not a copy assignment operator [misc-deprecated-special-member-generation]
+};
+
+// CHECK-FIXES: DefinesDefaultedCopyConstructor & operator=(const DefinesDefaultedCopyConstructor &) = default;
+
+class DefinesDeletedCopyConstructor {
+ DefinesDeletedCopyConstructor(const DefinesDeletedCopyConstructor &) = delete;
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: class 'DefinesDeletedCopyConstructor' defines a copy constructor but not a copy assignment operator [misc-deprecated-special-member-generation]
+};
+
+// CHECK-FIXES: DefinesDeletedCopyConstructor & operator=(const DefinesDeletedCopyConstructor &) = delete;
+
+
+//
+// User defined copy assignment
+//
+class DeclaresCopyAssignment {
+ DeclaresCopyAssignment & operator=(const DeclaresCopyAssignment &);
+ // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: class 'DeclaresCopyAssignment' defines a copy assignment operator but not a copy constructor [misc-deprecated-special-member-generation]
+};
+
+// CHECK-FIXES: DeclaresCopyAssignment(const DeclaresCopyAssignment &) = delete;
+
+class DefinesDefaultedCopyAssignment {
+ DefinesDefaultedCopyAssignment & operator=(const DefinesDefaultedCopyAssignment &) = default;
+ // CHECK-MESSAGES: :[[@LINE-1]]:36: warning: class 'DefinesDefaultedCopyAssignment' defines a copy assignment operator but not a copy constructor [misc-deprecated-special-member-generation]
+};
+
+// CHECK-FIXES: DefinesDefaultedCopyAssignment(const DefinesDefaultedCopyAssignment &) = default;
+
+class DefinesDeletedCopyAssignment {
+ DefinesDeletedCopyAssignment & operator=(const DefinesDeletedCopyAssignment &) = delete;
+ // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: class 'DefinesDeletedCopyAssignment' defines a copy assignment operator but not a copy constructor [misc-deprecated-special-member-generation]
+};
+
+// CHECK-FIXES: DefinesDeletedCopyAssignment(const DefinesDeletedCopyAssignment &) = delete;
+
+class DeclaresDestructor {
+ ~DeclaresDestructor();
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: class 'DeclaresDestructor' defines a destructor but not a copy constructor or copy assignment operator [misc-deprecated-special-member-generation]
+};
+// CHECK-FIXES: DeclaresDestructor(const DeclaresDestructor &) = delete;
+// CHECK-FIXES: DeclaresDestructor & operator=(const DeclaresDestructor &) = delete;
+
+class DefinesDestructor {
+ ~DefinesDestructor() {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: class 'DefinesDestructor' defines a destructor but not a copy constructor or copy assignment operator [misc-deprecated-special-member-generation]
+};
+// CHECK-FIXES: DefinesDestructor(const DefinesDestructor &) = delete;
+// CHECK-FIXES: DefinesDestructor & operator=(const DefinesDestructor &) = delete;
+
+
+class DefinesDefaultedDestructor {
+ ~DefinesDefaultedDestructor() = default;
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: class 'DefinesDefaultedDestructor' defines a destructor but not a copy constructor or copy assignment operator [misc-deprecated-special-member-generation]
+};
+// CHECK-FIXES: DefinesDefaultedDestructor(const DefinesDefaultedDestructor &) = delete;
+// CHECK-FIXES: DefinesDefaultedDestructor & operator=(const DefinesDefaultedDestructor &) = delete;
+
+
+class DefinesDeletedDestructor {
+ ~DefinesDeletedDestructor() = delete;
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: class 'DefinesDeletedDestructor' defines a destructor but not a copy constructor or copy assignment operator [misc-deprecated-special-member-generation]
+};
+// CHECK-FIXES: DefinesDeletedDestructor(const DefinesDeletedDestructor &) = delete;
+// CHECK-FIXES: DefinesDeletedDestructor & operator=(const DefinesDeletedDestructor &) = delete;
+
+template <class T>
+class ClassTemplateDeclaresDestructor {
+ ~ClassTemplateDeclaresDestructor();
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: class 'ClassTemplateDeclaresDestructor' defines a destructor but not a copy constructor or copy assignment operator [misc-deprecated-special-member-generation]
+};
+// CHECK-FIXES: ClassTemplateDeclaresDestructor(const ClassTemplateDeclaresDestructor &) = delete;
+// CHECK-FIXES: ClassTemplateDeclaresDestructor & operator=(const ClassTemplateDeclaresDestructor &) = delete;
+
+template <>
+class ClassTemplateDeclaresDestructor<int> {
+ ~ClassTemplateDeclaresDestructor();
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: class 'ClassTemplateDeclaresDestructor<int>' defines a destructor but not a copy constructor or copy assignment operator [misc-deprecated-special-member-generation]
+};
+// CHECK-FIXES: ClassTemplateDeclaresDestructor(const ClassTemplateDeclaresDestructor &) = delete;
+// CHECK-FIXES: ClassTemplateDeclaresDestructor & operator=(const ClassTemplateDeclaresDestructor &) = delete;
+
+#define DEFAULTED_DESTRUCTOR(X) ~X() = default
+
+class MacroDefaultsDestructor {
+ DEFAULTED_DESTRUCTOR(MacroDefaultsDestructor);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: class 'MacroDefaultsDestructor' defines a destructor but not a copy constructor or copy assignment operator [misc-deprecated-special-member-generation]
+};
+// CHECK-FIXES: MacroDefaultsDestructor(const MacroDefaultsDestructor &) = delete;
+// CHECK-FIXES: MacroDefaultsDestructor & operator=(const MacroDefaultsDestructor &) = delete;
+
+#define VIRTUAL_BASE_CLASS(X) class X { virtual ~X() = default; }
+
+VIRTUAL_BASE_CLASS(VirtualBase);
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: class 'VirtualBase' defines a destructor but not a copy constructor or copy assignment operator [misc-deprecated-special-member-generation]
+
+class DeclaresAllThree {
+ ~DeclaresAllThree();
+ DeclaresAllThree(const DeclaresAllThree&);
+ DeclaresAllThree & operator=(const DeclaresAllThree&);
+};
+
+class DeclaresCopyAndAssignment {
+ DeclaresCopyAndAssignment(const DeclaresCopyAndAssignment&);
+ DeclaresCopyAndAssignment & operator=(const DeclaresCopyAndAssignment&);
+};
+
Index: docs/clang-tidy/checks/misc-deprecated-special-member-generation.rst
===================================================================
--- /dev/null
+++ docs/clang-tidy/checks/misc-deprecated-special-member-generation.rst
@@ -0,0 +1,40 @@
+.. title:: clang-tidy - misc-deprecated-special-member-generation
+
+misc-deprecated-special-member-generation
+=========================================
+
+Modern compilers generate copy constructors and copy assignment operators in
+cases where generation of special functions is deprecated by the standard.
+
+C++14 standard [class.copy] paragraph 7:
+
+"If the class definition does not explicitly declare a copy constructor, one is
+declared implicitly. If the class definition declares a move constructor or
+move assignment operator, the implicitly declared copy constructor is defined
+as deleted; otherwise, it is defined as defaulted (8.4). The latter case is
+deprecated if the class has a user-declared copy assignment operator or a
+user-declared destructor."
+
+C++14 standard [class.copy] paragraph 18:
+
+"If the class definition does not explicitly declare a copy assignment
+operator, one is declared implicitly. If the class definition declares a move
+constructor or move assignment operator, the implicitly declared copy
+assignment operator is defined as deleted; otherwise, it is defined as
+defaulted (8.4). The latter case is deprecated if the class has a user-declared
+copy constructor or a user-declared destructor."
+
+This check finds classes where deprecated compiler-generation of special member
+functions may generate a copy constructor or copy assignment operator.
+
+If the destructor is declared, missing copy constructors or copy assignment
+operators are declared '=delete'.
+
+If a copy constructor or assignment operator is declared '=default' and no
+destructor is declared, the missing copy constructor or assignment operator is
+declared '=default'.
+
+Otherwise, if a copy constructor or assignment operator is declared and no
+destructor is declared, the missing copy constructor or assignment operator is
+declared '=delete'.
+
Index: docs/clang-tidy/checks/list.rst
===================================================================
--- docs/clang-tidy/checks/list.rst
+++ docs/clang-tidy/checks/list.rst
@@ -46,6 +46,7 @@
misc-argument-comment
misc-assert-side-effect
misc-assign-operator-signature
+ misc-deprecated-special-member-generation
misc-bool-pointer-implicit-conversion
misc-definitions-in-headers
misc-inaccurate-erase
Index: clang-tidy/misc/MiscTidyModule.cpp
===================================================================
--- clang-tidy/misc/MiscTidyModule.cpp
+++ clang-tidy/misc/MiscTidyModule.cpp
@@ -37,6 +37,7 @@
#include "UnusedAliasDeclsCheck.h"
#include "UnusedParametersCheck.h"
#include "UnusedRAIICheck.h"
+#include "DeprecatedSpecialMemberGenerationCheck.h"
#include "VirtualNearMissCheck.h"
namespace clang {
@@ -97,6 +98,8 @@
CheckFactories.registerCheck<UnusedParametersCheck>(
"misc-unused-parameters");
CheckFactories.registerCheck<UnusedRAIICheck>("misc-unused-raii");
+ CheckFactories.registerCheck<DeprecatedSpecialMemberGenerationCheck>(
+ "misc-deprecated-special-member-generation");
CheckFactories.registerCheck<VirtualNearMissCheck>(
"misc-virtual-near-miss");
}
Index: clang-tidy/misc/DeprecatedSpecialMemberGenerationCheck.h
===================================================================
--- /dev/null
+++ clang-tidy/misc/DeprecatedSpecialMemberGenerationCheck.h
@@ -0,0 +1,54 @@
+//===--- DeprecatedSpecialMemberGenerationCheck.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_MISC_DEPRECATED_SPECIAL_MEMBER_GENERATION_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_DEPRECATED_SPECIAL_MEMBER_GENERATION_H
+
+#include "../ClangTidy.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+namespace clang {
+namespace tidy {
+namespace misc {
+
+/// Finds classes where deprecated compiler-generation of special member
+/// functions will generate a copy constructor or copy assignment operator.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/misc-deprecated-special-member-generation.html
+class DeprecatedSpecialMemberGenerationCheck : public ClangTidyCheck {
+public:
+ DeprecatedSpecialMemberGenerationCheck(StringRef Name, ClangTidyContext *Context)
+ : ClangTidyCheck(Name, Context) {}
+ void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+ void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+
+private:
+ enum class SpecialFunctionKind {
+ CopyConstructor,
+ CopyAssignment,
+ Destructor
+ };
+
+ static std::string
+ buildFixIt(const CXXMethodDecl &MatchedDecl, StringRef ClassName,
+ DeprecatedSpecialMemberGenerationCheck::SpecialFunctionKind S);
+ static StringRef getDiagnosticFormat(
+ DeprecatedSpecialMemberGenerationCheck::SpecialFunctionKind S);
+ void
+ addDiagnosticAndFixIt(const ast_matchers::MatchFinder::MatchResult &Result,
+ const CXXMethodDecl &MatchedDecl,
+ SpecialFunctionKind S);
+};
+
+} // namespace misc
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_DEPRECATED_SPECIAL_MEMBER_GENERATION_H
Index: clang-tidy/misc/DeprecatedSpecialMemberGenerationCheck.cpp
===================================================================
--- /dev/null
+++ clang-tidy/misc/DeprecatedSpecialMemberGenerationCheck.cpp
@@ -0,0 +1,124 @@
+//===--- DeprecatedSpecialMemberGenerationCheck.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 "DeprecatedSpecialMemberGenerationCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/Lex/Lexer.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace misc {
+
+void DeprecatedSpecialMemberGenerationCheck::registerMatchers(
+ MatchFinder *Finder) {
+
+ if (!getLangOpts().CPlusPlus)
+ return;
+
+ Finder->addMatcher(
+ cxxRecordDecl(isDefinition(),
+ has(cxxDestructorDecl(unless(isImplicit())).bind("dtor")),
+ unless(anyOf(has(cxxConstructorDecl(isCopyConstructor(),
+ unless(isImplicit()))),
+ has(cxxMethodDecl(isCopyAssignmentOperator(),
+ unless(isImplicit())))))),
+ this);
+
+ Finder->addMatcher(
+ cxxRecordDecl(isDefinition(), has(cxxConstructorDecl(isCopyConstructor(),
+ unless(isImplicit()))
+ .bind("copy-ctor")),
+ unless(has(cxxMethodDecl(isCopyAssignmentOperator())))),
+ this);
+
+ Finder->addMatcher(
+ cxxRecordDecl(
+ isDefinition(),
+ has(cxxMethodDecl(isCopyAssignmentOperator(), unless(isImplicit()))
+ .bind("copy assignment")),
+ unless(has(cxxConstructorDecl(isCopyConstructor())))),
+ this);
+}
+
+StringRef DeprecatedSpecialMemberGenerationCheck::getDiagnosticFormat(
+ DeprecatedSpecialMemberGenerationCheck::SpecialFunctionKind S) {
+ switch (S) {
+ case SpecialFunctionKind::Destructor:
+ return "class %0 defines a destructor but not a copy constructor or copy "
+ "assignment operator";
+ case SpecialFunctionKind::CopyConstructor:
+ return "class %0 defines a copy constructor but not a copy assignment "
+ "operator";
+ case SpecialFunctionKind::CopyAssignment:
+ return "class %0 defines a copy assignment operator but not a "
+ "copy constructor";
+ }
+};
+
+std::string DeprecatedSpecialMemberGenerationCheck::buildFixIt(
+ const CXXMethodDecl &MatchedDecl, StringRef ClassName,
+ DeprecatedSpecialMemberGenerationCheck::SpecialFunctionKind S) {
+
+ StringRef DeleteOrDefault =
+ (!isa<CXXDestructorDecl>(&MatchedDecl) && MatchedDecl.isDefaulted())
+ ? "default"
+ : "delete";
+ switch (S) {
+ case SpecialFunctionKind::Destructor:
+ return (llvm::Twine("\n") + ClassName + "(const " + ClassName + " &) = " +
+ DeleteOrDefault + ";\n" + ClassName + " & operator=(const " +
+ ClassName + " &) = " + DeleteOrDefault + ";\n")
+ .str();
+ case SpecialFunctionKind::CopyConstructor:
+ return (llvm::Twine("\n") + ClassName + " & operator=(const " + ClassName +
+ " &) = " + DeleteOrDefault + ";\n")
+ .str();
+ case SpecialFunctionKind::CopyAssignment:
+ return (llvm::Twine("") + ClassName + "(const " + ClassName + " &) = " +
+ DeleteOrDefault + ";\n")
+ .str();
+ }
+};
+
+void DeprecatedSpecialMemberGenerationCheck::addDiagnosticAndFixIt(
+ const MatchFinder::MatchResult &Result, const CXXMethodDecl &MatchedDecl,
+ SpecialFunctionKind S) {
+ const CXXRecordDecl *Class = MatchedDecl.getParent();
+
+ DiagnosticBuilder Diag =
+ diag(MatchedDecl.getLocation(), getDiagnosticFormat(S)) << Class;
+
+ if (!getLangOpts().CPlusPlus11)
+ return;
+
+ Diag << FixItHint::CreateInsertion(
+ MatchedDecl.getLocStart(), buildFixIt(MatchedDecl, Class->getName(), S));
+}
+
+void DeprecatedSpecialMemberGenerationCheck::check(
+ const MatchFinder::MatchResult &Result) {
+ if (const auto *MatchedDecl =
+ Result.Nodes.getNodeAs<CXXDestructorDecl>("dtor"))
+ addDiagnosticAndFixIt(Result, *MatchedDecl,
+ SpecialFunctionKind::Destructor);
+ else if (const auto *MatchedDecl =
+ Result.Nodes.getNodeAs<CXXConstructorDecl>("copy-ctor"))
+ addDiagnosticAndFixIt(Result, *MatchedDecl,
+ SpecialFunctionKind::CopyConstructor);
+ else if (const auto *MatchedDecl =
+ Result.Nodes.getNodeAs<CXXMethodDecl>("copy assignment"))
+ addDiagnosticAndFixIt(Result, *MatchedDecl,
+ SpecialFunctionKind::CopyAssignment);
+}
+
+} // namespace misc
+} // namespace tidy
+} // namespace clang
Index: clang-tidy/misc/CMakeLists.txt
===================================================================
--- clang-tidy/misc/CMakeLists.txt
+++ clang-tidy/misc/CMakeLists.txt
@@ -29,6 +29,7 @@
UnusedParametersCheck.cpp
UnusedRAIICheck.cpp
UniqueptrResetReleaseCheck.cpp
+ DeprecatedSpecialMemberGenerationCheck.cpp
VirtualNearMissCheck.cpp
LINK_LIBS
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits