12 #include "clang/AST/ASTContext.h" 13 #include "clang/AST/Decl.h" 14 #include "clang/ASTMatchers/ASTMatchFinder.h" 15 #include "clang/ASTMatchers/ASTMatchers.h" 16 #include "clang/Lex/Lexer.h" 22 namespace performance {
29 if (
const auto *ICE = dyn_cast<ImplicitCastExpr>(ST)) {
30 return (ICE->getCastKind() != CK_NoOp) ||
36 void ImplicitConversionInLoopCheck::registerMatchers(MatchFinder *Finder) {
51 cxxForRangeStmt(hasLoopVariable(
53 hasType(qualType(references(qualType(isConstQualified())))),
55 expr(anyOf(hasDescendant(
56 cxxOperatorCallExpr().bind(
"operator-call")),
57 hasDescendant(unaryOperator(hasOperatorName(
"*"))
58 .bind(
"operator-call"))))
60 .bind(
"faulty-var"))),
64 void ImplicitConversionInLoopCheck::check(
65 const MatchFinder::MatchResult &Result) {
66 const auto *VD = Result.Nodes.getNodeAs<VarDecl>(
"faulty-var");
67 const auto *Init = Result.Nodes.getNodeAs<Expr>(
"init");
68 const auto *OperatorCall =
69 Result.Nodes.getNodeAs<Expr>(
"operator-call");
71 if (
const auto *Cleanup = dyn_cast<ExprWithCleanups>(Init))
72 Init = Cleanup->getSubExpr();
74 const auto *Materialized = dyn_cast<MaterializeTemporaryExpr>(Init);
83 ReportAndFix(Result.Context, VD, OperatorCall);
86 void ImplicitConversionInLoopCheck::ReportAndFix(
87 const ASTContext *Context,
const VarDecl *VD,
88 const Expr *OperatorCall) {
91 QualType ConstType = OperatorCall->getType().withConst();
92 QualType ConstRefType = Context->getLValueReferenceType(ConstType);
94 "the type of the loop variable %0 is different from the one returned " 95 "by the iterator and generates an implicit conversion; you can either " 96 "change the type to the matching one (%1 but 'const auto&' is always a " 97 "valid option) or remove the reference to make it explicit that you are " 98 "creating a new value";
99 diag(VD->getLocStart(),
Message) << VD << ConstRefType;
static const StringRef Message
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//