[clang-tidy] Fix redundant-string-init check with msvc 14 headers.
Summary:
The string constructors are not defined using optional parameters and are not recognized by the redundant-string-init checker.
The following patch fixes the redundant-string-init checker for the Visual Studio 14 headers file.
The matcher now accept both variant (with 1 and 2 parameters).
Also added new unittests.
Similar issue than: [[ http://reviews.llvm.org/D18285 | review ]]
In the xstring.h header, the constructors are defined this way:
```
basic_string(const _Myt& _Right) [...]
basic_string(const _Myt& _Right, const _Alloc& _Al) [...]
```
Reviewers: alexfh, hokein
Subscribers: cfe-commits
Differential Revision: http://reviews.llvm.org/D18293
llvm-svn: 264069
diff --git a/clang-tools-extra/clang-tidy/readability/RedundantStringInitCheck.cpp b/clang-tools-extra/clang-tidy/readability/RedundantStringInitCheck.cpp
index ad6c2cd..d49c55e 100644
--- a/clang-tools-extra/clang-tidy/readability/RedundantStringInitCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/RedundantStringInitCheck.cpp
@@ -20,31 +20,48 @@
AST_MATCHER(StringLiteral, lengthIsZero) { return Node.getLength() == 0; }
+AST_MATCHER_P(Expr, ignoringImplicit,
+ ast_matchers::internal::Matcher<Expr>, InnerMatcher) {
+ return InnerMatcher.matches(*Node.IgnoreImplicit(), Finder, Builder);
+}
+
} // namespace
void RedundantStringInitCheck::registerMatchers(MatchFinder *Finder) {
if (!getLangOpts().CPlusPlus)
return;
- const auto StringCtorExpr = cxxConstructExpr(
- hasDeclaration(cxxMethodDecl(hasName("basic_string"))),
- argumentCountIs(2),
- hasArgument(0, ignoringParenImpCasts(stringLiteral(lengthIsZero()))),
- hasArgument(1, cxxDefaultArgExpr()));
+ // Match string constructor.
+ const auto StringConstructorExpr = expr(anyOf(
+ cxxConstructExpr(argumentCountIs(1),
+ hasDeclaration(cxxMethodDecl(hasName("basic_string")))),
+ // If present, the second argument is the alloc object which must not
+ // be present explicitly.
+ cxxConstructExpr(argumentCountIs(2),
+ hasDeclaration(cxxMethodDecl(hasName("basic_string"))),
+ hasArgument(1, cxxDefaultArgExpr()))));
- // string foo = "";
- // OR
- // string bar("");
+ // Match a string constructor expression with an empty string literal.
+ const auto EmptyStringCtorExpr =
+ cxxConstructExpr(StringConstructorExpr,
+ hasArgument(0, ignoringParenImpCasts(
+ stringLiteral(lengthIsZero()))));
+
+ const auto EmptyStringCtorExprWithTemporaries =
+ expr(ignoringImplicit(
+ cxxConstructExpr(StringConstructorExpr,
+ hasArgument(0, ignoringImplicit(EmptyStringCtorExpr)))));
+
+ // Match a variable declaration with an empty string literal as initializer.
+ // Examples:
+ // string foo = "";
+ // string bar("");
Finder->addMatcher(
namedDecl(varDecl(hasType(cxxRecordDecl(hasName("basic_string"))),
hasInitializer(
- expr(anyOf(StringCtorExpr,
- exprWithCleanups(has(expr(anyOf(
- StringCtorExpr,
- cxxConstructExpr(hasArgument(
- 0, cxxBindTemporaryExpr(has(
- StringCtorExpr))))))))))
- .bind("expr"))))
+ expr(anyOf(EmptyStringCtorExpr,
+ EmptyStringCtorExprWithTemporaries))
+ .bind("expr"))))
.bind("decl"),
this);
}