10 #include "clang/AST/ASTContext.h" 11 #include "clang/ASTMatchers/ASTMatchFinder.h" 19 UseTransparentFunctorsCheck::UseTransparentFunctorsCheck(
21 :
ClangTidyCheck(Name, Context), SafeMode(Options.get(
"SafeMode", 0)) {}
32 const auto TransparentFunctors =
33 classTemplateSpecializationDecl(
34 unless(hasAnyTemplateArgument(refersToType(voidType()))),
35 hasAnyName(
"::std::plus",
"::std::minus",
"::std::multiplies",
36 "::std::divides",
"::std::modulus",
"::std::negate",
37 "::std::equal_to",
"::std::not_equal_to",
"::std::greater",
38 "::std::less",
"::std::greater_equal",
"::std::less_equal",
39 "::std::logical_and",
"::std::logical_or",
40 "::std::logical_not",
"::std::bit_and",
"::std::bit_or",
41 "::std::bit_xor",
"::std::bit_not"))
42 .bind(
"FunctorClass");
47 unless(elaboratedType()),
48 hasDeclaration(classTemplateSpecializationDecl(
49 unless(hasAnyTemplateArgument(templateArgument(refersToType(
50 qualType(pointsTo(qualType(isAnyCharacter()))))))),
51 hasAnyTemplateArgument(
52 templateArgument(refersToType(qualType(hasDeclaration(
53 TransparentFunctors))))
55 .bind(
"FunctorParentLoc"),
63 Finder->addMatcher(cxxConstructExpr(hasDeclaration(cxxMethodDecl(
64 ofClass(TransparentFunctors))),
65 unless(isInTemplateInstantiation()))
70 static const StringRef
Message =
"prefer transparent functors '%0'";
74 while (Result.isNull() && !Loc.isNull()) {
75 Result = Loc.getAs<T>();
76 Loc = Loc.getNextTypeLoc();
82 const MatchFinder::MatchResult &Result) {
83 const auto *FuncClass =
84 Result.Nodes.getNodeAs<ClassTemplateSpecializationDecl>(
"FunctorClass");
85 if (
const auto *FuncInst =
86 Result.Nodes.getNodeAs<CXXConstructExpr>(
"FuncInst")) {
88 << (FuncClass->getName() +
"<>").str();
92 const auto *Functor = Result.Nodes.getNodeAs<TemplateArgument>(
"Functor");
93 const auto FunctorParentLoc =
94 Result.Nodes.getNodeAs<TypeLoc>(
"FunctorParentLoc")
95 ->getAs<TemplateSpecializationTypeLoc>();
97 if (!FunctorParentLoc)
101 const auto *FunctorParentType =
102 FunctorParentLoc.getType()->castAs<TemplateSpecializationType>();
103 for (; ArgNum < FunctorParentType->getNumArgs(); ++ArgNum) {
104 const TemplateArgument &Arg = FunctorParentType->getArg(ArgNum);
107 QualType ParentArgType = Arg.getAsType();
108 if (ParentArgType->isRecordType() &&
109 ParentArgType->getAsCXXRecordDecl() ==
110 Functor->getAsType()->getAsCXXRecordDecl())
114 if (ArgNum == FunctorParentType->getNumArgs())
116 TemplateArgumentLoc FunctorLoc = FunctorParentLoc.getArgLoc(ArgNum);
117 auto FunctorTypeLoc = getInnerTypeLocAs<TemplateSpecializationTypeLoc>(
118 FunctorLoc.getTypeSourceInfo()->getTypeLoc());
119 if (FunctorTypeLoc.isNull())
122 SourceLocation ReportLoc = FunctorLoc.getLocation();
123 if (ReportLoc.isInvalid())
125 diag(ReportLoc, Message) << (FuncClass->getName() +
"<>").str()
126 << FixItHint::CreateRemoval(
127 FunctorTypeLoc.getArgLoc(0).getSourceRange());
SourceLocation Loc
'#' location in the include directive
static T getInnerTypeLocAs(TypeLoc Loc)
constexpr llvm::StringLiteral Message
Base class for all clang-tidy checks.
const LangOptions & getLangOpts() const
Returns the language options from the context.
void check(const ast_matchers::MatchFinder::MatchResult &Result) override
ClangTidyChecks that register ASTMatchers should do the actual work in here.
void registerMatchers(ast_matchers::MatchFinder *Finder) override
Override this to register AST matchers with Finder.
void store(ClangTidyOptions::OptionMap &Options, StringRef LocalName, StringRef Value) const
Stores an option with the check-local name LocalName with string value Value to Options.
static constexpr llvm::StringLiteral Name
std::map< std::string, std::string > OptionMap
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Every ClangTidyCheck reports errors through a DiagnosticsEngine provided by this context.
void storeOptions(ClangTidyOptions::OptionMap &Opts) override
Should store all options supported by this check with their current values or default values for opti...
DiagnosticBuilder diag(SourceLocation Loc, StringRef Description, DiagnosticIDs::Level Level=DiagnosticIDs::Warning)
Add a diagnostic with the check's name.