@@ -15,32 +15,53 @@ using namespace clang::ast_matchers;
15
15
16
16
namespace clang ::tidy::modernize {
17
17
18
+ namespace {
19
+ AST_MATCHER (FunctionDecl, hasAnyDefinition) {
20
+ if (Node.hasBody () || Node.isPure () || Node.isDefaulted () || Node.isDeleted ())
21
+ return true ;
22
+
23
+ if (const FunctionDecl *Definition = Node.getDefinition ())
24
+ if (Definition->hasBody () || Definition->isPure () ||
25
+ Definition->isDefaulted () || Definition->isDeleted ())
26
+ return true ;
27
+
28
+ return false ;
29
+ }
30
+
31
+ AST_MATCHER (Decl, isUsed) { return Node.isUsed (); }
32
+
33
+ AST_MATCHER (CXXMethodDecl, isSpecialFunction) {
34
+ if (const auto *Constructor = dyn_cast<CXXConstructorDecl>(&Node))
35
+ return Constructor->isDefaultConstructor () ||
36
+ Constructor->isCopyOrMoveConstructor ();
37
+
38
+ return isa<CXXDestructorDecl>(Node) || Node.isCopyAssignmentOperator () ||
39
+ Node.isMoveAssignmentOperator ();
40
+ }
41
+ } // namespace
42
+
18
43
static const char SpecialFunction[] = " SpecialFunction" ;
19
44
static const char DeletedNotPublic[] = " DeletedNotPublic" ;
20
45
46
+ UseEqualsDeleteCheck::UseEqualsDeleteCheck (StringRef Name,
47
+ ClangTidyContext *Context)
48
+ : ClangTidyCheck(Name, Context),
49
+ IgnoreMacros (Options.getLocalOrGlobal(" IgnoreMacros" , true )) {}
50
+
21
51
void UseEqualsDeleteCheck::storeOptions (ClangTidyOptions::OptionMap &Opts) {
22
52
Options.store (Opts, " IgnoreMacros" , IgnoreMacros);
23
53
}
24
54
25
55
void UseEqualsDeleteCheck::registerMatchers (MatchFinder *Finder) {
26
- auto PrivateSpecialFn = cxxMethodDecl (
27
- isPrivate (),
28
- anyOf (cxxConstructorDecl (anyOf (isDefaultConstructor (),
29
- isCopyConstructor (), isMoveConstructor ())),
30
- cxxMethodDecl (
31
- anyOf (isCopyAssignmentOperator (), isMoveAssignmentOperator ())),
32
- cxxDestructorDecl ()));
56
+ auto PrivateSpecialFn = cxxMethodDecl (isPrivate (), isSpecialFunction ());
33
57
34
58
Finder->addMatcher (
35
59
cxxMethodDecl (
36
- PrivateSpecialFn,
37
- unless (anyOf (hasAnyBody (stmt ()), isDefaulted (), isDeleted (),
38
- ast_matchers::isTemplateInstantiation (),
39
- // Ensure that all methods except private special member
40
- // functions are defined.
41
- hasParent (cxxRecordDecl (hasMethod (unless (
42
- anyOf (PrivateSpecialFn, hasAnyBody (stmt ()), isPure (),
43
- isDefaulted (), isDeleted ()))))))))
60
+ PrivateSpecialFn, unless (hasAnyDefinition ()), unless (isUsed ()),
61
+ // Ensure that all methods except private special member functions are
62
+ // defined.
63
+ unless (ofClass (hasMethod (cxxMethodDecl (unless (PrivateSpecialFn),
64
+ unless (hasAnyDefinition ()))))))
44
65
.bind (SpecialFunction),
45
66
this );
46
67
@@ -55,7 +76,7 @@ void UseEqualsDeleteCheck::check(const MatchFinder::MatchResult &Result) {
55
76
SourceLocation EndLoc = Lexer::getLocForEndOfToken (
56
77
Func->getEndLoc (), 0 , *Result.SourceManager , getLangOpts ());
57
78
58
- if (Func->getLocation ().isMacroID () && IgnoreMacros )
79
+ if (IgnoreMacros && Func->getLocation ().isMacroID ())
59
80
return ;
60
81
// FIXME: Improve FixItHint to make the method public.
61
82
diag (Func->getLocation (),
@@ -66,7 +87,7 @@ void UseEqualsDeleteCheck::check(const MatchFinder::MatchResult &Result) {
66
87
// Ignore this warning in macros, since it's extremely noisy in code using
67
88
// DISALLOW_COPY_AND_ASSIGN-style macros and there's no easy way to
68
89
// automatically fix the warning when macros are in play.
69
- if (Func->getLocation ().isMacroID () && IgnoreMacros )
90
+ if (IgnoreMacros && Func->getLocation ().isMacroID ())
70
91
return ;
71
92
// FIXME: Add FixItHint to make the method public.
72
93
diag (Func->getLocation (), " deleted member function should be public" );
0 commit comments