26 const auto TransparentFunctors =
27 classTemplateSpecializationDecl(
28 unless(hasAnyTemplateArgument(refersToType(voidType()))),
29 hasAnyName(
"::std::plus",
"::std::minus",
"::std::multiplies",
30 "::std::divides",
"::std::modulus",
"::std::negate",
31 "::std::equal_to",
"::std::not_equal_to",
"::std::greater",
32 "::std::less",
"::std::greater_equal",
"::std::less_equal",
33 "::std::logical_and",
"::std::logical_or",
34 "::std::logical_not",
"::std::bit_and",
"::std::bit_or",
35 "::std::bit_xor",
"::std::bit_not"))
36 .bind(
"FunctorClass");
40 loc(qualType(hasDeclaration(classTemplateSpecializationDecl(
41 unless(hasAnyTemplateArgument(templateArgument(refersToType(
42 qualType(pointsTo(qualType(isAnyCharacter()))))))),
43 hasAnyTemplateArgument(
44 templateArgument(refersToType(qualType(
45 hasDeclaration(TransparentFunctors))))
47 .bind(
"FunctorParentLoc"),
55 Finder->addMatcher(cxxConstructExpr(hasDeclaration(cxxMethodDecl(
56 ofClass(TransparentFunctors))),
57 unless(isInTemplateInstantiation()))
74 const MatchFinder::MatchResult &Result) {
75 const auto *FuncClass =
76 Result.Nodes.getNodeAs<ClassTemplateSpecializationDecl>(
"FunctorClass");
77 if (
const auto *FuncInst =
78 Result.Nodes.getNodeAs<CXXConstructExpr>(
"FuncInst")) {
79 diag(FuncInst->getBeginLoc(),
Message) << FuncClass->getName();
83 const auto *Functor = Result.Nodes.getNodeAs<TemplateArgument>(
"Functor");
84 const auto FunctorParentLoc =
85 Result.Nodes.getNodeAs<TypeLoc>(
"FunctorParentLoc")
86 ->getAs<TemplateSpecializationTypeLoc>();
88 if (!FunctorParentLoc)
92 const auto *FunctorParentType =
93 FunctorParentLoc.getType()->castAs<TemplateSpecializationType>();
94 for (; ArgNum < FunctorParentType->template_arguments().size(); ++ArgNum) {
95 const TemplateArgument &Arg =
96 FunctorParentType->template_arguments()[ArgNum];
97 if (Arg.getKind() != TemplateArgument::Type)
99 QualType ParentArgType = Arg.getAsType();
100 if (ParentArgType->isRecordType() &&
101 ParentArgType->getAsCXXRecordDecl() ==
102 Functor->getAsType()->getAsCXXRecordDecl())
106 if (ArgNum == FunctorParentType->template_arguments().size())
108 TemplateArgumentLoc FunctorLoc = FunctorParentLoc.getArgLoc(ArgNum);
110 FunctorLoc.getTypeSourceInfo()->getTypeLoc());
111 if (FunctorTypeLoc.isNull())
114 SourceLocation ReportLoc = FunctorLoc.getLocation();
115 if (ReportLoc.isInvalid())
117 diag(ReportLoc,
Message) << FuncClass->getName()
118 << FixItHint::CreateRemoval(
119 FunctorTypeLoc.getArgLoc(0).getSourceRange());
Every ClangTidyCheck reports errors through a DiagnosticsEngine provided by this context.