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 "../utils/Matchers.h" 12 #include "clang/ASTMatchers/ASTMatchers.h" 13 14 using namespace clang::ast_matchers; 15 using namespace clang::tidy::matchers; 16 17 namespace clang { 18 namespace tidy { 19 namespace readability { 20 21 void RedundantStringInitCheck::registerMatchers(MatchFinder *Finder) { 22 if (!getLangOpts().CPlusPlus) 23 return; 24 25 // Match string constructor. 26 const auto StringConstructorExpr = expr(anyOf( 27 cxxConstructExpr(argumentCountIs(1), 28 hasDeclaration(cxxMethodDecl(hasName("basic_string")))), 29 // If present, the second argument is the alloc object which must not 30 // be present explicitly. 31 cxxConstructExpr(argumentCountIs(2), 32 hasDeclaration(cxxMethodDecl(hasName("basic_string"))), 33 hasArgument(1, cxxDefaultArgExpr())))); 34 35 // Match a string constructor expression with an empty string literal. 36 const auto EmptyStringCtorExpr = cxxConstructExpr( 37 StringConstructorExpr, 38 hasArgument(0, ignoringParenImpCasts(stringLiteral(hasSize(0))))); 39 40 const auto EmptyStringCtorExprWithTemporaries = 41 cxxConstructExpr(StringConstructorExpr, 42 hasArgument(0, ignoringImplicit(EmptyStringCtorExpr))); 43 44 // Match a variable declaration with an empty string literal as initializer. 45 // Examples: 46 // string foo = ""; 47 // string bar(""); 48 Finder->addMatcher( 49 namedDecl( 50 varDecl(hasType(hasUnqualifiedDesugaredType(recordType( 51 hasDeclaration(cxxRecordDecl(hasName("basic_string")))))), 52 hasInitializer(expr(ignoringImplicit(anyOf( 53 EmptyStringCtorExpr, 54 EmptyStringCtorExprWithTemporaries))) 55 .bind("expr"))), 56 unless(parmVarDecl())) 57 .bind("decl"), 58 this); 59 } 60 61 void RedundantStringInitCheck::check(const MatchFinder::MatchResult &Result) { 62 const auto *CtorExpr = Result.Nodes.getNodeAs<Expr>("expr"); 63 const auto *Decl = Result.Nodes.getNodeAs<NamedDecl>("decl"); 64 diag(CtorExpr->getExprLoc(), "redundant string initialization") 65 << FixItHint::CreateReplacement(CtorExpr->getSourceRange(), 66 Decl->getName()); 67 } 68 69 } // namespace readability 70 } // namespace tidy 71 } // namespace clang 72