blob: 9a9a3830201b5cc58da1b92a3b9116f069cde8cb [file] [log] [blame]
Alexander Kornienko1612fa02016-02-25 23:57:23 +00001//===- RedundantStringInitCheck.cpp - clang-tidy ----------------*- C++ -*-===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Alexander Kornienko1612fa02016-02-25 23:57:23 +00006//
7//===----------------------------------------------------------------------===//
8
9#include "RedundantStringInitCheck.h"
Etienne Bergerone15ef2f2016-05-17 19:36:09 +000010#include "../utils/Matchers.h"
Alexander Kornienko1612fa02016-02-25 23:57:23 +000011#include "clang/ASTMatchers/ASTMatchers.h"
12
13using namespace clang::ast_matchers;
Etienne Bergerone15ef2f2016-05-17 19:36:09 +000014using namespace clang::tidy::matchers;
Alexander Kornienko1612fa02016-02-25 23:57:23 +000015
16namespace clang {
17namespace tidy {
18namespace readability {
19
Alexander Kornienko1612fa02016-02-25 23:57:23 +000020void RedundantStringInitCheck::registerMatchers(MatchFinder *Finder) {
21 if (!getLangOpts().CPlusPlus)
22 return;
23
Etienne Bergeron1329b982016-03-22 17:39:36 +000024 // Match string constructor.
25 const auto StringConstructorExpr = expr(anyOf(
26 cxxConstructExpr(argumentCountIs(1),
27 hasDeclaration(cxxMethodDecl(hasName("basic_string")))),
28 // If present, the second argument is the alloc object which must not
29 // be present explicitly.
30 cxxConstructExpr(argumentCountIs(2),
31 hasDeclaration(cxxMethodDecl(hasName("basic_string"))),
32 hasArgument(1, cxxDefaultArgExpr()))));
Alexander Kornienko1612fa02016-02-25 23:57:23 +000033
Etienne Bergeron1329b982016-03-22 17:39:36 +000034 // Match a string constructor expression with an empty string literal.
Mandeep Singh Grang7c7ea7d2016-11-08 07:50:19 +000035 const auto EmptyStringCtorExpr = cxxConstructExpr(
36 StringConstructorExpr,
37 hasArgument(0, ignoringParenImpCasts(stringLiteral(hasSize(0)))));
Etienne Bergeron1329b982016-03-22 17:39:36 +000038
39 const auto EmptyStringCtorExprWithTemporaries =
Tim Shen325c7272016-06-21 20:11:20 +000040 cxxConstructExpr(StringConstructorExpr,
41 hasArgument(0, ignoringImplicit(EmptyStringCtorExpr)));
Etienne Bergeron1329b982016-03-22 17:39:36 +000042
43 // Match a variable declaration with an empty string literal as initializer.
44 // Examples:
45 // string foo = "";
46 // string bar("");
Alexander Kornienko1612fa02016-02-25 23:57:23 +000047 Finder->addMatcher(
Tim Shen325c7272016-06-21 20:11:20 +000048 namedDecl(
Manuel Klimek7b9c1172017-08-02 13:13:11 +000049 varDecl(hasType(hasUnqualifiedDesugaredType(recordType(
50 hasDeclaration(cxxRecordDecl(hasName("basic_string")))))),
Tim Shen325c7272016-06-21 20:11:20 +000051 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