Skip to content

Commit

Permalink
[clang-tidy] Handle data() in readability-redundant-string-cstr
Browse files Browse the repository at this point in the history
Summary:
std::string::data() and std::string::c_str() are equivalent.
Enhance the readability-redundant-string-cstr check to also handle
calls to data().

Reviewers: etienneb, alexfh, aaron.ballman

Subscribers: cfe-commits

Differential Revision: https://reviews.llvm.org/D26279

llvm-svn: 285901
  • Loading branch information
pepsiman committed Nov 3, 2016
1 parent a705ab1 commit 8b70e26
Show file tree
Hide file tree
Showing 5 changed files with 24 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ void RedundantStringCStrCheck::registerMatchers(
const auto StringCStrCallExpr =
cxxMemberCallExpr(on(StringExpr.bind("arg")),
callee(memberExpr().bind("member")),
callee(cxxMethodDecl(hasName("c_str"))))
callee(cxxMethodDecl(hasAnyName("c_str", "data"))))
.bind("call");

// Detect redundant 'c_str()' calls through a string constructor.
Expand Down Expand Up @@ -192,15 +192,17 @@ void RedundantStringCStrCheck::registerMatchers(
void RedundantStringCStrCheck::check(const MatchFinder::MatchResult &Result) {
const auto *Call = Result.Nodes.getStmtAs<CallExpr>("call");
const auto *Arg = Result.Nodes.getStmtAs<Expr>("arg");
bool Arrow = Result.Nodes.getStmtAs<MemberExpr>("member")->isArrow();
const auto *Member = Result.Nodes.getStmtAs<MemberExpr>("member");
bool Arrow = Member->isArrow();
// Replace the "call" node with the "arg" node, prefixed with '*'
// if the call was using '->' rather than '.'.
std::string ArgText =
Arrow ? formatDereference(Result, *Arg) : getText(Result, *Arg).str();
if (ArgText.empty())
return;

diag(Call->getLocStart(), "redundant call to `c_str()`")
diag(Call->getLocStart(), "redundant call to %0")
<< Member->getMemberDecl()
<< FixItHint::CreateReplacement(Call->getSourceRange(), ArgText);
}

Expand Down
4 changes: 4 additions & 0 deletions clang-tools-extra/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,10 @@ Improvements to clang-tidy
Flags member initializations that are unnecessary because the same default
constructor would be called if they were not present.

- The `readability-redundant-string-cstr
<http://clang.llvm.org/extra/clang-tidy/checks/readability-redundant-string-cstr.html>`_ check
now warns about redundant calls to data() too.

Fixed bugs:

- `modernize-make-unique
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ readability-redundant-string-cstr
=================================


Finds unnecessary calls to ``std::string::c_str()``.
Finds unnecessary calls to ``std::string::c_str()`` and ``std::string::data()``.
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ struct basic_string {
basic_string(const C *p);
basic_string(const C *p, const A &a);
const C *c_str() const;
const C *data() const;
};
typedef basic_string<char, std::char_traits<char>, std::allocator<char>> string;
}
Expand All @@ -24,7 +25,10 @@ struct StringRef {

void f1(const std::string &s) {
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]
// CHECK-FIXES: {{^ }}f1(s);{{$}}
f1(s.data());
// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: redundant call to 'data' [readability-redundant-string-cstr]
// CHECK-FIXES: {{^ }}f1(s);{{$}}
}
void f2(const llvm::StringRef r) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ struct basic_string {
basic_string(const C *p, const A &a = A());

const C *c_str() const;
const C *data() const;

_Type& append(const C *s);
_Type& append(const C *s, size n);
Expand Down Expand Up @@ -66,7 +67,10 @@ struct StringRef {

void f1(const std::string &s) {
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]
// CHECK-FIXES: {{^ }}f1(s);{{$}}
f1(s.data());
// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: redundant call to 'data' [readability-redundant-string-cstr]
// CHECK-FIXES: {{^ }}f1(s);{{$}}
}
void f2(const llvm::StringRef r) {
Expand All @@ -86,7 +90,7 @@ void f3(const llvm::StringRef &r) {
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-MESSAGES: :[[@LINE-1]]:6: warning: redundant call to 'c_str' [readability-redundant-string-cstr]
// CHECK-FIXES: {{^ }}f1(*ptr);{{$}}
}
void f5(const std::string &s) {
Expand Down Expand Up @@ -168,23 +172,23 @@ void f6(const std::string &s) {

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-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-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-MESSAGES: :[[@LINE-1]]:6: warning: redundant call to 'c_str' [readability-redundant-string-cstr]
// CHECK-FIXES: {{^ }}k1(s);{{$}}
}

Expand Down

0 comments on commit 8b70e26

Please sign in to comment.