[clang-tidy] Add support for different char-types for the readability-redundant-string-cstr checker.
Summary: The current checker is able to recognize std::string but does not recognize other string variants. This patch is adding the support for any string defined with basic_string without considering the the underlying char type. The most common variant is: 'std::wstring' based on 'wchar_t'. There are also other string variants added to the standard: u16string, u32string, etc... Reviewers: alexfh Subscribers: mamai, dblaikie, cfe-commits Differential Revision: http://reviews.llvm.org/D18412 git-svn-id: https://llvm.org/svn/llvm-project/clang-tools-extra/trunk@264325 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
df5cd1802d
Коммит
18c46d063a
|
@ -65,14 +65,6 @@ formatDereference(const ast_matchers::MatchFinder::MatchResult &Result,
|
||||||
return (llvm::Twine("*") + Text).str();
|
return (llvm::Twine("*") + Text).str();
|
||||||
}
|
}
|
||||||
|
|
||||||
const char StringConstructor[] =
|
|
||||||
"::std::basic_string<char, std::char_traits<char>, std::allocator<char> >"
|
|
||||||
"::basic_string";
|
|
||||||
|
|
||||||
const char StringCStrMethod[] =
|
|
||||||
"::std::basic_string<char, std::char_traits<char>, std::allocator<char> >"
|
|
||||||
"::c_str";
|
|
||||||
|
|
||||||
} // end namespace
|
} // end namespace
|
||||||
|
|
||||||
namespace tidy {
|
namespace tidy {
|
||||||
|
@ -85,23 +77,31 @@ void RedundantStringCStrCheck::registerMatchers(
|
||||||
if (!getLangOpts().CPlusPlus)
|
if (!getLangOpts().CPlusPlus)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// Match expressions of type 'string' or 'string*'.
|
||||||
|
const auto StringDecl =
|
||||||
|
cxxRecordDecl(hasName("::std::basic_string"));
|
||||||
|
const auto StringExpr =
|
||||||
|
expr(anyOf(hasType(StringDecl),
|
||||||
|
hasType(qualType(pointsTo(StringDecl)))));
|
||||||
|
|
||||||
// Match string constructor.
|
// Match string constructor.
|
||||||
const auto StringConstructorExpr = expr(anyOf(
|
const auto StringConstructorExpr = expr(anyOf(
|
||||||
cxxConstructExpr(
|
cxxConstructExpr(
|
||||||
argumentCountIs(1),
|
argumentCountIs(1),
|
||||||
hasDeclaration(cxxMethodDecl(hasName(StringConstructor)))),
|
hasDeclaration(cxxMethodDecl(hasName("basic_string")))),
|
||||||
cxxConstructExpr(
|
cxxConstructExpr(
|
||||||
argumentCountIs(2),
|
argumentCountIs(2),
|
||||||
hasDeclaration(cxxMethodDecl(hasName(StringConstructor))),
|
hasDeclaration(cxxMethodDecl(hasName("basic_string"))),
|
||||||
// If present, the second argument is the alloc object which must not
|
// If present, the second argument is the alloc object which must not
|
||||||
// be present explicitly.
|
// be present explicitly.
|
||||||
hasArgument(1, cxxDefaultArgExpr()))));
|
hasArgument(1, cxxDefaultArgExpr()))));
|
||||||
|
|
||||||
// Match a call to the string 'c_str()' method.
|
// Match a call to the string 'c_str()' method.
|
||||||
const auto StringCStrCallExpr = cxxMemberCallExpr(
|
const auto StringCStrCallExpr =
|
||||||
callee(memberExpr().bind("member")),
|
cxxMemberCallExpr(on(StringExpr.bind("arg")),
|
||||||
callee(cxxMethodDecl(hasName(StringCStrMethod))),
|
callee(memberExpr().bind("member")),
|
||||||
on(expr().bind("arg"))).bind("call");
|
callee(cxxMethodDecl(hasName("c_str"))))
|
||||||
|
.bind("call");
|
||||||
|
|
||||||
Finder->addMatcher(
|
Finder->addMatcher(
|
||||||
cxxConstructExpr(StringConstructorExpr,
|
cxxConstructExpr(StringConstructorExpr,
|
||||||
|
|
|
@ -12,7 +12,11 @@ struct basic_string {
|
||||||
const C *c_str() const;
|
const C *c_str() const;
|
||||||
};
|
};
|
||||||
typedef basic_string<char, std::char_traits<char>, std::allocator<char>> string;
|
typedef basic_string<char, std::char_traits<char>, std::allocator<char>> string;
|
||||||
|
typedef basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t>> wstring;
|
||||||
|
typedef basic_string<char16_t, std::char_traits<char16_t>, std::allocator<char16_t>> u16string;
|
||||||
|
typedef basic_string<char32_t, std::char_traits<char32_t>, std::allocator<char32_t>> u32string;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
struct StringRef {
|
struct StringRef {
|
||||||
StringRef(const char *p);
|
StringRef(const char *p);
|
||||||
|
@ -20,6 +24,8 @@ struct StringRef {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Tests for std::string.
|
||||||
|
|
||||||
void f1(const std::string &s) {
|
void f1(const std::string &s) {
|
||||||
f1(s.c_str());
|
f1(s.c_str());
|
||||||
// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: redundant call to `c_str()` [readability-redundant-string-cstr]
|
// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: redundant call to `c_str()` [readability-redundant-string-cstr]
|
||||||
|
@ -39,3 +45,47 @@ void f3(const llvm::StringRef &r) {
|
||||||
// CHECK-FIXES: {{^ }}std::string s;{{$}}
|
// CHECK-FIXES: {{^ }}std::string s;{{$}}
|
||||||
// CHECK-FIXES-NEXT: {{^ }}f3(s);{{$}}
|
// CHECK-FIXES-NEXT: {{^ }}f3(s);{{$}}
|
||||||
}
|
}
|
||||||
|
void f4(const std::string &s) {
|
||||||
|
const std::string* ptr = &s;
|
||||||
|
f1(ptr->c_str());
|
||||||
|
// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: redundant call to `c_str()` [readability-redundant-string-cstr]
|
||||||
|
// CHECK-FIXES: {{^ }}f1(*ptr);{{$}}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tests for std::wstring.
|
||||||
|
|
||||||
|
void g1(const std::wstring &s) {
|
||||||
|
g1(s.c_str());
|
||||||
|
// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: redundant call to `c_str()` [readability-redundant-string-cstr]
|
||||||
|
// CHECK-FIXES: {{^ }}g1(s);{{$}}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tests for std::u16string.
|
||||||
|
|
||||||
|
void h1(const std::u16string &s) {
|
||||||
|
h1(s.c_str());
|
||||||
|
// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: redundant call to `c_str()` [readability-redundant-string-cstr]
|
||||||
|
// CHECK-FIXES: {{^ }}h1(s);{{$}}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tests for std::u32string.
|
||||||
|
|
||||||
|
void k1(const std::u32string &s) {
|
||||||
|
k1(s.c_str());
|
||||||
|
// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: redundant call to `c_str()` [readability-redundant-string-cstr]
|
||||||
|
// CHECK-FIXES: {{^ }}k1(s);{{$}}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tests on similar classes that aren't good candidates for this checker.
|
||||||
|
|
||||||
|
struct NotAString {
|
||||||
|
NotAString();
|
||||||
|
NotAString(const NotAString&);
|
||||||
|
const char *c_str() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
void dummy(const char*) {}
|
||||||
|
|
||||||
|
void invalid(const NotAString &s) {
|
||||||
|
dummy(s.c_str());
|
||||||
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче