12 #include "clang/AST/ASTContext.h" 13 #include "clang/ASTMatchers/ASTMatchFinder.h" 14 #include "llvm/ADT/DenseMapInfo.h" 15 #include "llvm/ADT/StringExtras.h" 17 #define DEBUG_TYPE "clang-tidy" 23 namespace cppcoreguidelines {
25 SpecialMemberFunctionsCheck::SpecialMemberFunctionsCheck(
28 AllowMissingMoveFunctions(Options.get(
"AllowMissingMoveFunctions", 0)),
29 AllowSoleDefaultDtor(Options.get(
"AllowSoleDefaultDtor", 0)) {}
33 Options.
store(Opts,
"AllowMissingMoveFunctions", AllowMissingMoveFunctions);
34 Options.
store(Opts,
"AllowSoleDefaultDtor", AllowSoleDefaultDtor);
43 has(cxxDestructorDecl(unless(isImplicit())).bind(
"dtor")),
44 has(cxxConstructorDecl(isCopyConstructor(), unless(isImplicit()))
46 has(cxxMethodDecl(isCopyAssignmentOperator(),
48 .bind(
"copy-assign")),
49 has(cxxConstructorDecl(isMoveConstructor(), unless(isImplicit()))
51 has(cxxMethodDecl(isMoveAssignmentOperator(),
53 .bind(
"move-assign"))))
58 static llvm::StringRef
62 return "a destructor";
65 return "a default destructor";
68 return "a non-default destructor";
70 return "a copy constructor";
72 return "a copy assignment operator";
74 return "a move constructor";
76 return "a move assignment operator";
78 llvm_unreachable(
"Unhandled SpecialMemberFunctionKind");
82 join(ArrayRef<SpecialMemberFunctionsCheck::SpecialMemberFunctionKind> SMFS,
83 llvm::StringRef AndOr) {
85 assert(!SMFS.empty() &&
86 "List of defined or undefined members should never be empty.");
88 llvm::raw_string_ostream Stream(Buffer);
91 size_t LastIndex = SMFS.size() - 1;
92 for (
size_t i = 1; i < LastIndex; ++i) {
96 Stream << AndOr <<
toString(SMFS[LastIndex]);
102 const MatchFinder::MatchResult &Result) {
103 const auto *MatchedDecl = Result.Nodes.getNodeAs<CXXRecordDecl>(
"class-def");
107 ClassDefId ID(MatchedDecl->getLocation(), MatchedDecl->getName());
110 llvm::SmallVectorImpl<SpecialMemberFunctionKind> &Members =
111 ClassWithSpecialMembers[ID];
112 if (!llvm::is_contained(Members,
Kind))
113 Members.push_back(
Kind);
116 if (
const auto *Dtor = Result.Nodes.getNodeAs<CXXMethodDecl>(
"dtor")) {
117 StoreMember(Dtor->isDefaulted()
122 std::initializer_list<std::pair<std::string, SpecialMemberFunctionKind>>
128 for (
const auto &KV : Matchers)
129 if (Result.Nodes.getNodeAs<CXXMethodDecl>(KV.first)) {
130 StoreMember(KV.second);
135 for (
const auto &C : ClassWithSpecialMembers) {
136 checkForMissingMembers(C.first, C.second);
140 void SpecialMemberFunctionsCheck::checkForMissingMembers(
142 llvm::ArrayRef<SpecialMemberFunctionKind> DefinedMembers) {
143 llvm::SmallVector<SpecialMemberFunctionKind, 5> MissingMembers;
146 return llvm::is_contained(DefinedMembers,
Kind);
150 if (!HasMember(
Kind))
151 MissingMembers.push_back(
Kind);
156 (!AllowSoleDefaultDtor &&
163 bool RequireFive = (!AllowMissingMoveFunctions && RequireThree &&
178 assert(RequireThree);
183 if (!MissingMembers.empty())
184 diag(ID.first,
"class '%0' defines %1 but does not define %2")
void onEndOfTranslationUnit() override
void store(ClangTidyOptions::OptionMap &Options, StringRef LocalName, StringRef Value) const
Stores an option with the check-local name LocalName with string value Value to Options.
void storeOptions(ClangTidyOptions::OptionMap &Opts) override
Should store all options supported by this check with their current values or default values for opti...
SpecialMemberFunctionKind
LangOptions getLangOpts() const
Returns the language options from the context.
void registerMatchers(ast_matchers::MatchFinder *Finder) override
Override this to register AST matchers with Finder.
void check(const ast_matchers::MatchFinder::MatchResult &Result) override
ClangTidyChecks that register ASTMatchers should do the actual work in here.
static llvm::StringRef toString(SpecialMemberFunctionsCheck::SpecialMemberFunctionKind K)
Base class for all clang-tidy checks.
std::map< std::string, std::string > OptionMap
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Every ClangTidyCheck reports errors through a DiagnosticsEngine provided by this context.
static std::string join(ArrayRef< SpecialMemberFunctionsCheck::SpecialMemberFunctionKind > SMFS, llvm::StringRef AndOr)
DiagnosticBuilder diag(SourceLocation Loc, StringRef Description, DiagnosticIDs::Level Level=DiagnosticIDs::Warning)
Add a diagnostic with the check's name.
std::pair< SourceLocation, std::string > ClassDefId