[PATCH] D154287: [clang-tidy] Add modernize-use-std-format check

2023-08-29 Thread Mike Crowe via Phabricator via cfe-commits
mikecrowe updated this revision to Diff 554486.
mikecrowe edited the summary of this revision.
mikecrowe added a comment.

Fix ReleaseNotes order and remove unnecessary .html from list.rst


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D154287

Files:
  clang-tools-extra/clang-tidy/modernize/CMakeLists.txt
  clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp
  clang-tools-extra/clang-tidy/modernize/UseStdFormatCheck.cpp
  clang-tools-extra/clang-tidy/modernize/UseStdFormatCheck.h
  clang-tools-extra/clang-tidy/modernize/UseStdPrintCheck.cpp
  clang-tools-extra/clang-tidy/utils/FormatStringConverter.cpp
  clang-tools-extra/clang-tidy/utils/FormatStringConverter.h
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  clang-tools-extra/docs/clang-tidy/checks/modernize/use-std-format.rst
  clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-format-custom.cpp
  clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-format-fmt.cpp
  clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-format.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-format.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-format.cpp
@@ -0,0 +1,97 @@
+// RUN: %check_clang_tidy \
+// RUN:   -std=c++20 %s modernize-use-std-format %t -- \
+// RUN:   -config="{CheckOptions: [{key: StrictMode, value: true}]}" \
+// RUN:   -- -isystem %clang_tidy_headers
+// RUN: %check_clang_tidy \
+// RUN:   -std=c++20 %s modernize-use-std-format %t -- \
+// RUN:   -config="{CheckOptions: [{key: StrictMode, value: false}]}" \
+// RUN:   -- -isystem %clang_tidy_headers
+#include 
+// CHECK-FIXES: #include 
+
+namespace absl
+{
+// Use const char * for the format since the real type is hard to mock up.
+template 
+std::string StrFormat(const char *format, const Args&... args);
+} // namespace absl
+
+template 
+struct iterator {
+  T *operator->();
+  T *();
+};
+
+std::string StrFormat_simple() {
+  return absl::StrFormat("Hello");
+  // CHECK-MESSAGES: [[@LINE-1]]:10: warning: use 'std::format' instead of 'StrFormat' [modernize-use-std-format]
+  // CHECK-FIXES: return std::format("Hello");
+}
+
+std::string StrFormat_complex(const char *name, double value) {
+  return absl::StrFormat("'%s'='%f'", name, value);
+  // CHECK-MESSAGES: [[@LINE-1]]:10: warning: use 'std::format' instead of 'StrFormat' [modernize-use-std-format]
+  // CHECK-FIXES: return std::format("'{}'='{:f}'", name, value);
+}
+
+std::string StrFormat_integer_conversions() {
+  return absl::StrFormat("int:%d int:%d char:%c char:%c", 65, 'A', 66, 'B');
+  // CHECK-MESSAGES: [[@LINE-1]]:10: warning: use 'std::format' instead of 'StrFormat' [modernize-use-std-format]
+  // CHECK-FIXES: return std::format("int:{} int:{:d} char:{:c} char:{}", 65, 'A', 66, 'B');
+}
+
+// FormatConverter is capable of removing newlines from the end of the format
+// string. Ensure that isn't incorrectly happening for std::format.
+std::string StrFormat_no_newline_removal() {
+  return absl::StrFormat("a line\n");
+  // CHECK-MESSAGES: [[@LINE-1]]:10: warning: use 'std::format' instead of 'StrFormat' [modernize-use-std-format]
+  // CHECK-FIXES: return std::format("a line\n");
+}
+
+// FormatConverter is capable of removing newlines from the end of the format
+// string. Ensure that isn't incorrectly happening for std::format.
+std::string StrFormat_cstr_removal(const std::string , const std::string *s2) {
+  return absl::StrFormat("%s %s %s %s", s1.c_str(), s1.data(), s2->c_str(), s2->data());
+  // CHECK-MESSAGES: [[@LINE-1]]:10: warning: use 'std::format' instead of 'StrFormat' [modernize-use-std-format]
+  // CHECK-FIXES: return std::format("{} {} {} {}", s1, s1, *s2, *s2);
+}
+
+std::string StrFormat_strict_conversion() {
+  const unsigned char uc = 'A';
+  return absl::StrFormat("Integer %hhd from unsigned char\n", uc);
+  // CHECK-MESSAGES: [[@LINE-1]]:10: warning: use 'std::format' instead of 'StrFormat' [modernize-use-std-format]
+  // CHECK-FIXES: return std::format("Integer {} from unsigned char\n", uc);
+}
+
+std::string StrFormat_field_width_and_precision() {
+  auto s1 = absl::StrFormat("width only:%*d width and precision:%*.*f precision only:%.*f", 3, 42, 4, 2, 3.14159265358979323846, 5, 2.718);
+  // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use 'std::format' instead of 'StrFormat' [modernize-use-std-format]
+  // CHECK-FIXES: std::format("width only:{:{}} width and precision:{:{}.{}f} precision only:{:.{}f}", 42, 3, 3.14159265358979323846, 4, 2, 2.718, 5);
+
+  auto s2 = absl::StrFormat("width and precision positional:%1$*2$.*3$f after", 3.14159265358979323846, 4, 2);
+  // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use 'std::format' instead of 'StrFormat' [modernize-use-std-format]
+  // CHECK-FIXES: std::format("width 

[PATCH] D154287: [clang-tidy] Add modernize-use-std-format check

2023-08-29 Thread Mike Crowe via Phabricator via cfe-commits
mikecrowe updated this revision to Diff 55.
mikecrowe added a comment.

Rebase and fix minor doc conflicts.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D154287

Files:
  clang-tools-extra/clang-tidy/modernize/CMakeLists.txt
  clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp
  clang-tools-extra/clang-tidy/modernize/UseStdFormatCheck.cpp
  clang-tools-extra/clang-tidy/modernize/UseStdFormatCheck.h
  clang-tools-extra/clang-tidy/modernize/UseStdPrintCheck.cpp
  clang-tools-extra/clang-tidy/utils/FormatStringConverter.cpp
  clang-tools-extra/clang-tidy/utils/FormatStringConverter.h
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  clang-tools-extra/docs/clang-tidy/checks/modernize/use-std-format.rst
  clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-format-custom.cpp
  clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-format-fmt.cpp
  clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-format.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-format.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-format.cpp
@@ -0,0 +1,97 @@
+// RUN: %check_clang_tidy \
+// RUN:   -std=c++20 %s modernize-use-std-format %t -- \
+// RUN:   -config="{CheckOptions: [{key: StrictMode, value: true}]}" \
+// RUN:   -- -isystem %clang_tidy_headers
+// RUN: %check_clang_tidy \
+// RUN:   -std=c++20 %s modernize-use-std-format %t -- \
+// RUN:   -config="{CheckOptions: [{key: StrictMode, value: false}]}" \
+// RUN:   -- -isystem %clang_tidy_headers
+#include 
+// CHECK-FIXES: #include 
+
+namespace absl
+{
+// Use const char * for the format since the real type is hard to mock up.
+template 
+std::string StrFormat(const char *format, const Args&... args);
+} // namespace absl
+
+template 
+struct iterator {
+  T *operator->();
+  T *();
+};
+
+std::string StrFormat_simple() {
+  return absl::StrFormat("Hello");
+  // CHECK-MESSAGES: [[@LINE-1]]:10: warning: use 'std::format' instead of 'StrFormat' [modernize-use-std-format]
+  // CHECK-FIXES: return std::format("Hello");
+}
+
+std::string StrFormat_complex(const char *name, double value) {
+  return absl::StrFormat("'%s'='%f'", name, value);
+  // CHECK-MESSAGES: [[@LINE-1]]:10: warning: use 'std::format' instead of 'StrFormat' [modernize-use-std-format]
+  // CHECK-FIXES: return std::format("'{}'='{:f}'", name, value);
+}
+
+std::string StrFormat_integer_conversions() {
+  return absl::StrFormat("int:%d int:%d char:%c char:%c", 65, 'A', 66, 'B');
+  // CHECK-MESSAGES: [[@LINE-1]]:10: warning: use 'std::format' instead of 'StrFormat' [modernize-use-std-format]
+  // CHECK-FIXES: return std::format("int:{} int:{:d} char:{:c} char:{}", 65, 'A', 66, 'B');
+}
+
+// FormatConverter is capable of removing newlines from the end of the format
+// string. Ensure that isn't incorrectly happening for std::format.
+std::string StrFormat_no_newline_removal() {
+  return absl::StrFormat("a line\n");
+  // CHECK-MESSAGES: [[@LINE-1]]:10: warning: use 'std::format' instead of 'StrFormat' [modernize-use-std-format]
+  // CHECK-FIXES: return std::format("a line\n");
+}
+
+// FormatConverter is capable of removing newlines from the end of the format
+// string. Ensure that isn't incorrectly happening for std::format.
+std::string StrFormat_cstr_removal(const std::string , const std::string *s2) {
+  return absl::StrFormat("%s %s %s %s", s1.c_str(), s1.data(), s2->c_str(), s2->data());
+  // CHECK-MESSAGES: [[@LINE-1]]:10: warning: use 'std::format' instead of 'StrFormat' [modernize-use-std-format]
+  // CHECK-FIXES: return std::format("{} {} {} {}", s1, s1, *s2, *s2);
+}
+
+std::string StrFormat_strict_conversion() {
+  const unsigned char uc = 'A';
+  return absl::StrFormat("Integer %hhd from unsigned char\n", uc);
+  // CHECK-MESSAGES: [[@LINE-1]]:10: warning: use 'std::format' instead of 'StrFormat' [modernize-use-std-format]
+  // CHECK-FIXES: return std::format("Integer {} from unsigned char\n", uc);
+}
+
+std::string StrFormat_field_width_and_precision() {
+  auto s1 = absl::StrFormat("width only:%*d width and precision:%*.*f precision only:%.*f", 3, 42, 4, 2, 3.14159265358979323846, 5, 2.718);
+  // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use 'std::format' instead of 'StrFormat' [modernize-use-std-format]
+  // CHECK-FIXES: std::format("width only:{:{}} width and precision:{:{}.{}f} precision only:{:.{}f}", 42, 3, 3.14159265358979323846, 4, 2, 2.718, 5);
+
+  auto s2 = absl::StrFormat("width and precision positional:%1$*2$.*3$f after", 3.14159265358979323846, 4, 2);
+  // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use 'std::format' instead of 'StrFormat' [modernize-use-std-format]
+  // CHECK-FIXES: std::format("width and precision positional:{0:{1}.{2}f} after", 3.14159265358979323846, 4, 2);
+

[PATCH] D156616: [clang-tidy] Fix c_str() removal and cast addition when re-ordering arguments

2023-08-29 Thread Mike Crowe via Phabricator via cfe-commits
mikecrowe added a comment.

Thanks for the review and landing this.

Mike.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D156616

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D156616: [clang-tidy] Fix c_str() removal and cast addition when re-ordering arguments

2023-08-28 Thread Mike Crowe via Phabricator via cfe-commits
mikecrowe added a comment.

> Additionally user could always take "main" version, and use it just to apply 
> fixes from this check.

OK. Can this land on main then?

Thanks.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D156616

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D156616: [clang-tidy] Fix c_str() removal and cast addition when re-ordering arguments

2023-08-28 Thread Mike Crowe via Phabricator via cfe-commits
mikecrowe added a comment.

In D156616#4621945 , @PiotrZSL wrote:

> In D156616#4621914 , @mikecrowe 
> wrote:
>
>> @PiotrZSL, I think that this is quite an important fix since without it the 
>> check completely mangles the code. Should it be put in the 17.x release 
>> branch too?
>
> If issue happens only when StrictMode is set to True, then I wouldn't worry 
> too much, and then this could wait for Clang 18 that is just half year away.

The removal of `c_str()` happens even without StrictMode set to True.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D156616

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D156616: [clang-tidy] Fix c_str() removal and cast addition when re-ordering arguments

2023-08-28 Thread Mike Crowe via Phabricator via cfe-commits
mikecrowe added a comment.

@PiotrZSL, I think that this is quite an important fix since without it the 
check completely mangles the code. Should it be put in the 17.x release branch 
too?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D156616

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D154287: [clang-tidy] Add modernize-use-std-format check

2023-08-02 Thread Mike Crowe via Phabricator via cfe-commits
mikecrowe updated this revision to Diff 546418.
mikecrowe added a comment.

Rebase on top of D156616  and add more tests


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D154287

Files:
  clang-tools-extra/clang-tidy/modernize/CMakeLists.txt
  clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp
  clang-tools-extra/clang-tidy/modernize/UseStdFormatCheck.cpp
  clang-tools-extra/clang-tidy/modernize/UseStdFormatCheck.h
  clang-tools-extra/clang-tidy/modernize/UseStdPrintCheck.cpp
  clang-tools-extra/clang-tidy/utils/FormatStringConverter.cpp
  clang-tools-extra/clang-tidy/utils/FormatStringConverter.h
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  clang-tools-extra/docs/clang-tidy/checks/modernize/use-std-format.rst
  clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-format-custom.cpp
  clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-format-fmt.cpp
  clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-format.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-format.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-format.cpp
@@ -0,0 +1,97 @@
+// RUN: %check_clang_tidy \
+// RUN:   -std=c++20 %s modernize-use-std-format %t -- \
+// RUN:   -config="{CheckOptions: [{key: StrictMode, value: true}]}" \
+// RUN:   -- -isystem %clang_tidy_headers
+// RUN: %check_clang_tidy \
+// RUN:   -std=c++20 %s modernize-use-std-format %t -- \
+// RUN:   -config="{CheckOptions: [{key: StrictMode, value: false}]}" \
+// RUN:   -- -isystem %clang_tidy_headers
+#include 
+// CHECK-FIXES: #include 
+
+namespace absl
+{
+// Use const char * for the format since the real type is hard to mock up.
+template 
+std::string StrFormat(const char *format, const Args&... args);
+} // namespace absl
+
+template 
+struct iterator {
+  T *operator->();
+  T *();
+};
+
+std::string StrFormat_simple() {
+  return absl::StrFormat("Hello");
+  // CHECK-MESSAGES: [[@LINE-1]]:10: warning: use 'std::format' instead of 'StrFormat' [modernize-use-std-format]
+  // CHECK-FIXES: return std::format("Hello");
+}
+
+std::string StrFormat_complex(const char *name, double value) {
+  return absl::StrFormat("'%s'='%f'", name, value);
+  // CHECK-MESSAGES: [[@LINE-1]]:10: warning: use 'std::format' instead of 'StrFormat' [modernize-use-std-format]
+  // CHECK-FIXES: return std::format("'{}'='{:f}'", name, value);
+}
+
+std::string StrFormat_integer_conversions() {
+  return absl::StrFormat("int:%d int:%d char:%c char:%c", 65, 'A', 66, 'B');
+  // CHECK-MESSAGES: [[@LINE-1]]:10: warning: use 'std::format' instead of 'StrFormat' [modernize-use-std-format]
+  // CHECK-FIXES: return std::format("int:{} int:{:d} char:{:c} char:{}", 65, 'A', 66, 'B');
+}
+
+// FormatConverter is capable of removing newlines from the end of the format
+// string. Ensure that isn't incorrectly happening for std::format.
+std::string StrFormat_no_newline_removal() {
+  return absl::StrFormat("a line\n");
+  // CHECK-MESSAGES: [[@LINE-1]]:10: warning: use 'std::format' instead of 'StrFormat' [modernize-use-std-format]
+  // CHECK-FIXES: return std::format("a line\n");
+}
+
+// FormatConverter is capable of removing newlines from the end of the format
+// string. Ensure that isn't incorrectly happening for std::format.
+std::string StrFormat_cstr_removal(const std::string , const std::string *s2) {
+  return absl::StrFormat("%s %s %s %s", s1.c_str(), s1.data(), s2->c_str(), s2->data());
+  // CHECK-MESSAGES: [[@LINE-1]]:10: warning: use 'std::format' instead of 'StrFormat' [modernize-use-std-format]
+  // CHECK-FIXES: return std::format("{} {} {} {}", s1, s1, *s2, *s2);
+}
+
+std::string StrFormat_strict_conversion() {
+  const unsigned char uc = 'A';
+  return absl::StrFormat("Integer %hhd from unsigned char\n", uc);
+  // CHECK-MESSAGES: [[@LINE-1]]:10: warning: use 'std::format' instead of 'StrFormat' [modernize-use-std-format]
+  // CHECK-FIXES: return std::format("Integer {} from unsigned char\n", uc);
+}
+
+std::string StrFormat_field_width_and_precision() {
+  auto s1 = absl::StrFormat("width only:%*d width and precision:%*.*f precision only:%.*f", 3, 42, 4, 2, 3.14159265358979323846, 5, 2.718);
+  // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use 'std::format' instead of 'StrFormat' [modernize-use-std-format]
+  // CHECK-FIXES: std::format("width only:{:{}} width and precision:{:{}.{}f} precision only:{:.{}f}", 42, 3, 3.14159265358979323846, 4, 2, 2.718, 5);
+
+  auto s2 = absl::StrFormat("width and precision positional:%1$*2$.*3$f after", 3.14159265358979323846, 4, 2);
+  // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use 'std::format' instead of 'StrFormat' [modernize-use-std-format]
+  // CHECK-FIXES: std::format("width and precision 

[PATCH] D156616: [clang-tidy] Fix c_str() removal and cast addition when re-ordering arguments

2023-08-02 Thread Mike Crowe via Phabricator via cfe-commits
mikecrowe updated this revision to Diff 546414.
mikecrowe added a comment.

Reinstate version I incorrectly replaced with D154287 



Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D156616

Files:
  clang-tools-extra/clang-tidy/utils/FormatStringConverter.cpp
  clang-tools-extra/clang-tidy/utils/FormatStringConverter.h
  clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print.cpp
===
--- clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print.cpp
@@ -14,6 +14,12 @@
 #include 
 #include 
 
+template 
+struct iterator {
+  T *operator->();
+  T *();
+};
+
 void printf_simple() {
   printf("Hello");
   // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'printf' [modernize-use-std-print]
@@ -1121,11 +1127,32 @@
   // CHECK-FIXES: std::println("Hello {:.5}", 'G');
 }
 
-void printf_field_width_and_precision() {
+void printf_field_width_and_precision(const std::string , const std::string , const std::string )
+{
   printf("width only:%*d width and precision:%*.*f precision only:%.*f\n", 3, 42, 4, 2, 3.14159265358979323846, 5, 2.718);
   // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
   // CHECK-FIXES: std::println("width only:{:{}} width and precision:{:{}.{}f} precision only:{:.{}f}", 42, 3, 3.14159265358979323846, 4, 2, 2.718, 5);
 
+  const unsigned int ui1 = 42, ui2 = 43, ui3 = 44;
+  printf("casts width only:%*d width and precision:%*.*d precision only:%.*d\n", 3, ui1, 4, 2, ui2, 5, ui3);
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
+  // CHECK-FIXES-NOTSTRICT: std::println("casts width only:{:{}} width and precision:{:{}.{}} precision only:{:.{}}", ui1, 3, ui2, 4, 2, ui3, 5);
+  // CHECK-FIXES-STRICT: std::println("casts width only:{:{}} width and precision:{:{}.{}} precision only:{:.{}}", static_cast(ui1), 3, static_cast(ui2), 4, 2, static_cast(ui3), 5);
+
+  printf("c_str removal width only:%*s width and precision:%*.*s precision only:%.*s\n", 3, s1.c_str(), 4, 2, s2.c_str(), 5, s3.c_str());
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
+  // CHECK-FIXES: std::println("c_str removal width only:{:>{}} width and precision:{:>{}.{}} precision only:{:.{}}", s1, 3, s2, 4, 2, s3, 5);
+
+  const std::string *ps1 = , *ps2 = , *ps3 = 
+  printf("c_str() removal pointer width only:%-*s width and precision:%-*.*s precision only:%-.*s\n", 3, ps1->c_str(), 4, 2, ps2->c_str(), 5, ps3->c_str());
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
+  // CHECK-FIXES: std::println("c_str() removal pointer width only:{:{}} width and precision:{:{}.{}} precision only:{:.{}}", *ps1, 3, *ps2, 4, 2, *ps3, 5);
+
+  iterator is1, is2, is3;
+  printf("c_str() removal iterator width only:%-*s width and precision:%-*.*s precision only:%-.*s\n", 3, is1->c_str(), 4, 2, is2->c_str(), 5, is3->c_str());
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
+  // CHECK-FIXES: std::println("c_str() removal iterator width only:{:{}} width and precision:{:{}.{}} precision only:{:.{}}", *is1, 3, *is2, 4, 2, *is3, 5);
+
   printf("width and precision positional:%1$*2$.*3$f after\n", 3.14159265358979323846, 4, 2);
   // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
   // CHECK-FIXES: std::println("width and precision positional:{0:{1}.{2}f} after", 3.14159265358979323846, 4, 2);
@@ -1134,9 +1161,13 @@
   printf("width only:%3$*1$d width and precision:%4$*1$.*2$f precision only:%5$.*2$f\n", width, precision, 42, 3.1415926, 2.718);
   // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
   // CHECK-FIXES: std::println("width only:{2:{0}} width and precision:{3:{0}.{1}f} precision only:{4:.{1}f}", width, precision, 42, 3.1415926, 2.718);
+
+  printf("c_str removal width only:%3$*1$s width and precision:%4$*1$.*2$s precision only:%5$.*2$s\n", width, precision, s1.c_str(), s2.c_str(), s3.c_str());
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
+  // CHECK-FIXES: std::println("c_str removal width only:{2:>{0}} width and precision:{3:>{0}.{1}} precision only:{4:.{1}}", width, precision, s1, s2, s3);
 }
 
-void fprintf_field_width_and_precision() {
+void fprintf_field_width_and_precision(const std::string , const std::string , const std::string ) {
   fprintf(stderr, "width only:%*d width and 

[PATCH] D156616: [clang-tidy] Fix c_str() removal and cast addition when re-ordering arguments

2023-07-30 Thread Mike Crowe via Phabricator via cfe-commits
mikecrowe updated this revision to Diff 545446.
mikecrowe added a comment.

Rebase on top of D156616  and add more tests


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D156616

Files:
  clang-tools-extra/clang-tidy/modernize/CMakeLists.txt
  clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp
  clang-tools-extra/clang-tidy/modernize/UseStdFormatCheck.cpp
  clang-tools-extra/clang-tidy/modernize/UseStdFormatCheck.h
  clang-tools-extra/clang-tidy/modernize/UseStdPrintCheck.cpp
  clang-tools-extra/clang-tidy/utils/FormatStringConverter.cpp
  clang-tools-extra/clang-tidy/utils/FormatStringConverter.h
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  clang-tools-extra/docs/clang-tidy/checks/modernize/use-std-format.rst
  clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-format-custom.cpp
  clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-format-fmt.cpp
  clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-format.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-format.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-format.cpp
@@ -0,0 +1,97 @@
+// RUN: %check_clang_tidy \
+// RUN:   -std=c++20 %s modernize-use-std-format %t -- \
+// RUN:   -config="{CheckOptions: [{key: StrictMode, value: true}]}" \
+// RUN:   -- -isystem %clang_tidy_headers
+// RUN: %check_clang_tidy \
+// RUN:   -std=c++20 %s modernize-use-std-format %t -- \
+// RUN:   -config="{CheckOptions: [{key: StrictMode, value: false}]}" \
+// RUN:   -- -isystem %clang_tidy_headers
+#include 
+// CHECK-FIXES: #include 
+
+namespace absl
+{
+// Use const char * for the format since the real type is hard to mock up.
+template 
+std::string StrFormat(const char *format, const Args&... args);
+} // namespace absl
+
+template 
+struct iterator {
+  T *operator->();
+  T *();
+};
+
+std::string StrFormat_simple() {
+  return absl::StrFormat("Hello");
+  // CHECK-MESSAGES: [[@LINE-1]]:10: warning: use 'std::format' instead of 'StrFormat' [modernize-use-std-format]
+  // CHECK-FIXES: return std::format("Hello");
+}
+
+std::string StrFormat_complex(const char *name, double value) {
+  return absl::StrFormat("'%s'='%f'", name, value);
+  // CHECK-MESSAGES: [[@LINE-1]]:10: warning: use 'std::format' instead of 'StrFormat' [modernize-use-std-format]
+  // CHECK-FIXES: return std::format("'{}'='{:f}'", name, value);
+}
+
+std::string StrFormat_integer_conversions() {
+  return absl::StrFormat("int:%d int:%d char:%c char:%c", 65, 'A', 66, 'B');
+  // CHECK-MESSAGES: [[@LINE-1]]:10: warning: use 'std::format' instead of 'StrFormat' [modernize-use-std-format]
+  // CHECK-FIXES: return std::format("int:{} int:{:d} char:{:c} char:{}", 65, 'A', 66, 'B');
+}
+
+// FormatConverter is capable of removing newlines from the end of the format
+// string. Ensure that isn't incorrectly happening for std::format.
+std::string StrFormat_no_newline_removal() {
+  return absl::StrFormat("a line\n");
+  // CHECK-MESSAGES: [[@LINE-1]]:10: warning: use 'std::format' instead of 'StrFormat' [modernize-use-std-format]
+  // CHECK-FIXES: return std::format("a line\n");
+}
+
+// FormatConverter is capable of removing newlines from the end of the format
+// string. Ensure that isn't incorrectly happening for std::format.
+std::string StrFormat_cstr_removal(const std::string , const std::string *s2) {
+  return absl::StrFormat("%s %s %s %s", s1.c_str(), s1.data(), s2->c_str(), s2->data());
+  // CHECK-MESSAGES: [[@LINE-1]]:10: warning: use 'std::format' instead of 'StrFormat' [modernize-use-std-format]
+  // CHECK-FIXES: return std::format("{} {} {} {}", s1, s1, *s2, *s2);
+}
+
+std::string StrFormat_strict_conversion() {
+  const unsigned char uc = 'A';
+  return absl::StrFormat("Integer %hhd from unsigned char\n", uc);
+  // CHECK-MESSAGES: [[@LINE-1]]:10: warning: use 'std::format' instead of 'StrFormat' [modernize-use-std-format]
+  // CHECK-FIXES: return std::format("Integer {} from unsigned char\n", uc);
+}
+
+std::string StrFormat_field_width_and_precision() {
+  auto s1 = absl::StrFormat("width only:%*d width and precision:%*.*f precision only:%.*f", 3, 42, 4, 2, 3.14159265358979323846, 5, 2.718);
+  // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use 'std::format' instead of 'StrFormat' [modernize-use-std-format]
+  // CHECK-FIXES: std::format("width only:{:{}} width and precision:{:{}.{}f} precision only:{:.{}f}", 42, 3, 3.14159265358979323846, 4, 2, 2.718, 5);
+
+  auto s2 = absl::StrFormat("width and precision positional:%1$*2$.*3$f after", 3.14159265358979323846, 4, 2);
+  // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use 'std::format' instead of 'StrFormat' [modernize-use-std-format]
+  // CHECK-FIXES: std::format("width and precision 

[PATCH] D156616: [clang-tidy] Fix c_str() removal and cast addition when re-ordering arguments

2023-07-30 Thread Mike Crowe via Phabricator via cfe-commits
mikecrowe added a comment.

Fixing this was rather messier than I expected, but this solution does seem to 
work for the test cases. Here's my original commit message before I trimmed it, 
in case it provides any more insight.

  [clang-tidy] Fix c_str() removal and cast addition when re-ordering arguments
  
  The modernize-use-std-print check would get confused if it had to
  re-order field-width and precision arguments at the same time as adding
  casts or removing calls to c_str(). For example applying the check with
  StrictMode enabled to:
  
   printf("%*s=%*d\n", 4, s.c_str(), 3, ui);
  
  yields:
  
   std::println("{:>{}}={:{}}", s.c_str(), s4, ui, static_cast(3));
  
  rather than the expected:
  
   std::println("{:>{}}={:{}}", s, 4, static_cast(ui), 3);
  
  Fix this by:
  
  - storing the ArgIndex rather than the Expr pointer for any arguments
that need casts to be added in ArgFixes so that the index can be
modified when the arguments are re-ordered. Use a struct rather than a
tuple for clarity.
  
  - Making applyFixes do argument re-ordering first, but also taking care
of c_str() removal at the same time if necessary. Update the argument
index of any ArgFixes too.
  
  - Apply the ArgFixes afterwards.
  
  - Finally apply and c_str() removals that remain.
  
  - Add lit check test cases for the combinations of argument reordering,
casts and c_str() removal. This required moving the definition of
struct iterator earlier in use-std-print.cpp.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D156616

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D156616: [clang-tidy] Fix c_str() removal and cast addition when re-ordering arguments

2023-07-30 Thread Mike Crowe via Phabricator via cfe-commits
mikecrowe created this revision.
mikecrowe added a reviewer: PiotrZSL.
Herald added subscribers: carlosgalvezp, xazax.hun.
Herald added a reviewer: njames93.
Herald added a project: All.
mikecrowe requested review of this revision.
Herald added a project: clang-tools-extra.
Herald added a subscriber: cfe-commits.

The modernize-use-std-print check would get confused if it had to
re-order field-width and precision arguments at the same time as adding
casts or removing calls to c_str().

Fix this by tracking the argument indices and combining c_str() removal
with argument re-ordering. Add missing test cases to lit check.

Fixes https://github.com/llvm/llvm-project/issues/64033


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D156616

Files:
  clang-tools-extra/clang-tidy/utils/FormatStringConverter.cpp
  clang-tools-extra/clang-tidy/utils/FormatStringConverter.h
  clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print.cpp
===
--- clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print.cpp
@@ -14,6 +14,12 @@
 #include 
 #include 
 
+template 
+struct iterator {
+  T *operator->();
+  T *();
+};
+
 void printf_simple() {
   printf("Hello");
   // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'printf' [modernize-use-std-print]
@@ -1121,11 +1127,32 @@
   // CHECK-FIXES: std::println("Hello {:.5}", 'G');
 }
 
-void printf_field_width_and_precision() {
+void printf_field_width_and_precision(const std::string , const std::string , const std::string )
+{
   printf("width only:%*d width and precision:%*.*f precision only:%.*f\n", 3, 42, 4, 2, 3.14159265358979323846, 5, 2.718);
   // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
   // CHECK-FIXES: std::println("width only:{:{}} width and precision:{:{}.{}f} precision only:{:.{}f}", 42, 3, 3.14159265358979323846, 4, 2, 2.718, 5);
 
+  const unsigned int ui1 = 42, ui2 = 43, ui3 = 44;
+  printf("casts width only:%*d width and precision:%*.*d precision only:%.*d\n", 3, ui1, 4, 2, ui2, 5, ui3);
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
+  // CHECK-FIXES-NOTSTRICT: std::println("casts width only:{:{}} width and precision:{:{}.{}} precision only:{:.{}}", ui1, 3, ui2, 4, 2, ui3, 5);
+  // CHECK-FIXES-STRICT: std::println("casts width only:{:{}} width and precision:{:{}.{}} precision only:{:.{}}", static_cast(ui1), 3, static_cast(ui2), 4, 2, static_cast(ui3), 5);
+
+  printf("c_str removal width only:%*s width and precision:%*.*s precision only:%.*s\n", 3, s1.c_str(), 4, 2, s2.c_str(), 5, s3.c_str());
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
+  // CHECK-FIXES: std::println("c_str removal width only:{:>{}} width and precision:{:>{}.{}} precision only:{:.{}}", s1, 3, s2, 4, 2, s3, 5);
+
+  const std::string *ps1 = , *ps2 = , *ps3 = 
+  printf("c_str() removal pointer width only:%-*s width and precision:%-*.*s precision only:%-.*s\n", 3, ps1->c_str(), 4, 2, ps2->c_str(), 5, ps3->c_str());
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
+  // CHECK-FIXES: std::println("c_str() removal pointer width only:{:{}} width and precision:{:{}.{}} precision only:{:.{}}", *ps1, 3, *ps2, 4, 2, *ps3, 5);
+
+  iterator is1, is2, is3;
+  printf("c_str() removal iterator width only:%-*s width and precision:%-*.*s precision only:%-.*s\n", 3, is1->c_str(), 4, 2, is2->c_str(), 5, is3->c_str());
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
+  // CHECK-FIXES: std::println("c_str() removal iterator width only:{:{}} width and precision:{:{}.{}} precision only:{:.{}}", *is1, 3, *is2, 4, 2, *is3, 5);
+
   printf("width and precision positional:%1$*2$.*3$f after\n", 3.14159265358979323846, 4, 2);
   // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
   // CHECK-FIXES: std::println("width and precision positional:{0:{1}.{2}f} after", 3.14159265358979323846, 4, 2);
@@ -1134,9 +1161,13 @@
   printf("width only:%3$*1$d width and precision:%4$*1$.*2$f precision only:%5$.*2$f\n", width, precision, 42, 3.1415926, 2.718);
   // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
   // CHECK-FIXES: std::println("width only:{2:{0}} width and precision:{3:{0}.{1}f} precision only:{4:.{1}f}", width, precision, 42, 3.1415926, 2.718);
+
+  printf("c_str removal width only:%3$*1$s width and precision:%4$*1$.*2$s precision only:%5$.*2$s\n", width, precision, s1.c_str(), s2.c_str(), s3.c_str());
+  // CHECK-MESSAGES: 

[PATCH] D154884: [clang-tidy] Make MatchesAnyListedNameMatcher cope with unnamed Decl

2023-07-11 Thread Mike Crowe via Phabricator via cfe-commits
mikecrowe added a comment.

Thanks for the review.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D154884

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D154884: [clang-tidy] Make MatchesAnyListedNameMatcher cope with unnamed Decl

2023-07-11 Thread Mike Crowe via Phabricator via cfe-commits
mikecrowe updated this revision to Diff 538940.
mikecrowe marked an inline comment as done.
mikecrowe added a comment.

Remove unnecessary init-statement and test case in commit message


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D154884

Files:
  clang-tools-extra/clang-tidy/utils/Matchers.h
  clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print-custom.cpp


Index: 
clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print-custom.cpp
===
--- 
clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print-custom.cpp
+++ 
clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print-custom.cpp
@@ -3,7 +3,7 @@
 // RUN: [ \
 // RUN:  { \
 // RUN:   key: modernize-use-std-print.PrintfLikeFunctions, \
-// RUN:   value: '::myprintf; mynamespace::myprintf2' \
+// RUN:   value: 'unqualified_printf;::myprintf; 
mynamespace::myprintf2' \
 // RUN:  }, \
 // RUN:  { \
 // RUN:   key: modernize-use-std-print.FprintfLikeFunctions, \
@@ -14,7 +14,7 @@
 // RUN:   -- -isystem %clang_tidy_headers
 
 #include 
-#include 
+#include 
 
 int myprintf(const char *, ...);
 int myfprintf(FILE *fp, const char *, ...);
@@ -85,3 +85,10 @@
   // CHECK-MESSAGES-NOT: [[@LINE-1]]:10: warning: use 'std::println' instead 
of 'myprintf' [modernize-use-std-print]
   // CHECK-FIXES-NOT: std::println(stderr, "return value {}", i);
 }
+
+// Ensure that MatchesAnyListedNameMatcher::NameMatcher::match() can cope with 
a
+// NamedDecl that has no name when we're trying to match unqualified_printf.
+void no_name(const std::string )
+{
+  "A" + in;
+}
Index: clang-tools-extra/clang-tidy/utils/Matchers.h
===
--- clang-tools-extra/clang-tidy/utils/Matchers.h
+++ clang-tools-extra/clang-tidy/utils/Matchers.h
@@ -112,7 +112,9 @@
   case MatchMode::MatchFullyQualified:
 return Regex.match("::" + ND.getQualifiedNameAsString());
   default:
-return Regex.match(ND.getName());
+if (const IdentifierInfo *II = ND.getIdentifier())
+  return Regex.match(II->getName());
+return false;
   }
 }
 


Index: clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print-custom.cpp
===
--- clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print-custom.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print-custom.cpp
@@ -3,7 +3,7 @@
 // RUN: [ \
 // RUN:  { \
 // RUN:   key: modernize-use-std-print.PrintfLikeFunctions, \
-// RUN:   value: '::myprintf; mynamespace::myprintf2' \
+// RUN:   value: 'unqualified_printf;::myprintf; mynamespace::myprintf2' \
 // RUN:  }, \
 // RUN:  { \
 // RUN:   key: modernize-use-std-print.FprintfLikeFunctions, \
@@ -14,7 +14,7 @@
 // RUN:   -- -isystem %clang_tidy_headers
 
 #include 
-#include 
+#include 
 
 int myprintf(const char *, ...);
 int myfprintf(FILE *fp, const char *, ...);
@@ -85,3 +85,10 @@
   // CHECK-MESSAGES-NOT: [[@LINE-1]]:10: warning: use 'std::println' instead of 'myprintf' [modernize-use-std-print]
   // CHECK-FIXES-NOT: std::println(stderr, "return value {}", i);
 }
+
+// Ensure that MatchesAnyListedNameMatcher::NameMatcher::match() can cope with a
+// NamedDecl that has no name when we're trying to match unqualified_printf.
+void no_name(const std::string )
+{
+  "A" + in;
+}
Index: clang-tools-extra/clang-tidy/utils/Matchers.h
===
--- clang-tools-extra/clang-tidy/utils/Matchers.h
+++ clang-tools-extra/clang-tidy/utils/Matchers.h
@@ -112,7 +112,9 @@
   case MatchMode::MatchFullyQualified:
 return Regex.match("::" + ND.getQualifiedNameAsString());
   default:
-return Regex.match(ND.getName());
+if (const IdentifierInfo *II = ND.getIdentifier())
+  return Regex.match(II->getName());
+return false;
   }
 }
 
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D154287: [clang-tidy] Add modernize-use-std-format check

2023-07-10 Thread Mike Crowe via Phabricator via cfe-commits
mikecrowe updated this revision to Diff 538806.
mikecrowe added a comment.

Use isOrdinary in stringLiteral() match on first argument


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D154287

Files:
  clang-tools-extra/clang-tidy/modernize/CMakeLists.txt
  clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp
  clang-tools-extra/clang-tidy/modernize/UseStdFormatCheck.cpp
  clang-tools-extra/clang-tidy/modernize/UseStdFormatCheck.h
  clang-tools-extra/clang-tidy/modernize/UseStdPrintCheck.cpp
  clang-tools-extra/clang-tidy/utils/FormatStringConverter.cpp
  clang-tools-extra/clang-tidy/utils/FormatStringConverter.h
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  clang-tools-extra/docs/clang-tidy/checks/modernize/use-std-format.rst
  clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-format-custom.cpp
  clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-format-fmt.cpp
  clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-format.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-format.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-format.cpp
@@ -0,0 +1,75 @@
+// RUN: %check_clang_tidy \
+// RUN:   -std=c++20 %s modernize-use-std-format %t -- \
+// RUN:   -config="{CheckOptions: [{key: StrictMode, value: true}]}" \
+// RUN:   -- -isystem %clang_tidy_headers
+// RUN: %check_clang_tidy \
+// RUN:   -std=c++20 %s modernize-use-std-format %t -- \
+// RUN:   -config="{CheckOptions: [{key: StrictMode, value: false}]}" \
+// RUN:   -- -isystem %clang_tidy_headers
+#include 
+// CHECK-FIXES: #include 
+
+namespace absl
+{
+// Use const char * for the format since the real type is hard to mock up.
+template 
+std::string StrFormat(const char *format, const Args&... args);
+} // namespace absl
+
+std::string StrFormat_simple() {
+  return absl::StrFormat("Hello");
+  // CHECK-MESSAGES: [[@LINE-1]]:10: warning: use 'std::format' instead of 'StrFormat' [modernize-use-std-format]
+  // CHECK-FIXES: return std::format("Hello");
+}
+
+std::string StrFormat_complex(const char *name, double value) {
+  return absl::StrFormat("'%s'='%f'", name, value);
+  // CHECK-MESSAGES: [[@LINE-1]]:10: warning: use 'std::format' instead of 'StrFormat' [modernize-use-std-format]
+  // CHECK-FIXES: return std::format("'{}'='{:f}'", name, value);
+}
+
+std::string StrFormat_integer_conversions() {
+  return absl::StrFormat("int:%d int:%d char:%c char:%c", 65, 'A', 66, 'B');
+  // CHECK-MESSAGES: [[@LINE-1]]:10: warning: use 'std::format' instead of 'StrFormat' [modernize-use-std-format]
+  // CHECK-FIXES: return std::format("int:{} int:{:d} char:{:c} char:{}", 65, 'A', 66, 'B');
+}
+
+// FormatConverter is capable of removing newlines from the end of the format
+// string. Ensure that isn't incorrectly happening for std::format.
+std::string StrFormat_no_newline_removal() {
+  return absl::StrFormat("a line\n");
+  // CHECK-MESSAGES: [[@LINE-1]]:10: warning: use 'std::format' instead of 'StrFormat' [modernize-use-std-format]
+  // CHECK-FIXES: return std::format("a line\n");
+}
+
+// FormatConverter is capable of removing newlines from the end of the format
+// string. Ensure that isn't incorrectly happening for std::format.
+std::string StrFormat_cstr_removal(const std::string , const std::string *s2) {
+  return absl::StrFormat("%s %s %s %s", s1.c_str(), s1.data(), s2->c_str(), s2->data());
+  // CHECK-MESSAGES: [[@LINE-1]]:10: warning: use 'std::format' instead of 'StrFormat' [modernize-use-std-format]
+  // CHECK-FIXES: return std::format("{} {} {} {}", s1, s1, *s2, *s2);
+}
+
+std::string StrFormat_strict_conversion() {
+  const unsigned char uc = 'A';
+  return absl::StrFormat("Integer %hhd from unsigned char\n", uc);
+  // CHECK-MESSAGES: [[@LINE-1]]:10: warning: use 'std::format' instead of 'StrFormat' [modernize-use-std-format]
+  // CHECK-FIXES: return std::format("Integer {} from unsigned char\n", uc);
+}
+
+std::string StrFormat_field_width_and_precision() {
+  auto s1 = absl::StrFormat("width only:%*d width and precision:%*.*f precision only:%.*f", 3, 42, 4, 2, 3.14159265358979323846, 5, 2.718);
+  // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use 'std::format' instead of 'StrFormat' [modernize-use-std-format]
+  // CHECK-FIXES: std::format("width only:{:{}} width and precision:{:{}.{}f} precision only:{:.{}f}", 42, 3, 3.14159265358979323846, 4, 2, 2.718, 5);
+
+  auto s2 = absl::StrFormat("width and precision positional:%1$*2$.*3$f after", 3.14159265358979323846, 4, 2);
+  // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use 'std::format' instead of 'StrFormat' [modernize-use-std-format]
+  // CHECK-FIXES: std::format("width and precision positional:{0:{1}.{2}f} after", 3.14159265358979323846, 4, 2);
+
+  const int width = 10, precision = 3;
+  

[PATCH] D154287: [clang-tidy] Add modernize-use-std-format check

2023-07-10 Thread Mike Crowe via Phabricator via cfe-commits
mikecrowe added inline comments.



Comment at: clang-tools-extra/clang-tidy/modernize/UseStdFormatCheck.cpp:46
+void UseStdFormatCheck::registerMatchers(MatchFinder *Finder) {
+  Finder->addMatcher(
+  callExpr(argumentCountAtLeast(1), hasArgument(0, stringLiteral()),

PiotrZSL wrote:
> mikecrowe wrote:
> > This matcher also matches the `operator+` call in:
> > ```
> > std::string A(const std::string )
> > 
> > 
> > {   
> > 
> > 
> > return "_" + in;
> > 
> > 
> > }   
> > 
> > 
> > ```
> > which causes an assertion failure:
> > ```
> > clang-tidy: /home/mac/git/llvm-project/clang/include/clang/AST/Decl.h:275: 
> > llvm::StringRef clang::NamedDecl::getName() const: Assertion 
> > `Name.isIdentifier() && "Name is not a simple identifier"' failed.
> > ```
> > when the `StrFormatLikeFunctions` option is set to an unqualified name:
> > ```
> > -config="{CheckOptions: [{key: modernize-use-std-format.StrictMode, value: 
> > false}, {key: modernize-use-std-format.StrFormatLikeFunctions, value: 
> > 'strprintf'}]}"
> > ```
> > 
> > `MatchesAnyListedNameMatcher::NameMatcher::match` calls 
> > `NamedDecl.getName()` which presumably raises the assertion due to the 
> > `operator+` not having a name (that's mentioned in the source anyway.)
> > 
> > I'm unsure whether I should be narrowing the matcher here so that it 
> > guaranteed to not try calling `matchesAnyListedName` on something that 
> > lacks a name, or whether `MatchesAnyListedNameMatcher` ought to be more 
> > tolerant of being called in such situations.
> > 
> > I note that `HasNameMatcher` has rather more elaborate code for generating 
> > the name than `MatchesAnyListedNameMatcher` does.
> > 
> > This problem also affects `modernize-use-std-print`, but due to the need 
> > for there to be no return value in that check it requires somewhat-unlikely 
> > code like:
> > ```
> > void A(const std::string )
> > {
> >   "_" + in;
> > }
> > ```
> > 
> > Do you have any advice? Given that this problem affects a check that has 
> > already landed should I open a bug?
> `unless(hasName(""))` could do a trick, or create own matcher to verify first 
> if function got name.
> Probably similar issues can be with cxxConversionDecl.
> 
> Other best option would be to change 
> MatchesAnyListedNameMatcher::NameMatcher::match to verify if NamedDecl got 
> name before calling it.
> `unless(hasName(""))` could do a trick, or create own matcher to verify first 
> if function got name.

That fails with a similar assertion failure.

> Probably similar issues can be with cxxConversionDecl.

I didn't really understand that one.

> Other best option would be to change 
> MatchesAnyListedNameMatcher::NameMatcher::match to verify if NamedDecl got 
> name before calling it.

That's easy and I think it's the best solution since it saves every check 
having to defend against this. I've done that in [[ 
https://reviews.llvm.org/D154884 | D154884 ]] .


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D154287

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D154884: [clang-tidy] Make MatchesAnyListedNameMatcher cope with unnamed Decl

2023-07-10 Thread Mike Crowe via Phabricator via cfe-commits
mikecrowe created this revision.
mikecrowe added a reviewer: PiotrZSL.
Herald added subscribers: carlosgalvezp, xazax.hun.
Herald added a reviewer: njames93.
Herald added a project: All.
mikecrowe requested review of this revision.
Herald added a project: clang-tools-extra.
Herald added a subscriber: cfe-commits.

If MatchesAnyListedNameMatcher::NameMatcher::match() is called in
MatchMode::MatchUnqualified mode with a NamedDecl that has no name then
calling NamedDecl::getName() will assert with:
 `Name.isIdentifier() && "Name is not a simple identifier"'

This situation can be reproduced by running:
 clang-tidy '-checks=-*,modernize-use-std-print' -fix -config="{CheckOptions: 
[[:] + [modernize-use-std-print.PrintfLikeFunctions,] + [value:] + ['printf']]}"
on:
 void A(const std::string )
 {

  "A" + in;

}

It seems unfair to force all matchers using
matchers::matchesAnyListedName to defend against this, particularly
since test cases are unlikely to provoke the problem. Let's just check
whether the identifier has a name before attempting to use it instead.

Add test case that reproduces the problem to the
use-std-print-custom.cpp lit check.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D154884

Files:
  clang-tools-extra/clang-tidy/utils/Matchers.h
  clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print-custom.cpp


Index: 
clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print-custom.cpp
===
--- 
clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print-custom.cpp
+++ 
clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print-custom.cpp
@@ -3,7 +3,7 @@
 // RUN: [ \
 // RUN:  { \
 // RUN:   key: modernize-use-std-print.PrintfLikeFunctions, \
-// RUN:   value: '::myprintf; mynamespace::myprintf2' \
+// RUN:   value: 'unqualified_printf;::myprintf; 
mynamespace::myprintf2' \
 // RUN:  }, \
 // RUN:  { \
 // RUN:   key: modernize-use-std-print.FprintfLikeFunctions, \
@@ -14,7 +14,7 @@
 // RUN:   -- -isystem %clang_tidy_headers
 
 #include 
-#include 
+#include 
 
 int myprintf(const char *, ...);
 int myfprintf(FILE *fp, const char *, ...);
@@ -85,3 +85,10 @@
   // CHECK-MESSAGES-NOT: [[@LINE-1]]:10: warning: use 'std::println' instead 
of 'myprintf' [modernize-use-std-print]
   // CHECK-FIXES-NOT: std::println(stderr, "return value {}", i);
 }
+
+// Ensure that MatchesAnyListedNameMatcher::NameMatcher::match() can cope with 
a
+// NamedDecl that has no name when we're trying to match unqualified_printf.
+void no_name(const std::string )
+{
+  "A" + in;
+}
Index: clang-tools-extra/clang-tidy/utils/Matchers.h
===
--- clang-tools-extra/clang-tidy/utils/Matchers.h
+++ clang-tools-extra/clang-tidy/utils/Matchers.h
@@ -112,7 +112,9 @@
   case MatchMode::MatchFullyQualified:
 return Regex.match("::" + ND.getQualifiedNameAsString());
   default:
-return Regex.match(ND.getName());
+if (const IdentifierInfo *II = ND.getIdentifier(); II)
+  return Regex.match(II->getName());
+return false;
   }
 }
 


Index: clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print-custom.cpp
===
--- clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print-custom.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print-custom.cpp
@@ -3,7 +3,7 @@
 // RUN: [ \
 // RUN:  { \
 // RUN:   key: modernize-use-std-print.PrintfLikeFunctions, \
-// RUN:   value: '::myprintf; mynamespace::myprintf2' \
+// RUN:   value: 'unqualified_printf;::myprintf; mynamespace::myprintf2' \
 // RUN:  }, \
 // RUN:  { \
 // RUN:   key: modernize-use-std-print.FprintfLikeFunctions, \
@@ -14,7 +14,7 @@
 // RUN:   -- -isystem %clang_tidy_headers
 
 #include 
-#include 
+#include 
 
 int myprintf(const char *, ...);
 int myfprintf(FILE *fp, const char *, ...);
@@ -85,3 +85,10 @@
   // CHECK-MESSAGES-NOT: [[@LINE-1]]:10: warning: use 'std::println' instead of 'myprintf' [modernize-use-std-print]
   // CHECK-FIXES-NOT: std::println(stderr, "return value {}", i);
 }
+
+// Ensure that MatchesAnyListedNameMatcher::NameMatcher::match() can cope with a
+// NamedDecl that has no name when we're trying to match unqualified_printf.
+void no_name(const std::string )
+{
+  "A" + in;
+}
Index: clang-tools-extra/clang-tidy/utils/Matchers.h
===
--- clang-tools-extra/clang-tidy/utils/Matchers.h
+++ clang-tools-extra/clang-tidy/utils/Matchers.h
@@ -112,7 +112,9 @@
   case MatchMode::MatchFullyQualified:
 return Regex.match("::" + ND.getQualifiedNameAsString());
   default:
- 

[PATCH] D154287: [clang-tidy] Add modernize-use-std-format check

2023-07-09 Thread Mike Crowe via Phabricator via cfe-commits
mikecrowe added inline comments.



Comment at: clang-tools-extra/clang-tidy/modernize/UseStdFormatCheck.cpp:46
+void UseStdFormatCheck::registerMatchers(MatchFinder *Finder) {
+  Finder->addMatcher(
+  callExpr(argumentCountAtLeast(1), hasArgument(0, stringLiteral()),

This matcher also matches the `operator+` call in:
```
std::string A(const std::string )


{   


return "_" + in;


}   


```
which causes an assertion failure:
```
clang-tidy: /home/mac/git/llvm-project/clang/include/clang/AST/Decl.h:275: 
llvm::StringRef clang::NamedDecl::getName() const: Assertion 
`Name.isIdentifier() && "Name is not a simple identifier"' failed.
```
when the `StrFormatLikeFunctions` option is set to an unqualified name:
```
-config="{CheckOptions: [{key: modernize-use-std-format.StrictMode, value: 
false}, {key: modernize-use-std-format.StrFormatLikeFunctions, value: 
'strprintf'}]}"
```

`MatchesAnyListedNameMatcher::NameMatcher::match` calls `NamedDecl.getName()` 
which presumably raises the assertion due to the `operator+` not having a name 
(that's mentioned in the source anyway.)

I'm unsure whether I should be narrowing the matcher here so that it guaranteed 
to not try calling `matchesAnyListedName` on something that lacks a name, or 
whether `MatchesAnyListedNameMatcher` ought to be more tolerant of being called 
in such situations.

I note that `HasNameMatcher` has rather more elaborate code for generating the 
name than `MatchesAnyListedNameMatcher` does.

This problem also affects `modernize-use-std-print`, but due to the need for 
there to be no return value in that check it requires somewhat-unlikely code 
like:
```
void A(const std::string )
{
  "_" + in;
}
```

Do you have any advice? Given that this problem affects a check that has 
already landed should I open a bug?



Comment at: clang-tools-extra/clang-tidy/modernize/UseStdFormatCheck.cpp:47
+  Finder->addMatcher(
+  callExpr(argumentCountAtLeast(1), hasArgument(0, stringLiteral()),
+   callee(functionDecl(matchers::matchesAnyListedName(

I need to add an `isOrdinary()` call here like `modernize-use-std-print` has.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D154287

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D154287: [clang-tidy] Add modernize-use-std-format check

2023-07-09 Thread Mike Crowe via Phabricator via cfe-commits
mikecrowe updated this revision to Diff 538427.
mikecrowe marked 3 inline comments as done.
mikecrowe added a comment.

Address review comments and improve documentation.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D154287

Files:
  clang-tools-extra/clang-tidy/modernize/CMakeLists.txt
  clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp
  clang-tools-extra/clang-tidy/modernize/UseStdFormatCheck.cpp
  clang-tools-extra/clang-tidy/modernize/UseStdFormatCheck.h
  clang-tools-extra/clang-tidy/modernize/UseStdPrintCheck.cpp
  clang-tools-extra/clang-tidy/utils/FormatStringConverter.cpp
  clang-tools-extra/clang-tidy/utils/FormatStringConverter.h
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  clang-tools-extra/docs/clang-tidy/checks/modernize/use-std-format.rst
  clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-format-custom.cpp
  clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-format-fmt.cpp
  clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-format.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-format.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-format.cpp
@@ -0,0 +1,75 @@
+// RUN: %check_clang_tidy \
+// RUN:   -std=c++20 %s modernize-use-std-format %t -- \
+// RUN:   -config="{CheckOptions: [{key: StrictMode, value: true}]}" \
+// RUN:   -- -isystem %clang_tidy_headers
+// RUN: %check_clang_tidy \
+// RUN:   -std=c++20 %s modernize-use-std-format %t -- \
+// RUN:   -config="{CheckOptions: [{key: StrictMode, value: false}]}" \
+// RUN:   -- -isystem %clang_tidy_headers
+#include 
+// CHECK-FIXES: #include 
+
+namespace absl
+{
+// Use const char * for the format since the real type is hard to mock up.
+template 
+std::string StrFormat(const char *format, const Args&... args);
+} // namespace absl
+
+std::string StrFormat_simple() {
+  return absl::StrFormat("Hello");
+  // CHECK-MESSAGES: [[@LINE-1]]:10: warning: use 'std::format' instead of 'StrFormat' [modernize-use-std-format]
+  // CHECK-FIXES: return std::format("Hello");
+}
+
+std::string StrFormat_complex(const char *name, double value) {
+  return absl::StrFormat("'%s'='%f'", name, value);
+  // CHECK-MESSAGES: [[@LINE-1]]:10: warning: use 'std::format' instead of 'StrFormat' [modernize-use-std-format]
+  // CHECK-FIXES: return std::format("'{}'='{:f}'", name, value);
+}
+
+std::string StrFormat_integer_conversions() {
+  return absl::StrFormat("int:%d int:%d char:%c char:%c", 65, 'A', 66, 'B');
+  // CHECK-MESSAGES: [[@LINE-1]]:10: warning: use 'std::format' instead of 'StrFormat' [modernize-use-std-format]
+  // CHECK-FIXES: return std::format("int:{} int:{:d} char:{:c} char:{}", 65, 'A', 66, 'B');
+}
+
+// FormatConverter is capable of removing newlines from the end of the format
+// string. Ensure that isn't incorrectly happening for std::format.
+std::string StrFormat_no_newline_removal() {
+  return absl::StrFormat("a line\n");
+  // CHECK-MESSAGES: [[@LINE-1]]:10: warning: use 'std::format' instead of 'StrFormat' [modernize-use-std-format]
+  // CHECK-FIXES: return std::format("a line\n");
+}
+
+// FormatConverter is capable of removing newlines from the end of the format
+// string. Ensure that isn't incorrectly happening for std::format.
+std::string StrFormat_cstr_removal(const std::string , const std::string *s2) {
+  return absl::StrFormat("%s %s %s %s", s1.c_str(), s1.data(), s2->c_str(), s2->data());
+  // CHECK-MESSAGES: [[@LINE-1]]:10: warning: use 'std::format' instead of 'StrFormat' [modernize-use-std-format]
+  // CHECK-FIXES: return std::format("{} {} {} {}", s1, s1, *s2, *s2);
+}
+
+std::string StrFormat_strict_conversion() {
+  const unsigned char uc = 'A';
+  return absl::StrFormat("Integer %hhd from unsigned char\n", uc);
+  // CHECK-MESSAGES: [[@LINE-1]]:10: warning: use 'std::format' instead of 'StrFormat' [modernize-use-std-format]
+  // CHECK-FIXES: return std::format("Integer {} from unsigned char\n", uc);
+}
+
+std::string StrFormat_field_width_and_precision() {
+  auto s1 = absl::StrFormat("width only:%*d width and precision:%*.*f precision only:%.*f", 3, 42, 4, 2, 3.14159265358979323846, 5, 2.718);
+  // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use 'std::format' instead of 'StrFormat' [modernize-use-std-format]
+  // CHECK-FIXES: std::format("width only:{:{}} width and precision:{:{}.{}f} precision only:{:.{}f}", 42, 3, 3.14159265358979323846, 4, 2, 2.718, 5);
+
+  auto s2 = absl::StrFormat("width and precision positional:%1$*2$.*3$f after", 3.14159265358979323846, 4, 2);
+  // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use 'std::format' instead of 'StrFormat' [modernize-use-std-format]
+  // CHECK-FIXES: std::format("width and precision positional:{0:{1}.{2}f} after", 3.14159265358979323846, 4, 2);
+
+  

[PATCH] D154788: [clang-tidy] Don't split \r\n in modernize-use-std-print check

2023-07-09 Thread Mike Crowe via Phabricator via cfe-commits
mikecrowe created this revision.
mikecrowe added a reviewer: PiotrZSL.
Herald added subscribers: carlosgalvezp, xazax.hun.
Herald added a reviewer: njames93.
Herald added a project: All.
mikecrowe requested review of this revision.
Herald added a project: clang-tools-extra.
Herald added a subscriber: cfe-commits.

When given:
 printf("Hello\r\n");

it's clearer to leave the CRLF intact and convert this to:
 std::print("Hello\r\n");

than to remove the trailing newline and convert it to:
 std::println("Hello\r");

Update the documentation to match, and clarify the situations for using
println vs print which weren't previously explained.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D154788

Files:
  clang-tools-extra/clang-tidy/utils/FormatStringConverter.cpp
  clang-tools-extra/docs/clang-tidy/checks/modernize/use-std-print.rst
  clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print.cpp


Index: clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print.cpp
===
--- clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print.cpp
@@ -44,6 +44,16 @@
   // CHECK-FIXES: std::println("Hello");
 }
 
+void printf_crlf_newline() {
+  printf("Hello\r\n");
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 
'printf' [modernize-use-std-print]
+  // CHECK-FIXES: std::print("Hello\r\n");
+
+  printf("Hello\r\\n");
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 
'printf' [modernize-use-std-print]
+  // CHECK-FIXES: std::print("Hello\r\\n");
+}
+
 // std::print returns nothing, so any callers that use the return
 // value cannot be automatically translated.
 int printf_uses_return_value(int choice) {
Index: clang-tools-extra/docs/clang-tidy/checks/modernize/use-std-print.rst
===
--- clang-tools-extra/docs/clang-tidy/checks/modernize/use-std-print.rst
+++ clang-tools-extra/docs/clang-tidy/checks/modernize/use-std-print.rst
@@ -70,8 +70,10 @@
   `FprintfLikeFunctions` are replaced with the function specified by the
   `ReplacementPrintlnFunction` option if the format string ends with ``\n``
   or `ReplacementPrintFunction` otherwise.
-- the format string is rewritten to use the ``std::formatter`` language and
-  a ``\n`` is removed from the end.
+- the format string is rewritten to use the ``std::formatter`` language. If
+  a ``\n`` is found at the end of the format string not preceded by ``r``
+  then it is removed and `ReplacementPrintlnFunction` is used rather than
+  `ReplacementPrintFunction`.
 - any arguments that corresponded to ``%p`` specifiers that
   ``std::formatter`` wouldn't accept are wrapped in a ``static_cast``
   to ``const void *``.
Index: clang-tools-extra/clang-tidy/utils/FormatStringConverter.cpp
===
--- clang-tools-extra/clang-tidy/utils/FormatStringConverter.cpp
+++ clang-tools-extra/clang-tidy/utils/FormatStringConverter.cpp
@@ -623,8 +623,11 @@
 PrintfFormatString.size() - PrintfFormatStringPos));
   PrintfFormatStringPos = PrintfFormatString.size();
 
+  // It's clearer to convert printf("Hello\r\n"); to std::print("Hello\r\n")
+  // than to std::println("Hello\r");
   if (StringRef(StandardFormatString).ends_with("\\n") &&
-  !StringRef(StandardFormatString).ends_with("n")) {
+  !StringRef(StandardFormatString).ends_with("n") &&
+  !StringRef(StandardFormatString).ends_with("\\r\\n")) {
 UsePrintNewlineFunction = true;
 FormatStringNeededRewriting = true;
 StandardFormatString.erase(StandardFormatString.end() - 2,


Index: clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print.cpp
===
--- clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print.cpp
@@ -44,6 +44,16 @@
   // CHECK-FIXES: std::println("Hello");
 }
 
+void printf_crlf_newline() {
+  printf("Hello\r\n");
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'printf' [modernize-use-std-print]
+  // CHECK-FIXES: std::print("Hello\r\n");
+
+  printf("Hello\r\\n");
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'printf' [modernize-use-std-print]
+  // CHECK-FIXES: std::print("Hello\r\\n");
+}
+
 // std::print returns nothing, so any callers that use the return
 // value cannot be automatically translated.
 int printf_uses_return_value(int choice) {
Index: clang-tools-extra/docs/clang-tidy/checks/modernize/use-std-print.rst
===
--- clang-tools-extra/docs/clang-tidy/checks/modernize/use-std-print.rst
+++ 

[PATCH] D154287: [clang-tidy] Add modernize-use-std-format check

2023-07-09 Thread Mike Crowe via Phabricator via cfe-commits
mikecrowe marked 9 inline comments as done.
mikecrowe added a comment.

Thanks for the reviews!




Comment at: clang-tools-extra/clang-tidy/modernize/UseStdFormatCheck.cpp:81
+ << ReplacementFormatFunction
+ << OldFunction->getIdentifier()
+ << Converter.conversionNotPossibleReason();

PiotrZSL wrote:
> using ``<< OldFunction`` should be sufficient and more safe, same in line 88
I don't think that's the same. If I use just `OldFunction` then I get the 
template arguments in strings like `StrFormat` and `sprintf` when I just want `StrFormat` 
and `sprintf` respectively.



Comment at: clang-tools-extra/clang-tidy/utils/FormatStringConverter.cpp:629-630
+  if (Config.AllowTrailingNewlineRemoval &&
+  StringRef(StandardFormatString).ends_with("\\n") &&
   !StringRef(StandardFormatString).ends_with("n")) {
 UsePrintNewlineFunction = true;

PiotrZSL wrote:
> what if it's ends with Windows new line style ? Will it work ?
Good point. Your question actually relates to the `modernize-use-std-print` 
check only since `config.AllowTrailingNewlineRemoval` is always `false` in this 
check.

`std::println` is [[ https://en.cppreference.com/w/cpp/io/println | described 
]] as just appending `\n` to the end of the formatted string when written to 
the desired output. The code here means that `printf("A\r\n")` would be 
converted to `std::println("A\r")` which would behave in the same way, though I 
would admit that it's rather confusing.

This situation isn't really Windows-specific. Most the of the time a POSIX tty 
would be in cooked mode, so the `\r` would be added automatically before the 
`\n`. However, when the tty is in raw mode using `\r\n` line endings would be 
necessary there too, just as they might be on Windows when writing to a binary 
stream.

I think that the least confusing outcome would be for this code to not consider 
format strings that end with `\r\n`  to be suitable for conversion to 
`std::println` and let them use `std::print` instead. I think that this better 
reflects the intent of the existing code.

I will prepare a separate change for this.



Comment at: 
clang-tools-extra/docs/clang-tidy/checks/modernize/use-std-format.rst:27
+The check uses the same format-string-conversion algorithm as
+`modernize-use-std-print ` and its
+shortcomings are described in the documentation for that check.

PiotrZSL wrote:
> is this link correct ? shouldn't this be put into `doc:`, verify if its 
> working
It was wrong, but I believe that I've fixed it.



Comment at: 
clang-tools-extra/docs/clang-tidy/checks/modernize/use-std-format.rst:33
+
+.. option:: StrictMode TODO
+

PiotrZSL wrote:
> If not implemented, do not add it
It is implemented, I just forgot to remove the TODO.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D154287

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D154283: [clang-tidy] Fix width/precision argument order in modernize-use-std-print

2023-07-02 Thread Mike Crowe via Phabricator via cfe-commits
mikecrowe added inline comments.



Comment at: clang-tools-extra/clang-tidy/utils/FormatStringConverter.h:73
+  // puts the width and preicision first.
+  std::vector> ArgRotates;
+

PiotrZSL wrote:
> mikecrowe wrote:
> > PiotrZSL wrote:
> > > NOTE: You can use std::pair here.
> > True, but in my mind `std::pair` only exists because `std::tuple` couldn't 
> > be implemented in the C++98.
> > 
> > I was going to change it to use `std::pair` anyway, but I notice that I 
> > already use `std::tuple` for `ArgFixes` just above. Should I change both of 
> > them?
> It will be compiled to same thing anyway. So it's up to you. Keep it 
> consistent.
> I personally use std::pair for 2 arguments, and std::tuple for more than 2.
> But to be honest probably better would be to introduce some structure so that 
> those two `unsigned` could be named. And probably same for ArgFixes, but 
> there we got different types, so it's not a big problem.
I think that you're probably right, but the names won't be used from the call 
site since I use structured binding there. Do you mind if I do both together in 
a separate commit?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D154283

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D154283: [clang-tidy] Fix width/precision argument order in modernize-use-std-print

2023-07-02 Thread Mike Crowe via Phabricator via cfe-commits
mikecrowe updated this revision to Diff 536595.
mikecrowe added a comment.

Use emplace_back rather than push_back(make_tuple())


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D154283

Files:
  clang-tools-extra/clang-tidy/utils/FormatStringConverter.cpp
  clang-tools-extra/clang-tidy/utils/FormatStringConverter.h
  clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print.cpp
===
--- clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print.cpp
@@ -1024,7 +1024,7 @@
 
   printf("Right-justified integer with field width argument %*d after\n", 5, 424242);
   // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
-  // CHECK-FIXES: std::println("Right-justified integer with field width argument {:{}} after", 5, 424242);
+  // CHECK-FIXES: std::println("Right-justified integer with field width argument {:{}} after", 424242, 5);
 
   printf("Right-justified integer with field width argument %2$*1$d after\n", 5, 424242);
   // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
@@ -1061,7 +1061,7 @@
 
   printf("Left-justified integer with field width argument %-*d after\n", 5, 424242);
   // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
-  // CHECK-FIXES: std::println("Left-justified integer with field width argument {:<{}} after", 5, 424242);
+  // CHECK-FIXES: std::println("Left-justified integer with field width argument {:<{}} after", 424242, 5);
 
   printf("Left-justified integer with field width argument %2$-*1$d after\n", 5, 424242);
   // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
@@ -1087,15 +1087,15 @@
 
   printf("Hello %.*f after\n", 10, 3.14159265358979323846);
   // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
-  // CHECK-FIXES: std::println("Hello {:.{}f} after", 10, 3.14159265358979323846);
+  // CHECK-FIXES: std::println("Hello {:.{}f} after", 3.14159265358979323846, 10);
 
   printf("Hello %10.*f after\n", 3, 3.14159265358979323846);
   // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
-  // CHECK-FIXES: std::println("Hello {:10.{}f} after", 3, 3.14159265358979323846);
+  // CHECK-FIXES: std::println("Hello {:10.{}f} after", 3.14159265358979323846, 3);
 
   printf("Hello %*.*f after\n", 10, 4, 3.14159265358979323846);
   // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
-  // CHECK-FIXES: std::println("Hello {:{}.{}f} after", 10, 4, 3.14159265358979323846);
+  // CHECK-FIXES: std::println("Hello {:{}.{}f} after", 3.14159265358979323846, 10, 4);
 
   printf("Hello %1$.*2$f after\n", 3.14159265358979323846, 4);
   // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
@@ -1112,9 +1112,33 @@
 }
 
 void printf_field_width_and_precision() {
-  printf("Hello %1$*2$.*3$f after\n", 3.14159265358979323846, 4, 2);
+  printf("width only:%*d width and precision:%*.*f precision only:%.*f\n", 3, 42, 4, 2, 3.14159265358979323846, 5, 2.718);
   // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
-  // CHECK-FIXES: std::println("Hello {0:{1}.{2}f} after", 3.14159265358979323846, 4, 2);
+  // CHECK-FIXES: std::println("width only:{:{}} width and precision:{:{}.{}f} precision only:{:.{}f}", 42, 3, 3.14159265358979323846, 4, 2, 2.718, 5);
+
+  printf("width and precision positional:%1$*2$.*3$f after\n", 3.14159265358979323846, 4, 2);
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
+  // CHECK-FIXES: std::println("width and precision positional:{0:{1}.{2}f} after", 3.14159265358979323846, 4, 2);
+
+  const int width = 10, precision = 3;
+  printf("width only:%3$*1$d width and precision:%4$*1$.*2$f precision only:%5$.*2$f\n", width, precision, 42, 3.1415926, 2.718);
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
+  // CHECK-FIXES: std::println("width only:{2:{0}} width and precision:{3:{0}.{1}f} precision only:{4:.{1}f}", width, precision, 42, 3.1415926, 2.718);
+}
+
+void fprintf_field_width_and_precision() {
+  fprintf(stderr, "width only:%*d width and precision:%*.*f precision only:%.*f\n", 3, 42, 4, 2, 3.14159265358979323846, 5, 2.718);
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'fprintf' [modernize-use-std-print]
+  // CHECK-FIXES: 

[PATCH] D154283: [clang-tidy] Fix width/precision argument order in modernize-use-std-print

2023-07-02 Thread Mike Crowe via Phabricator via cfe-commits
mikecrowe added a comment.

Thanks for the review.




Comment at: clang-tools-extra/clang-tidy/utils/FormatStringConverter.cpp:356-357
+  if (ArgCount)
+ArgRotates.push_back(
+std::make_tuple(FS.getArgIndex() + ArgsOffset, ArgCount));
+}

PiotrZSL wrote:
> 
Good point.



Comment at: clang-tools-extra/clang-tidy/utils/FormatStringConverter.h:73
+  // puts the width and preicision first.
+  std::vector> ArgRotates;
+

PiotrZSL wrote:
> NOTE: You can use std::pair here.
True, but in my mind `std::pair` only exists because `std::tuple` couldn't be 
implemented in the C++98.

I was going to change it to use `std::pair` anyway, but I notice that I already 
use `std::tuple` for `ArgFixes` just above. Should I change both of them?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D154283

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D154287: [clang-tidy] Add modernize-use-std-format check

2023-07-01 Thread Mike Crowe via Phabricator via cfe-commits
mikecrowe created this revision.
mikecrowe added a reviewer: PiotrZSL.
Herald added subscribers: carlosgalvezp, xazax.hun.
Herald added a reviewer: njames93.
Herald added a project: All.
mikecrowe requested review of this revision.
Herald added a project: clang-tools-extra.
Herald added a subscriber: cfe-commits.

Add a new clang-tidy check that converts absl::StrFormat (and similar
functions) to std::format (and similar functions.)

Separate the configuration of FormatStringConverter out to a separate
Configuration class so that we don't risk confusion by passing two
boolean configuration parameters into the constructor. Add
AllowTrailingNewlineRemoval option since we never want to remove
trailing newlines in this check.

Depends on D154283 


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D154287

Files:
  clang-tools-extra/clang-tidy/modernize/CMakeLists.txt
  clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp
  clang-tools-extra/clang-tidy/modernize/UseStdFormatCheck.cpp
  clang-tools-extra/clang-tidy/modernize/UseStdFormatCheck.h
  clang-tools-extra/clang-tidy/modernize/UseStdPrintCheck.cpp
  clang-tools-extra/clang-tidy/utils/FormatStringConverter.cpp
  clang-tools-extra/clang-tidy/utils/FormatStringConverter.h
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  clang-tools-extra/docs/clang-tidy/checks/modernize/use-std-format.rst
  clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-format-custom.cpp
  clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-format-fmt.cpp
  clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-format.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-format.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-format.cpp
@@ -0,0 +1,75 @@
+// RUN: %check_clang_tidy \
+// RUN:   -std=c++20 %s modernize-use-std-format %t -- \
+// RUN:   -config="{CheckOptions: [{key: StrictMode, value: true}]}" \
+// RUN:   -- -isystem %clang_tidy_headers
+// RUN: %check_clang_tidy \
+// RUN:   -std=c++20 %s modernize-use-std-format %t -- \
+// RUN:   -config="{CheckOptions: [{key: StrictMode, value: false}]}" \
+// RUN:   -- -isystem %clang_tidy_headers
+#include 
+// CHECK-FIXES: #include 
+
+namespace absl
+{
+// Use const char * for the format since the real type is hard to mock up.
+template 
+std::string StrFormat(const char *format, const Args&... args);
+} // namespace absl
+
+std::string StrFormat_simple() {
+  return absl::StrFormat("Hello");
+  // CHECK-MESSAGES: [[@LINE-1]]:10: warning: use 'std::format' instead of 'StrFormat' [modernize-use-std-format]
+  // CHECK-FIXES: return std::format("Hello");
+}
+
+std::string StrFormat_complex(const char *name, double value) {
+  return absl::StrFormat("'%s'='%f'", name, value);
+  // CHECK-MESSAGES: [[@LINE-1]]:10: warning: use 'std::format' instead of 'StrFormat' [modernize-use-std-format]
+  // CHECK-FIXES: return std::format("'{}'='{:f}'", name, value);
+}
+
+std::string StrFormat_integer_conversions() {
+  return absl::StrFormat("int:%d int:%d char:%c char:%c", 65, 'A', 66, 'B');
+  // CHECK-MESSAGES: [[@LINE-1]]:10: warning: use 'std::format' instead of 'StrFormat' [modernize-use-std-format]
+  // CHECK-FIXES: return std::format("int:{} int:{:d} char:{:c} char:{}", 65, 'A', 66, 'B');
+}
+
+// FormatConverter is capable of removing newlines from the end of the format
+// string. Ensure that isn't incorrectly happening for std::format.
+std::string StrFormat_no_newline_removal() {
+  return absl::StrFormat("a line\n");
+  // CHECK-MESSAGES: [[@LINE-1]]:10: warning: use 'std::format' instead of 'StrFormat' [modernize-use-std-format]
+  // CHECK-FIXES: return std::format("a line\n");
+}
+
+// FormatConverter is capable of removing newlines from the end of the format
+// string. Ensure that isn't incorrectly happening for std::format.
+std::string StrFormat_cstr_removal(const std::string , const std::string *s2) {
+  return absl::StrFormat("%s %s %s %s", s1.c_str(), s1.data(), s2->c_str(), s2->data());
+  // CHECK-MESSAGES: [[@LINE-1]]:10: warning: use 'std::format' instead of 'StrFormat' [modernize-use-std-format]
+  // CHECK-FIXES: return std::format("{} {} {} {}", s1, s1, *s2, *s2);
+}
+
+std::string StrFormat_strict_conversion() {
+  const unsigned char uc = 'A';
+  return absl::StrFormat("Integer %hhd from unsigned char\n", uc);
+  // CHECK-MESSAGES: [[@LINE-1]]:10: warning: use 'std::format' instead of 'StrFormat' [modernize-use-std-format]
+  // CHECK-FIXES: return std::format("Integer {} from unsigned char\n", uc);
+}
+
+std::string StrFormat_field_width_and_precision() {
+  auto s1 = absl::StrFormat("width only:%*d width and precision:%*.*f precision only:%.*f", 3, 42, 4, 2, 3.14159265358979323846, 5, 2.718);
+  // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use 'std::format' 

[PATCH] D154283: [clang-tidy] Fix width/precision argument order in modernize-use-std-print

2023-07-01 Thread Mike Crowe via Phabricator via cfe-commits
mikecrowe created this revision.
mikecrowe added a reviewer: PiotrZSL.
Herald added subscribers: carlosgalvezp, xazax.hun.
Herald added a reviewer: njames93.
Herald added a project: All.
mikecrowe requested review of this revision.
Herald added a project: clang-tools-extra.
Herald added a subscriber: cfe-commits.

Victor Zverovich pointed out[1] that printf takes the field width and
precision arguments before the value to be printed whereas std::print
takes the value first (unless positional arguments are used.) Many of
the test cases in use-std-print.cpp were incorrect.

Teach the check to rotate the arguments when required to correct
this. Correct the test cases and add more.

[1] https://github.com/fmtlib/fmt/pull/3515#issuecomment-1615259893


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D154283

Files:
  clang-tools-extra/clang-tidy/utils/FormatStringConverter.cpp
  clang-tools-extra/clang-tidy/utils/FormatStringConverter.h
  clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print.cpp
===
--- clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print.cpp
@@ -1024,7 +1024,7 @@
 
   printf("Right-justified integer with field width argument %*d after\n", 5, 424242);
   // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
-  // CHECK-FIXES: std::println("Right-justified integer with field width argument {:{}} after", 5, 424242);
+  // CHECK-FIXES: std::println("Right-justified integer with field width argument {:{}} after", 424242, 5);
 
   printf("Right-justified integer with field width argument %2$*1$d after\n", 5, 424242);
   // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
@@ -1061,7 +1061,7 @@
 
   printf("Left-justified integer with field width argument %-*d after\n", 5, 424242);
   // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
-  // CHECK-FIXES: std::println("Left-justified integer with field width argument {:<{}} after", 5, 424242);
+  // CHECK-FIXES: std::println("Left-justified integer with field width argument {:<{}} after", 424242, 5);
 
   printf("Left-justified integer with field width argument %2$-*1$d after\n", 5, 424242);
   // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
@@ -1087,15 +1087,15 @@
 
   printf("Hello %.*f after\n", 10, 3.14159265358979323846);
   // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
-  // CHECK-FIXES: std::println("Hello {:.{}f} after", 10, 3.14159265358979323846);
+  // CHECK-FIXES: std::println("Hello {:.{}f} after", 3.14159265358979323846, 10);
 
   printf("Hello %10.*f after\n", 3, 3.14159265358979323846);
   // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
-  // CHECK-FIXES: std::println("Hello {:10.{}f} after", 3, 3.14159265358979323846);
+  // CHECK-FIXES: std::println("Hello {:10.{}f} after", 3.14159265358979323846, 3);
 
   printf("Hello %*.*f after\n", 10, 4, 3.14159265358979323846);
   // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
-  // CHECK-FIXES: std::println("Hello {:{}.{}f} after", 10, 4, 3.14159265358979323846);
+  // CHECK-FIXES: std::println("Hello {:{}.{}f} after", 3.14159265358979323846, 10, 4);
 
   printf("Hello %1$.*2$f after\n", 3.14159265358979323846, 4);
   // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
@@ -1112,9 +1112,33 @@
 }
 
 void printf_field_width_and_precision() {
-  printf("Hello %1$*2$.*3$f after\n", 3.14159265358979323846, 4, 2);
+  printf("width only:%*d width and precision:%*.*f precision only:%.*f\n", 3, 42, 4, 2, 3.14159265358979323846, 5, 2.718);
   // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
-  // CHECK-FIXES: std::println("Hello {0:{1}.{2}f} after", 3.14159265358979323846, 4, 2);
+  // CHECK-FIXES: std::println("width only:{:{}} width and precision:{:{}.{}f} precision only:{:.{}f}", 42, 3, 3.14159265358979323846, 4, 2, 2.718, 5);
+
+  printf("width and precision positional:%1$*2$.*3$f after\n", 3.14159265358979323846, 4, 2);
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
+  // CHECK-FIXES: std::println("width and precision positional:{0:{1}.{2}f} after", 3.14159265358979323846, 4, 2);
+
+  const int width = 10, precision = 3;
+  printf("width only:%3$*1$d width and precision:%4$*1$.*2$f precision only:%5$.*2$f\n", width, precision, 42, 3.1415926, 2.718);
+  // 

[PATCH] D154151: [clang-tidy] Improve documentation for modernize-use-std-print check

2023-06-29 Thread Mike Crowe via Phabricator via cfe-commits
mikecrowe created this revision.
mikecrowe added a reviewer: PiotrZSL.
Herald added subscribers: carlosgalvezp, xazax.hun.
Herald added a reviewer: njames93.
Herald added a project: All.
mikecrowe requested review of this revision.
Herald added a project: clang-tools-extra.
Herald added a subscriber: cfe-commits.

Remove incorrect use of double colons so that the code blocks are
rendered correctly to HTML.

Wrap the name of another check in single backticks. Wrap the name of a
macro in double backticks.

Explain that with the default settings the check is only enabled with
C++23 or later standards.

Correct std::string_data() to std::string::data().


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D154151

Files:
  clang-tools-extra/docs/clang-tidy/checks/modernize/use-std-print.rst


Index: clang-tools-extra/docs/clang-tidy/checks/modernize/use-std-print.rst
===
--- clang-tools-extra/docs/clang-tidy/checks/modernize/use-std-print.rst
+++ clang-tools-extra/docs/clang-tidy/checks/modernize/use-std-print.rst
@@ -9,21 +9,25 @@
 The replaced and replacement functions can be customised by configuration
 options. Each argument that is the result of a call to 
``std::string::c_str()`` and
 ``std::string::data()`` will have that now-unnecessary call removed in a
-similar manner to the readability-redundant-string-cstr check.
+similar manner to the `readability-redundant-string-cstr` check.
 
-In other words, it turns lines like::
+In other words, it turns lines like:
 
 .. code-block:: c++
 
   fprintf(stderr, "The %s is %3d\n", description.c_str(), value);
 
-into::
+into:
 
 .. code-block:: c++
 
   std::println(stderr, "The {} is {:3}", description, value);
 
-It doesn't do a bad job, but it's not perfect. In particular:
+If the `ReplacementPrintFunction` or `ReplacementPrintlnFunction` options
+are left, or assigned to their default values then this check is only
+enabled with `-std=c++23` or later.
+
+The check doesn't do a bad job, but it's not perfect. In particular:
 
 - It assumes that the format string is correct for the arguments. If you
   get any warnings when compiling with `-Wformat` then misbehaviour is
@@ -35,7 +39,7 @@
   handled. Although it's possible for the check to automatically put the
   escapes back, they may not be exactly as they were written (e.g.
   ``"\x0a"`` will become ``"\n"`` and ``"ab" "cd"`` will become
-  ``"abcd"``.) This is helpful since it means that the PRIx macros from
+  ``"abcd"``.) This is helpful since it means that the ``PRIx`` macros from
    are removed correctly.
 
 - It supports field widths, precision, positional arguments, leading zeros,
@@ -78,7 +82,7 @@
   signedness will be wrapped in an approprate ``static_cast`` if `StrictMode`
   is enabled.
 - any arguments that end in a call to ``std::string::c_str()`` or
-  ``std::string_data()`` will have that call removed.
+  ``std::string::data()`` will have that call removed.
 
 Options
 ---
@@ -99,7 +103,7 @@
 unsigned int u = 0x;
 printf("%d %u\n", i, u);
 
-  would be converted to::
+  would be converted to:
 
   .. code-block:: c++
 


Index: clang-tools-extra/docs/clang-tidy/checks/modernize/use-std-print.rst
===
--- clang-tools-extra/docs/clang-tidy/checks/modernize/use-std-print.rst
+++ clang-tools-extra/docs/clang-tidy/checks/modernize/use-std-print.rst
@@ -9,21 +9,25 @@
 The replaced and replacement functions can be customised by configuration
 options. Each argument that is the result of a call to ``std::string::c_str()`` and
 ``std::string::data()`` will have that now-unnecessary call removed in a
-similar manner to the readability-redundant-string-cstr check.
+similar manner to the `readability-redundant-string-cstr` check.
 
-In other words, it turns lines like::
+In other words, it turns lines like:
 
 .. code-block:: c++
 
   fprintf(stderr, "The %s is %3d\n", description.c_str(), value);
 
-into::
+into:
 
 .. code-block:: c++
 
   std::println(stderr, "The {} is {:3}", description, value);
 
-It doesn't do a bad job, but it's not perfect. In particular:
+If the `ReplacementPrintFunction` or `ReplacementPrintlnFunction` options
+are left, or assigned to their default values then this check is only
+enabled with `-std=c++23` or later.
+
+The check doesn't do a bad job, but it's not perfect. In particular:
 
 - It assumes that the format string is correct for the arguments. If you
   get any warnings when compiling with `-Wformat` then misbehaviour is
@@ -35,7 +39,7 @@
   handled. Although it's possible for the check to automatically put the
   escapes back, they may not be exactly as they were written (e.g.
   ``"\x0a"`` will become ``"\n"`` and ``"ab" "cd"`` will become
-  ``"abcd"``.) This is helpful since it means that the PRIx macros from
+  ``"abcd"``.) This is helpful since it means that the ``PRIx`` macros from
    are 

[PATCH] D153860: [clang-tidy] Fix modernize-use-std-print check when return value used

2023-06-29 Thread Mike Crowe via Phabricator via cfe-commits
mikecrowe requested review of this revision.
mikecrowe added a comment.

I believe that the problems that caused this to be reverted have been fixed.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D153860

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D153860: [clang-tidy] Fix modernize-use-std-print check when return value used

2023-06-27 Thread Mike Crowe via Phabricator via cfe-commits
mikecrowe updated this revision to Diff 535106.
mikecrowe added a comment.

Fix test failures on PS4 and PS5 and improve tests

- Ensure that exceptions are available so the test can use try/catch
- Remove unwanted -NOT checks
- Add more return value tests


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D153860

Files:
  clang-tools-extra/clang-tidy/modernize/UseStdPrintCheck.cpp
  clang-tools-extra/docs/clang-tidy/checks/modernize/use-std-print.rst
  clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print-absl.cpp
  clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print-custom.cpp
  clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print.cpp
===
--- clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print.cpp
@@ -1,11 +1,11 @@
 // RUN: %check_clang_tidy -check-suffixes=,STRICT \
 // RUN:   -std=c++23 %s modernize-use-std-print %t -- \
 // RUN:   -config="{CheckOptions: [{key: StrictMode, value: true}]}" \
-// RUN:   -- -isystem %clang_tidy_headers
+// RUN:   -- -isystem %clang_tidy_headers -fexceptions
 // RUN: %check_clang_tidy -check-suffixes=,NOTSTRICT \
 // RUN:   -std=c++23 %s modernize-use-std-print %t -- \
 // RUN:   -config="{CheckOptions: [{key: StrictMode, value: false}]}" \
-// RUN:   -- -isystem %clang_tidy_headers
+// RUN:   -- -isystem %clang_tidy_headers -fexceptions
 #include 
 #include 
 #include 
@@ -44,6 +44,239 @@
   // CHECK-FIXES: std::println("Hello");
 }
 
+// std::print returns nothing, so any callers that use the return
+// value cannot be automatically translated.
+int printf_uses_return_value(int choice) {
+  const int i = printf("Return value assigned to variable %d\n", 42);
+
+  extern void accepts_int(int);
+  accepts_int(printf("Return value passed to function %d\n", 42));
+
+  if (choice == 0)
+printf("if body %d\n", i);
+// CHECK-MESSAGES: [[@LINE-1]]:5: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
+// CHECK-FIXES: std::println("if body {}", i);
+  else if (choice == 1)
+printf("else if body %d\n", i);
+// CHECK-MESSAGES: [[@LINE-1]]:5: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
+// CHECK-FIXES: std::println("else if body {}", i);
+  else
+printf("else body %d\n", i);
+// CHECK-MESSAGES: [[@LINE-1]]:5: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
+// CHECK-FIXES: std::println("else body {}", i);
+
+  if (printf("Return value used as boolean in if statement"))
+if (printf("Return value used in expression if statement") == 44)
+  if (const int j = printf("Return value used in assignment in if statement"))
+if (const int k = printf("Return value used with initializer in if statement"); k == 44)
+  ;
+
+  int d = 0;
+  while (printf("%d", d) < 2)
+++d;
+
+  while (true)
+printf("while body %d\n", i);
+// CHECK-MESSAGES: [[@LINE-1]]:5: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
+// CHECK-FIXES: std::println("while body {}", i);
+
+  do
+printf("do body %d\n", i);
+// CHECK-MESSAGES: [[@LINE-1]]:5: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
+// CHECK-FIXES: std::println("do body {}", i);
+  while (true);
+
+  for (;;)
+printf("for body %d\n", i);
+// CHECK-MESSAGES: [[@LINE-1]]:5: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
+// CHECK-FIXES: std::println("for body {}", i);
+
+  for (printf("for init statement %d\n", i);;)
+// CHECK-MESSAGES: [[@LINE-1]]:8: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
+// CHECK-FIXES: std::println("for init statement {}", i);
+;;
+
+  for (int j = printf("for init statement %d\n", i);;)
+;;
+
+  for (; printf("for condition %d\n", i);)
+;;
+
+  for (;; printf("for expression %d\n", i))
+// CHECK-MESSAGES: [[@LINE-1]]:11: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
+// CHECK-FIXES: std::println("for expression {}", i)
+;;
+
+  for (auto C : "foo")
+printf("ranged-for body %d\n", i);
+// CHECK-MESSAGES: [[@LINE-1]]:5: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
+// CHECK-FIXES: std::println("ranged-for body {}", i);
+
+  switch (1) {
+  case 1:
+printf("switch case body %d\n", i);
+// CHECK-MESSAGES: [[@LINE-1]]:5: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
+// CHECK-FIXES: std::println("switch case body {}", i);
+break;
+  default:
+printf("switch default body %d\n", i);
+// CHECK-MESSAGES: [[@LINE-1]]:5: warning: use 'std::println' instead of 

[PATCH] D153860: [clang-tidy] Fix modernize-use-std-print check when return value used

2023-06-27 Thread Mike Crowe via Phabricator via cfe-commits
mikecrowe marked an inline comment as done.
mikecrowe added a comment.

In D153860#4453572 , @dyung wrote:

> @mikecrowe Your change is causing a test failure on the PS4 linux and PS5 
> Windows build bots. Can you take a look and fix or revert if you need time to 
> investigate?
>
> https://lab.llvm.org/buildbot/#/builders/139/builds/43856
> https://lab.llvm.org/buildbot/#/builders/216/builds/23017

The failure is due to:

  use-std-print.cpp.tmp.cpp:125:3: error: cannot use 'try' with exceptions 
disabled [clang-diagnostic-error]

I wasn't expecting that!

It looks like I failed to notice that the `bugprone-unused-return-value` check 
explicitly added `-fexceptions` to the `clang-tidy` command line to avoid this 
problem. I can add that to hopefully fix the problem, and I had some other 
changes that I hadn't pushed for review before this landed the first time too.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D153860

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D153860: [clang-tidy] Fix modernize-use-std-print check when return value used

2023-06-27 Thread Mike Crowe via Phabricator via cfe-commits
mikecrowe marked an inline comment as done.
mikecrowe added inline comments.



Comment at: clang-tools-extra/clang-tidy/modernize/UseStdPrintCheck.cpp:73-95
+static clang::ast_matchers::StatementMatcher
+unusedReturnValue(clang::ast_matchers::StatementMatcher MatchedCallExpr) {
+  auto UnusedInCompoundStmt =
+  compoundStmt(forEach(MatchedCallExpr),
+   // The checker can't currently differentiate between the
+   // return statement and other statements inside GNU 
statement
+   // expressions, so disable the checker inside them to avoid

PiotrZSL wrote:
> NOTE: Personally I do not thing that this is right way. Instead of using 
> "inclusion" matcher, better would be to use elimination.
> like:
> ```callExpr(unless(hasParent(anyOf(varDecl(), callExpr(), ifStmt(), ...```.
> 
> But if it's working fine, then it could be for now, so lets leave it. Simply 
> with this it may not find all cases.
I'm happy to try doing it a different way. I just took this code from the 
`bugprone-unused-return-value` check. I had a go at using:
```C++
Finder->addMatcher(
  callExpr(unless(hasParent(anyOf(varDecl(), callExpr(), ifStmt(), 
whileStmt(), doStmt(), forStmt(), cxxForRangeStmt(), switchCase(, 
argumentCountAtLeast(1),
```
but there's no overload of `hasParent` that will accept the return type of 
`anyOf`:
```
/home/mac/git/llvm-project/clang-tools-extra/clang-tidy/modernize/UseStdPrintCheck.cpp:100:23:
 error: no matching function for call to object of type 'const 
internal::ArgumentAdaptingMatcherFunc, 
internal::TypeList>'
  callExpr(unless(hasParent(anyOf(varDecl(), callExpr(), ifStmt(), 
whileStmt(), doStmt(), forStmt(), cxxForRangeStmt(), switchCase(, 
argumentCountAtLeast(1),
  ^
/home/mac/git/llvm-project/clang/include/clang/ASTMatchers/ASTMatchersInternal.h:1491:3:
 note: candidate template ignored: could not match 'Matcher' against 
'VariadicOperatorMatcher'
  operator()(const Matcher ) const {
  ^
/home/mac/git/llvm-project/clang/include/clang/ASTMatchers/ASTMatchersInternal.h:1498:3:
 note: candidate template ignored: could not match 'MapAnyOfHelper' against 
'VariadicOperatorMatcher'
  operator()(const MapAnyOfHelper ) const {
```
(Reducing the set of matchers inside the `anyOf` didn't help.)



Comment at: 
clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print-absl.cpp:63
+  // CHECK-MESSAGES-NOT: [[@LINE-1]]:10: warning: use 'std::println' instead 
of 'PrintF' [modernize-use-std-print]
+  // CHECK-FIXES-NOT: std::println("return value {}", i);
+}

PiotrZSL wrote:
> NOTE: I don't think that those FIXES-NOT are needed.
OK. I'll leave only the ones that are for deficiencies that might one day be 
fixed.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D153860

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D153860: [clang-tidy] Fix modernize-use-std-print check when return value used

2023-06-27 Thread Mike Crowe via Phabricator via cfe-commits
mikecrowe created this revision.
mikecrowe added a reviewer: PiotrZSL.
Herald added subscribers: carlosgalvezp, xazax.hun.
Herald added a reviewer: njames93.
Herald added a project: All.
mikecrowe requested review of this revision.
Herald added a project: clang-tools-extra.
Herald added a subscriber: cfe-commits.

The initial implementation of the modernize-use-std-print check was
capable of converting calls to printf (etc.) which used the return value
to calls to std::print which has no return value, thus breaking the
code.

Use code inspired by the implementation of bugprone-unused-return-value
check to ignore cases where the return value is used. Add appropriate
lit test cases and documentation.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D153860

Files:
  clang-tools-extra/clang-tidy/modernize/UseStdPrintCheck.cpp
  clang-tools-extra/docs/clang-tidy/checks/modernize/use-std-print.rst
  clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print-absl.cpp
  clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print-custom.cpp
  clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print.cpp
===
--- clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print.cpp
@@ -44,6 +44,233 @@
   // CHECK-FIXES: std::println("Hello");
 }
 
+// std::print returns nothing, so any callers that use the return
+// value cannot be automatically translated.
+int printf_uses_return_value(int choice) {
+  const int i = printf("Return value assigned to variable %d\n", 42);
+
+  if (choice == 0)
+printf("if body %d\n", i);
+// CHECK-MESSAGES: [[@LINE-1]]:5: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
+// CHECK-FIXES: std::println("if body {}", i);
+  else if (choice == 1)
+printf("else if body %d\n", i);
+// CHECK-MESSAGES: [[@LINE-1]]:5: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
+// CHECK-FIXES: std::println("else if body {}", i);
+  else
+printf("else body %d\n", i);
+// CHECK-MESSAGES: [[@LINE-1]]:5: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
+// CHECK-FIXES: std::println("else body {}", i);
+
+  if (printf("Return value used as boolean in if statement"))
+if (printf("Return value used in expression if statement") == 44)
+  if (const int j = printf("Return value used in assignment in if statement"))
+if (const int k = printf("Return value used with initializer in if statement"); k == 44)
+  ;
+
+  int d = 0;
+  while (printf("%d", d) < 2)
+++d;
+
+  while (true)
+printf("while body %d\n", i);
+// CHECK-MESSAGES: [[@LINE-1]]:5: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
+// CHECK-FIXES: std::println("while body {}", i);
+
+  do
+printf("do body %d\n", i);
+// CHECK-MESSAGES: [[@LINE-1]]:5: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
+// CHECK-FIXES: std::println("do body {}", i);
+  while (true);
+
+  for (;;)
+printf("for body %d\n", i);
+// CHECK-MESSAGES: [[@LINE-1]]:5: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
+// CHECK-FIXES: std::println("for body {}", i);
+
+  for (printf("for init statement %d\n", i);;)
+// CHECK-MESSAGES: [[@LINE-1]]:8: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
+// CHECK-FIXES: std::println("for init statement {}", i);
+;;
+
+  for (int j = printf("for init statement %d\n", i);;)
+;;
+
+  for (; printf("for condition %d\n", i);)
+;;
+
+  for (;; printf("for expression %d\n", i))
+// CHECK-MESSAGES: [[@LINE-1]]:11: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
+// CHECK-FIXES: std::println("for expression {}", i)
+;;
+
+  for (auto C : "foo")
+printf("ranged-for body %d\n", i);
+// CHECK-MESSAGES: [[@LINE-1]]:5: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
+// CHECK-FIXES: std::println("ranged-for body {}", i);
+
+  switch (1) {
+  case 1:
+printf("switch case body %d\n", i);
+// CHECK-MESSAGES: [[@LINE-1]]:5: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
+// CHECK-FIXES: std::println("switch case body {}", i);
+break;
+  default:
+printf("switch default body %d\n", i);
+// CHECK-MESSAGES: [[@LINE-1]]:5: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
+// CHECK-FIXES: std::println("switch default body {}", i);
+break;
+  }
+
+  try {
+printf("try body %d\n", i);
+// CHECK-MESSAGES: [[@LINE-1]]:5: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
+// CHECK-FIXES: std::println("try body {}", i);
+  } catch 

[PATCH] D149280: [clang-tidy] Add modernize-printf-to-std-print check

2023-06-26 Thread Mike Crowe via Phabricator via cfe-commits
mikecrowe added a comment.

Despite the fact that I've worked on what became this check for about two 
years, now that it's landed I've suddenly spotted a significant flaw: `printf` 
returns the number of characters printed, whereas `std::print` doesn't return 
anything. None of my test cases made use of the return value. I think this 
means that I need to only match on calls that don't make use of the return 
value. I shall try to do that.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D149280

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D149280: [clang-tidy] Add modernize-printf-to-std-print check

2023-06-26 Thread Mike Crowe via Phabricator via cfe-commits
mikecrowe added inline comments.



Comment at: 
clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print.cpp:169
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 
'printf' [modernize-use-std-print]
+  // CHECK-FIXES: std::println("Integer {:d} from char", c);
+

This should have a cast to `signed char` if `StrictMode=true`. That cast is 
currently there by accident on targets where `char` is unsigned, but not on 
targets where `char` is signed. This is a real problem, but luckily one that's 
easy to fix.



Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D149280

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D149280: [clang-tidy] Add modernize-printf-to-std-print check

2023-06-26 Thread Mike Crowe via Phabricator via cfe-commits
mikecrowe marked an inline comment as done.
mikecrowe added a comment.

In D149280#4448158 , @PiotrZSL wrote:

> Test is failing:
> https://lab.llvm.org/buildbot/#/builders/230/builds/14939/steps/6/logs/FAIL__Clang_Tools__use-std-print_cpp
> https://lab.llvm.org/buildbot/#/builders/245/builds/10266

It  looks like the `char` test is failing on targets where unadorned `char` is 
`unsigned`. I have access to two such machines, so I ought to be able to 
reproduce this myself (either on the up-to-date slow one, or the fast one that 
lacks a sufficiently-new cmake.)

@thakis, http://45.33.8.238/win/80313/summary.html makes it looks like Windows 
may be happy now, but I may be misinterpreting the results.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D149280

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D149280: [clang-tidy] Add modernize-printf-to-std-print check

2023-06-25 Thread Mike Crowe via Phabricator via cfe-commits
mikecrowe marked an inline comment as done.
mikecrowe added inline comments.



Comment at: 
clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print.cpp:9-15
+#include 
+#include 
+#include 
+// CHECK-FIXES: #include 
+#include 
+#include 
+#include 

PiotrZSL wrote:
> Those includes need to be removed. We cannot use system includes, some dummy 
> one can be used only.
I believe that `` is the only one that isn't present in 
`test/clang-tidy/checkers/Inputs/Headers/`. Hopefully adding it will have been 
sufficient.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D149280

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D149280: [clang-tidy] Add modernize-printf-to-std-print check

2023-06-25 Thread Mike Crowe via Phabricator via cfe-commits
mikecrowe added a comment.

In D149280#4447363 , @thakis wrote:

> This breaks tests on windows: http://45.33.8.238/win/80283/step_8.txt
>
> Please take a look and revert for now if it takes a while to fix.

Thanks for letting me know, I thought I could get away with including 
 from a test since it is a compiler header rather than a libc 
header.

I've added a potential fix, but I don't have a Windows machine (or many other 
targets) to test it on. Is there a way to get this change to run through the 
buildbots without landing it?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D149280

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D149280: [clang-tidy] Add modernize-printf-to-std-print check

2023-06-25 Thread Mike Crowe via Phabricator via cfe-commits
mikecrowe added inline comments.



Comment at: clang-tools-extra/clang-tidy/modernize/UseStdPrintCheck.cpp:64
+  if (MaybeHeaderToInclude)
+Options.store(Opts, "PrintHeader", *MaybeHeaderToInclude);
+}

This is going to write the default value set in the constructor if 
`ReplacementPrintFunction` is `std::print` or `ReplacementPrintlnFunction` is 
`std::println` even if `PrintHeader` was not specified in the configuration. I 
don't know how much of a problem this is.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D149280

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D153716: [ASTMatchers] Add argumentCountAtLeast narrowing matcher

2023-06-25 Thread Mike Crowe via Phabricator via cfe-commits
mikecrowe created this revision.
mikecrowe added a reviewer: PiotrZSL.
Herald added a project: All.
mikecrowe requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.
mikecrowe added inline comments.



Comment at: clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp:1671
+  notMatches("void x(int, int = 1) { x(0); }",
+ traverse(TK_IgnoreUnlessSpelledInSource, Call2PlusArgs)));
+  EXPECT_TRUE(

I'm not sure if this is the best way to trigger testing of the ignoring default 
argument path in the implementation of `argumentCountAtLeast`, but it does seem 
to work. I added explicit `TK_AsIs` to the tests above to make it clear that 
they are not testing that path.


This will be used by the modernize-use-std-print clang-tidy check and
related checks later.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D153716

Files:
  clang/docs/LibASTMatchersReference.html
  clang/include/clang/ASTMatchers/ASTMatchers.h
  clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp

Index: clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
===
--- clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
+++ clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
@@ -1640,6 +1640,95 @@
  cxxConversionDecl(isExplicit(;
 }
 
+TEST_P(ASTMatchersTest, ArgumentCountAtLeast_CallExpr) {
+  StatementMatcher Call2PlusArgs = callExpr(argumentCountAtLeast(2));
+
+  EXPECT_TRUE(notMatches("void x(void) { x(); }", Call2PlusArgs));
+  EXPECT_TRUE(notMatches("void x(int) { x(0); }", Call2PlusArgs));
+  EXPECT_TRUE(matches("void x(int, int) { x(0, 0); }", Call2PlusArgs));
+  EXPECT_TRUE(matches("void x(int, int, int) { x(0, 0, 0); }", Call2PlusArgs));
+
+  if (!GetParam().isCXX()) {
+return;
+  }
+
+  EXPECT_TRUE(
+  notMatches("void x(int = 1) { x(); }", traverse(TK_AsIs, Call2PlusArgs)));
+  EXPECT_TRUE(matches("void x(int, int = 1) { x(0); }",
+  traverse(TK_AsIs, Call2PlusArgs)));
+  EXPECT_TRUE(matches("void x(int, int = 1, int = 1) { x(0); }",
+  traverse(TK_AsIs, Call2PlusArgs)));
+  EXPECT_TRUE(matches("void x(int, int, int = 1) { x(0, 0); }",
+  traverse(TK_AsIs, Call2PlusArgs)));
+  EXPECT_TRUE(matches("void x(int, int, int, int = 1) { x(0, 0, 0); }",
+  traverse(TK_AsIs, Call2PlusArgs)));
+
+  EXPECT_TRUE(
+  notMatches("void x(int = 1) { x(); }",
+ traverse(TK_IgnoreUnlessSpelledInSource, Call2PlusArgs)));
+  EXPECT_TRUE(
+  notMatches("void x(int, int = 1) { x(0); }",
+ traverse(TK_IgnoreUnlessSpelledInSource, Call2PlusArgs)));
+  EXPECT_TRUE(
+  notMatches("void x(int, int = 1, int = 1) { x(0); }",
+ traverse(TK_IgnoreUnlessSpelledInSource, Call2PlusArgs)));
+  EXPECT_TRUE(matches("void x(int, int, int = 1) { x(0, 0); }",
+  traverse(TK_IgnoreUnlessSpelledInSource, Call2PlusArgs)));
+  EXPECT_TRUE(matches("void x(int, int, int, int = 1) { x(0, 0, 0); }",
+  traverse(TK_IgnoreUnlessSpelledInSource, Call2PlusArgs)));
+}
+
+TEST_P(ASTMatchersTest, ArgumentCountAtLeast_CallExpr_CXX) {
+  if (!GetParam().isCXX()) {
+return;
+  }
+
+  StatementMatcher Call2PlusArgs = callExpr(argumentCountAtLeast(2));
+  EXPECT_TRUE(notMatches("class X { void x() { x(); } };", Call2PlusArgs));
+  EXPECT_TRUE(notMatches("class X { void x(int) { x(0); } };", Call2PlusArgs));
+  EXPECT_TRUE(
+  matches("class X { void x(int, int) { x(0, 0); } };", Call2PlusArgs));
+  EXPECT_TRUE(matches("class X { void x(int, int, int) { x(0, 0, 0); } };",
+  Call2PlusArgs));
+
+  EXPECT_TRUE(notMatches("class X { void x(int = 1) { x(0); } };",
+ traverse(TK_AsIs, Call2PlusArgs)));
+  EXPECT_TRUE(matches("class X { void x(int, int = 1) { x(0); } };",
+  traverse(TK_AsIs, Call2PlusArgs)));
+  EXPECT_TRUE(matches("class X { void x(int, int = 1, int = 1) { x(0); } };",
+  traverse(TK_AsIs, Call2PlusArgs)));
+  EXPECT_TRUE(matches("class X { void x(int, int, int = 1) { x(0, 0); } };",
+  traverse(TK_AsIs, Call2PlusArgs)));
+  EXPECT_TRUE(
+  matches("class X { void x(int, int, int, int = 1) { x(0, 0, 0); } };",
+  traverse(TK_AsIs, Call2PlusArgs)));
+
+  EXPECT_TRUE(
+  notMatches("class X { void x(int = 1) { x(0); } };",
+ traverse(TK_IgnoreUnlessSpelledInSource, Call2PlusArgs)));
+  EXPECT_TRUE(
+  notMatches("class X { void x(int, int = 1) { x(0); } };",
+ traverse(TK_IgnoreUnlessSpelledInSource, Call2PlusArgs)));
+  EXPECT_TRUE(
+  notMatches("class X { void x(int, int = 1, int = 1) { x(0); } };",
+ traverse(TK_IgnoreUnlessSpelledInSource, Call2PlusArgs)));
+  

[PATCH] D153716: [ASTMatchers] Add argumentCountAtLeast narrowing matcher

2023-06-25 Thread Mike Crowe via Phabricator via cfe-commits
mikecrowe added inline comments.



Comment at: clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp:1671
+  notMatches("void x(int, int = 1) { x(0); }",
+ traverse(TK_IgnoreUnlessSpelledInSource, Call2PlusArgs)));
+  EXPECT_TRUE(

I'm not sure if this is the best way to trigger testing of the ignoring default 
argument path in the implementation of `argumentCountAtLeast`, but it does seem 
to work. I added explicit `TK_AsIs` to the tests above to make it clear that 
they are not testing that path.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D153716

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D149280: [clang-tidy] Add modernize-printf-to-std-print check

2023-06-24 Thread Mike Crowe via Phabricator via cfe-commits
mikecrowe marked 2 inline comments as done.
mikecrowe added a comment.

Thanks for the further reviews.




Comment at: clang-tools-extra/clang-tidy/modernize/UseStdPrintCheck.cpp:37
+
+  if (PrintfLikeFunctions.empty() && FprintfLikeFunctions.empty()) {
+PrintfLikeFunctions.push_back("::printf");

PiotrZSL wrote:
> those 2 looks in-depended. Cannot they be put as default value into Option 
> config ?
My expectation was that if you didn't want to replace `printf` (and instead 
wanted to replace some other `printf`-like function) then you'd also not want 
to replace `fprintf` and vice-versa. In my head the two options do go together. 
If setting one didn't also remove the default for the other you'd end up having 
to specify `PrintfLikeFunctions=my_printf, FPrintfLikeFunctions=` just to 
replace a single function.



Comment at: clang-tools-extra/clang-tidy/modernize/UseStdPrintCheck.cpp:79
+  Finder->addMatcher(
+  callExpr(callee(functionDecl(
+  matchers::matchesAnyListedName(FprintfLikeFunctions))

PiotrZSL wrote:
> this could match also methods, maybe something `unless(cxxMethodDecl())` ?
I would like to be able to match methods. The code I wrote this check to run on 
has classes that have methods that used to call `std::fprintf`, and currently 
call `fmt::fprintf`. I wish to convert those methods to use `fmt::print` and 
use this check to fix all their callers. Eventually I hope to be able to move 
to `std::print`.

However, the check doesn't currently seem to work for methods since the 
arguments are off-by-one and the replacement is incorrect too. I'll add the 
`unless(cxxMethodDecl)` checks for now and support can be added later.



Comment at: clang-tools-extra/clang-tidy/modernize/UseStdPrintCheck.cpp:82
+  .bind("func_decl")),
+   hasArgument(1, stringLiteral()))
+  .bind("fprintf"),

PiotrZSL wrote:
> consider moving this stringLiteral to be first, consider adding something 
> like `unless(argumentCountIs(0)), unless(argumentCountIs(1))`` at begining or 
> create matcher that verify first that argument count is >= 2, so we could 
> exlude most of callExpr at begining, even before we match functions
I would have hoped that `hasArgument` would fail quite fast if the argument 
index passed is greater than the number of arguments. I will add 
`argumentCountAtLeast` and use it regardless though.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D149280

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D149280: [clang-tidy] Add modernize-printf-to-std-print check

2023-06-24 Thread Mike Crowe via Phabricator via cfe-commits
mikecrowe added a comment.

@Eugene.Zelenko,
I will make the documentation changes you've suggested, but I can't say I 
really understand which document elements require single backticks and which 
require dual backticks. https://llvm.org/docs/SphinxQuickstartTemplate.html 
seems to imply that single backticks are only used for links and double 
backticks are used for monospace, but it's not completely clear. Most of the 
existing documentation seems to be consistent with what you've suggested though.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D149280

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D149280: [clang-tidy] Add modernize-printf-to-std-print check

2023-06-24 Thread Mike Crowe via Phabricator via cfe-commits
mikecrowe marked 4 inline comments as done.
mikecrowe added inline comments.



Comment at: clang-tools-extra/clang-tidy/utils/FormatStringConverter.cpp:384-397
+const auto StringDecl = type(hasUnqualifiedDesugaredType(recordType(
+hasDeclaration(cxxRecordDecl(hasName("::std::basic_string"));
+const auto StringExpr = expr(anyOf(
+hasType(StringDecl), hasType(qualType(pointsTo(StringDecl);
+
+const auto StringCStrCallExpr =
+cxxMemberCallExpr(on(StringExpr.bind("arg")),

PiotrZSL wrote:
> mikecrowe wrote:
> > PiotrZSL wrote:
> > > constant construction of those marchers may be costly.. can be cache them 
> > > somehow in this object ?
> > Good idea. Do you have any pointers to code that does this? I couldn't find 
> > any.
> > 
> > The types involved all seem to be in the `internal::` namespace and 
> > presumably subject to change. Ideally, I'd put:
> > ```
> > std::optional StringCStrCallExprMatcher;
> > ```
> > in the class and then populate it here the first time lazily. Unfortunately 
> > I have no idea what type to use for `SomeSortOfMatcherType`.
> `clang::ast_matchers::StatementMatcher`, this is defined 
> as `using clang::ast_matchers::StatementMatcher = typedef 
> internal::Matcher`.
> I would create it in class constructor as private member.
Thanks for the pointer. It turns out that I need just 
`clang::ast_matchers::StatementMatcher`.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D149280

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D149280: [clang-tidy] Add modernize-printf-to-std-print check

2023-06-24 Thread Mike Crowe via Phabricator via cfe-commits
mikecrowe marked 7 inline comments as done.
mikecrowe added a comment.

I'm still working on the remaining items.




Comment at: clang-tools-extra/clang-tidy/utils/FormatStringConverter.cpp:230
+return conversionNotPossible("'%m' is not supported in format string");
+  } else {
+StandardFormatString.push_back('{');

mikecrowe wrote:
> PiotrZSL wrote:
> > general: no need for else after return
> In general, you're correct that I've used else after return in other places 
> and I will fix them. However, in this case the else is required since the 
> very first `if` block above doesn't have a return. (Hopefully this complexity 
> will go away if I succeed in splitting this function up.)
I've now reworked this function extensively, so there's no longer an else here.



Comment at: 
clang-tools-extra/docs/clang-tidy/checks/modernize/use-std-print.rst:117
+
+.. option:: PrintFunction
+

PiotrZSL wrote:
> mikecrowe wrote:
> > Is `PrintFunction` (and the soon-to-arrive `PrintlnFunction`) distinct 
> > enough from `PrintfLikeFunctions` and `FprintfLikeFunctions`? Should I use 
> > `ReplacementPrintFunction` instead?
> Use `Replacement`. It will be way better.
I assume that you mean `ReplacementPrintFunction`. (I see `ReplacementString` 
used in other checks, so I think that just `Replacement` might be a bit vague.)


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D149280

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D149280: [clang-tidy] Add modernize-printf-to-std-print check

2023-06-18 Thread Mike Crowe via Phabricator via cfe-commits
mikecrowe added inline comments.



Comment at: clang-tools-extra/clang-tidy/utils/FormatStringConverter.cpp:202
+/// Called for each format specifier by ParsePrintfString.
+bool FormatStringConverter::HandlePrintfSpecifier(
+const analyze_printf::PrintfSpecifier , const char *StartSpecifier,

mikecrowe wrote:
> PiotrZSL wrote:
> > this function should be split into smaller one.
> I agree. I'm surprised it hasn't come up in review earlier. I tried to do so 
> prior to pushing the very first version of this for review and gave up since 
> the parts ended up referring to so many local variables making the code even 
> harder to understand than it is now. I will have another attempt.
It turns out that things are working out much better in my second attempt at 
splitting this function. I shall address the other new review comments before 
sending another revision for review though.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D149280

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D149280: [clang-tidy] Add modernize-printf-to-std-print check

2023-06-18 Thread Mike Crowe via Phabricator via cfe-commits
mikecrowe marked 6 inline comments as done.
mikecrowe added a comment.

Thanks for the comprehensive review.




Comment at: clang-tools-extra/clang-tidy/modernize/UseStdPrintCheck.cpp:43-44
+
+  if (!MaybeHeaderToInclude && (ReplacementPrintFunction == "std::print" ||
+ReplacementPrintlnFunction == "std::println"))
+MaybeHeaderToInclude = "";

PiotrZSL wrote:
> this code is already duplicated, move it to some separate private function, 
> like isCpp23PrintConfigured or something...
You're correct that `ReplacementPrintFunction == "std::print" || 
ReplacementPrintlnFunction == "std::println"` is duplicated in 
`isLanguageVersionSupported`, but in that code we're considering which C++ 
version the functions require and in this code we're considering which header 
the functions require. These are not the same question. It just so happens that 
these checks are against the same function names now, but they need not be. If 
another function is added to `` in C++26 and this code ends up being 
able to convert to it then the checks would need to diverge.

Nevertheless, I will do as you request if you still think it's worthwhile.




Comment at: clang-tools-extra/clang-tidy/modernize/UseStdPrintCheck.cpp:56
+  Finder->addMatcher(
+  traverse(TK_IgnoreUnlessSpelledInSource,
+   callExpr(callee(functionDecl(matchers::matchesAnyListedName(

PiotrZSL wrote:
> Those TK_IgnoreUnlessSpelledInSource should be moved into 
> getCheckTraversalKind()
Ah, that was added since I wrote the original version of this check. I'll 
address this.



Comment at: clang-tools-extra/clang-tidy/modernize/UseStdPrintCheck.h:40
+  StringRef ReplacementPrintlnFunction;
+  utils::IncludeInserter IncludeInserter;
+  std::optional MaybeHeaderToInclude;

PiotrZSL wrote:
> I heard that using clang::tooling::HeaderIncludes is more recommended.
> And this is just some house-made stuff
I'm afraid that I don't really understand this comment. The use of 
`IncludeInserter` is far more common in the existing checks than 
`HeaderIncludes` and from looking at `IncludeCleaner.cpp` the use of the latter 
is rather more complex. New features were being added to `IncludeInserter` 
within the last six months. I'm unsure what "house-made" means in the context 
of the `IncludeInserter` code that I didn't write.

Do you have anything more concrete than hearsay? If there is a plan to 
deprecate `IncludeInserter` then it feels like something closer to its 
convenient interface would need to be implemented in terms of `HeaderIncludes` 
for checks to use rather than them duplicating the code in `IncludeCleaner.cpp`.

If you can explain what you'd like me to do, and ideally provide pointers to 
similar things being done elsewhere then perhaps I can address this comment.



Comment at: clang-tools-extra/clang-tidy/utils/FormatStringConverter.cpp:185
+  assert(FormatExpr);
+  PrintfFormatString = FormatExpr->getString();
+

PiotrZSL wrote:
> This may crash for wchar, maybe better limit StringLiteral to Ordinary and 
> UTF8 or only Ordinary 
It doesn't look like there's any support for u8 literals in `printf` or 
`std::print` (yet), so I think just Ordinary is sufficient.



Comment at: clang-tools-extra/clang-tidy/utils/FormatStringConverter.cpp:202
+/// Called for each format specifier by ParsePrintfString.
+bool FormatStringConverter::HandlePrintfSpecifier(
+const analyze_printf::PrintfSpecifier , const char *StartSpecifier,

PiotrZSL wrote:
> this function should be split into smaller one.
I agree. I'm surprised it hasn't come up in review earlier. I tried to do so 
prior to pushing the very first version of this for review and gave up since 
the parts ended up referring to so many local variables making the code even 
harder to understand than it is now. I will have another attempt.



Comment at: clang-tools-extra/clang-tidy/utils/FormatStringConverter.cpp:230
+return conversionNotPossible("'%m' is not supported in format string");
+  } else {
+StandardFormatString.push_back('{');

PiotrZSL wrote:
> general: no need for else after return
In general, you're correct that I've used else after return in other places and 
I will fix them. However, in this case the else is required since the very 
first `if` block above doesn't have a return. (Hopefully this complexity will 
go away if I succeed in splitting this function up.)



Comment at: clang-tools-extra/clang-tidy/utils/FormatStringConverter.cpp:384-397
+const auto StringDecl = type(hasUnqualifiedDesugaredType(recordType(
+hasDeclaration(cxxRecordDecl(hasName("::std::basic_string"));
+const auto StringExpr = expr(anyOf(
+hasType(StringDecl), hasType(qualType(pointsTo(StringDecl);
+
+const 

[PATCH] D150602: [clang-tidy] Move formatDereference to FixitHintUtils

2023-06-13 Thread Mike Crowe via Phabricator via cfe-commits
mikecrowe updated this revision to Diff 530943.
mikecrowe added a comment.

Move clangTooling to clang_target_link_libraries


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D150602

Files:
  clang-tools-extra/clang-tidy/readability/RedundantStringCStrCheck.cpp
  clang-tools-extra/clang-tidy/utils/CMakeLists.txt
  clang-tools-extra/clang-tidy/utils/FixItHintUtils.cpp
  clang-tools-extra/clang-tidy/utils/FixItHintUtils.h

Index: clang-tools-extra/clang-tidy/utils/FixItHintUtils.h
===
--- clang-tools-extra/clang-tidy/utils/FixItHintUtils.h
+++ clang-tools-extra/clang-tidy/utils/FixItHintUtils.h
@@ -44,6 +44,9 @@
   DeclSpec::TQ Qualifier,
   QualifierTarget CT = QualifierTarget::Pointee,
   QualifierPolicy CP = QualifierPolicy::Left);
+
+// \brief Format a pointer to an expression
+std::string formatDereference(const Expr , const ASTContext );
 } // namespace clang::tidy::utils::fixit
 
 #endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_UTILS_FIXITHINTUTILS_H
Index: clang-tools-extra/clang-tidy/utils/FixItHintUtils.cpp
===
--- clang-tools-extra/clang-tidy/utils/FixItHintUtils.cpp
+++ clang-tools-extra/clang-tidy/utils/FixItHintUtils.cpp
@@ -9,7 +9,9 @@
 #include "FixItHintUtils.h"
 #include "LexerUtils.h"
 #include "clang/AST/ASTContext.h"
+#include "clang/AST/ExprCXX.h"
 #include "clang/AST/Type.h"
+#include "clang/Tooling/FixIt.h"
 #include 
 
 namespace clang::tidy::utils::fixit {
@@ -221,4 +223,46 @@
 
   return std::nullopt;
 }
+
+// Return true if expr needs to be put in parens when it is an argument of a
+// prefix unary operator, e.g. when it is a binary or ternary operator
+// syntactically.
+static bool needParensAfterUnaryOperator(const Expr ) {
+  if (isa() ||
+  isa()) {
+return true;
+  }
+  if (const auto *Op = dyn_cast()) {
+return Op->getNumArgs() == 2 && Op->getOperator() != OO_PlusPlus &&
+   Op->getOperator() != OO_MinusMinus && Op->getOperator() != OO_Call &&
+   Op->getOperator() != OO_Subscript;
+  }
+  return false;
+}
+
+// Format a pointer to an expression: prefix with '*' but simplify
+// when it already begins with '&'.  Return empty string on failure.
+std::string formatDereference(const Expr , const ASTContext ) {
+  if (const auto *Op = dyn_cast()) {
+if (Op->getOpcode() == UO_AddrOf) {
+  // Strip leading '&'.
+  return std::string(
+  tooling::fixit::getText(*Op->getSubExpr()->IgnoreParens(), Context));
+}
+  }
+  StringRef Text = tooling::fixit::getText(ExprNode, Context);
+
+  if (Text.empty())
+return std::string();
+
+  // Remove remaining '->' from overloaded operator call
+  Text.consume_back("->");
+
+  // Add leading '*'.
+  if (needParensAfterUnaryOperator(ExprNode)) {
+return (llvm::Twine("*(") + Text + ")").str();
+  }
+  return (llvm::Twine("*") + Text).str();
+}
+
 } // namespace clang::tidy::utils::fixit
Index: clang-tools-extra/clang-tidy/utils/CMakeLists.txt
===
--- clang-tools-extra/clang-tidy/utils/CMakeLists.txt
+++ clang-tools-extra/clang-tidy/utils/CMakeLists.txt
@@ -37,5 +37,6 @@
   clangBasic
   clangLex
   clangSema
+  clangTooling
   clangTransformer
   )
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
@@ -11,6 +11,7 @@
 //===--===//
 
 #include "RedundantStringCStrCheck.h"
+#include "../utils/FixItHintUtils.h"
 #include "../utils/Matchers.h"
 #include "../utils/OptionsUtils.h"
 #include "clang/Lex/Lexer.h"
@@ -22,49 +23,6 @@
 
 namespace {
 
-// Return true if expr needs to be put in parens when it is an argument of a
-// prefix unary operator, e.g. when it is a binary or ternary operator
-// syntactically.
-bool needParensAfterUnaryOperator(const Expr ) {
-  if (isa() ||
-  isa()) {
-return true;
-  }
-  if (const auto *Op = dyn_cast()) {
-return Op->getNumArgs() == 2 && Op->getOperator() != OO_PlusPlus &&
-   Op->getOperator() != OO_MinusMinus && Op->getOperator() != OO_Call &&
-   Op->getOperator() != OO_Subscript;
-  }
-  return false;
-}
-
-// Format a pointer to an expression: prefix with '*' but simplify
-// when it already begins with '&'.  Return empty string on failure.
-std::string
-formatDereference(const ast_matchers::MatchFinder::MatchResult ,
-  const Expr ) {
-  if (const auto *Op = dyn_cast()) {
-if (Op->getOpcode() == UO_AddrOf) {
-  // Strip leading '&'.
-  return 

[PATCH] D150602: [clang-tidy] Move formatDereference to FixitHintUtils

2023-06-12 Thread Mike Crowe via Phabricator via cfe-commits
mikecrowe updated this revision to Diff 530662.
mikecrowe added a comment.

Add clangTooling to LINK_LIBS for tooling::fixit::getText for clangTidyUtils to 
fix failure to build with BUILD_SHARED_LIBS=ON:

  ld.lld: error: undefined symbol: 
clang::tooling::fixit::internal::getText(clang::CharSourceRange, 
clang::ASTContext const&)
  >>> referenced by FixItHintUtils.cpp
  >>>   
tools/clang/tools/extra/clang-tidy/utils/CMakeFiles/obj.clangTidyUtils.dir/FixItHintUtils.cpp.o:(clang::tidy::utils::fixit::formatDereference[abi:cxx11](clang::Expr
 const&, clang::ASTContext const&))
  >>> referenced by FixItHintUtils.cpp
  >>>   
tools/clang/tools/extra/clang-tidy/utils/CMakeFiles/obj.clangTidyUtils.dir/FixItHintUtils.cpp.o:(clang::tidy::utils::fixit::formatDereference[abi:cxx11](clang::Expr
 const&, clang::ASTContext const&))

I've no idea whether this is a sensible solution, but it does seem to work in 
my testing.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D150602

Files:
  clang-tools-extra/clang-tidy/readability/RedundantStringCStrCheck.cpp
  clang-tools-extra/clang-tidy/utils/CMakeLists.txt
  clang-tools-extra/clang-tidy/utils/FixItHintUtils.cpp
  clang-tools-extra/clang-tidy/utils/FixItHintUtils.h

Index: clang-tools-extra/clang-tidy/utils/FixItHintUtils.h
===
--- clang-tools-extra/clang-tidy/utils/FixItHintUtils.h
+++ clang-tools-extra/clang-tidy/utils/FixItHintUtils.h
@@ -44,6 +44,9 @@
   DeclSpec::TQ Qualifier,
   QualifierTarget CT = QualifierTarget::Pointee,
   QualifierPolicy CP = QualifierPolicy::Left);
+
+// \brief Format a pointer to an expression
+std::string formatDereference(const Expr , const ASTContext );
 } // namespace clang::tidy::utils::fixit
 
 #endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_UTILS_FIXITHINTUTILS_H
Index: clang-tools-extra/clang-tidy/utils/FixItHintUtils.cpp
===
--- clang-tools-extra/clang-tidy/utils/FixItHintUtils.cpp
+++ clang-tools-extra/clang-tidy/utils/FixItHintUtils.cpp
@@ -9,7 +9,9 @@
 #include "FixItHintUtils.h"
 #include "LexerUtils.h"
 #include "clang/AST/ASTContext.h"
+#include "clang/AST/ExprCXX.h"
 #include "clang/AST/Type.h"
+#include "clang/Tooling/FixIt.h"
 #include 
 
 namespace clang::tidy::utils::fixit {
@@ -221,4 +223,46 @@
 
   return std::nullopt;
 }
+
+// Return true if expr needs to be put in parens when it is an argument of a
+// prefix unary operator, e.g. when it is a binary or ternary operator
+// syntactically.
+static bool needParensAfterUnaryOperator(const Expr ) {
+  if (isa() ||
+  isa()) {
+return true;
+  }
+  if (const auto *Op = dyn_cast()) {
+return Op->getNumArgs() == 2 && Op->getOperator() != OO_PlusPlus &&
+   Op->getOperator() != OO_MinusMinus && Op->getOperator() != OO_Call &&
+   Op->getOperator() != OO_Subscript;
+  }
+  return false;
+}
+
+// Format a pointer to an expression: prefix with '*' but simplify
+// when it already begins with '&'.  Return empty string on failure.
+std::string formatDereference(const Expr , const ASTContext ) {
+  if (const auto *Op = dyn_cast()) {
+if (Op->getOpcode() == UO_AddrOf) {
+  // Strip leading '&'.
+  return std::string(
+  tooling::fixit::getText(*Op->getSubExpr()->IgnoreParens(), Context));
+}
+  }
+  StringRef Text = tooling::fixit::getText(ExprNode, Context);
+
+  if (Text.empty())
+return std::string();
+
+  // Remove remaining '->' from overloaded operator call
+  Text.consume_back("->");
+
+  // Add leading '*'.
+  if (needParensAfterUnaryOperator(ExprNode)) {
+return (llvm::Twine("*(") + Text + ")").str();
+  }
+  return (llvm::Twine("*") + Text).str();
+}
+
 } // namespace clang::tidy::utils::fixit
Index: clang-tools-extra/clang-tidy/utils/CMakeLists.txt
===
--- clang-tools-extra/clang-tidy/utils/CMakeLists.txt
+++ clang-tools-extra/clang-tidy/utils/CMakeLists.txt
@@ -25,6 +25,7 @@
 
   LINK_LIBS
   clangTidy
+  clangTooling
 
   DEPENDS
   omp_gen
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
@@ -11,6 +11,7 @@
 //===--===//
 
 #include "RedundantStringCStrCheck.h"
+#include "../utils/FixItHintUtils.h"
 #include "../utils/Matchers.h"
 #include "../utils/OptionsUtils.h"
 #include "clang/Lex/Lexer.h"
@@ -22,49 +23,6 @@
 
 namespace {
 
-// Return true if expr needs to be put in parens when it is an argument of a
-// prefix unary operator, e.g. when it is a 

[PATCH] D150602: [clang-tidy] Move formatDereference to FixitHintUtils

2023-06-11 Thread Mike Crowe via Phabricator via cfe-commits
mikecrowe updated this revision to Diff 530384.
mikecrowe added a comment.

Rebase, no changes.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D150602

Files:
  clang-tools-extra/clang-tidy/readability/RedundantStringCStrCheck.cpp
  clang-tools-extra/clang-tidy/utils/FixItHintUtils.cpp
  clang-tools-extra/clang-tidy/utils/FixItHintUtils.h

Index: clang-tools-extra/clang-tidy/utils/FixItHintUtils.h
===
--- clang-tools-extra/clang-tidy/utils/FixItHintUtils.h
+++ clang-tools-extra/clang-tidy/utils/FixItHintUtils.h
@@ -44,6 +44,9 @@
   DeclSpec::TQ Qualifier,
   QualifierTarget CT = QualifierTarget::Pointee,
   QualifierPolicy CP = QualifierPolicy::Left);
+
+// \brief Format a pointer to an expression
+std::string formatDereference(const Expr , const ASTContext );
 } // namespace clang::tidy::utils::fixit
 
 #endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_UTILS_FIXITHINTUTILS_H
Index: clang-tools-extra/clang-tidy/utils/FixItHintUtils.cpp
===
--- clang-tools-extra/clang-tidy/utils/FixItHintUtils.cpp
+++ clang-tools-extra/clang-tidy/utils/FixItHintUtils.cpp
@@ -9,7 +9,9 @@
 #include "FixItHintUtils.h"
 #include "LexerUtils.h"
 #include "clang/AST/ASTContext.h"
+#include "clang/AST/ExprCXX.h"
 #include "clang/AST/Type.h"
+#include "clang/Tooling/FixIt.h"
 #include 
 
 namespace clang::tidy::utils::fixit {
@@ -221,4 +223,46 @@
 
   return std::nullopt;
 }
+
+// Return true if expr needs to be put in parens when it is an argument of a
+// prefix unary operator, e.g. when it is a binary or ternary operator
+// syntactically.
+static bool needParensAfterUnaryOperator(const Expr ) {
+  if (isa() ||
+  isa()) {
+return true;
+  }
+  if (const auto *Op = dyn_cast()) {
+return Op->getNumArgs() == 2 && Op->getOperator() != OO_PlusPlus &&
+   Op->getOperator() != OO_MinusMinus && Op->getOperator() != OO_Call &&
+   Op->getOperator() != OO_Subscript;
+  }
+  return false;
+}
+
+// Format a pointer to an expression: prefix with '*' but simplify
+// when it already begins with '&'.  Return empty string on failure.
+std::string formatDereference(const Expr , const ASTContext ) {
+  if (const auto *Op = dyn_cast()) {
+if (Op->getOpcode() == UO_AddrOf) {
+  // Strip leading '&'.
+  return std::string(
+  tooling::fixit::getText(*Op->getSubExpr()->IgnoreParens(), Context));
+}
+  }
+  StringRef Text = tooling::fixit::getText(ExprNode, Context);
+
+  if (Text.empty())
+return std::string();
+
+  // Remove remaining '->' from overloaded operator call
+  Text.consume_back("->");
+
+  // Add leading '*'.
+  if (needParensAfterUnaryOperator(ExprNode)) {
+return (llvm::Twine("*(") + Text + ")").str();
+  }
+  return (llvm::Twine("*") + Text).str();
+}
+
 } // namespace clang::tidy::utils::fixit
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
@@ -11,6 +11,7 @@
 //===--===//
 
 #include "RedundantStringCStrCheck.h"
+#include "../utils/FixItHintUtils.h"
 #include "../utils/Matchers.h"
 #include "../utils/OptionsUtils.h"
 #include "clang/Lex/Lexer.h"
@@ -22,49 +23,6 @@
 
 namespace {
 
-// Return true if expr needs to be put in parens when it is an argument of a
-// prefix unary operator, e.g. when it is a binary or ternary operator
-// syntactically.
-bool needParensAfterUnaryOperator(const Expr ) {
-  if (isa() ||
-  isa()) {
-return true;
-  }
-  if (const auto *Op = dyn_cast()) {
-return Op->getNumArgs() == 2 && Op->getOperator() != OO_PlusPlus &&
-   Op->getOperator() != OO_MinusMinus && Op->getOperator() != OO_Call &&
-   Op->getOperator() != OO_Subscript;
-  }
-  return false;
-}
-
-// Format a pointer to an expression: prefix with '*' but simplify
-// when it already begins with '&'.  Return empty string on failure.
-std::string
-formatDereference(const ast_matchers::MatchFinder::MatchResult ,
-  const Expr ) {
-  if (const auto *Op = dyn_cast()) {
-if (Op->getOpcode() == UO_AddrOf) {
-  // Strip leading '&'.
-  return std::string(tooling::fixit::getText(
-  *Op->getSubExpr()->IgnoreParens(), *Result.Context));
-}
-  }
-  StringRef Text = tooling::fixit::getText(ExprNode, *Result.Context);
-
-  if (Text.empty())
-return std::string();
-
-  // Remove remaining '->' from overloaded operator call
-  Text.consume_back("->");
-
-  // Add leading '*'.
-  if (needParensAfterUnaryOperator(ExprNode)) {
-return (llvm::Twine("*(") + 

[PATCH] D149280: [clang-tidy] Add modernize-printf-to-std-print check

2023-05-31 Thread Mike Crowe via Phabricator via cfe-commits
mikecrowe added inline comments.



Comment at: 
clang-tools-extra/docs/clang-tidy/checks/modernize/use-std-print.rst:79
+
+.. option:: StrictMode
+

mikecrowe wrote:
> It turns out that absl::PrintF and absl::FPrintF work like std::format, 
> fmt::printf, etc. and use the signedness of the argument rather than the 
> signedness indicated in the format string to determine how to format the 
> number. In other words:
> `unsigned int ui = 0x; absl::PrintF("%d\n", ui);` yields `4294967295` 
> (see https://godbolt.org/z/dYcbehxP9 ), so the casts that StrictMode adds 
> would change the behaviour of the converted code.
> 
> I can think of several ways around this:
> 
> 1. Update the documentation to explain this, recommending not to use 
> StrictMode when converting Abseil functions.
> 
> 2. Remove built-in support for Abseil functions from this check. Anyone 
> wishing to convert them can do so via the customisation features, and can 
> choose not to use StrictMode. (This could be documented here.)
> 
> 3. Teach the code to recognise whether the arguments is being passed as a 
> C-style variable argument list or as fully-typed arguments to a templated 
> function and make StrictMode only add the casts for the former. (I've not 
> investigated how feasible this is.)
> 
> 4. Treat the known Abseil functions in this check differently by name and 
> disable the casting behaviour. This means that conversion from fmt::printf 
> via the customisation mechanism wouldn't automatically get that behaviour.
> 
> As someone who doesn't use Abseil I'm inclined towards option 2, with the 
> possibility of implementing option 3 in a separate commit later. I'm not 
> particularly keen on the other two options.
It turns out that option 3 was easier to implement than I expected, so I've 
implemented it in the latest version.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D149280

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D150602: [clang-tidy] Move formatDereference to FixitHintUtils

2023-05-23 Thread Mike Crowe via Phabricator via cfe-commits
mikecrowe updated this revision to Diff 524815.
mikecrowe added a comment.

Make needParensAfterUnaryOperator static


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D150602

Files:
  clang-tools-extra/clang-tidy/readability/RedundantStringCStrCheck.cpp
  clang-tools-extra/clang-tidy/utils/FixItHintUtils.cpp
  clang-tools-extra/clang-tidy/utils/FixItHintUtils.h

Index: clang-tools-extra/clang-tidy/utils/FixItHintUtils.h
===
--- clang-tools-extra/clang-tidy/utils/FixItHintUtils.h
+++ clang-tools-extra/clang-tidy/utils/FixItHintUtils.h
@@ -44,6 +44,9 @@
   DeclSpec::TQ Qualifier,
   QualifierTarget CT = QualifierTarget::Pointee,
   QualifierPolicy CP = QualifierPolicy::Left);
+
+// \brief Format a pointer to an expression
+std::string formatDereference(const Expr , const ASTContext );
 } // namespace clang::tidy::utils::fixit
 
 #endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_UTILS_FIXITHINTUTILS_H
Index: clang-tools-extra/clang-tidy/utils/FixItHintUtils.cpp
===
--- clang-tools-extra/clang-tidy/utils/FixItHintUtils.cpp
+++ clang-tools-extra/clang-tidy/utils/FixItHintUtils.cpp
@@ -9,7 +9,9 @@
 #include "FixItHintUtils.h"
 #include "LexerUtils.h"
 #include "clang/AST/ASTContext.h"
+#include "clang/AST/ExprCXX.h"
 #include "clang/AST/Type.h"
+#include "clang/Tooling/FixIt.h"
 #include 
 
 namespace clang::tidy::utils::fixit {
@@ -221,4 +223,46 @@
 
   return std::nullopt;
 }
+
+// Return true if expr needs to be put in parens when it is an argument of a
+// prefix unary operator, e.g. when it is a binary or ternary operator
+// syntactically.
+static bool needParensAfterUnaryOperator(const Expr ) {
+  if (isa() ||
+  isa()) {
+return true;
+  }
+  if (const auto *Op = dyn_cast()) {
+return Op->getNumArgs() == 2 && Op->getOperator() != OO_PlusPlus &&
+   Op->getOperator() != OO_MinusMinus && Op->getOperator() != OO_Call &&
+   Op->getOperator() != OO_Subscript;
+  }
+  return false;
+}
+
+// Format a pointer to an expression: prefix with '*' but simplify
+// when it already begins with '&'.  Return empty string on failure.
+std::string formatDereference(const Expr , const ASTContext ) {
+  if (const auto *Op = dyn_cast()) {
+if (Op->getOpcode() == UO_AddrOf) {
+  // Strip leading '&'.
+  return std::string(
+  tooling::fixit::getText(*Op->getSubExpr()->IgnoreParens(), Context));
+}
+  }
+  StringRef Text = tooling::fixit::getText(ExprNode, Context);
+
+  if (Text.empty())
+return std::string();
+
+  // Remove remaining '->' from overloaded operator call
+  Text.consume_back("->");
+
+  // Add leading '*'.
+  if (needParensAfterUnaryOperator(ExprNode)) {
+return (llvm::Twine("*(") + Text + ")").str();
+  }
+  return (llvm::Twine("*") + Text).str();
+}
+
 } // namespace clang::tidy::utils::fixit
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
@@ -11,6 +11,7 @@
 //===--===//
 
 #include "RedundantStringCStrCheck.h"
+#include "../utils/FixItHintUtils.h"
 #include "../utils/Matchers.h"
 #include "../utils/OptionsUtils.h"
 #include "clang/Lex/Lexer.h"
@@ -22,49 +23,6 @@
 
 namespace {
 
-// Return true if expr needs to be put in parens when it is an argument of a
-// prefix unary operator, e.g. when it is a binary or ternary operator
-// syntactically.
-bool needParensAfterUnaryOperator(const Expr ) {
-  if (isa() ||
-  isa()) {
-return true;
-  }
-  if (const auto *Op = dyn_cast()) {
-return Op->getNumArgs() == 2 && Op->getOperator() != OO_PlusPlus &&
-   Op->getOperator() != OO_MinusMinus && Op->getOperator() != OO_Call &&
-   Op->getOperator() != OO_Subscript;
-  }
-  return false;
-}
-
-// Format a pointer to an expression: prefix with '*' but simplify
-// when it already begins with '&'.  Return empty string on failure.
-std::string
-formatDereference(const ast_matchers::MatchFinder::MatchResult ,
-  const Expr ) {
-  if (const auto *Op = dyn_cast()) {
-if (Op->getOpcode() == UO_AddrOf) {
-  // Strip leading '&'.
-  return std::string(tooling::fixit::getText(
-  *Op->getSubExpr()->IgnoreParens(), *Result.Context));
-}
-  }
-  StringRef Text = tooling::fixit::getText(ExprNode, *Result.Context);
-
-  if (Text.empty())
-return std::string();
-
-  // Remove remaining '->' from overloaded operator call
-  Text.consume_back("->");
-
-  // Add leading '*'.
-  if (needParensAfterUnaryOperator(ExprNode)) {
-return 

[PATCH] D150602: [clang-tidy] Move formatDereference to FixitHintUtils

2023-05-23 Thread Mike Crowe via Phabricator via cfe-commits
mikecrowe marked an inline comment as done.
mikecrowe added a comment.

Thanks for the review. New version with the `static` added coming shortly.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D150602

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D149280: [clang-tidy] Add modernize-printf-to-std-print check

2023-05-20 Thread Mike Crowe via Phabricator via cfe-commits
mikecrowe added inline comments.



Comment at: 
clang-tools-extra/docs/clang-tidy/checks/modernize/use-std-print.rst:79
+
+.. option:: StrictMode
+

It turns out that absl::PrintF and absl::FPrintF work like std::format, 
fmt::printf, etc. and use the signedness of the argument rather than the 
signedness indicated in the format string to determine how to format the 
number. In other words:
`unsigned int ui = 0x; absl::PrintF("%d\n", ui);` yields `4294967295` 
(see https://godbolt.org/z/dYcbehxP9 ), so the casts that StrictMode adds would 
change the behaviour of the converted code.

I can think of several ways around this:

1. Update the documentation to explain this, recommending not to use StrictMode 
when converting Abseil functions.

2. Remove built-in support for Abseil functions from this check. Anyone wishing 
to convert them can do so via the customisation features, and can choose not to 
use StrictMode. (This could be documented here.)

3. Teach the code to recognise whether the arguments is being passed as a 
C-style variable argument list or as fully-typed arguments to a templated 
function and make StrictMode only add the casts for the former. (I've not 
investigated how feasible this is.)

4. Treat the known Abseil functions in this check differently by name and 
disable the casting behaviour. This means that conversion from fmt::printf via 
the customisation mechanism wouldn't automatically get that behaviour.

As someone who doesn't use Abseil I'm inclined towards option 2, with the 
possibility of implementing option 3 in a separate commit later. I'm not 
particularly keen on the other two options.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D149280

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D150602: [clang-tidy] Move formatDereference to FixitHintUtils

2023-05-15 Thread Mike Crowe via Phabricator via cfe-commits
mikecrowe created this revision.
mikecrowe added reviewers: njames93, carlosgalvezp, PiotrZSL.
Herald added a subscriber: xazax.hun.
Herald added a project: All.
mikecrowe requested review of this revision.
Herald added a project: clang-tools-extra.
Herald added a subscriber: cfe-commits.

I'd like to use RedundantStringCStrCheck's formatDereference function
from the up-coming modernize-use-std-print check. Let's move it to
FixItHintUtils so that the implementation can be shared.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D150602

Files:
  clang-tools-extra/clang-tidy/readability/RedundantStringCStrCheck.cpp
  clang-tools-extra/clang-tidy/utils/FixItHintUtils.cpp
  clang-tools-extra/clang-tidy/utils/FixItHintUtils.h

Index: clang-tools-extra/clang-tidy/utils/FixItHintUtils.h
===
--- clang-tools-extra/clang-tidy/utils/FixItHintUtils.h
+++ clang-tools-extra/clang-tidy/utils/FixItHintUtils.h
@@ -44,6 +44,9 @@
   DeclSpec::TQ Qualifier,
   QualifierTarget CT = QualifierTarget::Pointee,
   QualifierPolicy CP = QualifierPolicy::Left);
+
+// \brief Format a pointer to an expression
+std::string formatDereference(const Expr , const ASTContext );
 } // namespace clang::tidy::utils::fixit
 
 #endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_UTILS_FIXITHINTUTILS_H
Index: clang-tools-extra/clang-tidy/utils/FixItHintUtils.cpp
===
--- clang-tools-extra/clang-tidy/utils/FixItHintUtils.cpp
+++ clang-tools-extra/clang-tidy/utils/FixItHintUtils.cpp
@@ -9,7 +9,9 @@
 #include "FixItHintUtils.h"
 #include "LexerUtils.h"
 #include "clang/AST/ASTContext.h"
+#include "clang/AST/ExprCXX.h"
 #include "clang/AST/Type.h"
+#include "clang/Tooling/FixIt.h"
 #include 
 
 namespace clang::tidy::utils::fixit {
@@ -221,4 +223,46 @@
 
   return std::nullopt;
 }
+
+// Return true if expr needs to be put in parens when it is an argument of a
+// prefix unary operator, e.g. when it is a binary or ternary operator
+// syntactically.
+bool needParensAfterUnaryOperator(const Expr ) {
+  if (isa() ||
+  isa()) {
+return true;
+  }
+  if (const auto *Op = dyn_cast()) {
+return Op->getNumArgs() == 2 && Op->getOperator() != OO_PlusPlus &&
+   Op->getOperator() != OO_MinusMinus && Op->getOperator() != OO_Call &&
+   Op->getOperator() != OO_Subscript;
+  }
+  return false;
+}
+
+// Format a pointer to an expression: prefix with '*' but simplify
+// when it already begins with '&'.  Return empty string on failure.
+std::string formatDereference(const Expr , const ASTContext ) {
+  if (const auto *Op = dyn_cast()) {
+if (Op->getOpcode() == UO_AddrOf) {
+  // Strip leading '&'.
+  return std::string(
+  tooling::fixit::getText(*Op->getSubExpr()->IgnoreParens(), Context));
+}
+  }
+  StringRef Text = tooling::fixit::getText(ExprNode, Context);
+
+  if (Text.empty())
+return std::string();
+
+  // Remove remaining '->' from overloaded operator call
+  Text.consume_back("->");
+
+  // Add leading '*'.
+  if (needParensAfterUnaryOperator(ExprNode)) {
+return (llvm::Twine("*(") + Text + ")").str();
+  }
+  return (llvm::Twine("*") + Text).str();
+}
+
 } // namespace clang::tidy::utils::fixit
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
@@ -11,6 +11,7 @@
 //===--===//
 
 #include "RedundantStringCStrCheck.h"
+#include "../utils/FixItHintUtils.h"
 #include "../utils/Matchers.h"
 #include "../utils/OptionsUtils.h"
 #include "clang/Lex/Lexer.h"
@@ -22,49 +23,6 @@
 
 namespace {
 
-// Return true if expr needs to be put in parens when it is an argument of a
-// prefix unary operator, e.g. when it is a binary or ternary operator
-// syntactically.
-bool needParensAfterUnaryOperator(const Expr ) {
-  if (isa() ||
-  isa()) {
-return true;
-  }
-  if (const auto *Op = dyn_cast()) {
-return Op->getNumArgs() == 2 && Op->getOperator() != OO_PlusPlus &&
-   Op->getOperator() != OO_MinusMinus && Op->getOperator() != OO_Call &&
-   Op->getOperator() != OO_Subscript;
-  }
-  return false;
-}
-
-// Format a pointer to an expression: prefix with '*' but simplify
-// when it already begins with '&'.  Return empty string on failure.
-std::string
-formatDereference(const ast_matchers::MatchFinder::MatchResult ,
-  const Expr ) {
-  if (const auto *Op = dyn_cast()) {
-if (Op->getOpcode() == UO_AddrOf) {
-  // Strip leading '&'.
-  return std::string(tooling::fixit::getText(
-  *Op->getSubExpr()->IgnoreParens(), *Result.Context));
-}
-  }
-  

[PATCH] D149280: [clang-tidy] Add modernize-printf-to-std-print check

2023-05-14 Thread Mike Crowe via Phabricator via cfe-commits
mikecrowe added inline comments.



Comment at: clang-tools-extra/clang-tidy/utils/FormatStringConverter.cpp:27
+  using namespace clang;
+  if (const auto *BT = llvm::dyn_cast(Ty)) {
+const bool result = (BT->getKind() == BuiltinType::Char_U ||

This apparently need to be `Ty->getUnqualifiedDesugaredType()` to ensure that 
arguments like std::string().c_str() are correctly treated as being of `char` 
type. Without, the `dyn_cast` fails.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D149280

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D149280: [clang-tidy] Add modernize-printf-to-std-print check

2023-05-11 Thread Mike Crowe via Phabricator via cfe-commits
mikecrowe added inline comments.



Comment at: 
clang-tools-extra/docs/clang-tidy/checks/modernize/use-std-print.rst:117
+
+.. option:: PrintFunction
+

Is `PrintFunction` (and the soon-to-arrive `PrintlnFunction`) distinct enough 
from `PrintfLikeFunctions` and `FprintfLikeFunctions`? Should I use 
`ReplacementPrintFunction` instead?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D149280

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D149280: [clang-tidy] Add modernize-printf-to-std-print check

2023-05-08 Thread Mike Crowe via Phabricator via cfe-commits
mikecrowe updated this revision to Diff 520439.
mikecrowe added a comment.

Address many more review comments, including:

- Only add casts for signed/unsigned discrepancy if StrictMode option is set.
- Use IncludeInserter to add  or other required header.

Review comments still outstanding:

- Use println if format string ends in `\n`.
- Remove c_str() as part of the same check (I'm not really sure how to do this, 
are there any other checks that I should look at for inspiration?)
- Emit warnings to explain why if conversion is not possible.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D149280

Files:
  clang-tools-extra/clang-tidy/modernize/CMakeLists.txt
  clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp
  clang-tools-extra/clang-tidy/modernize/UseStdPrintCheck.cpp
  clang-tools-extra/clang-tidy/modernize/UseStdPrintCheck.h
  clang-tools-extra/clang-tidy/utils/CMakeLists.txt
  clang-tools-extra/clang-tidy/utils/FormatStringConverter.cpp
  clang-tools-extra/clang-tidy/utils/FormatStringConverter.h
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  clang-tools-extra/docs/clang-tidy/checks/modernize/use-std-print.rst
  clang-tools-extra/test/clang-tidy/checkers/Inputs/Headers/cstdio
  clang-tools-extra/test/clang-tidy/checkers/Inputs/Headers/stdio.h
  clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print-absl.cpp
  clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print-custom.cpp
  clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print-fmt.cpp
  clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print.cpp
@@ -0,0 +1,1049 @@
+// RUN: %check_clang_tidy -check-suffixes=,STRICT \
+// RUN:   -std=c++2b %s modernize-use-std-print %t -- \
+// RUN:   -config="{CheckOptions: [{key: StrictMode, value: true}]}" \
+// RUN:   -- -isystem %clang_tidy_headers
+// RUN: %check_clang_tidy -check-suffixes=,NOTSTRICT \
+// RUN:   -std=c++2b %s modernize-use-std-print %t -- \
+// RUN:   -config="{CheckOptions: [{key: StrictMode, value: false}]}" \
+// RUN:   -- -isystem %clang_tidy_headers
+#include 
+// CHECK-FIXES: #include 
+#include 
+#include 
+
+void printf_simple() {
+  printf("Hello");
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'printf' [modernize-use-std-print]
+  // CHECK-FIXES: std::print("Hello");
+}
+
+void fprintf_simple() {
+  fprintf(stderr, "Hello");
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'fprintf' [modernize-use-std-print]
+  // CHECK-FIXES: std::print(stderr, "Hello");
+}
+
+void std_printf_simple() {
+  std::printf("std::Hello");
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'printf' [modernize-use-std-print]
+  // CHECK-FIXES: std::print("std::Hello");
+}
+
+void printf_escape() {
+  printf("before \t");
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'printf' [modernize-use-std-print]
+  // CHECK-FIXES: std::print("before \t");
+
+  printf("\n after");
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'printf' [modernize-use-std-print]
+  // CHECK-FIXES: std::print("\n after");
+
+  printf("before \a after");
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'printf' [modernize-use-std-print]
+  // CHECK-FIXES: std::print("before \a after");
+
+  printf("Bell\a%dBackspace\bFF%s\fNewline\nCR\rTab\tVT\vEscape\x1b\x07%d", 42, "string", 99);
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'printf' [modernize-use-std-print]
+  // CHECK-FIXES: std::print("Bell\a{}Backspace\bFF{}\fNewline\nCR\rTab\tVT\vEscape\x1b\a{}", 42, "string", 99);
+
+  printf("not special \x1b\x01\x7f");
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'printf' [modernize-use-std-print]
+  // CHECK-FIXES: std::print("not special \x1b\x01\x7f");
+}
+
+void printf_percent() {
+  printf("before %%");
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'printf' [modernize-use-std-print]
+  // CHECK-FIXES: std::print("before %");
+
+  printf("%% after");
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'printf' [modernize-use-std-print]
+  // CHECK-FIXES: std::print("% after");
+
+  printf("before %% after");
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'printf' [modernize-use-std-print]
+  // CHECK-FIXES: std::print("before % after");
+
+  printf("Hello %% and another %%");
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'printf' [modernize-use-std-print]
+  // CHECK-FIXES: std::print("Hello % and another 

[PATCH] D149280: [clang-tidy] Add modernize-printf-to-std-print check

2023-05-08 Thread Mike Crowe via Phabricator via cfe-commits
mikecrowe marked 3 inline comments as done.
mikecrowe added inline comments.



Comment at: 
clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print.cpp:124-126
+  printf("Integer %d from bool\n", b);
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 
'printf' [modernize-use-std-print]
+  // CHECK-FIXES: std::print("Integer {:d} from bool\n", b);

njames93 wrote:
> It would be nice if the there was support for changing this to 
> `std::println("Integer {:d} from bool", b);`
Yes. That was item 2 on the plans for the future in my first comment. Would you 
prefer that everything is completed in this single commit, or would you be 
happy to the core functionality first with future enhancements in separate 
commits afterwards?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D149280

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D149280: [clang-tidy] Add modernize-printf-to-std-print check

2023-04-30 Thread Mike Crowe via Phabricator via cfe-commits
mikecrowe updated this revision to Diff 518315.
mikecrowe added a comment.

I've addressed most of the review comments. The work that remains outstanding 
is:

- Emit warnings when conversion is not possible explaining why.

- Only add signed/unsigned casts when in StrictMode.

- Automatically remove now-unnecessary calls to c_str() in arguments rather 
than requiring readability-redundant-string-cstr check to be run afterwards.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D149280

Files:
  clang-tools-extra/clang-tidy/modernize/CMakeLists.txt
  clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp
  clang-tools-extra/clang-tidy/modernize/UseStdPrintCheck.cpp
  clang-tools-extra/clang-tidy/modernize/UseStdPrintCheck.h
  clang-tools-extra/clang-tidy/utils/CMakeLists.txt
  clang-tools-extra/clang-tidy/utils/FormatStringConverter.cpp
  clang-tools-extra/clang-tidy/utils/FormatStringConverter.h
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  clang-tools-extra/docs/clang-tidy/checks/modernize/use-std-print.rst
  clang-tools-extra/test/clang-tidy/checkers/Inputs/Headers/cstdio
  clang-tools-extra/test/clang-tidy/checkers/Inputs/Headers/stdio.h
  clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print-absl.cpp
  clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print-custom.cpp
  clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print-fmt.cpp
  clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print.cpp
@@ -0,0 +1,1021 @@
+// RUN: %check_clang_tidy -std=c++2b %s modernize-use-std-print %t -- -- -isystem %clang_tidy_headers
+
+#include 
+#include 
+#include 
+
+void printf_simple() {
+  printf("Hello");
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'printf' [modernize-use-std-print]
+  // CHECK-FIXES: std::print("Hello");
+}
+
+void fprintf_simple() {
+  fprintf(stderr, "Hello");
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'fprintf' [modernize-use-std-print]
+  // CHECK-FIXES: std::print(stderr, "Hello");
+}
+
+void std_printf_simple() {
+  std::printf("std::Hello");
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'printf' [modernize-use-std-print]
+  // CHECK-FIXES: std::print("std::Hello");
+}
+
+void printf_escape() {
+  printf("before \t");
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'printf' [modernize-use-std-print]
+  // CHECK-FIXES: std::print("before \t");
+
+  printf("\n after");
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'printf' [modernize-use-std-print]
+  // CHECK-FIXES: std::print("\n after");
+
+  printf("before \a after");
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'printf' [modernize-use-std-print]
+  // CHECK-FIXES: std::print("before \a after");
+
+  printf("Bell\a%dBackspace\bFF%s\fNewline\nCR\rTab\tVT\vEscape\x1b\x07%d", 42, "string", 99);
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'printf' [modernize-use-std-print]
+  // CHECK-FIXES: std::print("Bell\a{}Backspace\bFF{}\fNewline\nCR\rTab\tVT\vEscape\x1b\a{}", 42, "string", 99);
+
+  printf("not special \x1b\x01\x7f");
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'printf' [modernize-use-std-print]
+  // CHECK-FIXES: std::print("not special \x1b\x01\x7f");
+}
+
+void printf_percent() {
+  printf("before %%");
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'printf' [modernize-use-std-print]
+  // CHECK-FIXES: std::print("before %");
+
+  printf("%% after");
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'printf' [modernize-use-std-print]
+  // CHECK-FIXES: std::print("% after");
+
+  printf("before %% after");
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'printf' [modernize-use-std-print]
+  // CHECK-FIXES: std::print("before % after");
+
+  printf("Hello %% and another %%");
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'printf' [modernize-use-std-print]
+  // CHECK-FIXES: std::print("Hello % and another %");
+
+  printf("Not a string %%s");
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'printf' [modernize-use-std-print]
+  // CHECK-FIXES: std::print("Not a string %s");
+}
+
+void printf_curlies() {
+  printf("%d {}", 42);
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'printf' [modernize-use-std-print]
+  // CHECK-FIXES: std::print("{} {{[{][{]", 42);
+
+  printf("{}");
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 

[PATCH] D149280: [clang-tidy] Add modernize-printf-to-std-print check

2023-04-30 Thread Mike Crowe via Phabricator via cfe-commits
mikecrowe added inline comments.



Comment at: 
clang-tools-extra/test/clang-tidy/checkers/modernize/printf-to-std-print-convert.cpp:289
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: Replace 'printf' with 
'std::print' [modernize-printf-to-std-print]
+  // CHECK-FIXES: std::print("Integer {} from signed char\n", sc);
+

mikecrowe wrote:
> This requires a cast to `unsigned char`. It appears that 
> `Arg->getType()->isSignedIntegerType()` inside the `uArg` case is returning 
> `false` for `signed char`, which means that it doesn't get one. Strange!
> This requires a cast to `unsigned char`. It appears that 
> `Arg->getType()->isSignedIntegerType()` inside the `uArg` case is returning 
> `false` for `signed char`, which means that it doesn't get one. Strange!

Operator error. Apologies for the noise. :(


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D149280

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D149280: [clang-tidy] Add modernize-printf-to-std-print check

2023-04-30 Thread Mike Crowe via Phabricator via cfe-commits
mikecrowe marked an inline comment as done.
mikecrowe added inline comments.



Comment at: 
clang-tools-extra/test/clang-tidy/checkers/modernize/printf-to-std-print-convert.cpp:289
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: Replace 'printf' with 
'std::print' [modernize-printf-to-std-print]
+  // CHECK-FIXES: std::print("Integer {} from signed char\n", sc);
+

This requires a cast to `unsigned char`. It appears that 
`Arg->getType()->isSignedIntegerType()` inside the `uArg` case is returning 
`false` for `signed char`, which means that it doesn't get one. Strange!


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D149280

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D149280: [clang-tidy] Add modernize-printf-to-std-print check

2023-04-30 Thread Mike Crowe via Phabricator via cfe-commits
mikecrowe marked 4 inline comments as done.
mikecrowe added inline comments.



Comment at: 
clang-tools-extra/docs/clang-tidy/checks/modernize/printf-to-std-print.rst:61
+- any arguments where the format string and the parameter differ in
+  signedness will be wrapped in an approprate ``static_cast``. For example,
+  given ``int i = 42``, then ``printf("%u\n", i)`` will become

njames93 wrote:
> Perhaps these conversions should only be done in StrictMode
I think that's probably a good idea. The casts are ugly, and probably 
unnecessary in many cases. I've implemented it, but I'm currently wrestling 
with the lit tests for it.



Comment at: 
clang-tools-extra/docs/clang-tidy/checks/modernize/printf-to-std-print.rst:73
+   printf-style format string and the arguments to be formatted follow
+   immediately afterwards.
+

Eugene.Zelenko wrote:
> mikecrowe wrote:
> > Eugene.Zelenko wrote:
> > > Please add information about default value.
> > The current implementation always "fixes" `printf`, `fprintf`, 
> > `absl::PrintF` and `absl::FPrintf`, even when this option is used (see 
> > `UseStdPrintCheck` constructor.) Should the option inhibit this default?
> It may be reasonable to provide possibility to override default.
I think it's likely that anyone using a custom value for either 
`PrintfLikeFunctions` or `FPrintfLikeFunctions` won't want the default function 
list for either.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D149280

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D149280: [clang-tidy] Add modernize-printf-to-std-print check

2023-04-29 Thread Mike Crowe via Phabricator via cfe-commits
mikecrowe marked 12 inline comments as done.
mikecrowe added a comment.

Thank you for all the review comments.




Comment at: clang-tools-extra/clang-tidy/utils/FormatStringConverter.cpp:322
+  if (!isRealCharType(Pointee))
+ArgFixes.emplace_back(Arg, "reinterpret_cast(");
+}

njames93 wrote:
> By default this check should not do this conversion, we shouldn't be creating 
> UB in fixes emitted by clang-tidy unless the user explicitly opts in.
> Maybe a good framework moving forward is to still a warning about converting 
> up std::print, but emit a note here saying why the automatic conversation 
> isn't possible.
Good spot. This was wider than I intended. The cast is only supposed to be used 
if the argument is a pointer to `unsigned char` or `signed char`.

I think that I probably ought to make sure that all the places that decide that 
conversion is not possible emit a warning explaining why.



Comment at: clang-tools-extra/clang-tidy/utils/FormatStringConverter.cpp:412
+else
+  ArgFixes.emplace_back(Arg, "reinterpret_cast(");
+break;

njames93 wrote:
> `reinterpret_cast` is not needed here, a static cast to`const void*` will 
> work.
Good spot. I'm sure I used the right cast in an earlier version... :(



Comment at: 
clang-tools-extra/docs/clang-tidy/checks/modernize/printf-to-std-print.rst:73
+   printf-style format string and the arguments to be formatted follow
+   immediately afterwards.
+

Eugene.Zelenko wrote:
> Please add information about default value.
The current implementation always "fixes" `printf`, `fprintf`, `absl::PrintF` 
and `absl::FPrintf`, even when this option is used (see `UseStdPrintCheck` 
constructor.) Should the option inhibit this default?



Comment at: 
clang-tools-extra/docs/clang-tidy/checks/modernize/printf-to-std-print.rst:92
+
+It is helpful to use the `readability-redundant-string-cstr
+<../readability/redundant-string-cstr.html>` check after this check to

njames93 wrote:
> It may be wise in a future version to just do that conversion anyway. 2 stage 
> fixes are annoying for users to have to use 
I shall investigate how to do that.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D149280

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D149280: [clang-tidy] Add modernize-printf-to-std-print check

2023-04-27 Thread Mike Crowe via Phabricator via cfe-commits
mikecrowe added a comment.

Thanks for all the reviews.

In D149280#4301188 , @njames93 wrote:

> It may be a good idea to create unittests for the formatconverter in 
> `clang-tools-extra/unittests/clang-tidy/`

I started there but had decided that the easiest and most reviewable form for 
the tests was in lit tests since the code that uses `FormatStringConverter` is 
so simple. (Particularly since I was hoping to persuade the inventor of 
`std::format` to review the tests too.) Are you proposing that I should 
duplicate (most of) the lit tests in the unit tests or migrate most of the lit 
tests to unit tests? Are there any existing tests that do similar things that I 
should model them on?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D149280

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D149280: [clang-tidy] Add modernize-printf-to-std-print check

2023-04-26 Thread Mike Crowe via Phabricator via cfe-commits
mikecrowe added a comment.

If this sort of check is deemed acceptable then I have plans for future 
improvements, including:

1. Automatically turning absl::StrFormat into fmt::format too (with an option 
to choose an alternative to `absl::StrFormat`.)

2. Detecting format strings that end in `"\n"` and turning the call into 
`std::println` rather than `std::print`.

3. It ought to be possible to do something with %m by using `std::error_code`.

4. Support for member functions and even `operator()` for help with converting 
logging class methods.

My attempts to do something sensible with wide characters failed miserably. 
I've never used wprintf etc. myself and it would probably require the skills of 
someone more familiar with them.

Since many other clang-tidy checks are for Abseil, support for `absl::PrintF` 
and `absl::FPrintF` is built in. They could be removed since it would always be 
possible to replace them using the provided options.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D149280

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D149280: [clang-tidy] Add modernize-printf-to-std-print check

2023-04-26 Thread Mike Crowe via Phabricator via cfe-commits
mikecrowe created this revision.
Herald added subscribers: carlosgalvezp, xazax.hun.
Herald added a reviewer: njames93.
Herald added a project: All.
mikecrowe requested review of this revision.
Herald added a project: clang-tools-extra.
Herald added a subscriber: cfe-commits.

Add FormatStringConverter utility class that is capable of converting
printf-style format strings into std::format-style format strings along
with recording a set of casts to wrap the arguments as required.

Use FormatStringConverter to implement a new clang-tidy check that is
capable of converting calls to printf, fprintf, absl::PrintF,
absl::FPrintF, or any function configured by an option to calls to
std::print or another function configured by an option.

In other words, the check turns:

fprintf(stderr, "The %s is %3d\n", answer, value);

into:

std::print(stderr, "The {} is {:3}\n", answer, value);

if it can.

std::print can do almost anything that standard printf can, but the
conversion has some some limitations that are described in the
documentation. If conversion is not possible then the call remains
unchanged.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D149280

Files:
  clang-tools-extra/clang-tidy/modernize/CMakeLists.txt
  clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp
  clang-tools-extra/clang-tidy/modernize/PrintfToStdPrintCheck.cpp
  clang-tools-extra/clang-tidy/modernize/PrintfToStdPrintCheck.h
  clang-tools-extra/clang-tidy/utils/CMakeLists.txt
  clang-tools-extra/clang-tidy/utils/FormatStringConverter.cpp
  clang-tools-extra/clang-tidy/utils/FormatStringConverter.h
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  clang-tools-extra/docs/clang-tidy/checks/modernize/printf-to-std-print.rst
  clang-tools-extra/test/clang-tidy/checkers/Inputs/Headers/cstdio
  clang-tools-extra/test/clang-tidy/checkers/Inputs/Headers/stdio.h
  
clang-tools-extra/test/clang-tidy/checkers/modernize/printf-to-fmt-print-convert.cpp
  
clang-tools-extra/test/clang-tidy/checkers/modernize/printf-to-std-print-convert-absl.cpp
  
clang-tools-extra/test/clang-tidy/checkers/modernize/printf-to-std-print-convert-custom.cpp
  
clang-tools-extra/test/clang-tidy/checkers/modernize/printf-to-std-print-convert.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/modernize/printf-to-std-print-convert.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/modernize/printf-to-std-print-convert.cpp
@@ -0,0 +1,1021 @@
+// RUN: %check_clang_tidy -std=c++2b %s modernize-printf-to-std-print %t -- -- -isystem %clang_tidy_headers
+
+#include 
+#include 
+#include 
+
+void printf_simple() {
+  printf("Hello");
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: Replace 'printf' with 'std::print' [modernize-printf-to-std-print]
+  // CHECK-FIXES: std::print("Hello");
+}
+
+void fprintf_simple() {
+  fprintf(stderr, "Hello");
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: Replace 'fprintf' with 'std::print' [modernize-printf-to-std-print]
+  // CHECK-FIXES: std::print(stderr, "Hello");
+}
+
+void std_printf_simple() {
+  std::printf("std::Hello");
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: Replace 'printf' with 'std::print' [modernize-printf-to-std-print]
+  // CHECK-FIXES: std::print("std::Hello");
+}
+
+void printf_escape() {
+  printf("before \t");
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: Replace 'printf' with 'std::print' [modernize-printf-to-std-print]
+  // CHECK-FIXES: std::print("before \t");
+
+  printf("\n after");
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: Replace 'printf' with 'std::print' [modernize-printf-to-std-print]
+  // CHECK-FIXES: std::print("\n after");
+
+  printf("before \a after");
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: Replace 'printf' with 'std::print' [modernize-printf-to-std-print]
+  // CHECK-FIXES: std::print("before \a after");
+
+  printf("Bell\a%dBackspace\bFF%s\fNewline\nCR\rTab\tVT\vEscape\x1b\x07%d", 42, "string", 99);
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: Replace 'printf' with 'std::print' [modernize-printf-to-std-print]
+  // CHECK-FIXES: std::print("Bell\a{}Backspace\bFF{}\fNewline\nCR\rTab\tVT\vEscape\x1b\a{}", 42, "string", 99);
+
+  printf("not special \x1b\x01\x7f");
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: Replace 'printf' with 'std::print' [modernize-printf-to-std-print]
+  // CHECK-FIXES: std::print("not special \x1b\x01\x7f");
+}
+
+void printf_percent() {
+  printf("before %%");
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: Replace 'printf' with 'std::print' [modernize-printf-to-std-print]
+  // CHECK-FIXES: std::print("before %");
+
+  printf("%% after");
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: Replace 'printf' with 'std::print' [modernize-printf-to-std-print]
+  // CHECK-FIXES: std::print("% after");
+
+  printf("before %% after");
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: Replace 'printf' with 'std::print' 

[PATCH] D145885: [clang-tidy] Support readability-redundant-string-cstr.StringParameterFunctions option

2023-03-13 Thread Mike Crowe via Phabricator via cfe-commits
mikecrowe updated this revision to Diff 504537.
mikecrowe edited the summary of this revision.
mikecrowe added a comment.

Quote types and functions correctly in redundant-string-cstr.rst.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D145885

Files:
  clang-tools-extra/clang-tidy/readability/RedundantStringCStrCheck.cpp
  clang-tools-extra/clang-tidy/readability/RedundantStringCStrCheck.h
  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-function.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/readability/redundant-string-cstr-function.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/readability/redundant-string-cstr-function.cpp
@@ -0,0 +1,148 @@
+// RUN: %check_clang_tidy %s readability-redundant-string-cstr %t -- \
+// RUN:   -config="{CheckOptions: \
+// RUN: [{key: readability-redundant-string-cstr.StringParameterFunctions, \
+// RUN:   value: '::fmt::format; ::fmt::print; ::BaseLogger::operator(); ::BaseLogger::Log'}] \
+// RUN: }" \
+// RUN:   -- -isystem %clang_tidy_headers
+#include 
+
+namespace fmt {
+  inline namespace v8 {
+template
+void print(const char *, Args &&...);
+template
+std::string format(const char *, Args &&...);
+  }
+}
+
+namespace notfmt {
+  inline namespace v8 {
+template
+void print(const char *, Args &&...);
+template
+std::string format(const char *, Args &&...);
+  }
+}
+
+void fmt_print(const std::string , const std::string , const std::string ) {
+  fmt::print("One:{}\n", s1.c_str());
+  // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: redundant call to 'c_str' [readability-redundant-string-cstr]
+  // CHECK-FIXES: {{^  }}fmt::print("One:{}\n", s1);
+
+  fmt::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-MESSAGES: :[[@LINE-2]]:58: warning: redundant call to 'c_str' [readability-redundant-string-cstr]
+  // CHECK-FIXES: {{^  }}fmt::print("One:{} Two:{} Three:{}\n", s1, s2, s3);
+}
+
+// There's no c_str() call here, so it shouldn't be touched
+void fmt_print_no_cstr(const std::string , const std::string ) {
+fmt::print("One: {}, Two: {}\n", s1, s2);
+}
+
+// This isn't fmt::print, so it shouldn't be fixed.
+void not_fmt_print(const std::string ) {
+notfmt::print("One: {}\n", s1.c_str());
+}
+
+void fmt_format(const std::string , const std::string , const std::string ) {
+  auto r1 = fmt::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 = fmt::format("One:{}\n", s1);
+
+  auto r2 = fmt::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-MESSAGES: :[[@LINE-2]]:69: warning: redundant call to 'c_str' [readability-redundant-string-cstr]
+  // CHECK-FIXES: {{^  }}auto r2 = fmt::format("One:{} Two:{} Three:{}\n", s1, s2, s3);
+}
+
+// There's are c_str() calls here, so it shouldn't be touched
+void fmt_format_no_cstr(const std::string , const std::string ) {
+fmt::format("One: {}, Two: {}\n", s1, s2);
+}
+
+// This is not fmt::format, so it shouldn't be fixed
+std::string not_fmt_format(const std::string ) {
+return notfmt::format("One: {}\n", s1.c_str());
+}
+
+class BaseLogger {
+public:
+  template 
+  void operator()(const char *fmt, Args &&...args) {
+  }
+
+  template 
+  void Log(const char *fmt, Args &&...args) {
+  }
+};
+
+class DerivedLogger : public BaseLogger {};
+class DoubleDerivedLogger : public DerivedLogger {};
+typedef DerivedLogger TypedefDerivedLogger;
+
+void logger1(const std::string , const std::string , const std::string ) {
+  BaseLogger LOGGER;
+
+  LOGGER("%s\n", s1.c_str(), s2, s3.c_str());
+  // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: redundant call to 'c_str' [readability-redundant-string-cstr]
+  // CHECK-MESSAGES: :[[@LINE-2]]:34: warning: redundant call to 'c_str' [readability-redundant-string-cstr]
+  // CHECK-FIXES: {{^  }}LOGGER("%s\n", s1, s2, s3);
+
+  DerivedLogger LOGGER2;
+  LOGGER2("%d %s\n", 42, s1.c_str(), s2.c_str(), s3);
+  // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: redundant call to 'c_str' [readability-redundant-string-cstr]
+  // CHECK-MESSAGES: :[[@LINE-2]]:38: warning: redundant call to 'c_str' [readability-redundant-string-cstr]
+  // CHECK-FIXES: {{^  }}LOGGER2("%d %s\n", 42, s1, s2, s3);
+
+  DoubleDerivedLogger LOGGERD;
+  LOGGERD("%d %s\n", 42, s1.c_str(), s2, s3.c_str());
+  // CHECK-MESSAGES: :[[@LINE-1]]:26: 

[PATCH] D145885: [clang-tidy] Support readability-redundant-string-cstr.StringParameterFunctions option

2023-03-13 Thread Mike Crowe via Phabricator via cfe-commits
mikecrowe updated this revision to Diff 504517.
mikecrowe marked 2 inline comments as done.
mikecrowe added a comment.

Documentation updates suggested by @PiotrZSL. Rebase.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D145885

Files:
  clang-tools-extra/clang-tidy/readability/RedundantStringCStrCheck.cpp
  clang-tools-extra/clang-tidy/readability/RedundantStringCStrCheck.h
  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-function.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/readability/redundant-string-cstr-function.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/readability/redundant-string-cstr-function.cpp
@@ -0,0 +1,148 @@
+// RUN: %check_clang_tidy %s readability-redundant-string-cstr %t -- \
+// RUN:   -config="{CheckOptions: \
+// RUN: [{key: readability-redundant-string-cstr.StringParameterFunctions, \
+// RUN:   value: '::fmt::format; ::fmt::print; ::BaseLogger::operator(); ::BaseLogger::Log'}] \
+// RUN: }" \
+// RUN:   -- -isystem %clang_tidy_headers
+#include 
+
+namespace fmt {
+  inline namespace v8 {
+template
+void print(const char *, Args &&...);
+template
+std::string format(const char *, Args &&...);
+  }
+}
+
+namespace notfmt {
+  inline namespace v8 {
+template
+void print(const char *, Args &&...);
+template
+std::string format(const char *, Args &&...);
+  }
+}
+
+void fmt_print(const std::string , const std::string , const std::string ) {
+  fmt::print("One:{}\n", s1.c_str());
+  // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: redundant call to 'c_str' [readability-redundant-string-cstr]
+  // CHECK-FIXES: {{^  }}fmt::print("One:{}\n", s1);
+
+  fmt::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-MESSAGES: :[[@LINE-2]]:58: warning: redundant call to 'c_str' [readability-redundant-string-cstr]
+  // CHECK-FIXES: {{^  }}fmt::print("One:{} Two:{} Three:{}\n", s1, s2, s3);
+}
+
+// There's no c_str() call here, so it shouldn't be touched
+void fmt_print_no_cstr(const std::string , const std::string ) {
+fmt::print("One: {}, Two: {}\n", s1, s2);
+}
+
+// This isn't fmt::print, so it shouldn't be fixed.
+void not_fmt_print(const std::string ) {
+notfmt::print("One: {}\n", s1.c_str());
+}
+
+void fmt_format(const std::string , const std::string , const std::string ) {
+  auto r1 = fmt::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 = fmt::format("One:{}\n", s1);
+
+  auto r2 = fmt::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-MESSAGES: :[[@LINE-2]]:69: warning: redundant call to 'c_str' [readability-redundant-string-cstr]
+  // CHECK-FIXES: {{^  }}auto r2 = fmt::format("One:{} Two:{} Three:{}\n", s1, s2, s3);
+}
+
+// There's are c_str() calls here, so it shouldn't be touched
+void fmt_format_no_cstr(const std::string , const std::string ) {
+fmt::format("One: {}, Two: {}\n", s1, s2);
+}
+
+// This is not fmt::format, so it shouldn't be fixed
+std::string not_fmt_format(const std::string ) {
+return notfmt::format("One: {}\n", s1.c_str());
+}
+
+class BaseLogger {
+public:
+  template 
+  void operator()(const char *fmt, Args &&...args) {
+  }
+
+  template 
+  void Log(const char *fmt, Args &&...args) {
+  }
+};
+
+class DerivedLogger : public BaseLogger {};
+class DoubleDerivedLogger : public DerivedLogger {};
+typedef DerivedLogger TypedefDerivedLogger;
+
+void logger1(const std::string , const std::string , const std::string ) {
+  BaseLogger LOGGER;
+
+  LOGGER("%s\n", s1.c_str(), s2, s3.c_str());
+  // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: redundant call to 'c_str' [readability-redundant-string-cstr]
+  // CHECK-MESSAGES: :[[@LINE-2]]:34: warning: redundant call to 'c_str' [readability-redundant-string-cstr]
+  // CHECK-FIXES: {{^  }}LOGGER("%s\n", s1, s2, s3);
+
+  DerivedLogger LOGGER2;
+  LOGGER2("%d %s\n", 42, s1.c_str(), s2.c_str(), s3);
+  // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: redundant call to 'c_str' [readability-redundant-string-cstr]
+  // CHECK-MESSAGES: :[[@LINE-2]]:38: warning: redundant call to 'c_str' [readability-redundant-string-cstr]
+  // CHECK-FIXES: {{^  }}LOGGER2("%d %s\n", 42, s1, s2, s3);
+
+  DoubleDerivedLogger LOGGERD;
+  LOGGERD("%d %s\n", 42, s1.c_str(), s2, s3.c_str());
+  // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: redundant 

[PATCH] D145885: [clang-tidy] Support readability-redundant-string-cstr.StringParameterFunctions option

2023-03-12 Thread Mike Crowe via Phabricator via cfe-commits
mikecrowe added a comment.

In D145885#4187679 , @PiotrZSL wrote:

> My only complain is documentation, changes in code and tests are correct.
> Build failed mainly due to conflicts in previous change.
> It should get green once prev patch will land, and this will be re-based.

Thanks for the comments. I will address them. I've rebased this change on top 
of the rebase of the previous one. Maybe that will help. Git didn't report any 
conflicts when I rebased.

> I strongly suggest using arc (less issues with patches).

I have been using arc. I couldn't find a way to make it submit updates to more 
than one change at a time. I've done these two with `git checkout HEAD~1 ; arc 
diff ; git checkout mybranch; arc diff`. Is there a better way?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D145885

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D145885: [clang-tidy] Support readability-redundant-string-cstr.StringParameterFunctions option

2023-03-12 Thread Mike Crowe via Phabricator via cfe-commits
mikecrowe updated this revision to Diff 504475.
mikecrowe added a comment.

Rebase.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D145885

Files:
  clang-tools-extra/clang-tidy/readability/RedundantStringCStrCheck.cpp
  clang-tools-extra/clang-tidy/readability/RedundantStringCStrCheck.h
  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-function.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/readability/redundant-string-cstr-function.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/readability/redundant-string-cstr-function.cpp
@@ -0,0 +1,124 @@
+// RUN: %check_clang_tidy %s readability-redundant-string-cstr %t -- \
+// RUN:   -config="{CheckOptions: \
+// RUN: [{key: readability-redundant-string-cstr.StringParameterFunctions, \
+// RUN:   value: '::fmt::format; ::fmt::print; ::BaseLogger::operator(); ::BaseLogger::Log'}] \
+// RUN: }" \
+// RUN:   -- -isystem %clang_tidy_headers
+#include 
+
+namespace fmt {
+  inline namespace v8 {
+template
+void print(const char *, Args &&...);
+template
+std::string format(const char *, Args &&...);
+  }
+}
+
+namespace notfmt {
+  inline namespace v8 {
+template
+void print(const char *, Args &&...);
+template
+std::string format(const char *, Args &&...);
+  }
+}
+
+void fmt_print(const std::string , const std::string , const std::string ) {
+  fmt::print("One:{}\n", s1.c_str());
+  // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: redundant call to 'c_str' [readability-redundant-string-cstr]
+  // CHECK-FIXES: {{^  }}fmt::print("One:{}\n", s1);
+
+  fmt::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-MESSAGES: :[[@LINE-2]]:58: warning: redundant call to 'c_str' [readability-redundant-string-cstr]
+  // CHECK-FIXES: {{^  }}fmt::print("One:{} Two:{} Three:{}\n", s1, s2, s3);
+}
+
+// There's no c_str() call here, so it shouldn't be touched
+void fmt_print_no_cstr(const std::string , const std::string ) {
+fmt::print("One: {}, Two: {}\n", s1, s2);
+}
+
+// This isn't fmt::print, so it shouldn't be fixed.
+void not_fmt_print(const std::string ) {
+notfmt::print("One: {}\n", s1.c_str());
+}
+
+void fmt_format(const std::string , const std::string , const std::string ) {
+  auto r1 = fmt::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 = fmt::format("One:{}\n", s1);
+
+  auto r2 = fmt::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-MESSAGES: :[[@LINE-2]]:69: warning: redundant call to 'c_str' [readability-redundant-string-cstr]
+  // CHECK-FIXES: {{^  }}auto r2 = fmt::format("One:{} Two:{} Three:{}\n", s1, s2, s3);
+}
+
+// There's are c_str() calls here, so it shouldn't be touched
+void fmt_format_no_cstr(const std::string , const std::string ) {
+fmt::format("One: {}, Two: {}\n", s1, s2);
+}
+
+// This is not fmt::format, so it shouldn't be fixed
+std::string not_fmt_format(const std::string ) {
+return notfmt::format("One: {}\n", s1.c_str());
+}
+
+class BaseLogger {
+public:
+  template 
+  void operator()(const char *fmt, Args &&...args) {
+  }
+
+  template 
+  void Log(const char *fmt, Args &&...args) {
+  }
+};
+
+class DerivedLogger : public BaseLogger {};
+class DoubleDerivedLogger : public DerivedLogger {};
+typedef DerivedLogger TypedefDerivedLogger;
+
+void logger1(const std::string , const std::string , const std::string ) {
+  BaseLogger LOGGER;
+
+  LOGGER("%s\n", s1.c_str(), s2, s3.c_str());
+  // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: redundant call to 'c_str' [readability-redundant-string-cstr]
+  // CHECK-MESSAGES: :[[@LINE-2]]:34: warning: redundant call to 'c_str' [readability-redundant-string-cstr]
+  // CHECK-FIXES: {{^  }}LOGGER("%s\n", s1, s2, s3);
+
+  DerivedLogger LOGGER2;
+  LOGGER2("%d %s\n", 42, s1.c_str(), s2.c_str(), s3);
+  // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: redundant call to 'c_str' [readability-redundant-string-cstr]
+  // CHECK-MESSAGES: :[[@LINE-2]]:38: warning: redundant call to 'c_str' [readability-redundant-string-cstr]
+  // CHECK-FIXES: {{^  }}LOGGER2("%d %s\n", 42, s1, s2, s3);
+
+  DoubleDerivedLogger LOGGERD;
+  LOGGERD("%d %s\n", 42, s1.c_str(), s2, s3.c_str());
+  // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: redundant call to 'c_str' [readability-redundant-string-cstr]
+  // CHECK-MESSAGES: :[[@LINE-2]]:42: 

[PATCH] D143342: [clang-tidy] Support std::format and std::print in readability-redundant-string-cstr

2023-03-12 Thread Mike Crowe via Phabricator via cfe-commits
mikecrowe updated this revision to Diff 504474.
mikecrowe edited the summary of this revision.
mikecrowe added a comment.

Rebase. No conflicts.


Repository:
  rG LLVM Github Monorepo

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/test/clang-tidy/checkers/Inputs/Headers/string
  
clang-tools-extra/test/clang-tidy/checkers/readability/redundant-string-cstr-format.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/readability/redundant-string-cstr-format.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/readability/redundant-string-cstr-format.cpp
@@ -0,0 +1,214 @@
+// RUN: %check_clang_tidy -check-suffix=STDFORMAT -std=c++20 %s readability-redundant-string-cstr %t -- --  -isystem %clang_tidy_headers -DTEST_STDFORMAT
+// RUN: %check_clang_tidy -check-suffixes=STDFORMAT,STDPRINT -std=c++2b %s readability-redundant-string-cstr %t -- --  -isystem %clang_tidy_headers -DTEST_STDFORMAT -DTEST_STDPRINT
+#include 
+
+namespace std {
+  template
+struct type_identity { using type = T; };
+  template
+using type_identity_t = typename type_identity::type;
+
+  template 
+  struct basic_format_string {
+consteval basic_format_string(const CharT *format) : str(format) {}
+basic_string_view> str;
+  };
+
+  template
+using format_string = basic_format_string...>;
+
+  template
+using wformat_string = basic_format_string...>;
+
+#if defined(TEST_STDFORMAT)
+  template
+  std::string format(format_string, Args &&...);
+  template
+  std::string format(wformat_string, Args &&...);
+#endif // TEST_STDFORMAT
+
+#if defined(TEST_STDPRINT)
+  template
+  void print(format_string, Args &&...);
+  template
+  void print(wformat_string, Args &&...);
+#endif // TEST_STDPRINT
+}
+
+namespace notstd {
+#if defined(TEST_STDFORMAT)
+  template
+  std::string format(const char *, Args &&...);
+  template
+  std::string format(const wchar_t *, Args &&...);
+#endif // TEST_STDFORMAT
+#if defined(TEST_STDPRINT)
+  template
+  void print(const char *, Args &&...);
+  template
+  void print(const wchar_t *, Args &&...);
+#endif // TEST_STDPRINT
+}
+
+std::string return_temporary();
+std::wstring return_wtemporary();
+
+#if defined(TEST_STDFORMAT)
+void std_format(const std::string , const std::string , const std::string ) {
+  auto r1 = std::format("One:{}\n", s1.c_str());
+  // CHECK-MESSAGES-STDFORMAT: :[[@LINE-1]]:37: warning: redundant call to 'c_str' [readability-redundant-string-cstr]
+  // CHECK-FIXES-STDFORMAT: {{^  }}auto r1 = std::format("One:{}\n", s1);
+
+  auto r2 = std::format("One:{} Two:{} Three:{} Four:{}\n", s1.c_str(), s2, s3.c_str(), return_temporary().c_str());
+  // CHECK-MESSAGES-STDFORMAT: :[[@LINE-1]]:61: warning: redundant call to 'c_str' [readability-redundant-string-cstr]
+  // CHECK-MESSAGES-STDFORMAT: :[[@LINE-2]]:77: warning: redundant call to 'c_str' [readability-redundant-string-cstr]
+  // CHECK-MESSAGES-STDFORMAT: :[[@LINE-3]]:89: warning: redundant call to 'c_str' [readability-redundant-string-cstr]
+  // CHECK-FIXES-STDFORMAT: {{^  }}auto r2 = std::format("One:{} Two:{} Three:{} Four:{}\n", s1, s2, s3, return_temporary());
+
+  using namespace std;
+  auto r3 = format("Four:{}\n", s1.c_str());
+  // CHECK-MESSAGES-STDFORMAT: :[[@LINE-1]]:33: warning: redundant call to 'c_str' [readability-redundant-string-cstr]
+  // CHECK-FIXES-STDFORMAT: {{^  }}auto r3 = format("Four:{}\n", s1);
+}
+
+void std_format_wide(const std::wstring , const std::wstring , const std::wstring ) {
+  auto r1 = std::format(L"One:{}\n", s1.c_str());
+  // CHECK-MESSAGES-STDFORMAT: :[[@LINE-1]]:38: warning: redundant call to 'c_str' [readability-redundant-string-cstr]
+  // CHECK-FIXES-STDFORMAT: {{^  }}auto r1 = std::format(L"One:{}\n", s1);
+
+  auto r2 = std::format(L"One:{} Two:{} Three:{} Four:{}\n", s1.c_str(), s2, s3.c_str(), return_wtemporary().c_str());
+  // CHECK-MESSAGES-STDFORMAT: :[[@LINE-1]]:62: warning: redundant call to 'c_str' [readability-redundant-string-cstr]
+  // CHECK-MESSAGES-STDFORMAT: :[[@LINE-2]]:78: warning: redundant call to 'c_str' [readability-redundant-string-cstr]
+  // CHECK-MESSAGES-STDFORMAT: :[[@LINE-3]]:90: warning: redundant call to 'c_str' [readability-redundant-string-cstr]
+  // CHECK-FIXES-STDFORMAT: {{^  }}auto r2 = std::format(L"One:{} Two:{} Three:{} Four:{}\n", s1, s2, s3, return_wtemporary());
+
+  using namespace std;
+  auto r3 = format(L"Four:{}\n", s1.c_str());
+  // CHECK-MESSAGES-STDFORMAT: :[[@LINE-1]]:34: warning: redundant call to 'c_str' [readability-redundant-string-cstr]
+  // CHECK-FIXES-STDFORMAT: {{^  }}auto r3 = format(L"Four:{}\n", s1);
+}
+
+// There's are c_str() calls here, so it shouldn't be touched.
+std::string std_format_no_cstr(const std::string , const 

[PATCH] D143342: [clang-tidy] Support std::format and std::print in readability-redundant-string-cstr

2023-03-12 Thread Mike Crowe via Phabricator via cfe-commits
mikecrowe added a comment.

Thank you for your patience.


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

https://reviews.llvm.org/D143342

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D143342: [clang-tidy] Support std::format and std::print in readability-redundant-string-cstr

2023-03-12 Thread Mike Crowe via Phabricator via cfe-commits
mikecrowe added a comment.

In D143342#4187641 , @PiotrZSL wrote:

> Correct commit message and this could land.

I've read through all the comments and the commit message itself and I can't 
spot what's wrong with the commit message, except perhaps for its verbosity. 
What would you like me to correct?


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

https://reviews.llvm.org/D143342

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D143342: [clang-tidy] Support std::format and std::print in readability-redundant-string-cstr

2023-03-12 Thread Mike Crowe via Phabricator via cfe-commits
mikecrowe added inline comments.



Comment at: 
clang-tools-extra/clang-tidy/readability/RedundantStringCStrCheck.cpp:189
+  getLangOpts().CPlusPlus2b
+  ? hasAnyName("::std::print", "::std::format")
+  : hasName("::std::format"))),

PiotrZSL wrote:
> mikecrowe wrote:
> > PiotrZSL wrote:
> > > mikecrowe wrote:
> > > > mikecrowe wrote:
> > > > > PiotrZSL wrote:
> > > > > > Please introduce configuration option to specify custom functions.
> > > > > > For example if some project (like mine) is wrapping fmt::format 
> > > > > > with some variadic template function, then such function could be 
> > > > > > specified.
> > > > > > Same goes to things like some loggers.
> > > > > > 
> > > > > > Check utils/OptionsUtils.h for configuration, and  utils/Matchers.h 
> > > > > > (matchesAnyListedName)
> > > > > > Please introduce configuration option to specify custom functions.
> > > > > > For example if some project (like mine) is wrapping fmt::format 
> > > > > > with some variadic template function, then such function could be 
> > > > > > specified.
> > > > > 
> > > > > That's exactly where this change originated (as part of [[ 
> > > > > https://github.com/mikecrowe/clang-tidy-fmt | my clang-tidy fmt fork 
> > > > > ]], which I hope to submit for review soon once I've made it 
> > > > > configurable too and improved the test cases.)
> > > > > 
> > > > > > Same goes to things like some loggers.
> > > > > > 
> > > > > > Check utils/OptionsUtils.h for configuration, and  utils/Matchers.h 
> > > > > > (matchesAnyListedName)
> > > > > 
> > > > > Thanks for the pointer. I shall study those files for how to support 
> > > > > this.
> > > > > 
> > > > > Do you think that the change can land like in its current state 
> > > > > first? Or would you prefer that the configuration option is added at 
> > > > > the same time?
> > > > > Please introduce configuration option to specify custom functions.
> > > > > For example if some project (like mine) is wrapping fmt::format with 
> > > > > some variadic template function, then such function could be 
> > > > > specified.
> > > > 
> > > > I could add some sort of 
> > > > `readability-redundant-string-cstr.PrintFunction` option or 
> > > > `readability-redundant-string-cstr.FormatFunction` option, but reducing 
> > > > this to its fundamental behaviour would be "a function that takes 
> > > > `const char *` arguments that is also willing to take `std::string` 
> > > > arguments". I'm struggling to find a sensible name for such an option. 
> > > > Maybe 
> > > > `readability-redundant-string-cstr.StdStringAcceptingFunction=::fmt::format`?
> > > >  Or just `readability-redundant-string-cstr.FunctionCall=::fmt::format`?
> > > > 
> > > > > Same goes to things like some loggers.
> > > > 
> > > > Loggers may be classes, so there would need to be an option that 
> > > > specifies a class name (or even a base class name) and a method name 
> > > > (which may be an operator.) See [[ 
> > > > https://github.com/mikecrowe/clang-tidy-fmt/blob/7ace8a3ff41e9679104fe558835b0ef3cb33d969/clang-tools-extra/clang-tidy/readability/RedundantStringCStrCheck.cpp#L196
> > > >  | this hard-coded example ]] (If it's not obvious, there's a 
> > > > description in the [[ 
> > > > https://github.com/mikecrowe/clang-tidy-fmt/blob/7ace8a3ff41e9679104fe558835b0ef3cb33d969/README.md?plain=1#L103
> > > >  | README ]]. In such cases the options could be 
> > > > `readability-redundant-string-cstr.Class=::BaseTrace` and 
> > > > `readability-redundant-string-cstr.Method=Log` or 
> > > > `readability-redundant-string-cstr.Operator=()`, but then it would be 
> > > > hard to tie together the right classes and methods. That could be 
> > > > avoided with something like 
> > > > `readability-redundant-string-cstr.MemberFunctionCall=::BaseTrace::operator(),::NullTrace::operator()`
> > > >  and some parsing I suppose.
> > > > 
> > > > Regardless, I'll try and get the simple case working and await 
> > > > suggestions for appropriate option names.
> > > > 
> > > > Thanks again for the suggestions.
> > > > 
> > > I asked AI, and it suggested 
> > > readability-redundant-string-cstr.FormattingFunctionsList.
> > > Also, I thing that matchesAnyListedName should support things like 
> > > '::NullTrace::operator()', so one option should be sufficient.
> > > 
> > > FormattingFunctionsList:
> > > A semicolon-separated list of (fully qualified) function/method/operator 
> > > names, with the requirement that 
> > > any parameter capable of accepting a 'const char*' input should also be 
> > > able to accept 'std::string' or 
> > > 'std::string_view' inputs, or proper overload candidates that can do so 
> > > should exist.
> > Far be it from me to question the wisdom of the AI :) , but my point was 
> > that the check works for any function that accepts `const char *` 
> > parameters that could equally 

[PATCH] D145885: [clang-tidy] Support readability-redundant-string-cstr.StringParameterFunctions option

2023-03-12 Thread Mike Crowe via Phabricator via cfe-commits
mikecrowe added a comment.

I can squash this with https://reviews.llvm.org/D143342 if required.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D145885

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D145885: [clang-tidy] Support readability-redundant-string-cstr.StringParameterFunctions option

2023-03-12 Thread Mike Crowe via Phabricator via cfe-commits
mikecrowe created this revision.
mikecrowe added reviewers: PiotrZSL, carlosgalvezp.
Herald added a subscriber: xazax.hun.
Herald added a reviewer: njames93.
Herald added a project: All.
mikecrowe requested review of this revision.
Herald added a project: clang-tools-extra.
Herald added a subscriber: cfe-commits.

Many libraries and code bases have functions that work like std::format
and std::print and it would be useful for the
readability-redundant-string-cstr check to work with these functions to
remove unnecessary calls to c_str() among their arguments.

The StringParameterFunctions option contains a semicolon-separated list
of function names for which any arguments which are the result of
calling std::string::c_str() or std::string::data() should be changed to
pass the object directly.

For example, when using the {fmt}[1] library, this option can be used to
change arguments to fmt::format and fmt::print.

Depends on D143342 


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D145885

Files:
  clang-tools-extra/clang-tidy/readability/RedundantStringCStrCheck.cpp
  clang-tools-extra/clang-tidy/readability/RedundantStringCStrCheck.h
  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-function.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/readability/redundant-string-cstr-function.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/readability/redundant-string-cstr-function.cpp
@@ -0,0 +1,124 @@
+// RUN: %check_clang_tidy %s readability-redundant-string-cstr %t -- \
+// RUN:   -config="{CheckOptions: \
+// RUN: [{key: readability-redundant-string-cstr.StringParameterFunctions, \
+// RUN:   value: '::fmt::format; ::fmt::print; ::BaseLogger::operator(); ::BaseLogger::Log'}] \
+// RUN: }" \
+// RUN:   -- -isystem %clang_tidy_headers
+#include 
+
+namespace fmt {
+  inline namespace v8 {
+template
+void print(const char *, Args &&...);
+template
+std::string format(const char *, Args &&...);
+  }
+}
+
+namespace notfmt {
+  inline namespace v8 {
+template
+void print(const char *, Args &&...);
+template
+std::string format(const char *, Args &&...);
+  }
+}
+
+void fmt_print(const std::string , const std::string , const std::string ) {
+  fmt::print("One:{}\n", s1.c_str());
+  // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: redundant call to 'c_str' [readability-redundant-string-cstr]
+  // CHECK-FIXES: {{^  }}fmt::print("One:{}\n", s1);
+
+  fmt::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-MESSAGES: :[[@LINE-2]]:58: warning: redundant call to 'c_str' [readability-redundant-string-cstr]
+  // CHECK-FIXES: {{^  }}fmt::print("One:{} Two:{} Three:{}\n", s1, s2, s3);
+}
+
+// There's no c_str() call here, so it shouldn't be touched
+void fmt_print_no_cstr(const std::string , const std::string ) {
+fmt::print("One: {}, Two: {}\n", s1, s2);
+}
+
+// This isn't fmt::print, so it shouldn't be fixed.
+void not_fmt_print(const std::string ) {
+notfmt::print("One: {}\n", s1.c_str());
+}
+
+void fmt_format(const std::string , const std::string , const std::string ) {
+  auto r1 = fmt::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 = fmt::format("One:{}\n", s1);
+
+  auto r2 = fmt::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-MESSAGES: :[[@LINE-2]]:69: warning: redundant call to 'c_str' [readability-redundant-string-cstr]
+  // CHECK-FIXES: {{^  }}auto r2 = fmt::format("One:{} Two:{} Three:{}\n", s1, s2, s3);
+}
+
+// There's are c_str() calls here, so it shouldn't be touched
+void fmt_format_no_cstr(const std::string , const std::string ) {
+fmt::format("One: {}, Two: {}\n", s1, s2);
+}
+
+// This is not fmt::format, so it shouldn't be fixed
+std::string not_fmt_format(const std::string ) {
+return notfmt::format("One: {}\n", s1.c_str());
+}
+
+class BaseLogger {
+public:
+  template 
+  void operator()(const char *fmt, Args &&...args) {
+  }
+
+  template 
+  void Log(const char *fmt, Args &&...args) {
+  }
+};
+
+class DerivedLogger : public BaseLogger {};
+class DoubleDerivedLogger : public DerivedLogger {};
+typedef DerivedLogger TypedefDerivedLogger;
+
+void logger1(const std::string , const std::string , const std::string ) {
+  BaseLogger LOGGER;
+
+  LOGGER("%s\n", s1.c_str(), s2, s3.c_str());
+  // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: 

[PATCH] D143342: [clang-tidy] Support std::format and std::print in readability-redundant-string-cstr

2023-03-12 Thread Mike Crowe via Phabricator via cfe-commits
mikecrowe added inline comments.



Comment at: 
clang-tools-extra/clang-tidy/readability/RedundantStringCStrCheck.cpp:189
+  getLangOpts().CPlusPlus2b
+  ? hasAnyName("::std::print", "::std::format")
+  : hasName("::std::format"))),

PiotrZSL wrote:
> mikecrowe wrote:
> > mikecrowe wrote:
> > > PiotrZSL wrote:
> > > > Please introduce configuration option to specify custom functions.
> > > > For example if some project (like mine) is wrapping fmt::format with 
> > > > some variadic template function, then such function could be specified.
> > > > Same goes to things like some loggers.
> > > > 
> > > > Check utils/OptionsUtils.h for configuration, and  utils/Matchers.h 
> > > > (matchesAnyListedName)
> > > > Please introduce configuration option to specify custom functions.
> > > > For example if some project (like mine) is wrapping fmt::format with 
> > > > some variadic template function, then such function could be specified.
> > > 
> > > That's exactly where this change originated (as part of [[ 
> > > https://github.com/mikecrowe/clang-tidy-fmt | my clang-tidy fmt fork ]], 
> > > which I hope to submit for review soon once I've made it configurable too 
> > > and improved the test cases.)
> > > 
> > > > Same goes to things like some loggers.
> > > > 
> > > > Check utils/OptionsUtils.h for configuration, and  utils/Matchers.h 
> > > > (matchesAnyListedName)
> > > 
> > > Thanks for the pointer. I shall study those files for how to support this.
> > > 
> > > Do you think that the change can land like in its current state first? Or 
> > > would you prefer that the configuration option is added at the same time?
> > > Please introduce configuration option to specify custom functions.
> > > For example if some project (like mine) is wrapping fmt::format with some 
> > > variadic template function, then such function could be specified.
> > 
> > I could add some sort of `readability-redundant-string-cstr.PrintFunction` 
> > option or `readability-redundant-string-cstr.FormatFunction` option, but 
> > reducing this to its fundamental behaviour would be "a function that takes 
> > `const char *` arguments that is also willing to take `std::string` 
> > arguments". I'm struggling to find a sensible name for such an option. 
> > Maybe 
> > `readability-redundant-string-cstr.StdStringAcceptingFunction=::fmt::format`?
> >  Or just `readability-redundant-string-cstr.FunctionCall=::fmt::format`?
> > 
> > > Same goes to things like some loggers.
> > 
> > Loggers may be classes, so there would need to be an option that specifies 
> > a class name (or even a base class name) and a method name (which may be an 
> > operator.) See [[ 
> > https://github.com/mikecrowe/clang-tidy-fmt/blob/7ace8a3ff41e9679104fe558835b0ef3cb33d969/clang-tools-extra/clang-tidy/readability/RedundantStringCStrCheck.cpp#L196
> >  | this hard-coded example ]] (If it's not obvious, there's a description 
> > in the [[ 
> > https://github.com/mikecrowe/clang-tidy-fmt/blob/7ace8a3ff41e9679104fe558835b0ef3cb33d969/README.md?plain=1#L103
> >  | README ]]. In such cases the options could be 
> > `readability-redundant-string-cstr.Class=::BaseTrace` and 
> > `readability-redundant-string-cstr.Method=Log` or 
> > `readability-redundant-string-cstr.Operator=()`, but then it would be hard 
> > to tie together the right classes and methods. That could be avoided with 
> > something like 
> > `readability-redundant-string-cstr.MemberFunctionCall=::BaseTrace::operator(),::NullTrace::operator()`
> >  and some parsing I suppose.
> > 
> > Regardless, I'll try and get the simple case working and await suggestions 
> > for appropriate option names.
> > 
> > Thanks again for the suggestions.
> > 
> I asked AI, and it suggested 
> readability-redundant-string-cstr.FormattingFunctionsList.
> Also, I thing that matchesAnyListedName should support things like 
> '::NullTrace::operator()', so one option should be sufficient.
> 
> FormattingFunctionsList:
> A semicolon-separated list of (fully qualified) function/method/operator 
> names, with the requirement that 
> any parameter capable of accepting a 'const char*' input should also be able 
> to accept 'std::string' or 
> 'std::string_view' inputs, or proper overload candidates that can do so 
> should exist.
Far be it from me to question the wisdom of the AI :) , but my point was that 
the check works for any function that accepts `const char *` parameters that 
could equally well be `std::string` parameters. It's not limitted to formatting 
functions. Despite this, I suspect that if the majority use case is formatting 
functions then maybe it's more helpful to use a name connected with that for 
discoverability.

In my prototype (which is proving easier to implement than I expected so far), 
I've used `readability-redundant-string-cstr.StringParameterFunctions`, which I 
can't say I'm entirely 

[PATCH] D143342: [clang-tidy] Support std::format and std::print in readability-redundant-string-cstr

2023-03-11 Thread Mike Crowe via Phabricator via cfe-commits
mikecrowe added inline comments.



Comment at: 
clang-tools-extra/clang-tidy/readability/RedundantStringCStrCheck.cpp:189
+  getLangOpts().CPlusPlus2b
+  ? hasAnyName("::std::print", "::std::format")
+  : hasName("::std::format"))),

mikecrowe wrote:
> PiotrZSL wrote:
> > Please introduce configuration option to specify custom functions.
> > For example if some project (like mine) is wrapping fmt::format with some 
> > variadic template function, then such function could be specified.
> > Same goes to things like some loggers.
> > 
> > Check utils/OptionsUtils.h for configuration, and  utils/Matchers.h 
> > (matchesAnyListedName)
> > Please introduce configuration option to specify custom functions.
> > For example if some project (like mine) is wrapping fmt::format with some 
> > variadic template function, then such function could be specified.
> 
> That's exactly where this change originated (as part of [[ 
> https://github.com/mikecrowe/clang-tidy-fmt | my clang-tidy fmt fork ]], 
> which I hope to submit for review soon once I've made it configurable too and 
> improved the test cases.)
> 
> > Same goes to things like some loggers.
> > 
> > Check utils/OptionsUtils.h for configuration, and  utils/Matchers.h 
> > (matchesAnyListedName)
> 
> Thanks for the pointer. I shall study those files for how to support this.
> 
> Do you think that the change can land like in its current state first? Or 
> would you prefer that the configuration option is added at the same time?
> Please introduce configuration option to specify custom functions.
> For example if some project (like mine) is wrapping fmt::format with some 
> variadic template function, then such function could be specified.

I could add some sort of `readability-redundant-string-cstr.PrintFunction` 
option or `readability-redundant-string-cstr.FormatFunction` option, but 
reducing this to its fundamental behaviour would be "a function that takes 
`const char *` arguments that is also willing to take `std::string` arguments". 
I'm struggling to find a sensible name for such an option. Maybe 
`readability-redundant-string-cstr.StdStringAcceptingFunction=::fmt::format`? 
Or just `readability-redundant-string-cstr.FunctionCall=::fmt::format`?

> Same goes to things like some loggers.

Loggers may be classes, so there would need to be an option that specifies a 
class name (or even a base class name) and a method name (which may be an 
operator.) See [[ 
https://github.com/mikecrowe/clang-tidy-fmt/blob/7ace8a3ff41e9679104fe558835b0ef3cb33d969/clang-tools-extra/clang-tidy/readability/RedundantStringCStrCheck.cpp#L196
 | this hard-coded example ]] (If it's not obvious, there's a description in 
the [[ 
https://github.com/mikecrowe/clang-tidy-fmt/blob/7ace8a3ff41e9679104fe558835b0ef3cb33d969/README.md?plain=1#L103
 | README ]]. In such cases the options could be 
`readability-redundant-string-cstr.Class=::BaseTrace` and 
`readability-redundant-string-cstr.Method=Log` or 
`readability-redundant-string-cstr.Operator=()`, but then it would be hard to 
tie together the right classes and methods. That could be avoided with 
something like 
`readability-redundant-string-cstr.MemberFunctionCall=::BaseTrace::operator(),::NullTrace::operator()`
 and some parsing I suppose.

Regardless, I'll try and get the simple case working and await suggestions for 
appropriate option names.

Thanks again for the suggestions.



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

https://reviews.llvm.org/D143342

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D143342: [clang-tidy] Support std::format and std::print in readability-redundant-string-cstr

2023-03-11 Thread Mike Crowe via Phabricator via cfe-commits
mikecrowe added a comment.

In D143342#4186809 , @PiotrZSL wrote:

> Code is fine, probably If would would write this, then I would bother to 
> split into C++20 and C++2B simply because `std::print` wouldn't compile if it 
> wouldn't be available. So I would just use hasAnyName.
> But code looks fine, configuration could be added later...

Thanks. I originally wrote it like that, but @njames93 requested that I checked 
the version, so I did. :) It doesn't do any harm and might avoid confusion.


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

https://reviews.llvm.org/D143342

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D143342: [clang-tidy] Support std::format and std::print in readability-redundant-string-cstr

2023-03-11 Thread Mike Crowe via Phabricator via cfe-commits
mikecrowe added inline comments.



Comment at: 
clang-tools-extra/clang-tidy/readability/RedundantStringCStrCheck.cpp:189
+  getLangOpts().CPlusPlus2b
+  ? hasAnyName("::std::print", "::std::format")
+  : hasName("::std::format"))),

PiotrZSL wrote:
> Please introduce configuration option to specify custom functions.
> For example if some project (like mine) is wrapping fmt::format with some 
> variadic template function, then such function could be specified.
> Same goes to things like some loggers.
> 
> Check utils/OptionsUtils.h for configuration, and  utils/Matchers.h 
> (matchesAnyListedName)
> Please introduce configuration option to specify custom functions.
> For example if some project (like mine) is wrapping fmt::format with some 
> variadic template function, then such function could be specified.

That's exactly where this change originated (as part of [[ 
https://github.com/mikecrowe/clang-tidy-fmt | my clang-tidy fmt fork ]], which 
I hope to submit for review soon once I've made it configurable too and 
improved the test cases.)

> Same goes to things like some loggers.
> 
> Check utils/OptionsUtils.h for configuration, and  utils/Matchers.h 
> (matchesAnyListedName)

Thanks for the pointer. I shall study those files for how to support this.

Do you think that the change can land like in its current state first? Or would 
you prefer that the configuration option is added at the same time?


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

https://reviews.llvm.org/D143342

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D145311: [clang-tidy] Make abseil-redundant-strcat-calls checker use header

2023-03-11 Thread Mike Crowe via Phabricator via cfe-commits
mikecrowe added a comment.

In D145311#4184159 , @PiotrZSL wrote:

> It's fine, absl::StrCat returns std::string.
> So those changes are correct.

Thanks. Would you like me to remove the unnecessary noise from the commit 
message then, or will you do that as part of landing it?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D145311

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D145730: [clang-tidy] Fix readability-redundant-string-cstr for smart pointer #576705

2023-03-10 Thread Mike Crowe via Phabricator via cfe-commits
mikecrowe added a comment.

Thanks, and sorry about the erroneous `[PATCH]` in the summary. :(


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D145730

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D145730: [PATCH] [clang-tidy] Fix readability-redundant-string-cstr for smart pointer #576705

2023-03-10 Thread Mike Crowe via Phabricator via cfe-commits
mikecrowe added a comment.

Thanks for the speedy re-review. I don't have commit permission, so please can 
you land this if you are happy to do so?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D145730

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D145730: [clang-tidy] readability-redundant-string-cstr for smart pointer #576705

2023-03-10 Thread Mike Crowe via Phabricator via cfe-commits
mikecrowe updated this revision to Diff 504108.
mikecrowe marked an inline comment as done.
mikecrowe added a comment.

Fix comment in code as suggested by PiotrZSL. Improve lit check tests.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D145730

Files:
  clang-tools-extra/clang-tidy/readability/RedundantStringCStrCheck.cpp
  
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
@@ -1,6 +1,12 @@
 // RUN: %check_clang_tidy %s readability-redundant-string-cstr %t -- -- 
-isystem %clang_tidy_headers
 #include 
 
+template 
+struct iterator {
+  T *operator->();
+  T *();
+};
+
 namespace llvm {
 struct StringRef {
   StringRef(const char *p);
@@ -202,6 +208,31 @@
   m1p2(s.c_str());  
 }
 
+// Test for overloaded operator->
+void it(iterator i)
+{
+  std::string tmp;
+  tmp = i->c_str();
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: redundant call to 'c_str' 
[readability-redundant-string-cstr]
+  // CHECK-FIXES: {{^  }}tmp = *i;{{$}}
+
+  // An unlikely situation and the outcome is not ideal, but at least the fix 
doesn't generate broken code.
+  tmp = i.operator->()->c_str();
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: redundant call to 'c_str' 
[readability-redundant-string-cstr]
+  // CHECK-FIXES: {{^  }}tmp = *i.operator->();{{$}}
+
+  // The fix contains an unnecessary set of parentheses, but these have no 
effect.
+  iterator *pi = 
+  tmp = (*pi)->c_str();
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: redundant call to 'c_str' 
[readability-redundant-string-cstr]
+  // CHECK-FIXES: {{^  }}tmp = *(*pi);{{$}}
+
+  // An unlikely situation, but at least the fix doesn't generate broken code.
+  tmp = pi->operator->()->c_str();
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: redundant call to 'c_str' 
[readability-redundant-string-cstr]
+  // CHECK-FIXES: {{^  }}tmp = *pi->operator->();{{$}}
+}
+
 namespace PR45286 {
 struct Foo {
   void func(const std::string &) {}
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
@@ -52,6 +52,10 @@
 
   if (Text.empty())
 return std::string();
+
+  // Remove remaining '->' from overloaded operator call
+  Text.consume_back("->");
+
   // Add leading '*'.
   if (needParensAfterUnaryOperator(ExprNode)) {
 return (llvm::Twine("*(") + Text + ")").str();


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
@@ -1,6 +1,12 @@
 // RUN: %check_clang_tidy %s readability-redundant-string-cstr %t -- -- -isystem %clang_tidy_headers
 #include 
 
+template 
+struct iterator {
+  T *operator->();
+  T *();
+};
+
 namespace llvm {
 struct StringRef {
   StringRef(const char *p);
@@ -202,6 +208,31 @@
   m1p2(s.c_str());  
 }
 
+// Test for overloaded operator->
+void it(iterator i)
+{
+  std::string tmp;
+  tmp = i->c_str();
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: redundant call to 'c_str' [readability-redundant-string-cstr]
+  // CHECK-FIXES: {{^  }}tmp = *i;{{$}}
+
+  // An unlikely situation and the outcome is not ideal, but at least the fix doesn't generate broken code.
+  tmp = i.operator->()->c_str();
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: redundant call to 'c_str' [readability-redundant-string-cstr]
+  // CHECK-FIXES: {{^  }}tmp = *i.operator->();{{$}}
+
+  // The fix contains an unnecessary set of parentheses, but these have no effect.
+  iterator *pi = 
+  tmp = (*pi)->c_str();
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: redundant call to 'c_str' [readability-redundant-string-cstr]
+  // CHECK-FIXES: {{^  }}tmp = *(*pi);{{$}}
+
+  // An unlikely situation, but at least the fix doesn't generate broken code.
+  tmp = pi->operator->()->c_str();
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: redundant call to 'c_str' [readability-redundant-string-cstr]
+  // CHECK-FIXES: {{^  }}tmp = *pi->operator->();{{$}}
+}
+
 namespace PR45286 {
 struct Foo {
   void func(const std::string &) {}
Index: clang-tools-extra/clang-tidy/readability/RedundantStringCStrCheck.cpp
===
--- clang-tools-extra/clang-tidy/readability/RedundantStringCStrCheck.cpp
+++ 

[PATCH] D145730: [clang-tidy] readability-redundant-string-cstr for smart pointer #576705

2023-03-10 Thread Mike Crowe via Phabricator via cfe-commits
mikecrowe added a comment.

In D145730#4182949 , @PiotrZSL wrote:

> Also consider reducing commit message, instead just copying issue description.
> Simple description about issue would be sufficient.

TBH, I wasn't expecting this change to be accepted. I was merely hoping that it 
would cause someone to give me a hint as to how to fix it properly. That's why 
I included so much information in the commit message. I will shorten the commit 
message.

> No functional issues, so LGTM.

Thanks for the review.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D145730

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D145730: [clang-tidy] readability-redundant-string-cstr for smart pointer #576705

2023-03-09 Thread Mike Crowe via Phabricator via cfe-commits
mikecrowe created this revision.
mikecrowe added a reviewer: njames93.
Herald added subscribers: PiotrZSL, carlosgalvezp, xazax.hun.
Herald added a project: All.
mikecrowe requested review of this revision.
Herald added a project: clang-tools-extra.
Herald added a subscriber: cfe-commits.

The readability-redundant-string-cstr check incorrectly replaces calls
to c_str() that involve an overloaded operator->.

Running `clang-tidy --checks="-*,readability-redundant-string-cstr"` on:

#include 
 #include 

void it(std::vector::const_iterator i)
 {

  std::string tmp;
  tmp = i->c_str();

}

yields:

/home/mac/git/llvm-project/build/../bug.cpp:7:9: warning: redundant call to 
'c_str' [readability-redundant-string-cstr]

  tmp = i->c_str();
^~
*i->

which means that the code is "fixed" to incorrectly say:

  tmp = *i->;

rather than the expected:

  tmp = *i;

This appears to be due to the overloaded `operator->` meaning that
RedundantStringCStrCheck.cpp#L53 ends up with Text containing "i->"
rather than just the expected "i".

Add test case for this and fix it in a somewhat nasty manner in the
absence of something better.

Fixes: https://github.com/llvm/llvm-project/issues/56705


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D145730

Files:
  clang-tools-extra/clang-tidy/readability/RedundantStringCStrCheck.cpp
  
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
@@ -1,6 +1,11 @@
 // RUN: %check_clang_tidy %s readability-redundant-string-cstr %t -- -- 
-isystem %clang_tidy_headers
 #include 
 
+template 
+struct iterator {
+  T *operator->();
+};
+
 namespace llvm {
 struct StringRef {
   StringRef(const char *p);
@@ -202,6 +207,15 @@
   m1p2(s.c_str());  
 }
 
+// Test for iterator
+void it(iterator i)
+{
+  std::string tmp;
+  tmp = i->c_str();
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: redundant call to 'c_str' 
[readability-redundant-string-cstr]
+  // CHECK-FIXES: {{^  }}tmp = *i;{{$}}
+}
+
 namespace PR45286 {
 struct Foo {
   void func(const std::string &) {}
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
@@ -52,6 +52,10 @@
 
   if (Text.empty())
 return std::string();
+
+  // https://github.com/llvm/llvm-project/issues/56705
+  Text.consume_back("->");
+
   // Add leading '*'.
   if (needParensAfterUnaryOperator(ExprNode)) {
 return (llvm::Twine("*(") + Text + ")").str();


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
@@ -1,6 +1,11 @@
 // RUN: %check_clang_tidy %s readability-redundant-string-cstr %t -- -- -isystem %clang_tidy_headers
 #include 
 
+template 
+struct iterator {
+  T *operator->();
+};
+
 namespace llvm {
 struct StringRef {
   StringRef(const char *p);
@@ -202,6 +207,15 @@
   m1p2(s.c_str());  
 }
 
+// Test for iterator
+void it(iterator i)
+{
+  std::string tmp;
+  tmp = i->c_str();
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: redundant call to 'c_str' [readability-redundant-string-cstr]
+  // CHECK-FIXES: {{^  }}tmp = *i;{{$}}
+}
+
 namespace PR45286 {
 struct Foo {
   void func(const std::string &) {}
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
@@ -52,6 +52,10 @@
 
   if (Text.empty())
 return std::string();
+
+  // https://github.com/llvm/llvm-project/issues/56705
+  Text.consume_back("->");
+
   // Add leading '*'.
   if (needParensAfterUnaryOperator(ExprNode)) {
 return (llvm::Twine("*(") + Text + ")").str();
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D145313: [clang-tidy] Make readability-container-size-empty check using header

2023-03-09 Thread Mike Crowe via Phabricator via cfe-commits
mikecrowe added a comment.

In D145313#4182637 , @mikecrowe wrote:

> Now a descendent of D145724 .

Oh. The commit message update didn't make it through. :( Never mind, this 
doesn't really depend on D145724  since that 
change modified a different part of ``.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D145313

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D145313: [clang-tidy] Make readability-container-size-empty check using header

2023-03-09 Thread Mike Crowe via Phabricator via cfe-commits
mikecrowe updated this revision to Diff 503896.
mikecrowe added a comment.
Herald added a subscriber: PiotrZSL.

Upload using arc diff so more context is available.

Now a descendent of D145724 .


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D145313

Files:
  clang-tools-extra/test/clang-tidy/checkers/Inputs/Headers/string
  
clang-tools-extra/test/clang-tidy/checkers/readability/container-size-empty.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/readability/container-size-empty.cpp
===
--- clang-tools-extra/test/clang-tidy/checkers/readability/container-size-empty.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/readability/container-size-empty.cpp
@@ -1,6 +1,7 @@
 // RUN: %check_clang_tidy %s readability-container-size-empty %t -- \
 // RUN: -config="{CheckOptions: [{key: readability-container-size-empty.ExcludedComparisonTypes , value: '::std::array;::IgnoredDummyType'}]}" \
-// RUN: -- -fno-delayed-template-parsing
+// RUN: -- -fno-delayed-template-parsing -isystem %clang_tidy_headers
+#include 
 
 namespace std {
 template  struct vector {
@@ -11,20 +12,6 @@
   bool empty() const;
 };
 
-template  struct basic_string {
-  basic_string();
-  bool operator==(const basic_string& other) const;
-  bool operator!=(const basic_string& other) const;
-  bool operator==(const char *) const;
-  bool operator!=(const char *) const;
-  basic_string operator+(const basic_string& other) const;
-  unsigned long size() const;
-  bool empty() const;
-};
-
-typedef basic_string string;
-typedef basic_string wstring;
-
 inline namespace __v2 {
 template  struct set {
   set();
@@ -125,12 +112,12 @@
 ;
   // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used to check for emptiness instead of 'size' [readability-container-size-empty]
   // CHECK-FIXES: {{^  }}if (intSet.empty()){{$}}
-  // CHECK-MESSAGES: :34:8: note: method 'set'::empty() defined here
+  // CHECK-MESSAGES: :21:8: note: method 'set'::empty() defined here
   if (intSet == std::set())
 ;
   // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used to check for emptiness
   // CHECK-FIXES: {{^  }}if (intSet.empty()){{$}}
-  // CHECK-MESSAGES: :34:8: note: method 'set'::empty() defined here
+  // CHECK-MESSAGES: :21:8: note: method 'set'::empty() defined here
   if (s_func() == "")
 ;
   // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
@@ -155,7 +142,7 @@
 ;
   // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
   // CHECK-FIXES: {{^  }}if (wstr.empty()){{$}}
-  if (wstr == "")
+  if (wstr == L"")
 ;
   // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
   // CHECK-FIXES: {{^  }}if (wstr.empty()){{$}}
@@ -452,7 +439,7 @@
 public:
   ConstructWithBoolField(const std::vector ) : B(C.size()) {}
 // CHECK-MESSAGES: :[[@LINE-1]]:57: warning: the 'empty' method should be used
-// CHECK-MESSAGES: :11:8: note: method 'vector'::empty() defined here
+// CHECK-MESSAGES: :12:8: note: method 'vector'::empty() defined here
 // CHECK-FIXES: {{^  }}ConstructWithBoolField(const std::vector ) : B(!C.empty()) {}
 };
 
@@ -460,21 +447,21 @@
   std::vector C;
   bool B = C.size();
 // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: the 'empty' method should be used
-// CHECK-MESSAGES: :11:8: note: method 'vector'::empty() defined here
+// CHECK-MESSAGES: :12:8: note: method 'vector'::empty() defined here
 // CHECK-FIXES: {{^  }}bool B = !C.empty();
 };
 
 int func(const std::vector ) {
   return C.size() ? 0 : 1;
 // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: the 'empty' method should be used
-// CHECK-MESSAGES: :11:8: note: method 'vector'::empty() defined here
+// CHECK-MESSAGES: :12:8: note: method 'vector'::empty() defined here
 // CHECK-FIXES: {{^  }}return !C.empty() ? 0 : 1;
 }
 
 constexpr Lazy L;
 static_assert(!L.size(), "");
 // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: the 'empty' method should be used
-// CHECK-MESSAGES: :103:18: note: method 'Lazy'::empty() defined here
+// CHECK-MESSAGES: :90:18: note: method 'Lazy'::empty() defined here
 // CHECK-FIXES: {{^}}static_assert(L.empty(), "");
 
 struct StructWithLazyNoexcept {
@@ -489,7 +476,7 @@
   if (v.size())
 ;
   // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used to check for emptiness instead of 'size' [readability-container-size-empty]
-  // CHECK-MESSAGES: :11:8: note: method 'vector'::empty() defined here
+  // CHECK-MESSAGES: :12:8: note: method 'vector'::empty() defined here
   // CHECK-FIXES: {{^  }}if (!v.empty()){{$}}
   if (v == std::vector())
 ;
@@ -498,24 +485,24 @@
   // CHECK-FIXES-NEXT: ;
   CHECKSIZE(v);
   // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: the 'empty' method should be used
-  // CHECK-MESSAGES: :11:8: note: method 

[PATCH] D145312: [clang-tidy] Make readability-string-compare check use header

2023-03-09 Thread Mike Crowe via Phabricator via cfe-commits
mikecrowe marked an inline comment as done.
mikecrowe added inline comments.
Herald added a subscriber: PiotrZSL.



Comment at: 
clang-tools-extra/test/clang-tidy/checkers/readability/string-compare.cpp:4-8
-template 
-class allocator {};
-template 
-class char_traits {};
-template , typename A = 
std::allocator>

carlosgalvezp wrote:
> Would it make sense to add these to the new header?
Done in https://reviews.llvm.org/D145724 .


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

https://reviews.llvm.org/D145312

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D145724: [clang-tidy] Provide default template arguments in

2023-03-09 Thread Mike Crowe via Phabricator via cfe-commits
mikecrowe created this revision.
mikecrowe added a reviewer: carlosgalvezp.
Herald added subscribers: PiotrZSL, xazax.hun.
Herald added a project: All.
mikecrowe requested review of this revision.
Herald added a project: clang-tools-extra.
Herald added a subscriber: cfe-commits.

Simplify the use of the basic_string and basic_string_view types by
providing default template arguments.

Depends on D145311 


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D145724

Files:
  clang-tools-extra/test/clang-tidy/checkers/Inputs/Headers/string


Index: clang-tools-extra/test/clang-tidy/checkers/Inputs/Headers/string
===
--- clang-tools-extra/test/clang-tidy/checkers/Inputs/Headers/string
+++ clang-tools-extra/test/clang-tidy/checkers/Inputs/Headers/string
@@ -12,7 +12,7 @@
 class allocator {};
 template 
 class char_traits {};
-template 
+template , typename A = allocator>
 struct basic_string {
   typedef size_t size_type;
   typedef basic_string _Type;
@@ -54,19 +54,19 @@
   _Type& operator=(const C* s);
 };
 
-typedef basic_string, std::allocator> 
string;
-typedef basic_string, 
std::allocator> wstring;
-typedef basic_string, std::allocator> 
u16string;
-typedef basic_string, std::allocator> 
u32string;
+typedef basic_string string;
+typedef basic_string wstring;
+typedef basic_string u16string;
+typedef basic_string u32string;
 
-template 
+template >
 struct basic_string_view {
   basic_string_view(const C* s);
 };
-typedef basic_string_view> string_view;
-typedef basic_string_view> wstring_view;
-typedef basic_string_view> u16string_view;
-typedef basic_string_view> u32string_view;
+typedef basic_string_view string_view;
+typedef basic_string_view wstring_view;
+typedef basic_string_view u16string_view;
+typedef basic_string_view u32string_view;
 
 std::string operator+(const std::string&, const std::string&);
 std::string operator+(const std::string&, const char*);


Index: clang-tools-extra/test/clang-tidy/checkers/Inputs/Headers/string
===
--- clang-tools-extra/test/clang-tidy/checkers/Inputs/Headers/string
+++ clang-tools-extra/test/clang-tidy/checkers/Inputs/Headers/string
@@ -12,7 +12,7 @@
 class allocator {};
 template 
 class char_traits {};
-template 
+template , typename A = allocator>
 struct basic_string {
   typedef size_t size_type;
   typedef basic_string _Type;
@@ -54,19 +54,19 @@
   _Type& operator=(const C* s);
 };
 
-typedef basic_string, std::allocator> string;
-typedef basic_string, std::allocator> wstring;
-typedef basic_string, std::allocator> u16string;
-typedef basic_string, std::allocator> u32string;
+typedef basic_string string;
+typedef basic_string wstring;
+typedef basic_string u16string;
+typedef basic_string u32string;
 
-template 
+template >
 struct basic_string_view {
   basic_string_view(const C* s);
 };
-typedef basic_string_view> string_view;
-typedef basic_string_view> wstring_view;
-typedef basic_string_view> u16string_view;
-typedef basic_string_view> u32string_view;
+typedef basic_string_view string_view;
+typedef basic_string_view wstring_view;
+typedef basic_string_view u16string_view;
+typedef basic_string_view u32string_view;
 
 std::string operator+(const std::string&, const std::string&);
 std::string operator+(const std::string&, const char*);
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D145311: [clang-tidy] Make abseil-redundant-strcat-calls checker use header

2023-03-09 Thread Mike Crowe via Phabricator via cfe-commits
mikecrowe updated this revision to Diff 503884.
mikecrowe added a comment.
Herald added a subscriber: PiotrZSL.

Re-upload using arc.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D145311

Files:
  clang-tools-extra/test/clang-tidy/checkers/abseil/redundant-strcat-calls.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/abseil/redundant-strcat-calls.cpp
===
--- clang-tools-extra/test/clang-tidy/checkers/abseil/redundant-strcat-calls.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/abseil/redundant-strcat-calls.cpp
@@ -1,92 +1,8 @@
-// RUN: %check_clang_tidy %s abseil-redundant-strcat-calls %t
+// RUN: %check_clang_tidy %s abseil-redundant-strcat-calls %t -- -- -isystem %clang_tidy_headers
+#include 
 
 int strlen(const char *);
 
-// Here we mimic the hierarchy of ::string.
-// We need to do so because we are matching on the fully qualified name of the
-// methods.
-struct __sso_string_base {};
-namespace __gnu_cxx {
-template 
-class __versa_string {
- public:
-  const char *c_str() const;
-  const char *data() const;
-  int size() const;
-  int capacity() const;
-  int length() const;
-  bool empty() const;
-  char [](int);
-  void clear();
-  void resize(int);
-  int compare(const __versa_string &) const;
-};
-}  // namespace __gnu_cxx
-
-namespace std {
-template 
-class char_traits {};
-template 
-class allocator {};
-}  // namespace std
-
-template ,
-  typename C = std::allocator>
-class basic_string : public __gnu_cxx::__versa_string {
- public:
-  basic_string();
-  basic_string(const basic_string &);
-  basic_string(const char *, C = C());
-  basic_string(const char *, int, C = C());
-  basic_string(const basic_string &, int, int, C = C());
-  ~basic_string();
-
-  basic_string +=(const basic_string &);
-};
-
-template 
-basic_string operator+(const basic_string &,
-const basic_string &);
-template 
-basic_string operator+(const basic_string &, const char *);
-
-typedef basic_string string;
-
-bool operator==(const string &, const string &);
-bool operator==(const string &, const char *);
-bool operator==(const char *, const string &);
-
-bool operator!=(const string &, const string &);
-bool operator<(const string &, const string &);
-bool operator>(const string &, const string &);
-bool operator<=(const string &, const string &);
-bool operator>=(const string &, const string &);
-
-namespace std {
-template ,
-  typename _Alloc = allocator<_CharT>>
-class basic_string;
-
-template 
-class basic_string {
- public:
-  basic_string();
-  basic_string(const basic_string &);
-  basic_string(const char *, const _Alloc & = _Alloc());
-  basic_string(const char *, int, const _Alloc & = _Alloc());
-  basic_string(const basic_string &, int, int, const _Alloc & = _Alloc());
-  ~basic_string();
-
-  basic_string +=(const basic_string &);
-
-  unsigned size() const;
-  unsigned length() const;
-  bool empty() const;
-};
-
-typedef basic_string string;
-}  // namespace std
-
 namespace absl {
 
 class string_view {
@@ -95,12 +11,12 @@
 
   string_view();
   string_view(const char *);
-  string_view(const string &);
+  string_view(const std::string &);
   string_view(const char *, int);
   string_view(string_view, int);
 
   template 
-  explicit operator ::basic_string() const;
+  explicit operator std::basic_string() const;
 
   const char *data() const;
   int size() const;
@@ -113,7 +29,7 @@
   AlphaNum(int i);
   AlphaNum(double f);
   AlphaNum(const char *c_str);
-  AlphaNum(const string );
+  AlphaNum(const std::string );
   AlphaNum(const string_view );
 
  private:
@@ -121,28 +37,28 @@
   AlphaNum =(const AlphaNum &);
 };
 
-string StrCat();
-string StrCat(const AlphaNum );
-string StrCat(const AlphaNum , const AlphaNum );
-string StrCat(const AlphaNum , const AlphaNum , const AlphaNum );
-string StrCat(const AlphaNum , const AlphaNum , const AlphaNum ,
-  const AlphaNum );
+std::string StrCat();
+std::string StrCat(const AlphaNum );
+std::string StrCat(const AlphaNum , const AlphaNum );
+std::string StrCat(const AlphaNum , const AlphaNum , const AlphaNum );
+std::string StrCat(const AlphaNum , const AlphaNum , const AlphaNum ,
+   const AlphaNum );
 
 // Support 5 or more arguments
 template 
-string StrCat(const AlphaNum , const AlphaNum , const AlphaNum ,
+std::string StrCat(const AlphaNum , const AlphaNum , const AlphaNum ,
   const AlphaNum , const AlphaNum , const AV &... args);
 
-void StrAppend(string *Dest, const AlphaNum );
-void StrAppend(string *Dest, const AlphaNum , const AlphaNum );
-void StrAppend(string *Dest, const AlphaNum , const AlphaNum ,
-   const AlphaNum );
-void StrAppend(string *Dest, const AlphaNum , const AlphaNum ,
-   const AlphaNum , const AlphaNum );
+void StrAppend(std::string *Dest, const AlphaNum );

[PATCH] D145310: [clang-tidy] Make readability-container-data-pointer use header

2023-03-09 Thread Mike Crowe via Phabricator via cfe-commits
mikecrowe updated this revision to Diff 503882.
mikecrowe added a comment.
Herald added a subscriber: PiotrZSL.

Rebase on top of fb7ef637a84652dbd3d973a1ba7db9470181b5aa 
 (which is 
a
descendent of ae25e2f19decb94198301f0726ee613f945cc405 
 aka 
D144216 , on
which this change relies.)


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D145310

Files:
  clang-tools-extra/test/clang-tidy/checkers/Inputs/Headers/string
  
clang-tools-extra/test/clang-tidy/checkers/readability/container-data-pointer.cpp


Index: 
clang-tools-extra/test/clang-tidy/checkers/readability/container-data-pointer.cpp
===
--- 
clang-tools-extra/test/clang-tidy/checkers/readability/container-data-pointer.cpp
+++ 
clang-tools-extra/test/clang-tidy/checkers/readability/container-data-pointer.cpp
@@ -1,4 +1,5 @@
-// RUN: %check_clang_tidy %s readability-container-data-pointer %t -- -- 
-fno-delayed-template-parsing
+// RUN: %check_clang_tidy %s readability-container-data-pointer %t -- -- 
-isystem %clang_tidy_headers -fno-delayed-template-parsing
+#include 
 
 typedef __SIZE_TYPE__ size_t;
 
@@ -17,22 +18,6 @@
   const T [](size_type) const;
 };
 
-template 
-struct basic_string {
-  using size_type = size_t;
-
-  basic_string();
-
-  T *data();
-  const T *data() const;
-
-  T [](size_t);
-  const T [](size_type) const;
-};
-
-typedef basic_string string;
-typedef basic_string wstring;
-
 template 
 struct is_integral;
 
Index: clang-tools-extra/test/clang-tidy/checkers/Inputs/Headers/string
===
--- clang-tools-extra/test/clang-tidy/checkers/Inputs/Headers/string
+++ clang-tools-extra/test/clang-tidy/checkers/Inputs/Headers/string
@@ -42,6 +42,9 @@
   _Type& insert(size_type pos, const C* s);
   _Type& insert(size_type pos, const C* s, size_type n);
 
+  _Type& operator[](size_type);
+  const _Type& operator[](size_type) const;
+
   _Type& operator+=(const _Type& str);
   _Type& operator+=(const C* s);
   _Type& operator=(const _Type& str);


Index: clang-tools-extra/test/clang-tidy/checkers/readability/container-data-pointer.cpp
===
--- clang-tools-extra/test/clang-tidy/checkers/readability/container-data-pointer.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/readability/container-data-pointer.cpp
@@ -1,4 +1,5 @@
-// RUN: %check_clang_tidy %s readability-container-data-pointer %t -- -- -fno-delayed-template-parsing
+// RUN: %check_clang_tidy %s readability-container-data-pointer %t -- -- -isystem %clang_tidy_headers -fno-delayed-template-parsing
+#include 
 
 typedef __SIZE_TYPE__ size_t;
 
@@ -17,22 +18,6 @@
   const T [](size_type) const;
 };
 
-template 
-struct basic_string {
-  using size_type = size_t;
-
-  basic_string();
-
-  T *data();
-  const T *data() const;
-
-  T [](size_t);
-  const T [](size_type) const;
-};
-
-typedef basic_string string;
-typedef basic_string wstring;
-
 template 
 struct is_integral;
 
Index: clang-tools-extra/test/clang-tidy/checkers/Inputs/Headers/string
===
--- clang-tools-extra/test/clang-tidy/checkers/Inputs/Headers/string
+++ clang-tools-extra/test/clang-tidy/checkers/Inputs/Headers/string
@@ -42,6 +42,9 @@
   _Type& insert(size_type pos, const C* s);
   _Type& insert(size_type pos, const C* s, size_type n);
 
+  _Type& operator[](size_type);
+  const _Type& operator[](size_type) const;
+
   _Type& operator+=(const _Type& str);
   _Type& operator+=(const C* s);
   _Type& operator=(const _Type& str);
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D145719: [clang-tidy] Make readability-container-data-pointer use header

2023-03-09 Thread Mike Crowe via Phabricator via cfe-commits
mikecrowe abandoned this revision.
mikecrowe added a comment.

Whoops. I accidentally uploaded https://reviews.llvm.org/D145719 as a new 
change. :(


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D145719

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D145719: [clang-tidy] Make readability-container-data-pointer use header

2023-03-09 Thread Mike Crowe via Phabricator via cfe-commits
mikecrowe created this revision.
Herald added subscribers: PiotrZSL, xazax.hun.
Herald added a project: All.
mikecrowe requested review of this revision.
Herald added a project: clang-tools-extra.
Herald added a subscriber: cfe-commits.

This requires operator[] to be added to the std::basic_string
implementation.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D145719

Files:
  clang-tools-extra/test/clang-tidy/checkers/Inputs/Headers/string
  
clang-tools-extra/test/clang-tidy/checkers/readability/container-data-pointer.cpp


Index: 
clang-tools-extra/test/clang-tidy/checkers/readability/container-data-pointer.cpp
===
--- 
clang-tools-extra/test/clang-tidy/checkers/readability/container-data-pointer.cpp
+++ 
clang-tools-extra/test/clang-tidy/checkers/readability/container-data-pointer.cpp
@@ -1,4 +1,5 @@
-// RUN: %check_clang_tidy %s readability-container-data-pointer %t -- -- 
-fno-delayed-template-parsing
+// RUN: %check_clang_tidy %s readability-container-data-pointer %t -- -- 
-isystem %clang_tidy_headers -fno-delayed-template-parsing
+#include 
 
 typedef __SIZE_TYPE__ size_t;
 
@@ -17,22 +18,6 @@
   const T [](size_type) const;
 };
 
-template 
-struct basic_string {
-  using size_type = size_t;
-
-  basic_string();
-
-  T *data();
-  const T *data() const;
-
-  T [](size_t);
-  const T [](size_type) const;
-};
-
-typedef basic_string string;
-typedef basic_string wstring;
-
 template 
 struct is_integral;
 
Index: clang-tools-extra/test/clang-tidy/checkers/Inputs/Headers/string
===
--- clang-tools-extra/test/clang-tidy/checkers/Inputs/Headers/string
+++ clang-tools-extra/test/clang-tidy/checkers/Inputs/Headers/string
@@ -42,6 +42,9 @@
   _Type& insert(size_type pos, const C* s);
   _Type& insert(size_type pos, const C* s, size_type n);
 
+  _Type& operator[](size_type);
+  const _Type& operator[](size_type) const;
+
   _Type& operator+=(const _Type& str);
   _Type& operator+=(const C* s);
   _Type& operator=(const _Type& str);


Index: clang-tools-extra/test/clang-tidy/checkers/readability/container-data-pointer.cpp
===
--- clang-tools-extra/test/clang-tidy/checkers/readability/container-data-pointer.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/readability/container-data-pointer.cpp
@@ -1,4 +1,5 @@
-// RUN: %check_clang_tidy %s readability-container-data-pointer %t -- -- -fno-delayed-template-parsing
+// RUN: %check_clang_tidy %s readability-container-data-pointer %t -- -- -isystem %clang_tidy_headers -fno-delayed-template-parsing
+#include 
 
 typedef __SIZE_TYPE__ size_t;
 
@@ -17,22 +18,6 @@
   const T [](size_type) const;
 };
 
-template 
-struct basic_string {
-  using size_type = size_t;
-
-  basic_string();
-
-  T *data();
-  const T *data() const;
-
-  T [](size_t);
-  const T [](size_type) const;
-};
-
-typedef basic_string string;
-typedef basic_string wstring;
-
 template 
 struct is_integral;
 
Index: clang-tools-extra/test/clang-tidy/checkers/Inputs/Headers/string
===
--- clang-tools-extra/test/clang-tidy/checkers/Inputs/Headers/string
+++ clang-tools-extra/test/clang-tidy/checkers/Inputs/Headers/string
@@ -42,6 +42,9 @@
   _Type& insert(size_type pos, const C* s);
   _Type& insert(size_type pos, const C* s, size_type n);
 
+  _Type& operator[](size_type);
+  const _Type& operator[](size_type) const;
+
   _Type& operator+=(const _Type& str);
   _Type& operator+=(const C* s);
   _Type& operator=(const _Type& str);
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D145313: [clang-tidy] Make readability-container-size-empty check using header

2023-03-05 Thread Mike Crowe via Phabricator via cfe-commits
mikecrowe added a comment.

In D145313#4169790 , @carlosgalvezp 
wrote:

> Could you upload the patch with full context? I believe you need to do 
> something like `git show HEAD -U99` as per the guidelines 
> . Otherwise `arc diff` should do the 
> job automatically. Reason I ask is that I cannot see the new line numbers 
> referred to by the `note` comments - Phab says "Context not available".

Of course. It had been sufficiently long since I last uploaded a new diff that 
I forgot that part of the instructions and just used `git format-patch` for 
this batch. I shall try to learn how to use `arc diff` because the copying and 
pasting of diffs was getting rather tedious and I knew I was bound to make a 
mistake with it eventually.

Thanks!


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

https://reviews.llvm.org/D145313

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D144216: [clang-tidy] Extract string header from redundant-string-cstr checker

2023-03-05 Thread Mike Crowe via Phabricator via cfe-commits
mikecrowe added a comment.

In D144216#4169772 , @carlosgalvezp 
wrote:

> In D144216#4169764 , @mikecrowe 
> wrote:
>
>>> I will double check that this is true once my current build is complete.
>>
>> Yes, it's true. I stuck a `#error` in 
>> `clang-tools-extra/test/clang-tidy/checkers/Inputs/Headers/string.h` and I 
>> saw the expected error from a file including ``.
>
> Awesome, thanks for checking, I wasn't aware we already had `string.h`. Then 
> if we do have headers named the same as the standard headers, would it make 
> sense to name this header `cstring` instead of `string`?

I think you mean rename `string.h` to `cstring`. (`string` clearly has to be 
just `string` if it's the standard C++ `string` header.)

A bit of searching in the existing checks shows that `string.h` is included by 
C checks (`bugprone/signal-handler*.c`) and also by checks that deliberately 
want `string.h` so they can suggest switching to `cstring` 
(`modernize/deprecated-headers*`) so it looks like it's necessary to keep 
`string.h`. If you wish, a `cstring` wrapper that just includes `string.h` 
could be created, but it really ought to put everything in `namespace std` too. 
(If so, I think this would probably be better done as a separate change.)


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

https://reviews.llvm.org/D144216

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D144216: [clang-tidy] Extract string header from redundant-string-cstr checker

2023-03-05 Thread Mike Crowe via Phabricator via cfe-commits
mikecrowe added a comment.

> I will double check that this is true once my current build is complete.

Yes, it's true. I stuck a `#error` in 
`clang-tools-extra/test/clang-tidy/checkers/Inputs/Headers/string.h` and I saw 
the expected error from a file including ``.


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

https://reviews.llvm.org/D144216

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D144216: [clang-tidy] Extract string header from redundant-string-cstr checker

2023-03-05 Thread Mike Crowe via Phabricator via cfe-commits
mikecrowe added a comment.

> The purpose of this header is to not include any standard header, and yet 
> this is done in line 5 so it kinda defeats the purpose.

I believe that this `` header is including 
`clang-tools-extra/test/clang-tidy/checkers/Inputs/Headers/string.h` rather 
than the system `string.h` header. (That's why I'm including `string.h` to get 
`size_t` rather than the more obvious `stdlib.h`.) If we're going to have sets 
of "standard-but-not-standard" headers for these checks then it feels like it 
ought to be safe to use them.

I will double check that this is true once my current build is complete.

Mike.


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

https://reviews.llvm.org/D144216

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D144216: [clang-tidy] Extract string header from redundant-string-cstr checker

2023-03-05 Thread Mike Crowe via Phabricator via cfe-commits
mikecrowe added a comment.

> Sounds good, should we land this?

If you're happy to do so, then so am I.

> If you don't have commit rights, please let us know Github name and email for 
> attribution.

These are my first code contributions to LLVM, so I don't really know the 
process. I don't believe that I have commit rights. My GitHub username is 
"mikecrowe" and my email address is "m...@mcrowe.com".

Thanks!

Mike.


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

https://reviews.llvm.org/D144216

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D144216: [clang-tidy] Extract string header from redundant-string-cstr checker

2023-03-04 Thread Mike Crowe via Phabricator via cfe-commits
mikecrowe added a comment.

The changes that extend the  header further and use it in a few more 
checks are:

- https://reviews.llvm.org/D145310
- https://reviews.llvm.org/D145311
- https://reviews.llvm.org/D145312
- https://reviews.llvm.org/D145313

and of course my original change:

- https://reviews.llvm.org/D143342


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

https://reviews.llvm.org/D144216

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D145313: [clang-tidy] Make readability-container-size-empty check using header

2023-03-04 Thread Mike Crowe via Phabricator via cfe-commits
mikecrowe created this revision.
mikecrowe added a reviewer: carlosgalvezp.
Herald added a subscriber: xazax.hun.
Herald added a project: All.
mikecrowe requested review of this revision.
Herald added a project: clang-tools-extra.
Herald added a subscriber: cfe-commits.

Improve the generic  header by adding the size() method so that
it can be used to replace the custom implementation in the
readability-container-size-empty check.

This requires fixing an incorrect comparison of a std::wstring with a
char string literal.

Unfortunately, removing the custom basic_string implementation means
fixing the line numbers for many of the checks.

Depends on D145312 


https://reviews.llvm.org/D145313

Files:
  clang-tools-extra/test/clang-tidy/checkers/Inputs/Headers/string
  
clang-tools-extra/test/clang-tidy/checkers/readability/container-size-empty.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/readability/container-size-empty.cpp
===
--- clang-tools-extra/test/clang-tidy/checkers/readability/container-size-empty.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/readability/container-size-empty.cpp
@@ -1,6 +1,7 @@
 // RUN: %check_clang_tidy %s readability-container-size-empty %t -- \
 // RUN: -config="{CheckOptions: [{key: readability-container-size-empty.ExcludedComparisonTypes , value: '::std::array;::IgnoredDummyType'}]}" \
-// RUN: -- -fno-delayed-template-parsing
+// RUN: -- -fno-delayed-template-parsing -isystem %clang_tidy_headers
+#include 
 
 namespace std {
 template  struct vector {
@@ -11,20 +12,6 @@
   bool empty() const;
 };
 
-template  struct basic_string {
-  basic_string();
-  bool operator==(const basic_string& other) const;
-  bool operator!=(const basic_string& other) const;
-  bool operator==(const char *) const;
-  bool operator!=(const char *) const;
-  basic_string operator+(const basic_string& other) const;
-  unsigned long size() const;
-  bool empty() const;
-};
-
-typedef basic_string string;
-typedef basic_string wstring;
-
 inline namespace __v2 {
 template  struct set {
   set();
@@ -125,12 +112,12 @@
 ;
   // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used to check for emptiness instead of 'size' [readability-container-size-empty]
   // CHECK-FIXES: {{^  }}if (intSet.empty()){{$}}
-  // CHECK-MESSAGES: :34:8: note: method 'set'::empty() defined here
+  // CHECK-MESSAGES: :21:8: note: method 'set'::empty() defined here
   if (intSet == std::set())
 ;
   // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used to check for emptiness
   // CHECK-FIXES: {{^  }}if (intSet.empty()){{$}}
-  // CHECK-MESSAGES: :34:8: note: method 'set'::empty() defined here
+  // CHECK-MESSAGES: :21:8: note: method 'set'::empty() defined here
   if (s_func() == "")
 ;
   // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
@@ -155,7 +142,7 @@
 ;
   // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
   // CHECK-FIXES: {{^  }}if (wstr.empty()){{$}}
-  if (wstr == "")
+  if (wstr == L"")
 ;
   // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
   // CHECK-FIXES: {{^  }}if (wstr.empty()){{$}}
@@ -452,7 +439,7 @@
 public:
   ConstructWithBoolField(const std::vector ) : B(C.size()) {}
 // CHECK-MESSAGES: :[[@LINE-1]]:57: warning: the 'empty' method should be used
-// CHECK-MESSAGES: :11:8: note: method 'vector'::empty() defined here
+// CHECK-MESSAGES: :12:8: note: method 'vector'::empty() defined here
 // CHECK-FIXES: {{^  }}ConstructWithBoolField(const std::vector ) : B(!C.empty()) {}
 };
 
@@ -460,21 +447,21 @@
   std::vector C;
   bool B = C.size();
 // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: the 'empty' method should be used
-// CHECK-MESSAGES: :11:8: note: method 'vector'::empty() defined here
+// CHECK-MESSAGES: :12:8: note: method 'vector'::empty() defined here
 // CHECK-FIXES: {{^  }}bool B = !C.empty();
 };
 
 int func(const std::vector ) {
   return C.size() ? 0 : 1;
 // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: the 'empty' method should be used
-// CHECK-MESSAGES: :11:8: note: method 'vector'::empty() defined here
+// CHECK-MESSAGES: :12:8: note: method 'vector'::empty() defined here
 // CHECK-FIXES: {{^  }}return !C.empty() ? 0 : 1;
 }
 
 constexpr Lazy L;
 static_assert(!L.size(), "");
 // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: the 'empty' method should be used
-// CHECK-MESSAGES: :103:18: note: method 'Lazy'::empty() defined here
+// CHECK-MESSAGES: :90:18: note: method 'Lazy'::empty() defined here
 // CHECK-FIXES: {{^}}static_assert(L.empty(), "");
 
 struct StructWithLazyNoexcept {
@@ -489,7 +476,7 @@
   if (v.size())
 ;
   // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used to check for emptiness instead of 'size' [readability-container-size-empty]
-  // CHECK-MESSAGES: :11:8: note: method 'vector'::empty() 

  1   2   >