36 MatchFinder *Finder) {
37 const auto PolymorphicPointerExpr =
38 expr(hasType(hasCanonicalType(pointerType(pointee(hasCanonicalType(
39 hasDeclaration(cxxRecordDecl(unless(isFinal()), isPolymorphic())
40 .bind(
"pointee"))))))))
43 const auto PointerExprWithVirtualMethod =
44 expr(hasType(hasCanonicalType(
45 pointerType(pointee(hasCanonicalType(hasDeclaration(
48 anyOf(hasMethod(isVirtualAsWritten()), isAbstract()))
49 .bind(
"pointee"))))))))
52 const auto SelectedPointerExpr = IgnoreInheritedVirtualFunctions
53 ? PointerExprWithVirtualMethod
54 : PolymorphicPointerExpr;
56 const auto ArraySubscript = arraySubscriptExpr(hasBase(SelectedPointerExpr));
58 const auto BinaryOperators =
59 binaryOperator(hasAnyOperatorName(
"+",
"-",
"+=",
"-="),
60 hasEitherOperand(SelectedPointerExpr));
62 const auto UnaryOperators = unaryOperator(
63 hasAnyOperatorName(
"++",
"--"), hasUnaryOperand(SelectedPointerExpr));
65 Finder->addMatcher(ArraySubscript,
this);
66 Finder->addMatcher(BinaryOperators,
this);
67 Finder->addMatcher(UnaryOperators,
this);
71 const MatchFinder::MatchResult &Result) {
72 const auto *PointerExpr = Result.Nodes.getNodeAs<Expr>(
"pointer");
73 const auto *PointeeDecl = Result.Nodes.getNodeAs<CXXRecordDecl>(
"pointee");
75 diag(PointerExpr->getBeginLoc(),
76 "pointer arithmetic on polymorphic object of type %0 can result in "
77 "undefined behavior if the dynamic type differs from the pointer type")
78 << PointeeDecl << PointerExpr->getSourceRange();
Every ClangTidyCheck reports errors through a DiagnosticsEngine provided by this context.