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/. */
5 #include "NoDuplicateRefCntMemberChecker.h"
6 #include "CustomMatchers.h"
8 void NoDuplicateRefCntMemberChecker::registerMatchers(MatchFinder
*AstMatcher
) {
9 AstMatcher
->addMatcher(cxxRecordDecl().bind("decl"), this);
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;
18 if (!D
->hasDefinition())
20 D
= D
->getDefinition();
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) {
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());
34 if (BaseRefCntMember
) {
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";
40 "Consider using the _INHERITED macros for AddRef and Release here";
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
);
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";
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();
61 // Record that we've found a base with a mRefCnt member
62 FoundRefCntBase
= BaseRefCntMember
;