66 MatchFinder *Finder) {
67 using namespace ast_matchers::internal;
68 auto IsStructPointer = [](Matcher<CXXRecordDecl> Constraint = anything(),
70 return expr(unaryOperator(
72 hasUnaryOperand(declRefExpr(
73 hasType(cxxRecordDecl(Constraint)),
74 hasType(Bind ? qualType().bind(
"Record") : qualType())))));
77 expr(sizeOfExpr(hasArgumentOfType(equalsBoundNode(
"Record"))));
78 auto ArgChecker = [&](Matcher<CXXRecordDecl> RecordConstraint,
79 BindableMatcher<Stmt> SecondArg = expr()) {
80 return allOf(argumentCountIs(3),
81 hasArgument(0, IsStructPointer(RecordConstraint,
true)),
82 hasArgument(1, SecondArg), hasArgument(2, IsRecordSizeOf));
86 callExpr(callee(namedDecl(hasAnyName(
88 ArgChecker(unless(isTriviallyDefaultConstructible())))
89 .bind(
"lazyConstruct"),
92 callExpr(callee(namedDecl(hasAnyName(
94 ArgChecker(unless(isTriviallyCopyable()), IsStructPointer()))
98 callExpr(callee(namedDecl(hasAnyName(
102 .bind(
"lazyCompare"),
107 const MatchFinder::MatchResult &Result) {
108 if (
const auto *Caller = Result.Nodes.getNodeAs<CallExpr>(
"lazyConstruct")) {
109 diag(Caller->getBeginLoc(),
"calling %0 on a non-trivially default "
110 "constructible class is undefined")
111 << cast<NamedDecl>(Caller->getCalleeDecl());
113 if (
const auto *Caller = Result.Nodes.getNodeAs<CallExpr>(
"lazyCopy")) {
114 diag(Caller->getBeginLoc(),
115 "calling %0 on a non-trivially copyable class is undefined")
116 << cast<NamedDecl>(Caller->getCalleeDecl());
118 if (
const auto *Caller = Result.Nodes.getNodeAs<CallExpr>(
"lazyCompare")) {
119 diag(Caller->getBeginLoc(),
120 "consider using comparison operators instead of calling %0")
121 << cast<NamedDecl>(Caller->getCalleeDecl());
Every ClangTidyCheck reports errors through a DiagnosticsEngine provided by this context.