15 #include "clang/Lex/Lexer.h" 16 #include "clang/Tooling/FixIt.h" 22 namespace readability {
29 bool needParensAfterUnaryOperator(
const Expr &ExprNode) {
30 if (isa<clang::BinaryOperator>(&ExprNode) ||
31 isa<clang::ConditionalOperator>(&ExprNode)) {
34 if (
const auto *Op = dyn_cast<CXXOperatorCallExpr>(&ExprNode)) {
35 return Op->getNumArgs() == 2 && Op->getOperator() != OO_PlusPlus &&
36 Op->getOperator() != OO_MinusMinus && Op->getOperator() != OO_Call &&
37 Op->getOperator() != OO_Subscript;
45 formatDereference(
const ast_matchers::MatchFinder::MatchResult &
Result,
46 const Expr &ExprNode) {
47 if (
const auto *Op = dyn_cast<clang::UnaryOperator>(&ExprNode)) {
48 if (Op->getOpcode() == UO_AddrOf) {
50 return tooling::fixit::getText(*Op->getSubExpr()->IgnoreParens(),
54 StringRef
Text = tooling::fixit::getText(ExprNode, *Result.Context);
59 if (needParensAfterUnaryOperator(ExprNode)) {
60 return (llvm::Twine(
"*(") + Text +
")").str();
62 return (llvm::Twine(
"*") + Text).str();
67 void RedundantStringCStrCheck::registerMatchers(
68 ast_matchers::MatchFinder *Finder) {
71 if (!getLangOpts().CPlusPlus)
75 const auto StringDecl = type(hasUnqualifiedDesugaredType(recordType(
76 hasDeclaration(cxxRecordDecl(hasName(
"::std::basic_string"))))));
77 const auto StringExpr =
78 expr(anyOf(hasType(StringDecl), hasType(qualType(pointsTo(StringDecl)))));
81 const auto StringConstructorExpr = expr(anyOf(
82 cxxConstructExpr(argumentCountIs(1),
83 hasDeclaration(cxxMethodDecl(hasName(
"basic_string")))),
86 hasDeclaration(cxxMethodDecl(hasName(
"basic_string"))),
89 hasArgument(1, cxxDefaultArgExpr()))));
92 const auto StringCStrCallExpr =
93 cxxMemberCallExpr(on(StringExpr.bind(
"arg")),
94 callee(memberExpr().bind(
"member")),
95 callee(cxxMethodDecl(hasAnyName(
"c_str",
"data"))))
99 Finder->addMatcher(cxxConstructExpr(StringConstructorExpr,
100 hasArgument(0, StringCStrCallExpr)),
107 hasOverloadedOperatorName(
"<"), hasOverloadedOperatorName(
">"),
108 hasOverloadedOperatorName(
">="), hasOverloadedOperatorName(
"<="),
109 hasOverloadedOperatorName(
"!="), hasOverloadedOperatorName(
"=="),
110 hasOverloadedOperatorName(
"+")),
111 anyOf(allOf(hasArgument(0, StringExpr),
112 hasArgument(1, StringCStrCallExpr)),
113 allOf(hasArgument(0, StringCStrCallExpr),
114 hasArgument(1, StringExpr)))),
119 Finder->addMatcher(cxxOperatorCallExpr(anyOf(hasOverloadedOperatorName(
"="),
120 hasOverloadedOperatorName(
"+=")),
121 hasArgument(0, StringExpr),
122 hasArgument(1, StringCStrCallExpr)),
127 cxxMemberCallExpr(on(StringExpr), callee(decl(cxxMethodDecl(hasAnyName(
128 "append",
"assign",
"compare")))),
129 argumentCountIs(1), hasArgument(0, StringCStrCallExpr)),
134 cxxMemberCallExpr(on(StringExpr),
135 callee(decl(cxxMethodDecl(hasName(
"compare")))),
136 argumentCountIs(3), hasArgument(2, StringCStrCallExpr)),
141 cxxMemberCallExpr(on(StringExpr),
142 callee(decl(cxxMethodDecl(hasAnyName(
143 "find",
"find_first_not_of",
"find_first_of",
144 "find_last_not_of",
"find_last_of",
"rfind")))),
145 anyOf(argumentCountIs(1), argumentCountIs(2)),
146 hasArgument(0, StringCStrCallExpr)),
151 cxxMemberCallExpr(on(StringExpr),
152 callee(decl(cxxMethodDecl(hasName(
"insert")))),
153 argumentCountIs(2), hasArgument(1, StringCStrCallExpr)),
163 hasDeclaration(cxxMethodDecl(hasAnyName(
164 "::llvm::StringRef::StringRef",
"::llvm::Twine::Twine"))),
171 hasArgument(0, StringCStrCallExpr)),
175 void RedundantStringCStrCheck::check(
const MatchFinder::MatchResult &Result) {
176 const auto *Call = Result.Nodes.getNodeAs<CallExpr>(
"call");
177 const auto *Arg = Result.Nodes.getNodeAs<Expr>(
"arg");
178 const auto *Member = Result.Nodes.getNodeAs<MemberExpr>(
"member");
179 bool Arrow = Member->isArrow();
182 std::string ArgText =
183 Arrow ? formatDereference(Result, *Arg)
184 : tooling::fixit::getText(*Arg, *Result.Context).str();
188 diag(Call->getBeginLoc(),
"redundant call to %0")
189 << Member->getMemberDecl()
190 << FixItHint::CreateReplacement(Call->getSourceRange(), ArgText);
llvm::Optional< llvm::Expected< tooling::AtomicChanges > > Result
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//