SpecialMemberFunctionsCheck.h
3.86 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
//===--- SpecialMemberFunctionsCheck.h - clang-tidy--------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#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 "../ClangTidyCheck.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);
bool isLanguageVersionSupported(const LangOptions &LangOpts) const override {
return LangOpts.CPlusPlus;
}
void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
void onEndOfTranslationUnit() override;
enum class SpecialMemberFunctionKind : uint8_t {
Destructor,
DefaultDestructor,
NonDefaultDestructor,
CopyConstructor,
CopyAssignment,
MoveConstructor,
MoveAssignment
};
struct SpecialMemberFunctionData {
SpecialMemberFunctionKind FunctionKind;
bool IsDeleted;
bool operator==(const SpecialMemberFunctionData &Other) {
return (Other.FunctionKind == FunctionKind) &&
(Other.IsDeleted == IsDeleted);
}
};
using ClassDefId = std::pair<SourceLocation, std::string>;
using ClassDefiningSpecialMembersMap =
llvm::DenseMap<ClassDefId,
llvm::SmallVector<SpecialMemberFunctionData, 5>>;
private:
void checkForMissingMembers(
const ClassDefId &ID,
llvm::ArrayRef<SpecialMemberFunctionData> DefinedSpecialMembers);
const bool AllowMissingMoveFunctions;
const bool AllowSoleDefaultDtor;
const bool AllowMissingMoveFunctionsWhenCopyIsDeleted;
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(const ClassDefId &LHS, const 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