File indexing completed on 2026-05-10 08:36:19
0001
0002
0003
0004
0005
0006
0007
0008
0009 #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_SPECIAL_MEMBER_FUNCTIONS_H
0010 #define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_SPECIAL_MEMBER_FUNCTIONS_H
0011
0012 #include "../ClangTidyCheck.h"
0013
0014 #include "llvm/ADT/DenseMapInfo.h"
0015
0016 namespace clang::tidy::cppcoreguidelines {
0017
0018
0019
0020
0021
0022
0023 class SpecialMemberFunctionsCheck : public ClangTidyCheck {
0024 public:
0025 SpecialMemberFunctionsCheck(StringRef Name, ClangTidyContext *Context);
0026 bool isLanguageVersionSupported(const LangOptions &LangOpts) const override {
0027 return LangOpts.CPlusPlus;
0028 }
0029 void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
0030 void registerMatchers(ast_matchers::MatchFinder *Finder) override;
0031 void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
0032 void onEndOfTranslationUnit() override;
0033 std::optional<TraversalKind> getCheckTraversalKind() const override;
0034
0035 enum class SpecialMemberFunctionKind : uint8_t {
0036 Destructor,
0037 DefaultDestructor,
0038 NonDefaultDestructor,
0039 CopyConstructor,
0040 CopyAssignment,
0041 MoveConstructor,
0042 MoveAssignment
0043 };
0044
0045 struct SpecialMemberFunctionData {
0046 SpecialMemberFunctionKind FunctionKind;
0047 bool IsDeleted;
0048 bool IsImplicit = false;
0049
0050 bool operator==(const SpecialMemberFunctionData &Other) const {
0051 return (Other.FunctionKind == FunctionKind) &&
0052 (Other.IsDeleted == IsDeleted);
0053 }
0054 };
0055
0056 using ClassDefId = std::pair<SourceLocation, std::string>;
0057
0058 using ClassDefiningSpecialMembersMap =
0059 llvm::DenseMap<ClassDefId,
0060 llvm::SmallVector<SpecialMemberFunctionData, 5>>;
0061
0062 private:
0063 void checkForMissingMembers(
0064 const ClassDefId &ID,
0065 llvm::ArrayRef<SpecialMemberFunctionData> DefinedMembers);
0066
0067 const bool AllowMissingMoveFunctions;
0068 const bool AllowSoleDefaultDtor;
0069 const bool AllowMissingMoveFunctionsWhenCopyIsDeleted;
0070 const bool AllowImplicitlyDeletedCopyOrMove;
0071 ClassDefiningSpecialMembersMap ClassWithSpecialMembers;
0072 };
0073
0074 }
0075
0076 namespace llvm {
0077
0078
0079
0080 template <>
0081 struct DenseMapInfo<
0082 clang::tidy::cppcoreguidelines::SpecialMemberFunctionsCheck::ClassDefId> {
0083 using ClassDefId =
0084 clang::tidy::cppcoreguidelines::SpecialMemberFunctionsCheck::ClassDefId;
0085
0086 static inline ClassDefId getEmptyKey() {
0087 return {DenseMapInfo<clang::SourceLocation>::getEmptyKey(),
0088 "EMPTY"};
0089 }
0090
0091 static inline ClassDefId getTombstoneKey() {
0092 return {DenseMapInfo<clang::SourceLocation>::getTombstoneKey(),
0093 "TOMBSTONE"};
0094 }
0095
0096 static unsigned getHashValue(ClassDefId Val) {
0097 assert(Val != getEmptyKey() && "Cannot hash the empty key!");
0098 assert(Val != getTombstoneKey() && "Cannot hash the tombstone key!");
0099
0100 std::hash<ClassDefId::second_type> SecondHash;
0101 return Val.first.getHashValue() + SecondHash(Val.second);
0102 }
0103
0104 static bool isEqual(const ClassDefId &LHS, const ClassDefId &RHS) {
0105 if (RHS == getEmptyKey())
0106 return LHS == getEmptyKey();
0107 if (RHS == getTombstoneKey())
0108 return LHS == getTombstoneKey();
0109 return LHS == RHS;
0110 }
0111 };
0112
0113 }
0114
0115 #endif