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