2016-12-18 00:35:53 +03:00
|
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
|
|
|
|
#include "NoDuplicateRefCntMemberChecker.h"
|
|
|
|
#include "CustomMatchers.h"
|
|
|
|
|
2017-10-20 20:11:50 +03:00
|
|
|
void NoDuplicateRefCntMemberChecker::registerMatchers(MatchFinder *AstMatcher) {
|
2016-12-18 05:14:37 +03:00
|
|
|
AstMatcher->addMatcher(cxxRecordDecl().bind("decl"), this);
|
2016-12-18 00:35:53 +03:00
|
|
|
}
|
|
|
|
|
2016-12-18 05:14:37 +03:00
|
|
|
void NoDuplicateRefCntMemberChecker::check(
|
2016-12-18 00:35:53 +03:00
|
|
|
const MatchFinder::MatchResult &Result) {
|
|
|
|
const CXXRecordDecl *D = Result.Nodes.getNodeAs<CXXRecordDecl>("decl");
|
|
|
|
const FieldDecl *RefCntMember = getClassRefCntMember(D);
|
|
|
|
const FieldDecl *FoundRefCntBase = nullptr;
|
|
|
|
|
|
|
|
if (!D->hasDefinition())
|
|
|
|
return;
|
|
|
|
D = D->getDefinition();
|
|
|
|
|
|
|
|
// If we don't have an mRefCnt member, and we have less than 2 superclasses,
|
|
|
|
// we don't have to run this loop, as neither case will ever apply.
|
|
|
|
if (!RefCntMember && D->getNumBases() < 2) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check every superclass for whether it has a base with a refcnt member, and
|
|
|
|
// warn for those which do
|
|
|
|
for (auto &Base : D->bases()) {
|
|
|
|
// Determine if this base class has an mRefCnt member
|
|
|
|
const FieldDecl *BaseRefCntMember = getBaseRefCntMember(Base.getType());
|
|
|
|
|
|
|
|
if (BaseRefCntMember) {
|
|
|
|
if (RefCntMember) {
|
|
|
|
// We have an mRefCnt, and superclass has an mRefCnt
|
2017-10-20 20:11:50 +03:00
|
|
|
const char *Error = "Refcounted record %0 has multiple mRefCnt members";
|
|
|
|
const char *Note1 = "Superclass %0 also has an mRefCnt member";
|
|
|
|
const char *Note2 =
|
2016-12-18 05:14:37 +03:00
|
|
|
"Consider using the _INHERITED macros for AddRef and Release here";
|
2016-12-18 00:35:53 +03:00
|
|
|
|
2018-11-03 16:41:36 +03:00
|
|
|
diag(D->getBeginLoc(), Error, DiagnosticIDs::Error) << D;
|
|
|
|
diag(BaseRefCntMember->getBeginLoc(), Note1, DiagnosticIDs::Note)
|
2017-10-20 20:11:50 +03:00
|
|
|
<< BaseRefCntMember->getParent();
|
2018-11-03 16:41:36 +03:00
|
|
|
diag(RefCntMember->getBeginLoc(), Note2, DiagnosticIDs::Note);
|
2016-12-18 00:35:53 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
if (FoundRefCntBase) {
|
2017-10-20 20:11:50 +03:00
|
|
|
const char *Error = "Refcounted record %0 has multiple superclasses "
|
|
|
|
"with mRefCnt members";
|
|
|
|
const char *Note = "Superclass %0 has an mRefCnt member";
|
2016-12-18 00:35:53 +03:00
|
|
|
|
|
|
|
// superclass has mRefCnt, and another superclass also has an mRefCnt
|
2018-11-03 16:41:36 +03:00
|
|
|
diag(D->getBeginLoc(), Error, DiagnosticIDs::Error) << D;
|
|
|
|
diag(BaseRefCntMember->getBeginLoc(), Note, DiagnosticIDs::Note)
|
2017-10-20 20:11:50 +03:00
|
|
|
<< BaseRefCntMember->getParent();
|
2018-11-03 16:41:36 +03:00
|
|
|
diag(FoundRefCntBase->getBeginLoc(), Note, DiagnosticIDs::Note)
|
2017-10-20 20:11:50 +03:00
|
|
|
<< FoundRefCntBase->getParent();
|
2016-12-18 00:35:53 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// Record that we've found a base with a mRefCnt member
|
|
|
|
FoundRefCntBase = BaseRefCntMember;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|