15 #include "clang/Lex/Lexer.h" 21 namespace readability {
26 StringRef getText(
const ast_matchers::MatchFinder::MatchResult &Result,
28 return Lexer::getSourceText(
29 CharSourceRange::getTokenRange(Node.getSourceRange()),
30 *Result.SourceManager, Result.Context->getLangOpts());
36 bool needParensAfterUnaryOperator(
const Expr &ExprNode) {
37 if (isa<clang::BinaryOperator>(&ExprNode) ||
38 isa<clang::ConditionalOperator>(&ExprNode)) {
41 if (
const auto *Op = dyn_cast<CXXOperatorCallExpr>(&ExprNode)) {
42 return Op->getNumArgs() == 2 && Op->getOperator() != OO_PlusPlus &&
43 Op->getOperator() != OO_MinusMinus && Op->getOperator() != OO_Call &&
44 Op->getOperator() != OO_Subscript;
52 formatDereference(
const ast_matchers::MatchFinder::MatchResult &Result,
53 const Expr &ExprNode) {
54 if (
const auto *Op = dyn_cast<clang::UnaryOperator>(&ExprNode)) {
55 if (Op->getOpcode() == UO_AddrOf) {
57 return getText(Result, *Op->getSubExpr()->IgnoreParens());
60 StringRef
Text = getText(Result, ExprNode);
64 if (needParensAfterUnaryOperator(ExprNode)) {
65 return (llvm::Twine(
"*(") + Text +
")").str();
67 return (llvm::Twine(
"*") + Text).str();
72 void RedundantStringCStrCheck::registerMatchers(
73 ast_matchers::MatchFinder *Finder) {
76 if (!getLangOpts().CPlusPlus)
80 const auto StringDecl = type(hasUnqualifiedDesugaredType(recordType(
81 hasDeclaration(cxxRecordDecl(hasName(
"::std::basic_string"))))));
82 const auto StringExpr =
83 expr(anyOf(hasType(StringDecl), hasType(qualType(pointsTo(StringDecl)))));
86 const auto StringConstructorExpr = expr(anyOf(
87 cxxConstructExpr(argumentCountIs(1),
88 hasDeclaration(cxxMethodDecl(hasName(
"basic_string")))),
91 hasDeclaration(cxxMethodDecl(hasName(
"basic_string"))),
94 hasArgument(1, cxxDefaultArgExpr()))));
97 const auto StringCStrCallExpr =
98 cxxMemberCallExpr(on(StringExpr.bind(
"arg")),
99 callee(memberExpr().bind(
"member")),
100 callee(cxxMethodDecl(hasAnyName(
"c_str",
"data"))))
104 Finder->addMatcher(cxxConstructExpr(StringConstructorExpr,
105 hasArgument(0, StringCStrCallExpr)),
112 hasOverloadedOperatorName(
"<"), hasOverloadedOperatorName(
">"),
113 hasOverloadedOperatorName(
">="), hasOverloadedOperatorName(
"<="),
114 hasOverloadedOperatorName(
"!="), hasOverloadedOperatorName(
"=="),
115 hasOverloadedOperatorName(
"+")),
116 anyOf(allOf(hasArgument(0, StringExpr),
117 hasArgument(1, StringCStrCallExpr)),
118 allOf(hasArgument(0, StringCStrCallExpr),
119 hasArgument(1, StringExpr)))),
124 Finder->addMatcher(cxxOperatorCallExpr(anyOf(hasOverloadedOperatorName(
"="),
125 hasOverloadedOperatorName(
"+=")),
126 hasArgument(0, StringExpr),
127 hasArgument(1, StringCStrCallExpr)),
132 cxxMemberCallExpr(on(StringExpr), callee(decl(cxxMethodDecl(hasAnyName(
133 "append",
"assign",
"compare")))),
134 argumentCountIs(1), hasArgument(0, StringCStrCallExpr)),
139 cxxMemberCallExpr(on(StringExpr),
140 callee(decl(cxxMethodDecl(hasName(
"compare")))),
141 argumentCountIs(3), hasArgument(2, StringCStrCallExpr)),
146 cxxMemberCallExpr(on(StringExpr),
147 callee(decl(cxxMethodDecl(hasAnyName(
148 "find",
"find_first_not_of",
"find_first_of",
149 "find_last_not_of",
"find_last_of",
"rfind")))),
150 anyOf(argumentCountIs(1), argumentCountIs(2)),
151 hasArgument(0, StringCStrCallExpr)),
156 cxxMemberCallExpr(on(StringExpr),
157 callee(decl(cxxMethodDecl(hasName(
"insert")))),
158 argumentCountIs(2), hasArgument(1, StringCStrCallExpr)),
168 hasDeclaration(cxxMethodDecl(hasAnyName(
169 "::llvm::StringRef::StringRef",
"::llvm::Twine::Twine"))),
176 hasArgument(0, StringCStrCallExpr)),
180 void RedundantStringCStrCheck::check(
const MatchFinder::MatchResult &Result) {
181 const auto *Call = Result.Nodes.getNodeAs<CallExpr>(
"call");
182 const auto *Arg = Result.Nodes.getNodeAs<Expr>(
"arg");
183 const auto *Member = Result.Nodes.getNodeAs<MemberExpr>(
"member");
184 bool Arrow = Member->isArrow();
187 std::string ArgText =
188 Arrow ? formatDereference(Result, *Arg) : getText(Result, *Arg).str();
192 diag(Call->getLocStart(),
"redundant call to %0")
193 << Member->getMemberDecl()
194 << FixItHint::CreateReplacement(Call->getSourceRange(), ArgText);
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//