mikecrowe updated this revision to Diff 494937.
mikecrowe added a comment.

carlosgalvezp wrote:

> Please document change in Release Notes, as well as in the check 
> documentation, together with its limitations (can only handle 1 argument at a 
> time).

Hopefully I've done those things.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D143342/new/

https://reviews.llvm.org/D143342

Files:
  clang-tools-extra/clang-tidy/readability/RedundantStringCStrCheck.cpp
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/readability/redundant-string-cstr.rst
  
clang-tools-extra/test/clang-tidy/checkers/readability/redundant-string-cstr.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/readability/redundant-string-cstr.cpp
===================================================================
--- clang-tools-extra/test/clang-tidy/checkers/readability/redundant-string-cstr.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/readability/redundant-string-cstr.cpp
@@ -291,3 +291,59 @@
   Foo.func2((Str.c_str()));
 }
 } // namespace PR45286
+
+namespace std {
+  template<typename ...Args>
+  void print(const char *, Args &&...);
+  template<typename ...Args>
+  std::string format(const char *, Args &&...);
+}
+
+namespace notstd {
+  template<typename ...Args>
+  void print(const char *, Args &&...);
+  template<typename ...Args>
+  std::string format(const char *, Args &&...);
+}
+
+void std_print(const std::string &s1, const std::string &s2, const std::string &s3) {
+  std::print("One:{}\n", s1.c_str());
+  // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: redundant call to 'c_str' [readability-redundant-string-cstr]
+  // CHECK-FIXES: {{^  }}std::print("One:{}\n", s1);
+
+  // Ideally we'd fix both the second and fourth parameters here, but that doesn't work.
+  std::print("One:{} Two:{} Three:{}\n", s1.c_str(), s2, s3.c_str());
+  // CHECK-MESSAGES: :[[@LINE-1]]:42: warning: redundant call to 'c_str' [readability-redundant-string-cstr]
+  // CHECK-FIXES: {{^  }}std::print("One:{} Two:{} Three:{}\n", s1, s2, s3.c_str());
+}
+
+// There's no c_str() call here, so it shouldn't be touched.
+void std_print_no_cstr(const std::string &s1, const std::string &s2) {
+  std::print("One: {}, Two: {}\n", s1, s2);
+}
+
+// This isn't std::print, so it shouldn't be fixed.
+void not_std_print(const std::string &s1) {
+  notstd::print("One: {}\n", s1.c_str());
+}
+
+void std_format(const std::string &s1, const std::string &s2, const std::string &s3) {
+  auto r1 = std::format("One:{}\n", s1.c_str());
+  // CHECK-MESSAGES: :[[@LINE-1]]:37: warning: redundant call to 'c_str' [readability-redundant-string-cstr]
+  // CHECK-FIXES: {{^  }}auto r1 = std::format("One:{}\n", s1);
+
+  // Ideally we'd fix both the second and fourth parameters here, but that doesn't work.
+  auto r2 = std::format("One:{} Two:{} Three:{}\n", s1.c_str(), s2, s3.c_str());
+  // CHECK-MESSAGES: :[[@LINE-1]]:53: warning: redundant call to 'c_str' [readability-redundant-string-cstr]
+  // CHECK-FIXES: {{^  }}auto r2 = std::format("One:{} Two:{} Three:{}\n", s1, s2, s3.c_str());
+}
+
+// There's are c_str() calls here, so it shouldn't be touched.
+std::string std_format_no_cstr(const std::string &s1, const std::string &s2) {
+  return std::format("One: {}, Two: {}\n", s1, s2);
+}
+
+// This is not std::format, so it shouldn't be fixed.
+std::string not_std_format(const std::string &s1) {
+  return notstd::format("One: {}\n", s1.c_str());
+}
Index: clang-tools-extra/docs/clang-tidy/checks/readability/redundant-string-cstr.rst
===================================================================
--- clang-tools-extra/docs/clang-tidy/checks/readability/redundant-string-cstr.rst
+++ clang-tools-extra/docs/clang-tidy/checks/readability/redundant-string-cstr.rst
@@ -5,3 +5,7 @@
 
 
 Finds unnecessary calls to ``std::string::c_str()`` and ``std::string::data()``.
+
+Only the first such call in an argument to ``std::print`` or
+``std::format`` will be detected, so it may be necessary to run the check
+more than once when applying fixes.
Index: clang-tools-extra/docs/ReleaseNotes.rst
===================================================================
--- clang-tools-extra/docs/ReleaseNotes.rst
+++ clang-tools-extra/docs/ReleaseNotes.rst
@@ -123,6 +123,12 @@
 
 Changes in existing checks
 ^^^^^^^^^^^^^^^^^^^^^^^^^^
+- Improved :doc:`readability-redundant-string-cstr
+  <clang-tidy/checks/readability/redundant-string-cstr>` check to recognise
+  unnecessary ``std::string::c_str()`` and ``std::string::data()`` calls in
+  arguments to ``std::print`` and ``std::format``. Note that only the first
+  such argument is currently reported so it may be necessary to run the
+  check multiple times to fix all of them.
 
 Removed checks
 ^^^^^^^^^^^^^^
Index: clang-tools-extra/clang-tidy/readability/RedundantStringCStrCheck.cpp
===================================================================
--- clang-tools-extra/clang-tidy/readability/RedundantStringCStrCheck.cpp
+++ clang-tools-extra/clang-tidy/readability/RedundantStringCStrCheck.cpp
@@ -178,6 +178,16 @@
               // directly.
               hasArgument(0, StringCStrCallExpr))),
       this);
+
+  // Detect the first redundant 'c_str()' call in parameters passed to
+  // std::print and std::format.
+  Finder->addMatcher(
+      traverse(TK_AsIs,
+               callExpr(anyOf(callee(functionDecl(hasName("::std::print"))),
+                              callee(functionDecl(hasName("::std::format")))),
+                        hasAnyArgument(materializeTemporaryExpr(
+                            has(StringCStrCallExpr))))),
+      this);
 }
 
 void RedundantStringCStrCheck::check(const MatchFinder::MatchResult &Result) {
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to