11#include "clang/AST/ASTContext.h"
12#include "clang/AST/Decl.h"
13#include "clang/ASTMatchers/ASTMatchFinder.h"
14#include "clang/ASTMatchers/ASTMatchers.h"
15#include "clang/Lex/Lexer.h"
26 if (
const auto *ICE = dyn_cast<ImplicitCastExpr>(ST)) {
27 return (ICE->getCastKind() != CK_NoOp) ||
50 cxxForRangeStmt(hasLoopVariable(
52 hasType(qualType(references(qualType(isConstQualified())))),
56 cxxOperatorCallExpr().bind(
"operator-call")),
57 hasDescendant(unaryOperator(hasOperatorName(
"*"))
58 .bind(
"operator-call"))))
60 .bind(
"faulty-var")))),
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);
86void ImplicitConversionInLoopCheck::reportAndFix(
const ASTContext *Context,
88 const Expr *OperatorCall) {
91 QualType ConstType = OperatorCall->getType().withConst();
92 QualType ConstRefType = Context->getLValueReferenceType(ConstType);
93 const char Message[] =
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->getBeginLoc(), Message) << VD << ConstRefType;
DiagnosticBuilder diag(SourceLocation Loc, StringRef Description, DiagnosticIDs::Level Level=DiagnosticIDs::Warning)
Add a diagnostic with the check's name.