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