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