Mercurial > hg > CbC > CbC_llvm
comparison clang-tools-extra/clang-tidy/cppcoreguidelines/SpecialMemberFunctionsCheck.cpp @ 173:0572611fdcc8 llvm10 llvm12
reorgnization done
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Mon, 25 May 2020 11:55:54 +0900 |
parents | 1d019706d866 |
children | 2e18cbf3894f |
comparison
equal
deleted
inserted
replaced
172:9fbae9c8bf63 | 173:0572611fdcc8 |
---|---|
21 namespace tidy { | 21 namespace tidy { |
22 namespace cppcoreguidelines { | 22 namespace cppcoreguidelines { |
23 | 23 |
24 SpecialMemberFunctionsCheck::SpecialMemberFunctionsCheck( | 24 SpecialMemberFunctionsCheck::SpecialMemberFunctionsCheck( |
25 StringRef Name, ClangTidyContext *Context) | 25 StringRef Name, ClangTidyContext *Context) |
26 : ClangTidyCheck(Name, Context), | 26 : ClangTidyCheck(Name, Context), AllowMissingMoveFunctions(Options.get( |
27 AllowMissingMoveFunctions(Options.get("AllowMissingMoveFunctions", 0)), | 27 "AllowMissingMoveFunctions", false)), |
28 AllowSoleDefaultDtor(Options.get("AllowSoleDefaultDtor", 0)) {} | 28 AllowSoleDefaultDtor(Options.get("AllowSoleDefaultDtor", false)), |
29 AllowMissingMoveFunctionsWhenCopyIsDeleted( | |
30 Options.get("AllowMissingMoveFunctionsWhenCopyIsDeleted", false)) {} | |
29 | 31 |
30 void SpecialMemberFunctionsCheck::storeOptions( | 32 void SpecialMemberFunctionsCheck::storeOptions( |
31 ClangTidyOptions::OptionMap &Opts) { | 33 ClangTidyOptions::OptionMap &Opts) { |
32 Options.store(Opts, "AllowMissingMoveFunctions", AllowMissingMoveFunctions); | 34 Options.store(Opts, "AllowMissingMoveFunctions", AllowMissingMoveFunctions); |
33 Options.store(Opts, "AllowSoleDefaultDtor", AllowSoleDefaultDtor); | 35 Options.store(Opts, "AllowSoleDefaultDtor", AllowSoleDefaultDtor); |
36 Options.store(Opts, "AllowMissingMoveFunctionsWhenCopyIsDeleted", | |
37 AllowMissingMoveFunctionsWhenCopyIsDeleted); | |
34 } | 38 } |
35 | 39 |
36 void SpecialMemberFunctionsCheck::registerMatchers(MatchFinder *Finder) { | 40 void SpecialMemberFunctionsCheck::registerMatchers(MatchFinder *Finder) { |
37 if (!getLangOpts().CPlusPlus) | |
38 return; | |
39 Finder->addMatcher( | 41 Finder->addMatcher( |
40 cxxRecordDecl( | 42 cxxRecordDecl( |
41 eachOf( | 43 eachOf( |
42 has(cxxDestructorDecl(unless(isImplicit())).bind("dtor")), | 44 has(cxxDestructorDecl(unless(isImplicit())).bind("dtor")), |
43 has(cxxConstructorDecl(isCopyConstructor(), unless(isImplicit())) | 45 has(cxxConstructorDecl(isCopyConstructor(), unless(isImplicit())) |
103 if (!MatchedDecl) | 105 if (!MatchedDecl) |
104 return; | 106 return; |
105 | 107 |
106 ClassDefId ID(MatchedDecl->getLocation(), std::string(MatchedDecl->getName())); | 108 ClassDefId ID(MatchedDecl->getLocation(), std::string(MatchedDecl->getName())); |
107 | 109 |
108 auto StoreMember = [this, &ID](SpecialMemberFunctionKind Kind) { | 110 auto StoreMember = [this, &ID](SpecialMemberFunctionData data) { |
109 llvm::SmallVectorImpl<SpecialMemberFunctionKind> &Members = | 111 llvm::SmallVectorImpl<SpecialMemberFunctionData> &Members = |
110 ClassWithSpecialMembers[ID]; | 112 ClassWithSpecialMembers[ID]; |
111 if (!llvm::is_contained(Members, Kind)) | 113 if (!llvm::is_contained(Members, data)) |
112 Members.push_back(Kind); | 114 Members.push_back(std::move(data)); |
113 }; | 115 }; |
114 | 116 |
115 if (const auto *Dtor = Result.Nodes.getNodeAs<CXXMethodDecl>("dtor")) { | 117 if (const auto *Dtor = Result.Nodes.getNodeAs<CXXMethodDecl>("dtor")) { |
116 StoreMember(Dtor->isDefaulted() | 118 StoreMember({Dtor->isDefaulted() |
117 ? SpecialMemberFunctionKind::DefaultDestructor | 119 ? SpecialMemberFunctionKind::DefaultDestructor |
118 : SpecialMemberFunctionKind::NonDefaultDestructor); | 120 : SpecialMemberFunctionKind::NonDefaultDestructor, |
121 Dtor->isDeleted()}); | |
119 } | 122 } |
120 | 123 |
121 std::initializer_list<std::pair<std::string, SpecialMemberFunctionKind>> | 124 std::initializer_list<std::pair<std::string, SpecialMemberFunctionKind>> |
122 Matchers = {{"copy-ctor", SpecialMemberFunctionKind::CopyConstructor}, | 125 Matchers = {{"copy-ctor", SpecialMemberFunctionKind::CopyConstructor}, |
123 {"copy-assign", SpecialMemberFunctionKind::CopyAssignment}, | 126 {"copy-assign", SpecialMemberFunctionKind::CopyAssignment}, |
124 {"move-ctor", SpecialMemberFunctionKind::MoveConstructor}, | 127 {"move-ctor", SpecialMemberFunctionKind::MoveConstructor}, |
125 {"move-assign", SpecialMemberFunctionKind::MoveAssignment}}; | 128 {"move-assign", SpecialMemberFunctionKind::MoveAssignment}}; |
126 | 129 |
127 for (const auto &KV : Matchers) | 130 for (const auto &KV : Matchers) |
128 if (Result.Nodes.getNodeAs<CXXMethodDecl>(KV.first)) { | 131 if (const auto *MethodDecl = |
129 StoreMember(KV.second); | 132 Result.Nodes.getNodeAs<CXXMethodDecl>(KV.first)) { |
133 StoreMember({KV.second, MethodDecl->isDeleted()}); | |
130 } | 134 } |
131 } | 135 } |
132 | 136 |
133 void SpecialMemberFunctionsCheck::onEndOfTranslationUnit() { | 137 void SpecialMemberFunctionsCheck::onEndOfTranslationUnit() { |
134 for (const auto &C : ClassWithSpecialMembers) { | 138 for (const auto &C : ClassWithSpecialMembers) { |
136 } | 140 } |
137 } | 141 } |
138 | 142 |
139 void SpecialMemberFunctionsCheck::checkForMissingMembers( | 143 void SpecialMemberFunctionsCheck::checkForMissingMembers( |
140 const ClassDefId &ID, | 144 const ClassDefId &ID, |
141 llvm::ArrayRef<SpecialMemberFunctionKind> DefinedMembers) { | 145 llvm::ArrayRef<SpecialMemberFunctionData> DefinedMembers) { |
142 llvm::SmallVector<SpecialMemberFunctionKind, 5> MissingMembers; | 146 llvm::SmallVector<SpecialMemberFunctionKind, 5> MissingMembers; |
143 | 147 |
144 auto HasMember = [&](SpecialMemberFunctionKind Kind) { | 148 auto HasMember = [&](SpecialMemberFunctionKind Kind) { |
145 return llvm::is_contained(DefinedMembers, Kind); | 149 return llvm::any_of(DefinedMembers, [Kind](const auto &data) { |
150 return data.FunctionKind == Kind; | |
151 }); | |
152 }; | |
153 | |
154 auto IsDeleted = [&](SpecialMemberFunctionKind Kind) { | |
155 return llvm::any_of(DefinedMembers, [Kind](const auto &data) { | |
156 return data.FunctionKind == Kind && data.IsDeleted; | |
157 }); | |
146 }; | 158 }; |
147 | 159 |
148 auto RequireMember = [&](SpecialMemberFunctionKind Kind) { | 160 auto RequireMember = [&](SpecialMemberFunctionKind Kind) { |
149 if (!HasMember(Kind)) | 161 if (!HasMember(Kind)) |
150 MissingMembers.push_back(Kind); | 162 MissingMembers.push_back(Kind); |
171 | 183 |
172 RequireMember(SpecialMemberFunctionKind::CopyConstructor); | 184 RequireMember(SpecialMemberFunctionKind::CopyConstructor); |
173 RequireMember(SpecialMemberFunctionKind::CopyAssignment); | 185 RequireMember(SpecialMemberFunctionKind::CopyAssignment); |
174 } | 186 } |
175 | 187 |
176 if (RequireFive) { | 188 if (RequireFive && |
189 !(AllowMissingMoveFunctionsWhenCopyIsDeleted && | |
190 (IsDeleted(SpecialMemberFunctionKind::CopyConstructor) && | |
191 IsDeleted(SpecialMemberFunctionKind::CopyAssignment)))) { | |
177 assert(RequireThree); | 192 assert(RequireThree); |
178 RequireMember(SpecialMemberFunctionKind::MoveConstructor); | 193 RequireMember(SpecialMemberFunctionKind::MoveConstructor); |
179 RequireMember(SpecialMemberFunctionKind::MoveAssignment); | 194 RequireMember(SpecialMemberFunctionKind::MoveAssignment); |
180 } | 195 } |
181 | 196 |
182 if (!MissingMembers.empty()) | 197 if (!MissingMembers.empty()) { |
198 llvm::SmallVector<SpecialMemberFunctionKind, 5> DefinedMemberKinds; | |
199 llvm::transform(DefinedMembers, std::back_inserter(DefinedMemberKinds), | |
200 [](const auto &data) { return data.FunctionKind; }); | |
183 diag(ID.first, "class '%0' defines %1 but does not define %2") | 201 diag(ID.first, "class '%0' defines %1 but does not define %2") |
184 << ID.second << cppcoreguidelines::join(DefinedMembers, " and ") | 202 << ID.second << cppcoreguidelines::join(DefinedMemberKinds, " and ") |
185 << cppcoreguidelines::join(MissingMembers, " or "); | 203 << cppcoreguidelines::join(MissingMembers, " or "); |
204 } | |
186 } | 205 } |
187 | 206 |
188 } // namespace cppcoreguidelines | 207 } // namespace cppcoreguidelines |
189 } // namespace tidy | 208 } // namespace tidy |
190 } // namespace clang | 209 } // namespace clang |