24 llvm::raw_string_ostream OS(Result);
25 Literal->outputString(OS);
28 auto OpenPos = Result.find_first_of(
'"');
29 if (OpenPos == std::string::npos)
31 Result[OpenPos] =
'\'';
33 auto ClosePos = Result.find_last_of(
'"');
34 if (ClosePos == std::string::npos)
36 Result[ClosePos] =
'\'';
39 if ((ClosePos - OpenPos) == 2 && Result[OpenPos + 1] ==
'\'')
40 Result.replace(OpenPos + 1, 1,
"\\'");
58 const auto SingleChar =
59 ignoringParenCasts(stringLiteral(hasSize(1)).bind(
"literal"));
61 const auto StringExpr = expr(hasType(hasUnqualifiedDesugaredType(
62 recordType(hasDeclaration(recordDecl(hasAnyName(StringLikeClasses)))))));
64 const auto InterestingStringFunction = hasAnyName(
65 "find",
"rfind",
"find_first_of",
"find_first_not_of",
"find_last_of",
66 "find_last_not_of",
"starts_with",
"ends_with",
"contains",
"operator+=");
70 callee(functionDecl(InterestingStringFunction).bind(
"func")),
71 anyOf(argumentCountIs(1), argumentCountIs(2)),
72 hasArgument(0, SingleChar), on(StringExpr)),
75 Finder->addMatcher(cxxOperatorCallExpr(hasOperatorName(
"+="),
76 hasLHS(StringExpr), hasRHS(SingleChar),
77 callee(functionDecl().bind(
"func"))),
82 const auto *Literal = Result.Nodes.getNodeAs<StringLiteral>(
"literal");
83 const auto *FindFunc = Result.Nodes.getNodeAs<FunctionDecl>(
"func");
89 diag(Literal->getBeginLoc(),
"%0 called with a string literal consisting of "
90 "a single character; consider using the more "
91 "effective overload accepting a character")
93 << FixItHint::CreateReplacement(Literal->getSourceRange(), *Replacement);
Every ClangTidyCheck reports errors through a DiagnosticsEngine provided by this context.