36 MatchFinder *Finder) {
37 auto DirectMemberVirtualFunctionPointer = unaryOperator(
38 allOf(hasOperatorName(
"&"),
39 hasUnaryOperand(declRefExpr(to(cxxMethodDecl(isVirtual()))))));
40 auto IndirectMemberPointer =
41 ignoringImpCasts(declRefExpr().bind(
"indirect_member_pointer"));
45 allOf(hasAnyOperatorName(
"==",
"!="),
47 hasType(memberPointerType(pointee(functionType())))),
48 anyOf(hasEitherOperand(DirectMemberVirtualFunctionPointer),
49 hasEitherOperand(IndirectMemberPointer)),
50 unless(hasEitherOperand(
51 castExpr(hasCastKind(CK_NullToMemberPointer))))))
52 .bind(
"binary_operator"),
57 const MatchFinder::MatchResult &Result) {
58 const auto *BO = Result.Nodes.getNodeAs<BinaryOperator>(
"binary_operator");
60 Result.Nodes.getNodeAs<DeclRefExpr>(
"indirect_member_pointer");
64 diag(BO->getOperatorLoc(), ErrorMsg);
68 llvm::SmallVector<SourceLocation, 12U> SameSignatureVirtualMethods{};
69 const auto *MPT = cast<MemberPointerType>(DRE->getType().getCanonicalType());
70 const CXXRecordDecl *RD = MPT->getMostRecentCXXRecordDecl();
74 constexpr bool StopVisit =
false;
76 auto VisitSameSignatureVirtualMethods =
77 [&](
const CXXRecordDecl *CurrentRecordDecl) ->
bool {
78 bool Ret = !StopVisit;
79 for (
const auto *MD : CurrentRecordDecl->methods()) {
80 if (MD->isVirtual() && MD->getType() == MPT->getPointeeType()) {
81 SameSignatureVirtualMethods.push_back(MD->getBeginLoc());
88 if (StopVisit != VisitSameSignatureVirtualMethods(RD)) {
89 RD->forallBases(VisitSameSignatureVirtualMethods);
92 if (!SameSignatureVirtualMethods.empty()) {
93 diag(BO->getOperatorLoc(), ErrorMsg);
94 for (
const auto Loc : SameSignatureVirtualMethods)
95 diag(Loc,
"potential member virtual function is declared here.",