1 //===- RedundantStringInitCheck.cpp - clang-tidy ----------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "RedundantStringInitCheck.h"
11 #include "clang/ASTMatchers/ASTMatchers.h"
12 
13 using namespace clang::ast_matchers;
14 
15 namespace clang {
16 namespace tidy {
17 namespace readability {
18 
19 namespace {
20 
21 AST_MATCHER(StringLiteral, lengthIsZero) { return Node.getLength() == 0; }
22 
23 } // namespace
24 
25 void RedundantStringInitCheck::registerMatchers(MatchFinder *Finder) {
26   if (!getLangOpts().CPlusPlus)
27     return;
28 
29   const auto StringCtorExpr = cxxConstructExpr(
30       hasDeclaration(cxxMethodDecl(hasName("basic_string"))),
31       argumentCountIs(2),
32       hasArgument(0, ignoringParenImpCasts(stringLiteral(lengthIsZero()))),
33       hasArgument(1, cxxDefaultArgExpr()));
34 
35   // string foo = "";
36   // OR
37   // string bar("");
38   Finder->addMatcher(
39       namedDecl(varDecl(hasType(cxxRecordDecl(hasName("basic_string"))),
40                         hasInitializer(
41                             expr(anyOf(StringCtorExpr,
42                                        exprWithCleanups(has(expr(anyOf(
43                                            StringCtorExpr,
44                                            cxxConstructExpr(hasArgument(
45                                                0, cxxBindTemporaryExpr(has(
46                                                       StringCtorExpr))))))))))
47                                 .bind("expr"))))
48           .bind("decl"),
49       this);
50 }
51 
52 void RedundantStringInitCheck::check(const MatchFinder::MatchResult &Result) {
53   const auto *CtorExpr = Result.Nodes.getNodeAs<Expr>("expr");
54   const auto *Decl = Result.Nodes.getNodeAs<NamedDecl>("decl");
55   diag(CtorExpr->getExprLoc(), "redundant string initialization")
56       << FixItHint::CreateReplacement(CtorExpr->getSourceRange(),
57                                       Decl->getName());
58 }
59 
60 } // namespace readability
61 } // namespace tidy
62 } // namespace clang
63