blob: b881e226e9cb50fdf721d56959400b4e55dbcdbe [file] [log] [blame]
Alexander Kornienko1612fa02016-02-25 23:57:23 +00001//===- 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"
Etienne Bergerone15ef2f2016-05-17 19:36:09 +000011#include "../utils/Matchers.h"
Alexander Kornienko1612fa02016-02-25 23:57:23 +000012#include "clang/ASTMatchers/ASTMatchers.h"
13
14using namespace clang::ast_matchers;
Etienne Bergerone15ef2f2016-05-17 19:36:09 +000015using namespace clang::tidy::matchers;
Alexander Kornienko1612fa02016-02-25 23:57:23 +000016
17namespace clang {
18namespace tidy {
19namespace readability {
20
Alexander Kornienko1612fa02016-02-25 23:57:23 +000021void RedundantStringInitCheck::registerMatchers(MatchFinder *Finder) {
22 if (!getLangOpts().CPlusPlus)
23 return;
24
Etienne Bergeron1329b982016-03-22 17:39:36 +000025 // 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()))));
Alexander Kornienko1612fa02016-02-25 23:57:23 +000034
Etienne Bergeron1329b982016-03-22 17:39:36 +000035 // Match a string constructor expression with an empty string literal.
Mandeep Singh Grang7c7ea7d2016-11-08 07:50:19 +000036 const auto EmptyStringCtorExpr = cxxConstructExpr(
37 StringConstructorExpr,
38 hasArgument(0, ignoringParenImpCasts(stringLiteral(hasSize(0)))));
Etienne Bergeron1329b982016-03-22 17:39:36 +000039
40 const auto EmptyStringCtorExprWithTemporaries =
Tim Shen325c7272016-06-21 20:11:20 +000041 cxxConstructExpr(StringConstructorExpr,
42 hasArgument(0, ignoringImplicit(EmptyStringCtorExpr)));
Etienne Bergeron1329b982016-03-22 17:39:36 +000043
44 // Match a variable declaration with an empty string literal as initializer.
45 // Examples:
46 // string foo = "";
47 // string bar("");
Alexander Kornienko1612fa02016-02-25 23:57:23 +000048 Finder->addMatcher(
Tim Shen325c7272016-06-21 20:11:20 +000049 namedDecl(
50 varDecl(hasType(cxxRecordDecl(hasName("basic_string"))),
51 hasInitializer(expr(ignoringImplicit(anyOf(
52 EmptyStringCtorExpr,
53 EmptyStringCtorExprWithTemporaries)))
54 .bind("expr"))),
55 unless(parmVarDecl()))
Alexander Kornienko1612fa02016-02-25 23:57:23 +000056 .bind("decl"),
57 this);
58}
59
60void RedundantStringInitCheck::check(const MatchFinder::MatchResult &Result) {
61 const auto *CtorExpr = Result.Nodes.getNodeAs<Expr>("expr");
62 const auto *Decl = Result.Nodes.getNodeAs<NamedDecl>("decl");
63 diag(CtorExpr->getExprLoc(), "redundant string initialization")
64 << FixItHint::CreateReplacement(CtorExpr->getSourceRange(),
65 Decl->getName());
66}
67
68} // namespace readability
69} // namespace tidy
70} // namespace clang