1 //===--- SpecialMemberFunctionsCheck.h - clang-tidy--------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_SPECIAL_MEMBER_FUNCTIONS_H 10 #define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_SPECIAL_MEMBER_FUNCTIONS_H 11 12 #include "../ClangTidyCheck.h" 13 14 #include "llvm/ADT/DenseMapInfo.h" 15 16 namespace clang { 17 namespace tidy { 18 namespace cppcoreguidelines { 19 20 /// Checks for classes where some, but not all, of the special member functions 21 /// are defined. 22 /// 23 /// For the user-facing documentation see: 24 /// http://clang.llvm.org/extra/clang-tidy/checks/cppcoreguidelines-special-member-functions.html 25 class SpecialMemberFunctionsCheck : public ClangTidyCheck { 26 public: 27 SpecialMemberFunctionsCheck(StringRef Name, ClangTidyContext *Context); isLanguageVersionSupported(const LangOptions & LangOpts)28 bool isLanguageVersionSupported(const LangOptions &LangOpts) const override { 29 return LangOpts.CPlusPlus; 30 } 31 void storeOptions(ClangTidyOptions::OptionMap &Opts) override; 32 void registerMatchers(ast_matchers::MatchFinder *Finder) override; 33 void check(const ast_matchers::MatchFinder::MatchResult &Result) override; 34 void onEndOfTranslationUnit() override; 35 36 enum class SpecialMemberFunctionKind : uint8_t { 37 Destructor, 38 DefaultDestructor, 39 NonDefaultDestructor, 40 CopyConstructor, 41 CopyAssignment, 42 MoveConstructor, 43 MoveAssignment 44 }; 45 46 struct SpecialMemberFunctionData { 47 SpecialMemberFunctionKind FunctionKind; 48 bool IsDeleted; 49 50 bool operator==(const SpecialMemberFunctionData &Other) { 51 return (Other.FunctionKind == FunctionKind) && 52 (Other.IsDeleted == IsDeleted); 53 } 54 }; 55 56 using ClassDefId = std::pair<SourceLocation, std::string>; 57 58 using ClassDefiningSpecialMembersMap = 59 llvm::DenseMap<ClassDefId, 60 llvm::SmallVector<SpecialMemberFunctionData, 5>>; 61 62 private: 63 void checkForMissingMembers( 64 const ClassDefId &ID, 65 llvm::ArrayRef<SpecialMemberFunctionData> DefinedSpecialMembers); 66 67 const bool AllowMissingMoveFunctions; 68 const bool AllowSoleDefaultDtor; 69 const bool AllowMissingMoveFunctionsWhenCopyIsDeleted; 70 ClassDefiningSpecialMembersMap ClassWithSpecialMembers; 71 }; 72 73 } // namespace cppcoreguidelines 74 } // namespace tidy 75 } // namespace clang 76 77 namespace llvm { 78 /// Specialisation of DenseMapInfo to allow ClassDefId objects in DenseMaps 79 /// FIXME: Move this to the corresponding cpp file as is done for 80 /// clang-tidy/readability/IdentifierNamingCheck.cpp. 81 template <> 82 struct DenseMapInfo< 83 clang::tidy::cppcoreguidelines::SpecialMemberFunctionsCheck::ClassDefId> { 84 using ClassDefId = 85 clang::tidy::cppcoreguidelines::SpecialMemberFunctionsCheck::ClassDefId; 86 87 static inline ClassDefId getEmptyKey() { 88 return ClassDefId(DenseMapInfo<clang::SourceLocation>::getEmptyKey(), 89 "EMPTY"); 90 } 91 92 static inline ClassDefId getTombstoneKey() { 93 return ClassDefId(DenseMapInfo<clang::SourceLocation>::getTombstoneKey(), 94 "TOMBSTONE"); 95 } 96 97 static unsigned getHashValue(ClassDefId Val) { 98 assert(Val != getEmptyKey() && "Cannot hash the empty key!"); 99 assert(Val != getTombstoneKey() && "Cannot hash the tombstone key!"); 100 101 std::hash<ClassDefId::second_type> SecondHash; 102 return Val.first.getHashValue() + SecondHash(Val.second); 103 } 104 105 static bool isEqual(const ClassDefId &LHS, const ClassDefId &RHS) { 106 if (RHS == getEmptyKey()) 107 return LHS == getEmptyKey(); 108 if (RHS == getTombstoneKey()) 109 return LHS == getTombstoneKey(); 110 return LHS == RHS; 111 } 112 }; 113 114 } // namespace llvm 115 116 #endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_SPECIAL_MEMBER_FUNCTIONS_H 117