blob: 46ce2a47b038127f90b3a0a695e6df740f7ba50e [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(
Manuel Klimek7b9c1172017-08-02 13:13:11 +000050 varDecl(hasType(hasUnqualifiedDesugaredType(recordType(
51 hasDeclaration(cxxRecordDecl(hasName("basic_string")))))),
Tim Shen325c7272016-06-21 20:11:20 +000052 hasInitializer(expr(ignoringImplicit(anyOf(
53 EmptyStringCtorExpr,
54 EmptyStringCtorExprWithTemporaries)))
55 .bind("expr"))),
56 unless(parmVarDecl()))
Alexander Kornienko1612fa02016-02-25 23:57:23 +000057 .bind("decl"),
58 this);
59}
60
61void 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