33 const auto *Call = Result.Nodes.getNodeAs<CXXMemberCallExpr>(
"call");
35 const auto *Lambda = Result.Nodes.getNodeAs<LambdaExpr>(
"lambda");
37 const auto *MemExpr = Result.Nodes.getNodeAs<MemberExpr>(
"member");
41 if (!MemExpr->hasExplicitTemplateArgs() || MemExpr->getNumTemplateArgs() != 1)
44 const TemplateArgumentLoc &TemplateArg = MemExpr->getTemplateArgs()[0];
45 if (TemplateArg.getArgument().getKind() != TemplateArgument::Type)
49 const CXXMethodDecl *CallOp = Lambda->getCallOperator();
50 if (!CallOp || CallOp->getNumParams() != 1)
53 const ParmVarDecl *LambdaParam = CallOp->getParamDecl(0);
54 const QualType ParamType = LambdaParam->getType();
57 QualType ParamBaseType = ParamType.getNonReferenceType();
58 while (ParamBaseType->isPointerType())
59 ParamBaseType = ParamBaseType->getPointeeType();
60 const bool ParamIsAuto = ParamBaseType->getUnqualifiedDesugaredType()
61 ->getAs<TemplateTypeParmType>() !=
nullptr;
70 diag(Call->getExprLoc(),
71 "lambda parameter needlessly uses 'auto', use explicit type instead");
72 diag(LambdaParam->getTypeSourceInfo()->getTypeLoc().getBeginLoc(),
73 "replace 'auto' with explicit type", DiagnosticIDs::Note);
74 diag(TemplateArg.getLocation(),
75 "type from template argument can be inferred and removed",
82 const QualType CaseType = TemplateArg.getArgument().getAsType();
83 if (CaseType->getCanonicalTypeUnqualified() !=
84 ParamBaseType->getCanonicalTypeUnqualified())
87 auto Diag = diag(Call->getExprLoc(),
"redundant explicit template argument");
90 const SourceLocation LAngleLoc = MemExpr->getLAngleLoc();
91 const SourceLocation RAngleLoc = MemExpr->getRAngleLoc();
92 if (LAngleLoc.isInvalid() || RAngleLoc.isInvalid() || LAngleLoc.isMacroID() ||
93 RAngleLoc.isMacroID())
96 Diag << FixItHint::CreateRemoval(SourceRange(LAngleLoc, RAngleLoc));
99 if (MemExpr->hasTemplateKeyword())
100 Diag << FixItHint::CreateRemoval(MemExpr->getTemplateKeywordLoc());