14 #include "clang/Lex/Lexer.h" 15 #include "clang/Tooling/FixIt.h" 21 namespace readability {
28 bool needParensAfterUnaryOperator(
const Expr &ExprNode) {
29 if (isa<clang::BinaryOperator>(&ExprNode) ||
30 isa<clang::ConditionalOperator>(&ExprNode)) {
33 if (
const auto *Op = dyn_cast<CXXOperatorCallExpr>(&ExprNode)) {
34 return Op->getNumArgs() == 2 && Op->getOperator() != OO_PlusPlus &&
35 Op->getOperator() != OO_MinusMinus && Op->getOperator() != OO_Call &&
36 Op->getOperator() != OO_Subscript;
44 formatDereference(
const ast_matchers::MatchFinder::MatchResult &
Result,
45 const Expr &ExprNode) {
46 if (
const auto *Op = dyn_cast<clang::UnaryOperator>(&ExprNode)) {
47 if (Op->getOpcode() == UO_AddrOf) {
49 return tooling::fixit::getText(*Op->getSubExpr()->IgnoreParens(),
53 StringRef
Text = tooling::fixit::getText(ExprNode, *Result.Context);
58 if (needParensAfterUnaryOperator(ExprNode)) {
59 return (llvm::Twine(
"*(") + Text +
")").str();
61 return (llvm::Twine(
"*") + Text).str();
66 void RedundantStringCStrCheck::registerMatchers(
67 ast_matchers::MatchFinder *Finder) {
70 if (!getLangOpts().CPlusPlus)
74 const auto StringDecl = type(hasUnqualifiedDesugaredType(recordType(
75 hasDeclaration(cxxRecordDecl(hasName(
"::std::basic_string"))))));
76 const auto StringExpr =
77 expr(anyOf(hasType(StringDecl), hasType(qualType(pointsTo(StringDecl)))));
80 const auto StringConstructorExpr = expr(anyOf(
81 cxxConstructExpr(argumentCountIs(1),
82 hasDeclaration(cxxMethodDecl(hasName(
"basic_string")))),
85 hasDeclaration(cxxMethodDecl(hasName(
"basic_string"))),
88 hasArgument(1, cxxDefaultArgExpr()))));
91 const auto StringCStrCallExpr =
92 cxxMemberCallExpr(on(StringExpr.bind(
"arg")),
93 callee(memberExpr().bind(
"member")),
94 callee(cxxMethodDecl(hasAnyName(
"c_str",
"data"))))
98 Finder->addMatcher(cxxConstructExpr(StringConstructorExpr,
99 hasArgument(0, StringCStrCallExpr)),
106 hasOverloadedOperatorName(
"<"), hasOverloadedOperatorName(
">"),
107 hasOverloadedOperatorName(
">="), hasOverloadedOperatorName(
"<="),
108 hasOverloadedOperatorName(
"!="), hasOverloadedOperatorName(
"=="),
109 hasOverloadedOperatorName(
"+")),
110 anyOf(allOf(hasArgument(0, StringExpr),
111 hasArgument(1, StringCStrCallExpr)),
112 allOf(hasArgument(0, StringCStrCallExpr),
113 hasArgument(1, StringExpr)))),
118 Finder->addMatcher(cxxOperatorCallExpr(anyOf(hasOverloadedOperatorName(
"="),
119 hasOverloadedOperatorName(
"+=")),
120 hasArgument(0, StringExpr),
121 hasArgument(1, StringCStrCallExpr)),
126 cxxMemberCallExpr(on(StringExpr), callee(decl(cxxMethodDecl(hasAnyName(
127 "append",
"assign",
"compare")))),
128 argumentCountIs(1), hasArgument(0, StringCStrCallExpr)),
133 cxxMemberCallExpr(on(StringExpr),
134 callee(decl(cxxMethodDecl(hasName(
"compare")))),
135 argumentCountIs(3), hasArgument(2, StringCStrCallExpr)),
140 cxxMemberCallExpr(on(StringExpr),
141 callee(decl(cxxMethodDecl(hasAnyName(
142 "find",
"find_first_not_of",
"find_first_of",
143 "find_last_not_of",
"find_last_of",
"rfind")))),
144 anyOf(argumentCountIs(1), argumentCountIs(2)),
145 hasArgument(0, StringCStrCallExpr)),
150 cxxMemberCallExpr(on(StringExpr),
151 callee(decl(cxxMethodDecl(hasName(
"insert")))),
152 argumentCountIs(2), hasArgument(1, StringCStrCallExpr)),
162 hasDeclaration(cxxMethodDecl(hasAnyName(
163 "::llvm::StringRef::StringRef",
"::llvm::Twine::Twine"))),
170 hasArgument(0, StringCStrCallExpr)),
174 void RedundantStringCStrCheck::check(
const MatchFinder::MatchResult &Result) {
175 const auto *Call = Result.Nodes.getNodeAs<CallExpr>(
"call");
176 const auto *Arg = Result.Nodes.getNodeAs<Expr>(
"arg");
177 const auto *Member = Result.Nodes.getNodeAs<MemberExpr>(
"member");
178 bool Arrow = Member->isArrow();
181 std::string ArgText =
182 Arrow ? formatDereference(Result, *Arg)
183 : tooling::fixit::getText(*Arg, *Result.Context).str();
187 diag(Call->getBeginLoc(),
"redundant call to %0")
188 << Member->getMemberDecl()
189 << FixItHint::CreateReplacement(Call->getSourceRange(), ArgText);
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
llvm::Optional< llvm::Expected< tooling::AtomicChanges > > Result