Source code

Revision control

Other Tools

1
/* This Source Code Form is subject to the terms of the Mozilla Public
2
* License, v. 2.0. If a copy of the MPL was not distributed with this
3
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5
#include "NoDuplicateRefCntMemberChecker.h"
6
#include "CustomMatchers.h"
7
8
void NoDuplicateRefCntMemberChecker::registerMatchers(MatchFinder *AstMatcher) {
9
AstMatcher->addMatcher(cxxRecordDecl().bind("decl"), this);
10
}
11
12
void NoDuplicateRefCntMemberChecker::check(
13
const MatchFinder::MatchResult &Result) {
14
const CXXRecordDecl *D = Result.Nodes.getNodeAs<CXXRecordDecl>("decl");
15
const FieldDecl *RefCntMember = getClassRefCntMember(D);
16
const FieldDecl *FoundRefCntBase = nullptr;
17
18
if (!D->hasDefinition())
19
return;
20
D = D->getDefinition();
21
22
// If we don't have an mRefCnt member, and we have less than 2 superclasses,
23
// we don't have to run this loop, as neither case will ever apply.
24
if (!RefCntMember && D->getNumBases() < 2) {
25
return;
26
}
27
28
// Check every superclass for whether it has a base with a refcnt member, and
29
// warn for those which do
30
for (auto &Base : D->bases()) {
31
// Determine if this base class has an mRefCnt member
32
const FieldDecl *BaseRefCntMember = getBaseRefCntMember(Base.getType());
33
34
if (BaseRefCntMember) {
35
if (RefCntMember) {
36
// We have an mRefCnt, and superclass has an mRefCnt
37
const char *Error = "Refcounted record %0 has multiple mRefCnt members";
38
const char *Note1 = "Superclass %0 also has an mRefCnt member";
39
const char *Note2 =
40
"Consider using the _INHERITED macros for AddRef and Release here";
41
42
diag(D->getBeginLoc(), Error, DiagnosticIDs::Error) << D;
43
diag(BaseRefCntMember->getBeginLoc(), Note1, DiagnosticIDs::Note)
44
<< BaseRefCntMember->getParent();
45
diag(RefCntMember->getBeginLoc(), Note2, DiagnosticIDs::Note);
46
}
47
48
if (FoundRefCntBase) {
49
const char *Error = "Refcounted record %0 has multiple superclasses "
50
"with mRefCnt members";
51
const char *Note = "Superclass %0 has an mRefCnt member";
52
53
// superclass has mRefCnt, and another superclass also has an mRefCnt
54
diag(D->getBeginLoc(), Error, DiagnosticIDs::Error) << D;
55
diag(BaseRefCntMember->getBeginLoc(), Note, DiagnosticIDs::Note)
56
<< BaseRefCntMember->getParent();
57
diag(FoundRefCntBase->getBeginLoc(), Note, DiagnosticIDs::Note)
58
<< FoundRefCntBase->getParent();
59
}
60
61
// Record that we've found a base with a mRefCnt member
62
FoundRefCntBase = BaseRefCntMember;
63
}
64
}
65
}