14#include "../utils/FixItHintUtils.h"
15#include "../utils/Matchers.h"
16#include "../utils/OptionsUtils.h"
17#include "clang/Lex/Lexer.h"
18#include "clang/Tooling/FixIt.h"
26AST_MATCHER(MaterializeTemporaryExpr, isBoundToLValue) {
27 return Node.isBoundToLvalueReference();
35 StringParameterFunctions(utils::options::parseStringList(
36 Options.get(
"StringParameterFunctions",
""))) {
38 StringParameterFunctions.emplace_back(
"::std::format");
40 StringParameterFunctions.emplace_back(
"::std::print");
44 ast_matchers::MatchFinder *Finder) {
46 const auto StringDecl = type(hasUnqualifiedDesugaredType(recordType(
47 hasDeclaration(cxxRecordDecl(hasName(
"::std::basic_string"))))));
48 const auto StringExpr =
49 expr(anyOf(hasType(StringDecl), hasType(qualType(pointsTo(StringDecl)))));
52 const auto StringConstructorExpr = expr(anyOf(
53 cxxConstructExpr(argumentCountIs(1),
54 hasDeclaration(cxxMethodDecl(hasName(
"basic_string")))),
57 hasDeclaration(cxxMethodDecl(hasName(
"basic_string"))),
60 hasArgument(1, cxxDefaultArgExpr()))));
63 const auto StringViewConstructorExpr = cxxConstructExpr(
65 hasDeclaration(cxxMethodDecl(hasName(
"basic_string_view"))));
68 const auto StringCStrCallExpr =
69 cxxMemberCallExpr(on(StringExpr.bind(
"arg")),
70 callee(memberExpr().bind(
"member")),
71 callee(cxxMethodDecl(hasAnyName(
"c_str",
"data"))))
73 const auto HasRValueTempParent =
74 hasParent(materializeTemporaryExpr(unless(isBoundToLValue())));
82 anyOf(StringConstructorExpr, StringViewConstructorExpr),
83 hasArgument(0, StringCStrCallExpr),
84 unless(anyOf(HasRValueTempParent, hasParent(cxxBindTemporaryExpr(
85 HasRValueTempParent)))))),
91 hasAnyOverloadedOperatorName(
"<",
">",
">=",
"<=",
"!=",
"==",
"+"),
92 anyOf(allOf(hasArgument(0, StringExpr),
93 hasArgument(1, StringCStrCallExpr)),
94 allOf(hasArgument(0, StringCStrCallExpr),
95 hasArgument(1, StringExpr)))),
101 cxxOperatorCallExpr(hasAnyOverloadedOperatorName(
"=",
"+="),
102 hasArgument(0, StringExpr),
103 hasArgument(1, StringCStrCallExpr)),
108 cxxMemberCallExpr(on(StringExpr), callee(decl(cxxMethodDecl(hasAnyName(
109 "append",
"assign",
"compare")))),
110 argumentCountIs(1), hasArgument(0, StringCStrCallExpr)),
115 cxxMemberCallExpr(on(StringExpr),
116 callee(decl(cxxMethodDecl(hasName(
"compare")))),
117 argumentCountIs(3), hasArgument(2, StringCStrCallExpr)),
122 cxxMemberCallExpr(on(StringExpr),
123 callee(decl(cxxMethodDecl(hasAnyName(
124 "find",
"find_first_not_of",
"find_first_of",
125 "find_last_not_of",
"find_last_of",
"rfind")))),
126 anyOf(argumentCountIs(1), argumentCountIs(2)),
127 hasArgument(0, StringCStrCallExpr)),
132 cxxMemberCallExpr(on(StringExpr),
133 callee(decl(cxxMethodDecl(hasName(
"insert")))),
134 argumentCountIs(2), hasArgument(1, StringCStrCallExpr)),
146 hasDeclaration(cxxMethodDecl(hasAnyName(
147 "::llvm::StringRef::StringRef",
"::llvm::Twine::Twine"))),
154 hasArgument(0, StringCStrCallExpr))),
157 if (!StringParameterFunctions.empty()) {
163 StringParameterFunctions))),
164 forEachArgumentWithParam(StringCStrCallExpr,
171 const auto *Call = Result.Nodes.getNodeAs<CallExpr>(
"call");
172 const auto *Arg = Result.Nodes.getNodeAs<Expr>(
"arg");
173 const auto *Member = Result.Nodes.getNodeAs<MemberExpr>(
"member");
174 bool Arrow = Member->isArrow();
177 std::string ArgText =
179 : tooling::fixit::getText(*Arg, *Result.Context).str();
183 diag(Call->getBeginLoc(),
"redundant call to %0")
184 << Member->getMemberDecl()
185 << FixItHint::CreateReplacement(Call->getSourceRange(), ArgText);
llvm::SmallString< 256U > Name
::clang::DynTypedNode Node
Base class for all clang-tidy checks.
DiagnosticBuilder diag(SourceLocation Loc, StringRef Description, DiagnosticIDs::Level Level=DiagnosticIDs::Warning)
Add a diagnostic with the check's name.
const LangOptions & getLangOpts() const
Returns the language options from the context.
Every ClangTidyCheck reports errors through a DiagnosticsEngine provided by this context.
RedundantStringCStrCheck(StringRef Name, ClangTidyContext *Context)
void registerMatchers(ast_matchers::MatchFinder *Finder) override
Override this to register AST matchers with Finder.
void check(const ast_matchers::MatchFinder::MatchResult &Result) override
ClangTidyChecks that register ASTMatchers should do the actual work in here.
inline ::clang::ast_matchers::internal::Matcher< NamedDecl > matchesAnyListedName(llvm::ArrayRef< StringRef > NameList)
AST_MATCHER(CXXMethodDecl, isStatic)
std::string formatDereference(const Expr &ExprNode, const ASTContext &Context)