blob: 8ab0c92be19b30c9ad3e62212796759be5df08ed [file] [log] [blame]
Jonathan Coe77ec2632016-08-02 21:18:37 +00001//===--- SpecialMemberFunctionsCheck.h - clang-tidy--------------*- C++ -*-===//
Jonathan Coe5d304b22016-07-30 08:58:54 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_SPECIAL_MEMBER_FUNCTIONS_H
11#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_SPECIAL_MEMBER_FUNCTIONS_H
12
13#include "../ClangTidy.h"
14
15#include "llvm/ADT/DenseMapInfo.h"
16
17namespace clang {
18namespace tidy {
19namespace cppcoreguidelines {
20
21/// Checks for classes where some, but not all, of the special member functions
22/// are defined.
23///
24/// For the user-facing documentation see:
25/// http://clang.llvm.org/extra/clang-tidy/checks/cppcoreguidelines-special-member-functions.html
26class SpecialMemberFunctionsCheck : public ClangTidyCheck {
27public:
Aaron Ballman9dd8caa2017-03-13 21:39:00 +000028 SpecialMemberFunctionsCheck(StringRef Name, ClangTidyContext *Context);
29 void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
Jonathan Coe5d304b22016-07-30 08:58:54 +000030 void registerMatchers(ast_matchers::MatchFinder *Finder) override;
31 void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
32 void onEndOfTranslationUnit() override;
Kirill Bobyrev11cea452016-08-01 12:06:18 +000033
Justin Lebarae90ad22016-10-21 20:13:39 +000034 enum class SpecialMemberFunctionKind : uint8_t {
Jonathan Coe5d304b22016-07-30 08:58:54 +000035 Destructor,
Aaron Ballman9dd8caa2017-03-13 21:39:00 +000036 DefaultDestructor,
37 NonDefaultDestructor,
Jonathan Coe5d304b22016-07-30 08:58:54 +000038 CopyConstructor,
39 CopyAssignment,
40 MoveConstructor,
41 MoveAssignment
42 };
43
44 using ClassDefId = std::pair<SourceLocation, std::string>;
45
Jonathan Coe77ec2632016-08-02 21:18:37 +000046 using ClassDefiningSpecialMembersMap =
47 llvm::DenseMap<ClassDefId,
Justin Lebarae90ad22016-10-21 20:13:39 +000048 llvm::SmallVector<SpecialMemberFunctionKind, 5>>;
Jonathan Coe5d304b22016-07-30 08:58:54 +000049
50private:
Aaron Ballman9dd8caa2017-03-13 21:39:00 +000051 void checkForMissingMembers(
52 const ClassDefId &ID,
53 llvm::ArrayRef<SpecialMemberFunctionKind> DefinedSpecialMembers);
54
55 const bool AllowMissingMoveFunctions;
56 const bool AllowSoleDefaultDtor;
Jonathan Coe5d304b22016-07-30 08:58:54 +000057 ClassDefiningSpecialMembersMap ClassWithSpecialMembers;
58};
59
60} // namespace cppcoreguidelines
61} // namespace tidy
62} // namespace clang
63
64namespace llvm {
65/// Specialisation of DenseMapInfo to allow ClassDefId objects in DenseMaps
66/// FIXME: Move this to the corresponding cpp file as is done for
Kirill Bobyrev11cea452016-08-01 12:06:18 +000067/// clang-tidy/readability/IdentifierNamingCheck.cpp.
Jonathan Coe5d304b22016-07-30 08:58:54 +000068template <>
69struct DenseMapInfo<
70 clang::tidy::cppcoreguidelines::SpecialMemberFunctionsCheck::ClassDefId> {
71 using ClassDefId =
Jonathan Coe77ec2632016-08-02 21:18:37 +000072 clang::tidy::cppcoreguidelines::SpecialMemberFunctionsCheck::ClassDefId;
Jonathan Coe5d304b22016-07-30 08:58:54 +000073
74 static inline ClassDefId getEmptyKey() {
75 return ClassDefId(
76 clang::SourceLocation::getFromRawEncoding(static_cast<unsigned>(-1)),
77 "EMPTY");
78 }
79
80 static inline ClassDefId getTombstoneKey() {
81 return ClassDefId(
82 clang::SourceLocation::getFromRawEncoding(static_cast<unsigned>(-2)),
83 "TOMBSTONE");
84 }
85
86 static unsigned getHashValue(ClassDefId Val) {
87 assert(Val != getEmptyKey() && "Cannot hash the empty key!");
88 assert(Val != getTombstoneKey() && "Cannot hash the tombstone key!");
89
90 std::hash<ClassDefId::second_type> SecondHash;
91 return Val.first.getRawEncoding() + SecondHash(Val.second);
92 }
93
Benjamin Kramera079cdb2017-03-21 21:34:58 +000094 static bool isEqual(const ClassDefId &LHS, const ClassDefId &RHS) {
Jonathan Coe5d304b22016-07-30 08:58:54 +000095 if (RHS == getEmptyKey())
96 return LHS == getEmptyKey();
97 if (RHS == getTombstoneKey())
98 return LHS == getTombstoneKey();
99 return LHS == RHS;
100 }
101};
102
103} // namespace llvm
104
105#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_SPECIAL_MEMBER_FUNCTIONS_H