diff options
author | Jonathan Coe <jbcoe@me.com> | 2016-07-30 08:58:54 +0000 |
---|---|---|
committer | Jonathan Coe <jbcoe@me.com> | 2016-07-30 08:58:54 +0000 |
commit | 5d304b2456afba562855a692a5ea4d10cc5da9e7 (patch) | |
tree | 6714b10b6672049bfa6ec9d3a0676a886b092ec5 /clang-tools-extra/clang-tidy/cppcoreguidelines/SpecialMemberFunctionsCheck.h | |
parent | fcfec5fdef79cb4d96033aaabdb8286912d131ea (diff) | |
download | bcm5719-llvm-5d304b2456afba562855a692a5ea4d10cc5da9e7.tar.gz bcm5719-llvm-5d304b2456afba562855a692a5ea4d10cc5da9e7.zip |
[clang-tidy] add check cppcoreguidelines-special-member-functions
Summary:
Check for classes that violate the rule of five and zero as specified in CppCoreGuidelines:
"If a class defines or deletes a default operation then it should define or delete them all."
https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#c21-if-you-define-or-delete-any-default-operation-define-or-delete-them-all.
Reviewers: alexfh, sbenza, aaron.ballman
Subscribers: Prazek, Eugene.Zelenko, cfe-commits, ericLemanissier, nemanjai
Projects: #clang-tools-extra
Differential Revision: https://reviews.llvm.org/D22513
llvm-svn: 277262
Diffstat (limited to 'clang-tools-extra/clang-tidy/cppcoreguidelines/SpecialMemberFunctionsCheck.h')
-rw-r--r-- | clang-tools-extra/clang-tidy/cppcoreguidelines/SpecialMemberFunctionsCheck.h | 101 |
1 files changed, 101 insertions, 0 deletions
diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/SpecialMemberFunctionsCheck.h b/clang-tools-extra/clang-tidy/cppcoreguidelines/SpecialMemberFunctionsCheck.h new file mode 100644 index 00000000000..62185354182 --- /dev/null +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/SpecialMemberFunctionsCheck.h @@ -0,0 +1,101 @@ +//===--- SpecialMemberFunctionsCheck.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_CPPCOREGUIDELINES_SPECIAL_MEMBER_FUNCTIONS_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_SPECIAL_MEMBER_FUNCTIONS_H + +#include "../ClangTidy.h" + +#include "llvm/ADT/DenseMapInfo.h" + +namespace clang { +namespace tidy { +namespace cppcoreguidelines { + +/// 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-special-member-functions.html +class SpecialMemberFunctionsCheck : public ClangTidyCheck { +public: + SpecialMemberFunctionsCheck(StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context) {} + void registerMatchers(ast_matchers::MatchFinder *Finder) override; + void check(const ast_matchers::MatchFinder::MatchResult &Result) override; + void onEndOfTranslationUnit() override; + + enum class SpecialMemberFunctionKind { + Destructor, + CopyConstructor, + CopyAssignment, + MoveConstructor, + MoveAssignment + }; + + using ClassDefId = std::pair<SourceLocation, std::string>; + + using ClassDefiningSpecialMembersMap = llvm::DenseMap<ClassDefId, llvm::SmallVector<SpecialMemberFunctionKind, 5>>; + +private: + + static llvm::StringRef toString(SpecialMemberFunctionKind K); + + static std::string join(llvm::ArrayRef<SpecialMemberFunctionKind> SMFS, + llvm::StringRef AndOr); + + ClassDefiningSpecialMembersMap ClassWithSpecialMembers; +}; + +} // namespace cppcoreguidelines +} // namespace tidy +} // namespace clang + +namespace llvm { +/// Specialisation of DenseMapInfo to allow ClassDefId objects in DenseMaps +/// FIXME: Move this to the corresponding cpp file as is done for +/// clang-tidy/readability/IdentifierNamingCheck.cpp. +template <> +struct DenseMapInfo< + clang::tidy::cppcoreguidelines::SpecialMemberFunctionsCheck::ClassDefId> { + using ClassDefId = + clang::tidy::cppcoreguidelines::SpecialMemberFunctionsCheck::ClassDefId; + + static inline ClassDefId getEmptyKey() { + return ClassDefId( + clang::SourceLocation::getFromRawEncoding(static_cast<unsigned>(-1)), + "EMPTY"); + } + + static inline ClassDefId getTombstoneKey() { + return ClassDefId( + clang::SourceLocation::getFromRawEncoding(static_cast<unsigned>(-2)), + "TOMBSTONE"); + } + + static unsigned getHashValue(ClassDefId Val) { + assert(Val != getEmptyKey() && "Cannot hash the empty key!"); + assert(Val != getTombstoneKey() && "Cannot hash the tombstone key!"); + + std::hash<ClassDefId::second_type> SecondHash; + return Val.first.getRawEncoding() + SecondHash(Val.second); + } + + static bool isEqual(ClassDefId LHS, ClassDefId RHS) { + if (RHS == getEmptyKey()) + return LHS == getEmptyKey(); + if (RHS == getTombstoneKey()) + return LHS == getTombstoneKey(); + return LHS == RHS; + } +}; + +} // namespace llvm + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_SPECIAL_MEMBER_FUNCTIONS_H |