29 const auto IsCharPointerOrArray =
30 anyOf(hasType(pointerType(pointee(isAnyCharacter()))),
31 hasType(arrayType(hasElementType(isAnyCharacter()))));
33 const auto ImplicitlyConvertibleToStringView =
34 expr(anyOf(hasType(IsStdStringView), IsCharPointerOrArray,
35 hasType(IsStdString)))
36 .bind(
"originalStringView");
41 const auto RedundantStringConstruction = cxxConstructExpr(
43 hasArgument(0, ignoringImplicit(ImplicitlyConvertibleToStringView)),
44 unless(hasArgument(1, unless(cxxDefaultArgExpr()))));
48 const auto RedundantFunctionalCast = cxxFunctionalCastExpr(
49 hasType(IsStdString), hasDescendant(RedundantStringConstruction));
53 const auto HasStringOperatorCall = hasDescendant(cxxOperatorCallExpr(
54 hasOverloadedOperatorName(
"+"), hasType(IsStdString)));
55 const auto HasStringMethodCall =
56 hasDescendant(cxxMemberCallExpr(on(hasType(IsStdString))));
58 const auto IsCallReturningString = callExpr(hasType(IsStdString));
59 const auto IsImplicitStringViewFromCall =
60 cxxConstructExpr(hasType(IsStdStringView),
61 hasArgument(0, ignoringImplicit(IsCallReturningString)));
71 callExpr(forEachArgumentWithParam(
72 expr(hasType(IsStdStringView),
74 unless(ignoringParenImpCasts(IsImplicitStringViewFromCall)),
76 hasDescendant(expr(anyOf(RedundantFunctionalCast,
77 RedundantStringConstruction))
78 .bind(
"redundantExpr")),
80 unless(anyOf(HasStringOperatorCall, HasStringMethodCall)))
82 parmVarDecl(hasType(IsStdStringView)))),
87 const auto *ParamExpr = Result.Nodes.getNodeAs<Expr>(
"expr");
88 const auto *RedundantExpr = Result.Nodes.getNodeAs<Expr>(
"redundantExpr");
89 const auto *OriginalExpr = Result.Nodes.getNodeAs<Expr>(
"originalStringView");
90 assert(RedundantExpr && ParamExpr && OriginalExpr);
95 assert(ParamExpr->getSourceRange() == RedundantExpr->getSourceRange());
97 const StringRef OriginalText = Lexer::getSourceText(
98 CharSourceRange::getTokenRange(OriginalExpr->getSourceRange()),
99 *Result.SourceManager, getLangOpts());
101 if (OriginalText.empty())
104 diag(RedundantExpr->getBeginLoc(),
105 "redundant conversion to %0 and then back to %1")
106 << RedundantExpr->getType() << ParamExpr->getType()
107 << FixItHint::CreateReplacement(RedundantExpr->getSourceRange(),