[PATCH] D158665: [clang-tidy] Improve cppcoreguidelines-avoid-reference-coroutine-parameters check

2023-08-23 Thread Chris Cotter via Phabricator via cfe-commits
ccotter accepted this revision.
ccotter added a comment.
This revision is now accepted and ready to land.

Thanks!




Comment at: 
clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidReferenceCoroutineParametersCheck.cpp:20
+  Finder->addMatcher(
+  functionDecl(unless(parameterCountIs(0)), hasBody(coroutineBodyStmt()))
+  .bind("fnt"),

Can we do this by matching if any parameter is of reference type, rather than 
relying on the logic living in `check` (I wrote this originally, although 
perhaps this would be an improvement). Happy to take this up as a followup...


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D158665

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


[PATCH] D157239: [clang-tidy] Implement bugprone-incorrect-enable-if

2023-08-13 Thread Chris Cotter via Phabricator via cfe-commits
ccotter marked an inline comment as done.
ccotter added a comment.

> Do you have plans to also detect the bugprone scenario described in the Notes 
> here?

I didn't have plans in this review, or in the immediate future after. I did 
name this check broadly as "bugprone-incorrect-enable-if," so I imagine this 
other scenario could go into this new check.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D157239

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


[PATCH] D157239: [clang-tidy] Implement bugprone-incorrect-enable-if

2023-08-13 Thread Chris Cotter via Phabricator via cfe-commits
ccotter marked an inline comment as done.
ccotter added inline comments.



Comment at: 
clang-tools-extra/clang-tidy/bugprone/IncorrectEnableIfCheck.cpp:61-62
+
+  FixItHint TypenameHint =
+  FixItHint::CreateInsertion(ElaboratedLoc->getBeginLoc(), "typename ");
+  FixItHint TypeHint =

PiotrZSL wrote:
> do we still need typename in C++20 in this context ?
> https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0634r3.html
Oh, I did not know that. Thanks!


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D157239

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


[PATCH] D157239: [clang-tidy] Implement bugprone-incorrect-enable-if

2023-08-13 Thread Chris Cotter via Phabricator via cfe-commits
ccotter updated this revision to Diff 549777.
ccotter marked 9 inline comments as done.
ccotter added a comment.

- Fix docs, handle C++20 simplification


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D157239

Files:
  clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
  clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
  clang-tools-extra/clang-tidy/bugprone/IncorrectEnableIfCheck.cpp
  clang-tools-extra/clang-tidy/bugprone/IncorrectEnableIfCheck.h
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/bugprone/incorrect-enable-if.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  clang-tools-extra/test/clang-tidy/checkers/bugprone/incorrect-enable-if.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/bugprone/incorrect-enable-if.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/bugprone/incorrect-enable-if.cpp
@@ -0,0 +1,59 @@
+// RUN: %check_clang_tidy -std=c++11 %s bugprone-incorrect-enable-if %t
+// RUN: %check_clang_tidy -check-suffix=CXX20 -std=c++20 %s bugprone-incorrect-enable-if %t
+
+// NOLINTBEGIN
+namespace std {
+template  struct enable_if { };
+
+template  struct enable_if { typedef T type; };
+
+template 
+using enable_if_t = typename enable_if::type;
+
+} // namespace std
+// NOLINTEND
+
+template ::type>
+void valid_function1() {}
+
+template ::type = nullptr>
+void valid_function2() {}
+
+template ::type = nullptr>
+struct ValidClass1 {};
+
+template >
+void invalid() {}
+// CHECK-MESSAGES: [[@LINE-2]]:23: warning: incorrect std::enable_if usage detected; use 'typename std::enable_if<...>::type' [bugprone-incorrect-enable-if]
+// CHECK-FIXES: template ::type>
+// CHECK-FIXES-CXX20: template ::type>
+
+template  >
+void invalid_extra_whitespace() {}
+// CHECK-MESSAGES: [[@LINE-2]]:23: warning: incorrect std::enable_if usage detected; use 'typename std::enable_if<...>::type' [bugprone-incorrect-enable-if]
+// CHECK-FIXES: template ::type >
+// CHECK-FIXES-CXX20: template ::type >
+
+template >
+void invalid_extra_no_whitespace() {}
+// CHECK-MESSAGES: [[@LINE-2]]:23: warning: incorrect std::enable_if usage detected; use 'typename std::enable_if<...>::type' [bugprone-incorrect-enable-if]
+// CHECK-FIXES: template ::type>
+// CHECK-FIXES-CXX20: template ::type>
+
+template /*comment3*/>
+void invalid_extra_comment() {}
+// CHECK-MESSAGES: [[@LINE-2]]:23: warning: incorrect std::enable_if usage detected; use 'typename std::enable_if<...>::type' [bugprone-incorrect-enable-if]
+// CHECK-FIXES: template ::type/*comment3*/>
+
+template , typename = std::enable_if>
+void invalid_multiple() {}
+// CHECK-MESSAGES: [[@LINE-2]]:23: warning: incorrect std::enable_if usage detected; use 'typename std::enable_if<...>::type' [bugprone-incorrect-enable-if]
+// CHECK-MESSAGES: [[@LINE-3]]:65: warning: incorrect std::enable_if usage detected; use 'typename std::enable_if<...>::type' [bugprone-incorrect-enable-if]
+// CHECK-FIXES: template ::type, typename = typename std::enable_if::type>
+// CHECK-FIXES-CXX20: template ::type, typename = std::enable_if::type>
+
+template >
+struct InvalidClass {};
+// CHECK-MESSAGES: [[@LINE-2]]:23: warning: incorrect std::enable_if usage detected; use 'typename std::enable_if<...>::type' [bugprone-incorrect-enable-if]
+// CHECK-FIXES: template ::type>
+// CHECK-FIXES-CXX20: template ::type>
Index: clang-tools-extra/docs/clang-tidy/checks/list.rst
===
--- clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -94,6 +94,7 @@
`bugprone-implicit-widening-of-multiplication-result `_, "Yes"
`bugprone-inaccurate-erase `_, "Yes"
`bugprone-inc-dec-in-conditions `_,
+   `bugprone-incorrect-enable-if `_, "Yes"
`bugprone-incorrect-roundings `_,
`bugprone-infinite-loop `_,
`bugprone-integer-division `_,
Index: clang-tools-extra/docs/clang-tidy/checks/bugprone/incorrect-enable-if.rst
===
--- /dev/null
+++ clang-tools-extra/docs/clang-tidy/checks/bugprone/incorrect-enable-if.rst
@@ -0,0 +1,48 @@
+.. title:: clang-tidy - bugprone-incorrect-enable-if
+
+bugprone-incorrect-enable-if
+
+
+Detects incorrect usages of ``std::enable_if`` that don't name the nested 
+``type`` type.
+
+In C++11 introduced ``std::enable_if`` as a convenient way to leverage SFINAE.
+One form of using ``std::enable_if`` is to declare an unnamed template type
+parameter with a default type equal to
+``typename std::enable_if::type``. If the author forgets to name
+the nested type ``type``, then the code will always consider the candidate
+template even if the condition is not met.
+
+Below are some examples of code using ``std::enable_if`` correctly and
+incorrect example

[PATCH] D157057: [clang-tidy] Implement cppcoreguidelines CP.52

2023-08-10 Thread Chris Cotter via Phabricator via cfe-commits
ccotter marked an inline comment as done.
ccotter added a comment.

@PiotrZSL would you mind landing this for me? Thanks


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D157057

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


[PATCH] D157239: [clang-tidy] Implement bugprone-incorrect-enable-if

2023-08-06 Thread Chris Cotter via Phabricator via cfe-commits
ccotter added inline comments.



Comment at: clang-tools-extra/clang-tidy/bugprone/IncorrectEnableIfCheck.cpp:67
+  diag(EnableIf->getBeginLoc(), "incorrect std::enable_if usage detected; use "
+"'typename std::enable_if<...>::type'")
+  << TypenameHint << TypeHint;

PiotrZSL wrote:
> since C++14 we should recommend using enable_if_t
I didn't add replacement logic for C++14 or C++20 since there are separate 
tools for those, and though it'd be cleaner to have independent set of tools 
(e.g., first run bugprone-incorrect-enable-if, then run modernize-type-traits).


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D157239

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


[PATCH] D157239: [clang-tidy] Implement bugprone-incorrect-enable-if

2023-08-06 Thread Chris Cotter via Phabricator via cfe-commits
ccotter updated this revision to Diff 547599.
ccotter added a comment.

- Edited wrong file


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D157239

Files:
  clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
  clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
  clang-tools-extra/clang-tidy/bugprone/IncorrectEnableIfCheck.cpp
  clang-tools-extra/clang-tidy/bugprone/IncorrectEnableIfCheck.h
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/bugprone/incorrect-enable-if.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  clang-tools-extra/test/clang-tidy/checkers/bugprone/incorrect-enable-if.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/bugprone/incorrect-enable-if.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/bugprone/incorrect-enable-if.cpp
@@ -0,0 +1,53 @@
+// RUN: %check_clang_tidy -std=c++11 %s bugprone-incorrect-enable-if %t
+
+// NOLINTBEGIN
+namespace std {
+template  struct enable_if { };
+
+template  struct enable_if { typedef T type; };
+
+template 
+using enable_if_t = typename enable_if::type;
+
+} // namespace std
+// NOLINTEND
+
+template ::type>
+void valid_function1() {}
+
+template ::type = nullptr>
+void valid_function2() {}
+
+template ::type = nullptr>
+struct ValidClass1 {};
+
+template >
+void invalid() {}
+// CHECK-MESSAGES: [[@LINE-2]]:23: warning: incorrect std::enable_if usage detected; use 'typename std::enable_if<...>::type' [bugprone-incorrect-enable-if]
+// CHECK-FIXES: template ::type>
+
+template  >
+void invalid_extra_whitespace() {}
+// CHECK-MESSAGES: [[@LINE-2]]:23: warning: incorrect std::enable_if usage detected; use 'typename std::enable_if<...>::type' [bugprone-incorrect-enable-if]
+// CHECK-FIXES: template ::type >
+
+template >
+void invalid_extra_no_whitespace() {}
+// CHECK-MESSAGES: [[@LINE-2]]:23: warning: incorrect std::enable_if usage detected; use 'typename std::enable_if<...>::type' [bugprone-incorrect-enable-if]
+// CHECK-FIXES: template ::type>
+
+template /*comment3*/>
+void invalid_extra_comment() {}
+// CHECK-MESSAGES: [[@LINE-2]]:23: warning: incorrect std::enable_if usage detected; use 'typename std::enable_if<...>::type' [bugprone-incorrect-enable-if]
+// CHECK-FIXES: template ::type/*comment3*/>
+
+template , typename = std::enable_if>
+void invalid_multiple() {}
+// CHECK-MESSAGES: [[@LINE-2]]:23: warning: incorrect std::enable_if usage detected; use 'typename std::enable_if<...>::type' [bugprone-incorrect-enable-if]
+// CHECK-MESSAGES: [[@LINE-3]]:65: warning: incorrect std::enable_if usage detected; use 'typename std::enable_if<...>::type' [bugprone-incorrect-enable-if]
+// CHECK-FIXES: template ::type, typename = typename std::enable_if::type>
+
+template >
+struct InvalidClass {};
+// CHECK-MESSAGES: [[@LINE-2]]:23: warning: incorrect std::enable_if usage detected; use 'typename std::enable_if<...>::type' [bugprone-incorrect-enable-if]
+// CHECK-FIXES: template ::type>
Index: clang-tools-extra/docs/clang-tidy/checks/list.rst
===
--- clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -94,6 +94,7 @@
`bugprone-implicit-widening-of-multiplication-result `_, "Yes"
`bugprone-inaccurate-erase `_, "Yes"
`bugprone-inc-dec-in-conditions `_,
+   `bugprone-incorrect-enable-if `_, "Yes"
`bugprone-incorrect-roundings `_,
`bugprone-infinite-loop `_,
`bugprone-integer-division `_,
Index: clang-tools-extra/docs/clang-tidy/checks/bugprone/incorrect-enable-if.rst
===
--- /dev/null
+++ clang-tools-extra/docs/clang-tidy/checks/bugprone/incorrect-enable-if.rst
@@ -0,0 +1,48 @@
+.. title:: clang-tidy - bugprone-incorrect-enable-if
+
+bugprone-incorrect-enable-if
+
+
+Detects incorrect usages of std::enable_if that don't name the nested 'type'
+type.
+
+In C++11 introduced ``std::enable_if`` as a convenient way to leverage SFINAE.
+One form of using ``std::enable_if`` is to declare an unnamed template type
+parameter with a default type equal to
+``typename std::enable_if::type``. If the author forgets to name
+the nested type ``type``, then the code will always consider the candidate
+template even if the condition is not met.
+
+Below are some examples of code using ``std::enable_if`` correctly and
+incorrect examples that this check flags.
+
+.. code-block:: c++
+
+  template ::type>
+  void valid_usage() { ... }
+
+  template >
+  void valid_usage_with_trait_helpers() { ... }
+
+  // The below code is not a correct application of SFINAE. Even if
+  // T::some_trait is not true, the function will still be considered in the
+  // set of function candidates. It can either incorrectly select the function
+ 

[PATCH] D157239: [clang-tidy] Implement bugprone-incorrect-enable-if

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

Detects incorrect usages of std::enable_if that don't name the
nested 'type' type.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D157239

Files:
  clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
  clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
  clang-tools-extra/clang-tidy/bugprone/IncDecInConditionsCheck.h
  clang-tools-extra/clang-tidy/bugprone/IncorrectEnableIfCheck.cpp
  clang-tools-extra/clang-tidy/bugprone/IncorrectEnableIfCheck.h
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/bugprone/incorrect-enable-if.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  clang-tools-extra/test/clang-tidy/checkers/bugprone/incorrect-enable-if.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/bugprone/incorrect-enable-if.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/bugprone/incorrect-enable-if.cpp
@@ -0,0 +1,53 @@
+// RUN: %check_clang_tidy -std=c++11 %s bugprone-incorrect-enable-if %t
+
+// NOLINTBEGIN
+namespace std {
+template  struct enable_if { };
+
+template  struct enable_if { typedef T type; };
+
+template 
+using enable_if_t = typename enable_if::type;
+
+} // namespace std
+// NOLINTEND
+
+template ::type>
+void valid_function1() {}
+
+template ::type = nullptr>
+void valid_function2() {}
+
+template ::type = nullptr>
+struct ValidClass1 {};
+
+template >
+void invalid() {}
+// CHECK-MESSAGES: [[@LINE-2]]:23: warning: incorrect std::enable_if usage detected; use 'typename std::enable_if<...>::type' [bugprone-incorrect-enable-if]
+// CHECK-FIXES: template ::type>
+
+template  >
+void invalid_extra_whitespace() {}
+// CHECK-MESSAGES: [[@LINE-2]]:23: warning: incorrect std::enable_if usage detected; use 'typename std::enable_if<...>::type' [bugprone-incorrect-enable-if]
+// CHECK-FIXES: template ::type >
+
+template >
+void invalid_extra_no_whitespace() {}
+// CHECK-MESSAGES: [[@LINE-2]]:23: warning: incorrect std::enable_if usage detected; use 'typename std::enable_if<...>::type' [bugprone-incorrect-enable-if]
+// CHECK-FIXES: template ::type>
+
+template /*comment3*/>
+void invalid_extra_comment() {}
+// CHECK-MESSAGES: [[@LINE-2]]:23: warning: incorrect std::enable_if usage detected; use 'typename std::enable_if<...>::type' [bugprone-incorrect-enable-if]
+// CHECK-FIXES: template ::type/*comment3*/>
+
+template , typename = std::enable_if>
+void invalid_multiple() {}
+// CHECK-MESSAGES: [[@LINE-2]]:23: warning: incorrect std::enable_if usage detected; use 'typename std::enable_if<...>::type' [bugprone-incorrect-enable-if]
+// CHECK-MESSAGES: [[@LINE-3]]:65: warning: incorrect std::enable_if usage detected; use 'typename std::enable_if<...>::type' [bugprone-incorrect-enable-if]
+// CHECK-FIXES: template ::type, typename = typename std::enable_if::type>
+
+template >
+struct InvalidClass {};
+// CHECK-MESSAGES: [[@LINE-2]]:23: warning: incorrect std::enable_if usage detected; use 'typename std::enable_if<...>::type' [bugprone-incorrect-enable-if]
+// CHECK-FIXES: template ::type>
Index: clang-tools-extra/docs/clang-tidy/checks/list.rst
===
--- clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -94,6 +94,7 @@
`bugprone-implicit-widening-of-multiplication-result `_, "Yes"
`bugprone-inaccurate-erase `_, "Yes"
`bugprone-inc-dec-in-conditions `_,
+   `bugprone-incorrect-enable-if `_, "Yes"
`bugprone-incorrect-roundings `_,
`bugprone-infinite-loop `_,
`bugprone-integer-division `_,
Index: clang-tools-extra/docs/clang-tidy/checks/bugprone/incorrect-enable-if.rst
===
--- /dev/null
+++ clang-tools-extra/docs/clang-tidy/checks/bugprone/incorrect-enable-if.rst
@@ -0,0 +1,48 @@
+.. title:: clang-tidy - bugprone-incorrect-enable-if
+
+bugprone-incorrect-enable-if
+
+
+Detects incorrect usages of std::enable_if that don't name the nested 'type'
+type.
+
+In C++11 introduced ``std::enable_if`` as a convenient way to leverage SFINAE.
+One form of using ``std::enable_if`` is to declare an unnamed template type
+parameter with a default type equal to
+``typename std::enable_if::type``. If the author forgets to name
+the nested type ``type``, then the code will always consider the candidate
+template even if the condition is not met.
+
+Below are some examples of code using ``std::enable_if`` correctly and
+incorrect examples that this check flags.
+
+.. code-block:: c++
+
+  template ::type>
+  void valid_usage() { ... }
+
+  template >
+  voi

[PATCH] D157057: [clang-tidy] Implement cppcoreguidelines CP.52

2023-08-06 Thread Chris Cotter via Phabricator via cfe-commits
ccotter updated this revision to Diff 547585.
ccotter added a comment.

- Use matchesAnyListedName and fix windows build


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D157057

Files:
  clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt
  clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp
  clang-tools-extra/clang-tidy/cppcoreguidelines/NoSuspendWithLockCheck.cpp
  clang-tools-extra/clang-tidy/cppcoreguidelines/NoSuspendWithLockCheck.h
  clang-tools-extra/docs/ReleaseNotes.rst
  
clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/no-suspend-with-lock.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  
clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/no-suspend-with-lock.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/no-suspend-with-lock.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/no-suspend-with-lock.cpp
@@ -0,0 +1,279 @@
+// RUN: %check_clang_tidy -std=c++20 %s cppcoreguidelines-no-suspend-with-lock %t -- -- -fno-delayed-template-parsing
+
+// NOLINTBEGIN
+namespace std {
+template 
+struct coroutine_traits {
+  using promise_type = typename T::promise_type;
+};
+template 
+struct coroutine_handle;
+template <>
+struct coroutine_handle {
+  coroutine_handle() noexcept;
+  coroutine_handle(decltype(nullptr)) noexcept;
+  static constexpr coroutine_handle from_address(void*);
+};
+template 
+struct coroutine_handle {
+  coroutine_handle() noexcept;
+  coroutine_handle(decltype(nullptr)) noexcept;
+  static constexpr coroutine_handle from_address(void*);
+  operator coroutine_handle<>() const noexcept;
+};
+
+template 
+class unique_lock {
+public:
+  unique_lock() noexcept;
+  explicit unique_lock(Mutex &m);
+  unique_lock& operator=(unique_lock&&);
+  void unlock();
+  Mutex* release() noexcept;
+  Mutex* mutex() const noexcept;
+  void swap(unique_lock& other) noexcept;
+};
+
+class mutex {
+public:
+  mutex() noexcept;
+  ~mutex();
+  mutex(const mutex &) = delete;
+  mutex &operator=(const mutex &) = delete;
+
+  void lock();
+  void unlock();
+};
+} // namespace std
+
+class my_own_mutex {
+public:
+  void lock();
+  void unlock();
+};
+
+struct Awaiter {
+  bool await_ready() noexcept;
+  void await_suspend(std::coroutine_handle<>) noexcept;
+  void await_resume() noexcept;
+};
+
+struct Coro {
+  struct promise_type {
+Awaiter initial_suspend();
+Awaiter final_suspend() noexcept;
+void return_void();
+Coro get_return_object();
+void unhandled_exception();
+Awaiter yield_value(int);
+  };
+};
+// NOLINTEND
+
+std::mutex mtx;
+std::mutex mtx2;
+
+Coro awaits_with_lock() {
+  std::unique_lock lock(mtx);
+
+  co_await Awaiter{};
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: coroutine suspended with lock 'lock' held [cppcoreguidelines-no-suspend-with-lock]
+
+  co_await Awaiter{};
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: coroutine suspended with lock 'lock' held [cppcoreguidelines-no-suspend-with-lock]
+
+  if (true) {
+co_await Awaiter{};
+// CHECK-MESSAGES: [[@LINE-1]]:5: warning: coroutine suspended with lock 'lock' held [cppcoreguidelines-no-suspend-with-lock]
+  }
+
+  if (true) {
+std::unique_lock lock2;
+lock2.unlock();
+co_await Awaiter{};
+// CHECK-MESSAGES: [[@LINE-1]]:5: warning: coroutine suspended with lock 'lock2' held [cppcoreguidelines-no-suspend-with-lock]
+  }
+}
+
+Coro awaits_with_lock_in_try() try {
+  std::unique_lock lock(mtx);
+  co_await Awaiter{};
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: coroutine suspended with lock 'lock' held [cppcoreguidelines-no-suspend-with-lock]
+} catch (...) {}
+
+Coro lock_possibly_unlocked() {
+  // CppCoreGuideline CP.52's enforcement strictly requires flagging
+  // code that suspends while any lock guard is not destructed.
+
+  {
+std::unique_lock lock(mtx);
+lock.unlock();
+co_await Awaiter{};
+// CHECK-MESSAGES: [[@LINE-1]]:5: warning: coroutine suspended with lock 'lock' held [cppcoreguidelines-no-suspend-with-lock]
+  }
+
+  {
+std::unique_lock lock(mtx);
+lock.release();
+co_await Awaiter{};
+// CHECK-MESSAGES: [[@LINE-1]]:5: warning: coroutine suspended with lock 'lock' held [cppcoreguidelines-no-suspend-with-lock]
+  }
+
+  {
+std::unique_lock lock(mtx);
+std::unique_lock lock2;
+lock.swap(lock2);
+co_await Awaiter{};
+// CHECK-MESSAGES: [[@LINE-1]]:5: warning: coroutine suspended with lock 'lock' held [cppcoreguidelines-no-suspend-with-lock]
+  }
+
+  {
+std::unique_lock lock(mtx);
+std::unique_lock lock2{mtx2};
+lock.swap(lock2);
+co_await Awaiter{};
+// CHECK-MESSAGES: [[@LINE-1]]:5: warning: coroutine suspended with lock 'lock' held [cppcoreguidelines-no-suspend-with-lock]
+  }
+
+  {
+std::unique_lock lock(mtx);
+lock = st

[PATCH] D157057: [clang-tidy] Implement cppcoreguidelines CP.52

2023-08-06 Thread Chris Cotter via Phabricator via cfe-commits
ccotter updated this revision to Diff 547573.
ccotter marked 5 inline comments as done.
ccotter added a comment.

- Add tests, do not inspect instantiations, add option


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D157057

Files:
  clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt
  clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp
  clang-tools-extra/clang-tidy/cppcoreguidelines/NoSuspendWithLockCheck.cpp
  clang-tools-extra/clang-tidy/cppcoreguidelines/NoSuspendWithLockCheck.h
  clang-tools-extra/docs/ReleaseNotes.rst
  
clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/no-suspend-with-lock.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  
clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/no-suspend-with-lock.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/no-suspend-with-lock.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/no-suspend-with-lock.cpp
@@ -0,0 +1,279 @@
+// RUN: %check_clang_tidy -std=c++20 %s cppcoreguidelines-no-suspend-with-lock %t
+
+// NOLINTBEGIN
+namespace std {
+template 
+struct coroutine_traits {
+  using promise_type = typename T::promise_type;
+};
+template 
+struct coroutine_handle;
+template <>
+struct coroutine_handle {
+  coroutine_handle() noexcept;
+  coroutine_handle(decltype(nullptr)) noexcept;
+  static constexpr coroutine_handle from_address(void*);
+};
+template 
+struct coroutine_handle {
+  coroutine_handle() noexcept;
+  coroutine_handle(decltype(nullptr)) noexcept;
+  static constexpr coroutine_handle from_address(void*);
+  operator coroutine_handle<>() const noexcept;
+};
+
+template 
+class unique_lock {
+public:
+  unique_lock() noexcept;
+  explicit unique_lock(Mutex &m);
+  unique_lock& operator=(unique_lock&&);
+  void unlock();
+  Mutex* release() noexcept;
+  Mutex* mutex() const noexcept;
+  void swap(unique_lock& other) noexcept;
+};
+
+class mutex {
+public:
+  mutex() noexcept;
+  ~mutex();
+  mutex(const mutex &) = delete;
+  mutex &operator=(const mutex &) = delete;
+
+  void lock();
+  void unlock();
+};
+} // namespace std
+
+class my_own_mutex {
+public:
+  void lock();
+  void unlock();
+};
+
+struct Awaiter {
+  bool await_ready() noexcept;
+  void await_suspend(std::coroutine_handle<>) noexcept;
+  void await_resume() noexcept;
+};
+
+struct Coro {
+  struct promise_type {
+Awaiter initial_suspend();
+Awaiter final_suspend() noexcept;
+void return_void();
+Coro get_return_object();
+void unhandled_exception();
+Awaiter yield_value(int);
+  };
+};
+// NOLINTEND
+
+std::mutex mtx;
+std::mutex mtx2;
+
+Coro awaits_with_lock() {
+  std::unique_lock lock(mtx);
+
+  co_await Awaiter{};
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: coroutine suspended with lock 'lock' held [cppcoreguidelines-no-suspend-with-lock]
+
+  co_await Awaiter{};
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: coroutine suspended with lock 'lock' held [cppcoreguidelines-no-suspend-with-lock]
+
+  if (true) {
+co_await Awaiter{};
+// CHECK-MESSAGES: [[@LINE-1]]:5: warning: coroutine suspended with lock 'lock' held [cppcoreguidelines-no-suspend-with-lock]
+  }
+
+  if (true) {
+std::unique_lock lock2;
+lock2.unlock();
+co_await Awaiter{};
+// CHECK-MESSAGES: [[@LINE-1]]:5: warning: coroutine suspended with lock 'lock2' held [cppcoreguidelines-no-suspend-with-lock]
+  }
+}
+
+Coro awaits_with_lock_in_try() try {
+  std::unique_lock lock(mtx);
+  co_await Awaiter{};
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: coroutine suspended with lock 'lock' held [cppcoreguidelines-no-suspend-with-lock]
+} catch (...) {}
+
+Coro lock_possibly_unlocked() {
+  // CppCoreGuideline CP.52's enforcement strictly requires flagging
+  // code that suspends while any lock guard is not destructed.
+
+  {
+std::unique_lock lock(mtx);
+lock.unlock();
+co_await Awaiter{};
+// CHECK-MESSAGES: [[@LINE-1]]:5: warning: coroutine suspended with lock 'lock' held [cppcoreguidelines-no-suspend-with-lock]
+  }
+
+  {
+std::unique_lock lock(mtx);
+lock.release();
+co_await Awaiter{};
+// CHECK-MESSAGES: [[@LINE-1]]:5: warning: coroutine suspended with lock 'lock' held [cppcoreguidelines-no-suspend-with-lock]
+  }
+
+  {
+std::unique_lock lock(mtx);
+std::unique_lock lock2;
+lock.swap(lock2);
+co_await Awaiter{};
+// CHECK-MESSAGES: [[@LINE-1]]:5: warning: coroutine suspended with lock 'lock' held [cppcoreguidelines-no-suspend-with-lock]
+  }
+
+  {
+std::unique_lock lock(mtx);
+std::unique_lock lock2{mtx2};
+lock.swap(lock2);
+co_await Awaiter{};
+// CHECK-MESSAGES: [[@LINE-1]]:5: warning: coroutine suspended with lock 'lock' held [cppcoreguidelines-no-suspend-with-lock]
+  }
+
+  {
+std::unique_lock lock(mtx);
+ 

[PATCH] D157057: [clang-tidy] Implement cppcoreguidelines CP.52

2023-08-05 Thread Chris Cotter via Phabricator via cfe-commits
ccotter added inline comments.



Comment at: 
clang-tools-extra/clang-tidy/cppcoreguidelines/NoSuspendWithLockCheck.cpp:24-26
+  hasType(recordDecl(hasAnyName(
+  "::std::unique_lock", "::std::lock_guard",
+  "::std::scoped_lock", 
"::std::shared_lock"

PiotrZSL wrote:
> add configuration option for lock types, many big project got own types or 
> wrappers.
I was just thinking about this case...my code base had its own lock types that 
I would want to be able to include.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D157057

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


[PATCH] D140760: [clang-tidy] Support begin/end free functions in modernize-loop-convert

2023-08-05 Thread Chris Cotter via Phabricator via cfe-commits
ccotter marked an inline comment as done.
ccotter added a comment.

All done on my end - @PiotrZSL if you're good would you mind landing this for 
me?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D140760

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


[PATCH] D140760: [clang-tidy] Support begin/end free functions in modernize-loop-convert

2023-08-05 Thread Chris Cotter via Phabricator via cfe-commits
ccotter marked 3 inline comments as done.
ccotter added inline comments.



Comment at: 
clang-tools-extra/test/clang-tidy/checkers/modernize/loop-convert-basic.cpp:484
 }
 
 // Tests to verify the proper use of auto where the init variable type and the

PiotrZSL wrote:
> Please add test with rbegin/rend
Will do.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D140760

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


[PATCH] D140760: [clang-tidy] Support begin/end free functions in modernize-loop-convert

2023-08-05 Thread Chris Cotter via Phabricator via cfe-commits
ccotter updated this revision to Diff 547483.
ccotter added a comment.

- Check nullptr
- Add tests for rbegin/crbegin


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D140760

Files:
  clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/modernize/loop-convert.rst
  
clang-tools-extra/test/clang-tidy/checkers/modernize/Inputs/loop-convert/structures.h
  clang-tools-extra/test/clang-tidy/checkers/modernize/loop-convert-basic.cpp
  clang-tools-extra/test/clang-tidy/checkers/modernize/loop-convert-negative.cpp
  clang-tools-extra/test/clang-tidy/checkers/modernize/loop-convert-reverse.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/modernize/loop-convert-reverse.cpp
===
--- clang-tools-extra/test/clang-tidy/checkers/modernize/loop-convert-reverse.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/modernize/loop-convert-reverse.cpp
@@ -40,6 +40,8 @@
 // Make sure no header is included in this example
 // CHECK-FIXES-CUSTOM-NO-HEADER-NOT: #include
 
+namespace ADL {
+
 template 
 struct Reversable {
   using iterator = T *;
@@ -61,6 +63,28 @@
   const_iterator crend() const;
 };
 
+template 
+constexpr auto rbegin(C& c) -> decltype(c.rbegin()) { return c.rbegin(); }
+template 
+constexpr auto rend(C& c) -> decltype(c.rend()) { return c.rend(); }
+template 
+constexpr auto rbegin(const C& c) -> decltype(c.rbegin()) { return c.rbegin(); }
+template 
+constexpr auto rend(const C& c) -> decltype(c.rend()) { return c.rend(); }
+
+template 
+constexpr auto crbegin(C& c) -> decltype(c.crbegin());
+template 
+constexpr auto crend(C& c) -> decltype(c.crend());
+template 
+constexpr auto crbegin(const C& c) -> decltype(c.crbegin());
+template 
+constexpr auto crend(const C& c) -> decltype(c.crend());
+
+} // namespace ADL
+
+using ADL::Reversable;
+
 template 
 void observe(const T &);
 template 
@@ -85,6 +109,24 @@
   //   CHECK-FIXES-NEXT:   observe(Number);
   //   CHECK-FIXES-NEXT: }
 
+  for (auto I = rbegin(Numbers), E = rend(Numbers); I != E; ++I) {
+observe(*I);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES-RANGES: for (int Number : std::ranges::reverse_view(Numbers)) {
+  // CHECK-FIXES-CUSTOM: for (int Number : llvm::reverse(Numbers)) {
+  //   CHECK-FIXES-NEXT:   observe(Number);
+  //   CHECK-FIXES-NEXT: }
+
+  for (auto I = crbegin(Numbers), E = crend(Numbers); I != E; ++I) {
+observe(*I);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES-RANGES: for (int Number : std::ranges::reverse_view(Numbers)) {
+  // CHECK-FIXES-CUSTOM: for (int Number : llvm::reverse(Numbers)) {
+  //   CHECK-FIXES-NEXT:   observe(Number);
+  //   CHECK-FIXES-NEXT: }
+
   // Ensure these bad loops aren't transformed.
   for (auto I = Numbers.rbegin(), E = Numbers.end(); I != E; ++I) {
 observe(*I);
@@ -112,4 +154,13 @@
   // CHECK-FIXES-CUSTOM: for (int Number : llvm::reverse(Numbers)) {
   //   CHECK-FIXES-NEXT:   observe(Number);
   //   CHECK-FIXES-NEXT: }
+
+  for (auto I = rbegin(Numbers), E = rend(Numbers); I != E; ++I) {
+mutate(*I);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES-RANGES: for (int & Number : std::ranges::reverse_view(Numbers)) {
+  // CHECK-FIXES-CUSTOM: for (int & Number : llvm::reverse(Numbers)) {
+  //   CHECK-FIXES-NEXT:   mutate(Number);
+  //   CHECK-FIXES-NEXT: }
 }
Index: clang-tools-extra/test/clang-tidy/checkers/modernize/loop-convert-negative.cpp
===
--- clang-tools-extra/test/clang-tidy/checkers/modernize/loop-convert-negative.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/modernize/loop-convert-negative.cpp
@@ -5,6 +5,22 @@
 // CHECK-FIXES-NOT: for ({{.*[^:]:[^:].*}})
 // CHECK-MESSAGES-NOT: modernize-loop-convert
 
+namespace somenamespace {
+  template  auto begin(T& t) -> decltype(t.begin());
+  template  auto begin(const T& t) -> decltype(t.begin());
+  template  auto end(T& t) -> decltype(t.end());
+  template  auto end(const T& t) -> decltype(t.end());
+  template  auto size(const T& t) -> decltype(t.size());
+} // namespace somenamespace
+
+struct SomeClass {
+  template  static auto begin(T& t) -> decltype(t.begin());
+  template  static auto begin(const T& t) -> decltype(t.begin());
+  template  static auto end(T& t) -> decltype(t.end());
+  template  static auto end(const T& t) -> decltype(t.end());
+  template  static auto size(const T& t) -> decltype(t.size());
+};
+
 namespace Negative {
 
 const int N = 6;
@@ -92,7 +108,7 @@
   }
 }
 
-}
+} // namespace Negative
 
 namespace NegativeIterator {
 
@@ -103,6 +119,10 @@
 struct BadBeginEnd : T {
   iterator notBegin();
   iterator notEnd();
+  iterat

[PATCH] D140760: [clang-tidy] Support begin/end free functions in modernize-loop-convert

2023-08-04 Thread Chris Cotter via Phabricator via cfe-commits
ccotter updated this revision to Diff 547433.
ccotter marked 2 inline comments as done.
ccotter added a comment.

- Feedback


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D140760

Files:
  clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/modernize/loop-convert.rst
  
clang-tools-extra/test/clang-tidy/checkers/modernize/Inputs/loop-convert/structures.h
  clang-tools-extra/test/clang-tidy/checkers/modernize/loop-convert-basic.cpp
  clang-tools-extra/test/clang-tidy/checkers/modernize/loop-convert-negative.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/modernize/loop-convert-negative.cpp
===
--- clang-tools-extra/test/clang-tidy/checkers/modernize/loop-convert-negative.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/modernize/loop-convert-negative.cpp
@@ -5,6 +5,22 @@
 // CHECK-FIXES-NOT: for ({{.*[^:]:[^:].*}})
 // CHECK-MESSAGES-NOT: modernize-loop-convert
 
+namespace somenamespace {
+  template  auto begin(T& t) -> decltype(t.begin());
+  template  auto begin(const T& t) -> decltype(t.begin());
+  template  auto end(T& t) -> decltype(t.end());
+  template  auto end(const T& t) -> decltype(t.end());
+  template  auto size(const T& t) -> decltype(t.size());
+} // namespace somenamespace
+
+struct SomeClass {
+  template  static auto begin(T& t) -> decltype(t.begin());
+  template  static auto begin(const T& t) -> decltype(t.begin());
+  template  static auto end(T& t) -> decltype(t.end());
+  template  static auto end(const T& t) -> decltype(t.end());
+  template  static auto size(const T& t) -> decltype(t.size());
+};
+
 namespace Negative {
 
 const int N = 6;
@@ -92,7 +108,7 @@
   }
 }
 
-}
+} // namespace Negative
 
 namespace NegativeIterator {
 
@@ -103,6 +119,10 @@
 struct BadBeginEnd : T {
   iterator notBegin();
   iterator notEnd();
+  iterator begin(int);
+  iterator end(int);
+  iterator begin();
+  iterator end();
 };
 
 void notBeginOrEnd() {
@@ -112,6 +132,9 @@
 
   for (T::iterator I = Bad.begin(), E = Bad.notEnd();  I != E; ++I)
 int K = *I;
+
+  for (T::iterator I = Bad.begin(0), E = Bad.end(0);  I != E; ++I)
+int K = *I;
 }
 
 void badLoopShapes() {
@@ -202,6 +225,8 @@
   T Other;
   for (T::iterator I = Tt.begin(), E = Other.end();  I != E; ++I)
 int K = *I;
+  for (T::iterator I = begin(Tt), E = end(Other);  I != E; ++I)
+int K = *I;
 
   for (T::iterator I = Other.begin(), E = Tt.end();  I != E; ++I)
 int K = *I;
@@ -214,6 +239,24 @@
 MutableVal K = *I;
 }
 
+void mixedMemberAndADL() {
+  for (T::iterator I = Tt.begin(), E = end(Tt);  I != E; ++I)
+int K = *I;
+  for (T::iterator I = begin(Tt), E = Tt.end();  I != E; ++I)
+int K = *I;
+  for (T::iterator I = std::begin(Tt), E = Tt.end();  I != E; ++I)
+int K = *I;
+  for (T::iterator I = std::begin(Tt), E = end(Tt);  I != E; ++I)
+int K = *I;
+}
+
+void nonADLOrStdCalls() {
+  for (T::iterator I = SomeClass::begin(Tt), E = SomeClass::end(Tt);  I != E; ++I)
+int K = *I;
+  for (T::iterator I = somenamespace::begin(Tt), E = somenamespace::end(Tt);  I != E; ++I)
+int K = *I;
+}
+
 void wrongIterators() {
   T::iterator Other;
   for (T::iterator I = Tt.begin(), E = Tt.end(); I != Other; ++I)
@@ -379,6 +422,13 @@
 Sum += V[I];
 }
 
+void nonADLOrStdCalls() {
+  for (int I = 0, E = somenamespace::size(V); E != I; ++I)
+printf("Fibonacci number is %d\n", V[I]);
+  for (int I = 0, E = SomeClass::size(V); E != I; ++I)
+printf("Fibonacci number is %d\n", V[I]);
+}
+
 // Checks to see that non-const member functions are not called on the container
 // object.
 // These could be conceivably allowed with a lower required confidence level.
Index: clang-tools-extra/test/clang-tidy/checkers/modernize/loop-convert-basic.cpp
===
--- clang-tools-extra/test/clang-tidy/checkers/modernize/loop-convert-basic.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/modernize/loop-convert-basic.cpp
@@ -445,6 +445,41 @@
   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
   // CHECK-FIXES: for (auto & I : Dpp)
   // CHECK-FIXES-NEXT: printf("%d\n", I->X);
+
+  for (S::iterator It = begin(Ss), E = end(Ss); It != E; ++It) {
+printf("s0 has value %d\n", (*It).X);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto & It : Ss)
+  // CHECK-FIXES-NEXT: printf("s0 has value %d\n", It.X);
+
+  for (S::iterator It = std::begin(Ss), E = std::end(Ss); It != E; ++It) {
+printf("s1 has value %d\n", (*It).X);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto & It : Ss)
+  // CHECK-FIXES-NEXT: printf("s1 has value %d\n", It.X);
+
+  for (S::iterato

[PATCH] D157057: [clang-tidy] Implement cppcoreguidelines CP.52

2023-08-03 Thread Chris Cotter via Phabricator via cfe-commits
ccotter updated this revision to Diff 547061.
ccotter added a comment.

- Specify version


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D157057

Files:
  clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt
  clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp
  clang-tools-extra/clang-tidy/cppcoreguidelines/NoSuspendWithLockCheck.cpp
  clang-tools-extra/clang-tidy/cppcoreguidelines/NoSuspendWithLockCheck.h
  clang-tools-extra/docs/ReleaseNotes.rst
  
clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/no-suspend-with-lock.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  
clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/no-suspend-with-lock.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/no-suspend-with-lock.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/no-suspend-with-lock.cpp
@@ -0,0 +1,189 @@
+// RUN: %check_clang_tidy -std=c++20 %s cppcoreguidelines-no-suspend-with-lock %t
+
+// NOLINTBEGIN
+namespace std {
+template 
+struct coroutine_traits {
+  using promise_type = typename T::promise_type;
+};
+template 
+struct coroutine_handle;
+template <>
+struct coroutine_handle {
+  coroutine_handle() noexcept;
+  coroutine_handle(decltype(nullptr)) noexcept;
+  static constexpr coroutine_handle from_address(void*);
+};
+template 
+struct coroutine_handle {
+  coroutine_handle() noexcept;
+  coroutine_handle(decltype(nullptr)) noexcept;
+  static constexpr coroutine_handle from_address(void*);
+  operator coroutine_handle<>() const noexcept;
+};
+
+template 
+class unique_lock {
+public:
+  unique_lock() noexcept;
+  explicit unique_lock(Mutex &m);
+  unique_lock& operator=(unique_lock&&);
+  void unlock();
+  Mutex* release() noexcept;
+  Mutex* mutex() const noexcept;
+  void swap(unique_lock& other) noexcept;
+};
+
+class mutex {
+public:
+  mutex() noexcept;
+  ~mutex();
+  mutex(const mutex &) = delete;
+  mutex &operator=(const mutex &) = delete;
+
+  void lock();
+  void unlock();
+};
+} // namespace std
+
+struct Awaiter {
+  bool await_ready() noexcept;
+  void await_suspend(std::coroutine_handle<>) noexcept;
+  void await_resume() noexcept;
+};
+
+struct Coro {
+  struct promise_type {
+Awaiter initial_suspend();
+Awaiter final_suspend() noexcept;
+void return_void();
+Coro get_return_object();
+void unhandled_exception();
+Awaiter yield_value(int);
+  };
+};
+// NOLINTEND
+
+std::mutex mtx;
+std::mutex mtx2;
+
+Coro awaits_with_lock() {
+  std::unique_lock lock(mtx);
+
+  co_await Awaiter{};
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: coroutine suspended with lock 'lock' held [cppcoreguidelines-no-suspend-with-lock]
+
+  co_await Awaiter{};
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: coroutine suspended with lock 'lock' held [cppcoreguidelines-no-suspend-with-lock]
+
+  if (true) {
+co_await Awaiter{};
+// CHECK-MESSAGES: [[@LINE-1]]:5: warning: coroutine suspended with lock 'lock' held [cppcoreguidelines-no-suspend-with-lock]
+  }
+
+  if (true) {
+std::unique_lock lock2;
+lock2.unlock();
+co_await Awaiter{};
+// CHECK-MESSAGES: [[@LINE-1]]:5: warning: coroutine suspended with lock 'lock2' held [cppcoreguidelines-no-suspend-with-lock]
+  }
+}
+
+Coro awaits_with_lock_in_try() try {
+  std::unique_lock lock(mtx);
+  co_await Awaiter{};
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: coroutine suspended with lock 'lock' held [cppcoreguidelines-no-suspend-with-lock]
+} catch (...) {}
+
+Coro lock_possibly_unlocked() {
+  // CppCoreGuideline CP.52's enforcement strictly requires flagging
+  // code that suspends while any lock guard is not destructed.
+
+  {
+std::unique_lock lock(mtx);
+lock.unlock();
+co_await Awaiter{};
+// CHECK-MESSAGES: [[@LINE-1]]:5: warning: coroutine suspended with lock 'lock' held [cppcoreguidelines-no-suspend-with-lock]
+  }
+
+  {
+std::unique_lock lock(mtx);
+lock.release();
+co_await Awaiter{};
+// CHECK-MESSAGES: [[@LINE-1]]:5: warning: coroutine suspended with lock 'lock' held [cppcoreguidelines-no-suspend-with-lock]
+  }
+
+  {
+std::unique_lock lock(mtx);
+std::unique_lock lock2;
+lock.swap(lock2);
+co_await Awaiter{};
+// CHECK-MESSAGES: [[@LINE-1]]:5: warning: coroutine suspended with lock 'lock' held [cppcoreguidelines-no-suspend-with-lock]
+  }
+
+  {
+std::unique_lock lock(mtx);
+std::unique_lock lock2{mtx2};
+lock.swap(lock2);
+co_await Awaiter{};
+// CHECK-MESSAGES: [[@LINE-1]]:5: warning: coroutine suspended with lock 'lock' held [cppcoreguidelines-no-suspend-with-lock]
+  }
+
+  {
+std::unique_lock lock(mtx);
+lock = std::unique_lock{};
+co_await Awaiter{};
+// CHECK-MESSAGES: [[@LINE-1]]:5: warning: coroutine suspended with lock 'lock' held [cppc

[PATCH] D157057: [clang-tidy] Implement cppcoreguidelines CP.52

2023-08-03 Thread Chris Cotter via Phabricator via cfe-commits
ccotter created this revision.
Herald added subscribers: PiotrZSL, carlosgalvezp, shchenz, kbarton, xazax.hun, 
nemanjai.
Herald added a reviewer: njames93.
Herald added a project: All.
ccotter requested review of this revision.
Herald added a project: clang-tools-extra.
Herald added a subscriber: cfe-commits.

Flag code that suspends a coroutine while a lock is held.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D157057

Files:
  clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt
  clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp
  clang-tools-extra/clang-tidy/cppcoreguidelines/NoSuspendWithLockCheck.cpp
  clang-tools-extra/clang-tidy/cppcoreguidelines/NoSuspendWithLockCheck.h
  clang-tools-extra/docs/ReleaseNotes.rst
  
clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/no-suspend-with-lock.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  
clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/no-suspend-with-lock.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/no-suspend-with-lock.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/no-suspend-with-lock.cpp
@@ -0,0 +1,189 @@
+// RUN: %check_clang_tidy -std=c++20-or-later %s cppcoreguidelines-no-suspend-with-lock %t
+
+// NOLINTBEGIN
+namespace std {
+template 
+struct coroutine_traits {
+  using promise_type = typename T::promise_type;
+};
+template 
+struct coroutine_handle;
+template <>
+struct coroutine_handle {
+  coroutine_handle() noexcept;
+  coroutine_handle(decltype(nullptr)) noexcept;
+  static constexpr coroutine_handle from_address(void*);
+};
+template 
+struct coroutine_handle {
+  coroutine_handle() noexcept;
+  coroutine_handle(decltype(nullptr)) noexcept;
+  static constexpr coroutine_handle from_address(void*);
+  operator coroutine_handle<>() const noexcept;
+};
+
+template 
+class unique_lock {
+public:
+  unique_lock() noexcept;
+  explicit unique_lock(Mutex &m);
+  unique_lock& operator=(unique_lock&&);
+  void unlock();
+  Mutex* release() noexcept;
+  Mutex* mutex() const noexcept;
+  void swap(unique_lock& other) noexcept;
+};
+
+class mutex {
+public:
+  mutex() noexcept;
+  ~mutex();
+  mutex(const mutex &) = delete;
+  mutex &operator=(const mutex &) = delete;
+
+  void lock();
+  void unlock();
+};
+} // namespace std
+
+struct Awaiter {
+  bool await_ready() noexcept;
+  void await_suspend(std::coroutine_handle<>) noexcept;
+  void await_resume() noexcept;
+};
+
+struct Coro {
+  struct promise_type {
+Awaiter initial_suspend();
+Awaiter final_suspend() noexcept;
+void return_void();
+Coro get_return_object();
+void unhandled_exception();
+Awaiter yield_value(int);
+  };
+};
+// NOLINTEND
+
+std::mutex mtx;
+std::mutex mtx2;
+
+Coro awaits_with_lock() {
+  std::unique_lock lock(mtx);
+
+  co_await Awaiter{};
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: coroutine suspended with lock 'lock' held [cppcoreguidelines-no-suspend-with-lock]
+
+  co_await Awaiter{};
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: coroutine suspended with lock 'lock' held [cppcoreguidelines-no-suspend-with-lock]
+
+  if (true) {
+co_await Awaiter{};
+// CHECK-MESSAGES: [[@LINE-1]]:5: warning: coroutine suspended with lock 'lock' held [cppcoreguidelines-no-suspend-with-lock]
+  }
+
+  if (true) {
+std::unique_lock lock2;
+lock2.unlock();
+co_await Awaiter{};
+// CHECK-MESSAGES: [[@LINE-1]]:5: warning: coroutine suspended with lock 'lock2' held [cppcoreguidelines-no-suspend-with-lock]
+  }
+}
+
+Coro awaits_with_lock_in_try() try {
+  std::unique_lock lock(mtx);
+  co_await Awaiter{};
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: coroutine suspended with lock 'lock' held [cppcoreguidelines-no-suspend-with-lock]
+} catch (...) {}
+
+Coro lock_possibly_unlocked() {
+  // CppCoreGuideline CP.52's enforcement strictly requires flagging
+  // code that suspends while any lock guard is not destructed.
+
+  {
+std::unique_lock lock(mtx);
+lock.unlock();
+co_await Awaiter{};
+// CHECK-MESSAGES: [[@LINE-1]]:5: warning: coroutine suspended with lock 'lock' held [cppcoreguidelines-no-suspend-with-lock]
+  }
+
+  {
+std::unique_lock lock(mtx);
+lock.release();
+co_await Awaiter{};
+// CHECK-MESSAGES: [[@LINE-1]]:5: warning: coroutine suspended with lock 'lock' held [cppcoreguidelines-no-suspend-with-lock]
+  }
+
+  {
+std::unique_lock lock(mtx);
+std::unique_lock lock2;
+lock.swap(lock2);
+co_await Awaiter{};
+// CHECK-MESSAGES: [[@LINE-1]]:5: warning: coroutine suspended with lock 'lock' held [cppcoreguidelines-no-suspend-with-lock]
+  }
+
+  {
+std::unique_lock lock(mtx);
+std::unique_lock lock2{mtx2};
+lock.swap(lock2);
+co_await Awaiter{};
+// CHECK-MESSAGES: [[@LINE-1]]:5: warning: coroutine suspended with lock 'lock' held [cppcoreguideli

[PATCH] D154999: [clang-tidy] Add bugprone-std-forward-type-mismatch check

2023-08-03 Thread Chris Cotter via Phabricator via cfe-commits
ccotter added inline comments.



Comment at: 
clang-tools-extra/docs/clang-tidy/checks/bugprone/std-forward-type-mismatch.rst:18
+doSomething(std::forward(base)); // Incorrect usage
+doSomething(static_cast(base)); // Suggested usage
+  }

How confident are we to suggest a fixit to use `static_cast`? Although 
equivalent, the code could be incorrect to begin with and merit manual review 
to decide what the correct cast really should be.



Comment at: 
clang-tools-extra/test/clang-tidy/checkers/bugprone/std-forward-type-mismatch.cpp:116
+void testPartialTemplateBad(WrapperEx value) {
+  test(std::forward>(value));
+// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: using 'std::forward' for type 
conversions from 'WrapperEx' to 'Wrapper' is not recommended here, use 
'static_cast' instead

Does this check work if `testPartialTemplateBad` is not instantiated?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D154999

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


[PATCH] D140760: [clang-tidy] Support begin/end free functions in modernize-loop-convert

2023-08-03 Thread Chris Cotter via Phabricator via cfe-commits
ccotter updated this revision to Diff 546996.
ccotter added a comment.

rebase


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D140760

Files:
  clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/modernize/loop-convert.rst
  
clang-tools-extra/test/clang-tidy/checkers/modernize/Inputs/loop-convert/structures.h
  clang-tools-extra/test/clang-tidy/checkers/modernize/loop-convert-basic.cpp
  clang-tools-extra/test/clang-tidy/checkers/modernize/loop-convert-negative.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/modernize/loop-convert-negative.cpp
===
--- clang-tools-extra/test/clang-tidy/checkers/modernize/loop-convert-negative.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/modernize/loop-convert-negative.cpp
@@ -5,6 +5,22 @@
 // CHECK-FIXES-NOT: for ({{.*[^:]:[^:].*}})
 // CHECK-MESSAGES-NOT: modernize-loop-convert
 
+namespace somenamespace {
+  template  auto begin(T& t) -> decltype(t.begin());
+  template  auto begin(const T& t) -> decltype(t.begin());
+  template  auto end(T& t) -> decltype(t.end());
+  template  auto end(const T& t) -> decltype(t.end());
+  template  auto size(const T& t) -> decltype(t.size());
+} // namespace somenamespace
+
+struct SomeClass {
+  template  static auto begin(T& t) -> decltype(t.begin());
+  template  static auto begin(const T& t) -> decltype(t.begin());
+  template  static auto end(T& t) -> decltype(t.end());
+  template  static auto end(const T& t) -> decltype(t.end());
+  template  static auto size(const T& t) -> decltype(t.size());
+};
+
 namespace Negative {
 
 const int N = 6;
@@ -92,7 +108,7 @@
   }
 }
 
-}
+} // namespace Negative
 
 namespace NegativeIterator {
 
@@ -103,6 +119,10 @@
 struct BadBeginEnd : T {
   iterator notBegin();
   iterator notEnd();
+  iterator begin(int);
+  iterator end(int);
+  iterator begin();
+  iterator end();
 };
 
 void notBeginOrEnd() {
@@ -112,6 +132,9 @@
 
   for (T::iterator I = Bad.begin(), E = Bad.notEnd();  I != E; ++I)
 int K = *I;
+
+  for (T::iterator I = Bad.begin(0), E = Bad.end(0);  I != E; ++I)
+int K = *I;
 }
 
 void badLoopShapes() {
@@ -202,6 +225,8 @@
   T Other;
   for (T::iterator I = Tt.begin(), E = Other.end();  I != E; ++I)
 int K = *I;
+  for (T::iterator I = begin(Tt), E = end(Other);  I != E; ++I)
+int K = *I;
 
   for (T::iterator I = Other.begin(), E = Tt.end();  I != E; ++I)
 int K = *I;
@@ -214,6 +239,24 @@
 MutableVal K = *I;
 }
 
+void mixedMemberAndADL() {
+  for (T::iterator I = Tt.begin(), E = end(Tt);  I != E; ++I)
+int K = *I;
+  for (T::iterator I = begin(Tt), E = Tt.end();  I != E; ++I)
+int K = *I;
+  for (T::iterator I = std::begin(Tt), E = Tt.end();  I != E; ++I)
+int K = *I;
+  for (T::iterator I = std::begin(Tt), E = end(Tt);  I != E; ++I)
+int K = *I;
+}
+
+void nonADLOrStdCalls() {
+  for (T::iterator I = SomeClass::begin(Tt), E = SomeClass::end(Tt);  I != E; ++I)
+int K = *I;
+  for (T::iterator I = somenamespace::begin(Tt), E = somenamespace::end(Tt);  I != E; ++I)
+int K = *I;
+}
+
 void wrongIterators() {
   T::iterator Other;
   for (T::iterator I = Tt.begin(), E = Tt.end(); I != Other; ++I)
@@ -379,6 +422,13 @@
 Sum += V[I];
 }
 
+void nonADLOrStdCalls() {
+  for (int I = 0, E = somenamespace::size(V); E != I; ++I)
+printf("Fibonacci number is %d\n", V[I]);
+  for (int I = 0, E = SomeClass::size(V); E != I; ++I)
+printf("Fibonacci number is %d\n", V[I]);
+}
+
 // Checks to see that non-const member functions are not called on the container
 // object.
 // These could be conceivably allowed with a lower required confidence level.
Index: clang-tools-extra/test/clang-tidy/checkers/modernize/loop-convert-basic.cpp
===
--- clang-tools-extra/test/clang-tidy/checkers/modernize/loop-convert-basic.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/modernize/loop-convert-basic.cpp
@@ -445,6 +445,41 @@
   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
   // CHECK-FIXES: for (auto & I : Dpp)
   // CHECK-FIXES-NEXT: printf("%d\n", I->X);
+
+  for (S::iterator It = begin(Ss), E = end(Ss); It != E; ++It) {
+printf("s0 has value %d\n", (*It).X);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto & It : Ss)
+  // CHECK-FIXES-NEXT: printf("s0 has value %d\n", It.X);
+
+  for (S::iterator It = std::begin(Ss), E = std::end(Ss); It != E; ++It) {
+printf("s1 has value %d\n", (*It).X);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto & It : Ss)
+  // CHECK-FIXES-NEXT: printf("s1 has value %d\n", It.X);
+
+  for (S::iterator It = begin(*Ps), E = end(*Ps); It != E; ++It

[PATCH] D145138: [clang-tidy] Implement FixIts for C arrays

2023-08-03 Thread Chris Cotter via Phabricator via cfe-commits
ccotter updated this revision to Diff 546991.
ccotter marked an inline comment as done.
ccotter added a comment.

rebase


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D145138

Files:
  clang-tools-extra/clang-tidy/modernize/AvoidCArraysCheck.cpp
  clang-tools-extra/clang-tidy/modernize/AvoidCArraysCheck.h
  clang-tools-extra/clang-tidy/modernize/UseTrailingReturnTypeCheck.cpp
  clang-tools-extra/clang-tidy/modernize/UseTrailingReturnTypeCheck.h
  clang-tools-extra/clang-tidy/utils/CMakeLists.txt
  clang-tools-extra/clang-tidy/utils/LexerUtils.cpp
  clang-tools-extra/clang-tidy/utils/TypeUtils.cpp
  clang-tools-extra/clang-tidy/utils/TypeUtils.h
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/modernize/avoid-c-arrays.rst
  clang-tools-extra/test/clang-tidy/checkers/modernize/avoid-c-arrays-cxx17.cpp
  clang-tools-extra/test/clang-tidy/checkers/modernize/avoid-c-arrays.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/modernize/avoid-c-arrays.cpp
===
--- clang-tools-extra/test/clang-tidy/checkers/modernize/avoid-c-arrays.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/modernize/avoid-c-arrays.cpp
@@ -1,4 +1,6 @@
-// RUN: %check_clang_tidy %s modernize-avoid-c-arrays %t
+// RUN: %check_clang_tidy -std=c++11 %s modernize-avoid-c-arrays %t
+
+//CHECK-FIXES: #include 
 
 int a[] = {1, 2};
 // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: do not declare C-style arrays, use std::array<> instead
@@ -86,3 +88,280 @@
   int j[1];
 };
 }
+
+template  struct TStruct {};
+
+void replacements() {
+  int ar[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: std::array ar;
+  TStruct ar2[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: std::array, 10> ar2;
+  TStruct< int > ar3[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: std::array, 10> ar3;
+  int * ar4[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: std::array ar4;
+  int * /*comment*/ar5[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: std::array /*comment*/ar5;
+  volatile const int * ar6[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: std::array ar6;
+  volatile int ar7[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: volatile std::array ar7;
+  int const * ar8[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: std::array ar8;
+  int ar9[1];
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: std::array ar9;
+  static int volatile constexpr ar10[10] = {};
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: static volatile constexpr std::array ar10 = {{[{][{]}}{{[}][}]}};
+  thread_local int ar11[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: thread_local std::array ar11;
+  thread_local/*a*/int/*b*/ar12[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: thread_local/*a*/std::array/*b*/ar12;
+  /*a*/ int/*b*/ /*c*/*/*d*/ /*e*/ /*f*/ar13[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: /*a*/ std::array/*d*/ /*e*/ /*f*/ar13;
+  TStruct ar14[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: std::array, 10> ar14;
+  volatile TStruct ar15[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: volatile std::array, 10> ar15;
+  TStruct ar16[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: std::array, 10> ar16;
+  TStruct ar17[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: std::array, 10> ar17;
+  volatile int static thread_local * ar18[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: static thread_local std::array ar18;
+
+  // Note, there is a tab '\t' before the semicolon in the declaration below.
+  int ar19[3]	;
+  // 

[PATCH] D141892: [clang-tidy] Implement modernize-use-constraints

2023-07-30 Thread Chris Cotter via Phabricator via cfe-commits
ccotter marked an inline comment as done.
ccotter added a comment.

> 3. What about boost enable_if ? Support it, or restrict check to std only.
> 4. What about enable_if used as an function argument ? Support it, or add 
> some info to documentation that such construction is not supported.

I added some notes to the documentation on supported constructions and 
unsupported ones. The unsupported ones can be added; I intentionally did not 
support them in this initial version of the tool to keep the review simpler, 
although I'd like to add them soon after it lands.

If there are no other comments, @PiotrZSL would you mind landing this for me? 
Thanks!




Comment at: clang-tools-extra/clang-tidy/modernize/UseConstraintsCheck.cpp:352
+  FixIts.push_back(FixItHint::CreateInsertion(
+  *ConstraintInsertionLoc, "requires " + *ConditionText + " "));
+  return FixIts;

PiotrZSL wrote:
> You not checking anywhere if this optional is initialized.
Indeed - `bugprone-unchecked-optional-access` finds this!


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D141892

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


[PATCH] D141892: [clang-tidy] Implement modernize-use-constraints

2023-07-30 Thread Chris Cotter via Phabricator via cfe-commits
ccotter updated this revision to Diff 545450.
ccotter marked 5 inline comments as done.
ccotter added a comment.

- Improve docs, check for null/empty


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D141892

Files:
  clang-tools-extra/clang-tidy/modernize/CMakeLists.txt
  clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp
  clang-tools-extra/clang-tidy/modernize/UseConstraintsCheck.cpp
  clang-tools-extra/clang-tidy/modernize/UseConstraintsCheck.h
  clang-tools-extra/clang-tidy/utils/LexerUtils.cpp
  clang-tools-extra/clang-tidy/utils/LexerUtils.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-constraints.rst
  
clang-tools-extra/test/clang-tidy/checkers/modernize/use-constraints-first-greatergreater.cpp
  clang-tools-extra/test/clang-tidy/checkers/modernize/use-constraints.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/modernize/use-constraints.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/modernize/use-constraints.cpp
@@ -0,0 +1,726 @@
+// RUN: %check_clang_tidy -std=c++20 %s modernize-use-constraints %t -- -- -fno-delayed-template-parsing
+
+// NOLINTBEGIN
+namespace std {
+template  struct enable_if { };
+
+template  struct enable_if { typedef T type; };
+
+template 
+using enable_if_t = typename enable_if::type;
+
+} // namespace std
+// NOLINTEND
+
+template 
+struct ConsumeVariadic;
+
+struct Obj {
+};
+
+namespace enable_if_in_return_type {
+
+
+// Section 1: enable_if in return type of function
+
+
+
+// General tests
+
+
+template 
+typename std::enable_if::type basic() {
+  return Obj{};
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
+// CHECK-FIXES: {{^}}Obj basic() requires T::some_value {{{$}}
+
+template 
+std::enable_if_t basic_t() {
+  return Obj{};
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
+// CHECK-FIXES: {{^}}Obj basic_t() requires T::some_value {{{$}}
+
+template 
+auto basic_trailing() -> typename std::enable_if::type {
+  return Obj{};
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:26: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
+// CHECK-FIXES: {{^}}auto basic_trailing() -> Obj requires T::some_value {{{$}}
+
+template 
+typename std::enable_if::type existing_constraint() requires (T::another_value) {
+  return Obj{};
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
+// CHECK-FIXES: {{^}}typename std::enable_if::type existing_constraint() requires (T::another_value) {{{$}}
+
+template 
+typename std::enable_if::type decl_without_def();
+
+template 
+typename std::enable_if::type decl_with_separate_def();
+
+template 
+typename std::enable_if::type decl_with_separate_def() {
+  return Obj{};
+}
+// FIXME - Support definitions with separate decls
+
+template 
+std::enable_if_t no_dependent_type(U) {
+  return Obj{};
+}
+// FIXME - Support non-dependent enable_ifs. Low priority though...
+
+template 
+typename std::enable_if::type* pointer_of_enable_if() {
+  return nullptr;
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
+// CHECK-FIXES: {{^}}template {{$}}
+// CHECK-FIXES-NEXT: {{^}}int* pointer_of_enable_if() requires T::some_value {{{$}}
+
+template 
+std::enable_if_t* pointer_of_enable_if_t() {
+  return nullptr;
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
+// CHECK-FIXES: {{^}}template {{$}}
+// CHECK-FIXES-NEXT: {{^}}int* pointer_of_enable_if_t() requires T::some_value {{{$}}
+
+template 
+const std::enable_if_t* const_pointer_of_enable_if_t() {
+  return nullptr;
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:7: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
+// CHECK-FIXES: {{^}}template {{$}}
+// CHECK-FIXES-NEXT: {{^}}const int* const_pointer_of_enable_if_t() requires T::some_value {{{$}}
+
+template 
+std::enable_if_t const * const_pointer_of_enable_if_t2() {
+  return nullptr;
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
+// CHECK-FIXES: {{^}}template {{$}}
+// CHECK-FIXES-NEXT: {{^}}int const * const_pointer_of_enable_if_t2() requires T::some_value {{{$}}
+
+
+template 
+std::enable_if_t& reference_of_enable_if_t() {
+  static int x; return x;
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:1: warning: use C++20 requires

[PATCH] D141892: [clang-tidy] Implement modernize-use-constraints

2023-07-29 Thread Chris Cotter via Phabricator via cfe-commits
ccotter updated this revision to Diff 545379.
ccotter added a comment.

- Fix docs


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D141892

Files:
  clang-tools-extra/clang-tidy/modernize/CMakeLists.txt
  clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp
  clang-tools-extra/clang-tidy/modernize/UseConstraintsCheck.cpp
  clang-tools-extra/clang-tidy/modernize/UseConstraintsCheck.h
  clang-tools-extra/clang-tidy/utils/LexerUtils.cpp
  clang-tools-extra/clang-tidy/utils/LexerUtils.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-constraints.rst
  
clang-tools-extra/test/clang-tidy/checkers/modernize/use-constraints-first-greatergreater.cpp
  clang-tools-extra/test/clang-tidy/checkers/modernize/use-constraints.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/modernize/use-constraints.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/modernize/use-constraints.cpp
@@ -0,0 +1,726 @@
+// RUN: %check_clang_tidy -std=c++20 %s modernize-use-constraints %t -- -- -fno-delayed-template-parsing
+
+// NOLINTBEGIN
+namespace std {
+template  struct enable_if { };
+
+template  struct enable_if { typedef T type; };
+
+template 
+using enable_if_t = typename enable_if::type;
+
+} // namespace std
+// NOLINTEND
+
+template 
+struct ConsumeVariadic;
+
+struct Obj {
+};
+
+namespace enable_if_in_return_type {
+
+
+// Section 1: enable_if in return type of function
+
+
+
+// General tests
+
+
+template 
+typename std::enable_if::type basic() {
+  return Obj{};
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
+// CHECK-FIXES: {{^}}Obj basic() requires T::some_value {{{$}}
+
+template 
+std::enable_if_t basic_t() {
+  return Obj{};
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
+// CHECK-FIXES: {{^}}Obj basic_t() requires T::some_value {{{$}}
+
+template 
+auto basic_trailing() -> typename std::enable_if::type {
+  return Obj{};
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:26: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
+// CHECK-FIXES: {{^}}auto basic_trailing() -> Obj requires T::some_value {{{$}}
+
+template 
+typename std::enable_if::type existing_constraint() requires (T::another_value) {
+  return Obj{};
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
+// CHECK-FIXES: {{^}}typename std::enable_if::type existing_constraint() requires (T::another_value) {{{$}}
+
+template 
+typename std::enable_if::type decl_without_def();
+
+template 
+typename std::enable_if::type decl_with_separate_def();
+
+template 
+typename std::enable_if::type decl_with_separate_def() {
+  return Obj{};
+}
+// FIXME - Support definitions with separate decls
+
+template 
+std::enable_if_t no_dependent_type(U) {
+  return Obj{};
+}
+// FIXME - Support non-dependent enable_ifs. Low priority though...
+
+template 
+typename std::enable_if::type* pointer_of_enable_if() {
+  return nullptr;
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
+// CHECK-FIXES: {{^}}template {{$}}
+// CHECK-FIXES-NEXT: {{^}}int* pointer_of_enable_if() requires T::some_value {{{$}}
+
+template 
+std::enable_if_t* pointer_of_enable_if_t() {
+  return nullptr;
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
+// CHECK-FIXES: {{^}}template {{$}}
+// CHECK-FIXES-NEXT: {{^}}int* pointer_of_enable_if_t() requires T::some_value {{{$}}
+
+template 
+const std::enable_if_t* const_pointer_of_enable_if_t() {
+  return nullptr;
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:7: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
+// CHECK-FIXES: {{^}}template {{$}}
+// CHECK-FIXES-NEXT: {{^}}const int* const_pointer_of_enable_if_t() requires T::some_value {{{$}}
+
+template 
+std::enable_if_t const * const_pointer_of_enable_if_t2() {
+  return nullptr;
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
+// CHECK-FIXES: {{^}}template {{$}}
+// CHECK-FIXES-NEXT: {{^}}int const * const_pointer_of_enable_if_t2() requires T::some_value {{{$}}
+
+
+template 
+std::enable_if_t& reference_of_enable_if_t() {
+  static int x; return x;
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
+// CH

[PATCH] D141892: Implement modernize-use-constraints

2023-07-28 Thread Chris Cotter via Phabricator via cfe-commits
ccotter updated this revision to Diff 545332.
ccotter added a comment.

- Fix ReleaseNotes again


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D141892

Files:
  clang-tools-extra/clang-tidy/modernize/CMakeLists.txt
  clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp
  clang-tools-extra/clang-tidy/modernize/UseConstraintsCheck.cpp
  clang-tools-extra/clang-tidy/modernize/UseConstraintsCheck.h
  clang-tools-extra/clang-tidy/utils/LexerUtils.cpp
  clang-tools-extra/clang-tidy/utils/LexerUtils.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-constraints.rst
  
clang-tools-extra/test/clang-tidy/checkers/modernize/use-constraints-first-greatergreater.cpp
  clang-tools-extra/test/clang-tidy/checkers/modernize/use-constraints.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/modernize/use-constraints.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/modernize/use-constraints.cpp
@@ -0,0 +1,726 @@
+// RUN: %check_clang_tidy -std=c++20 %s modernize-use-constraints %t -- -- -fno-delayed-template-parsing
+
+// NOLINTBEGIN
+namespace std {
+template  struct enable_if { };
+
+template  struct enable_if { typedef T type; };
+
+template 
+using enable_if_t = typename enable_if::type;
+
+} // namespace std
+// NOLINTEND
+
+template 
+struct ConsumeVariadic;
+
+struct Obj {
+};
+
+namespace enable_if_in_return_type {
+
+
+// Section 1: enable_if in return type of function
+
+
+
+// General tests
+
+
+template 
+typename std::enable_if::type basic() {
+  return Obj{};
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
+// CHECK-FIXES: {{^}}Obj basic() requires T::some_value {{{$}}
+
+template 
+std::enable_if_t basic_t() {
+  return Obj{};
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
+// CHECK-FIXES: {{^}}Obj basic_t() requires T::some_value {{{$}}
+
+template 
+auto basic_trailing() -> typename std::enable_if::type {
+  return Obj{};
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:26: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
+// CHECK-FIXES: {{^}}auto basic_trailing() -> Obj requires T::some_value {{{$}}
+
+template 
+typename std::enable_if::type existing_constraint() requires (T::another_value) {
+  return Obj{};
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
+// CHECK-FIXES: {{^}}typename std::enable_if::type existing_constraint() requires (T::another_value) {{{$}}
+
+template 
+typename std::enable_if::type decl_without_def();
+
+template 
+typename std::enable_if::type decl_with_separate_def();
+
+template 
+typename std::enable_if::type decl_with_separate_def() {
+  return Obj{};
+}
+// FIXME - Support definitions with separate decls
+
+template 
+std::enable_if_t no_dependent_type(U) {
+  return Obj{};
+}
+// FIXME - Support non-dependent enable_ifs. Low priority though...
+
+template 
+typename std::enable_if::type* pointer_of_enable_if() {
+  return nullptr;
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
+// CHECK-FIXES: {{^}}template {{$}}
+// CHECK-FIXES-NEXT: {{^}}int* pointer_of_enable_if() requires T::some_value {{{$}}
+
+template 
+std::enable_if_t* pointer_of_enable_if_t() {
+  return nullptr;
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
+// CHECK-FIXES: {{^}}template {{$}}
+// CHECK-FIXES-NEXT: {{^}}int* pointer_of_enable_if_t() requires T::some_value {{{$}}
+
+template 
+const std::enable_if_t* const_pointer_of_enable_if_t() {
+  return nullptr;
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:7: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
+// CHECK-FIXES: {{^}}template {{$}}
+// CHECK-FIXES-NEXT: {{^}}const int* const_pointer_of_enable_if_t() requires T::some_value {{{$}}
+
+template 
+std::enable_if_t const * const_pointer_of_enable_if_t2() {
+  return nullptr;
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
+// CHECK-FIXES: {{^}}template {{$}}
+// CHECK-FIXES-NEXT: {{^}}int const * const_pointer_of_enable_if_t2() requires T::some_value {{{$}}
+
+
+template 
+std::enable_if_t& reference_of_enable_if_t() {
+  static int x; return x;
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-const

[PATCH] D141892: Implement modernize-use-constraints

2023-07-28 Thread Chris Cotter via Phabricator via cfe-commits
ccotter updated this revision to Diff 545331.
ccotter added a comment.

rebase


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D141892

Files:
  clang-tools-extra/clang-tidy/modernize/CMakeLists.txt
  clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp
  clang-tools-extra/clang-tidy/modernize/UseConstraintsCheck.cpp
  clang-tools-extra/clang-tidy/modernize/UseConstraintsCheck.h
  clang-tools-extra/clang-tidy/utils/LexerUtils.cpp
  clang-tools-extra/clang-tidy/utils/LexerUtils.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-constraints.rst
  
clang-tools-extra/test/clang-tidy/checkers/modernize/use-constraints-first-greatergreater.cpp
  clang-tools-extra/test/clang-tidy/checkers/modernize/use-constraints.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/modernize/use-constraints.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/modernize/use-constraints.cpp
@@ -0,0 +1,726 @@
+// RUN: %check_clang_tidy -std=c++20 %s modernize-use-constraints %t -- -- -fno-delayed-template-parsing
+
+// NOLINTBEGIN
+namespace std {
+template  struct enable_if { };
+
+template  struct enable_if { typedef T type; };
+
+template 
+using enable_if_t = typename enable_if::type;
+
+} // namespace std
+// NOLINTEND
+
+template 
+struct ConsumeVariadic;
+
+struct Obj {
+};
+
+namespace enable_if_in_return_type {
+
+
+// Section 1: enable_if in return type of function
+
+
+
+// General tests
+
+
+template 
+typename std::enable_if::type basic() {
+  return Obj{};
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
+// CHECK-FIXES: {{^}}Obj basic() requires T::some_value {{{$}}
+
+template 
+std::enable_if_t basic_t() {
+  return Obj{};
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
+// CHECK-FIXES: {{^}}Obj basic_t() requires T::some_value {{{$}}
+
+template 
+auto basic_trailing() -> typename std::enable_if::type {
+  return Obj{};
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:26: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
+// CHECK-FIXES: {{^}}auto basic_trailing() -> Obj requires T::some_value {{{$}}
+
+template 
+typename std::enable_if::type existing_constraint() requires (T::another_value) {
+  return Obj{};
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
+// CHECK-FIXES: {{^}}typename std::enable_if::type existing_constraint() requires (T::another_value) {{{$}}
+
+template 
+typename std::enable_if::type decl_without_def();
+
+template 
+typename std::enable_if::type decl_with_separate_def();
+
+template 
+typename std::enable_if::type decl_with_separate_def() {
+  return Obj{};
+}
+// FIXME - Support definitions with separate decls
+
+template 
+std::enable_if_t no_dependent_type(U) {
+  return Obj{};
+}
+// FIXME - Support non-dependent enable_ifs. Low priority though...
+
+template 
+typename std::enable_if::type* pointer_of_enable_if() {
+  return nullptr;
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
+// CHECK-FIXES: {{^}}template {{$}}
+// CHECK-FIXES-NEXT: {{^}}int* pointer_of_enable_if() requires T::some_value {{{$}}
+
+template 
+std::enable_if_t* pointer_of_enable_if_t() {
+  return nullptr;
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
+// CHECK-FIXES: {{^}}template {{$}}
+// CHECK-FIXES-NEXT: {{^}}int* pointer_of_enable_if_t() requires T::some_value {{{$}}
+
+template 
+const std::enable_if_t* const_pointer_of_enable_if_t() {
+  return nullptr;
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:7: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
+// CHECK-FIXES: {{^}}template {{$}}
+// CHECK-FIXES-NEXT: {{^}}const int* const_pointer_of_enable_if_t() requires T::some_value {{{$}}
+
+template 
+std::enable_if_t const * const_pointer_of_enable_if_t2() {
+  return nullptr;
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
+// CHECK-FIXES: {{^}}template {{$}}
+// CHECK-FIXES-NEXT: {{^}}int const * const_pointer_of_enable_if_t2() requires T::some_value {{{$}}
+
+
+template 
+std::enable_if_t& reference_of_enable_if_t() {
+  static int x; return x;
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
+// CHECK-

[PATCH] D144347: [clang-tidy] Add readability-forward-usage check

2023-07-03 Thread Chris Cotter via Phabricator via cfe-commits
ccotter added a comment.

Great, thanks!


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D144347

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


[PATCH] D144347: [clang-tidy] Add readability-forward-usage check

2023-07-03 Thread Chris Cotter via Phabricator via cfe-commits
ccotter added a comment.

@PiotrZSL - checking back, do you plan to revisit this change soon (I think 
there are some pending feedback and you planned some changes)? I'd like to see 
this in change merged in. Let me know if I can help.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D144347

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


[PATCH] D143971: [clang-tidy] Flag more buggy string constructor cases

2023-06-11 Thread Chris Cotter via Phabricator via cfe-commits
ccotter added a comment.

Thanks, fixed the first false positive example you gave. Let me think about the 
second example in your most recent post:

  char c = '\n';
  using Size = int;
  Size size = 10U;
  std::string str2(c, size);

This is my newly added case `swapped4`, where one of my original intents was to 
flag this code as "swapped."  I can see the the ambiguity. Worst case, 
"confusing string fill constructor arguments" is the fallback that I think is 
acceptable, and still achieves the goal of at least flagging the code as 
potentially buggy.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D143971

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


[PATCH] D143971: [clang-tidy] Flag more buggy string constructor cases

2023-06-11 Thread Chris Cotter via Phabricator via cfe-commits
ccotter updated this revision to Diff 530349.
ccotter added a comment.

- Exclude false positive


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D143971

Files:
  clang-tools-extra/clang-tidy/bugprone/StringConstructorCheck.cpp
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/bugprone/string-constructor.rst
  clang-tools-extra/test/clang-tidy/checkers/bugprone/string-constructor.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/bugprone/string-constructor.cpp
===
--- clang-tools-extra/test/clang-tidy/checkers/bugprone/string-constructor.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/bugprone/string-constructor.cpp
@@ -5,12 +5,13 @@
 class allocator {};
 template 
 class char_traits {};
-template , typename A = std::allocator >
+template , typename A = std::allocator>
 struct basic_string {
   basic_string();
-  basic_string(const C*, unsigned int size);
-  basic_string(const C *, const A &allocator = A());
-  basic_string(unsigned int size, C c);
+  basic_string(const basic_string&, unsigned int, unsigned int, const A & = A());
+  basic_string(const C*, unsigned int);
+  basic_string(const C*, const A& = A());
+  basic_string(unsigned int, C);
 };
 typedef basic_string string;
 typedef basic_string wstring;
@@ -18,7 +19,7 @@
 template >
 struct basic_string_view {
   basic_string_view();
-  basic_string_view(const C *, unsigned int size);
+  basic_string_view(const C *, unsigned int);
   basic_string_view(const C *);
 };
 typedef basic_string_view string_view;
@@ -28,20 +29,76 @@
 const char* kText = "";
 const char kText2[] = "";
 extern const char kText3[];
+char getChar();
+const char* getCharPtr();
+
+struct CharLikeObj {
+  operator char() const;
+};
+
+unsigned char getUChar();
 
 void Test() {
-  std::string str('x', 4);
-  // CHECK-MESSAGES: [[@LINE-1]]:15: warning: string constructor parameters are probably swapped; expecting string(count, character) [bugprone-string-constructor]
-  // CHECK-FIXES: std::string str(4, 'x');
-  std::wstring wstr(L'x', 4);
-  // CHECK-MESSAGES: [[@LINE-1]]:16: warning: string constructor parameters are probably swapped
-  // CHECK-FIXES: std::wstring wstr(4, L'x');
+  short sh;
+  int i;
+  int& ref_i = i;
+  char ch;
+  CharLikeObj char_like_obj;
+
+  std::string swapped('x', 4);
+  // CHECK-MESSAGES: [[@LINE-1]]:15: warning: string constructor arguments are probably swapped; expecting string(count, character) [bugprone-string-constructor]
+  // CHECK-FIXES: std::string swapped(4, 'x');
+  std::wstring wswapped(L'x', 4);
+  // CHECK-MESSAGES: [[@LINE-1]]:16: warning: string constructor arguments are probably swapped; expecting string(count, character) [bugprone-string-constructor]
+  // CHECK-FIXES: std::wstring wswapped(4, L'x');
+  std::string swapped2('x', i);
+  // CHECK-MESSAGES: [[@LINE-1]]:15: warning: string constructor arguments are probably swapped; expecting string(count, character) [bugprone-string-constructor]
+  // CHECK-FIXES: std::string swapped2(i, 'x');
+  std::string swapped3(ch, 4);
+  // CHECK-MESSAGES: [[@LINE-1]]:15: warning: string constructor arguments are probably swapped; expecting string(count, character) [bugprone-string-constructor]
+  // CHECK-FIXES: std::string swapped3(4, ch);
+  std::string swapped4(ch, i);
+  // CHECK-MESSAGES: [[@LINE-1]]:15: warning: string constructor arguments are probably swapped; expecting string(count, character) [bugprone-string-constructor]
+  // CHECK-FIXES: std::string swapped4(i, ch);
+  std::string swapped5('x', (int)'x');
+  // CHECK-MESSAGES: [[@LINE-1]]:15: warning: string constructor arguments are probably swapped; expecting string(count, character) [bugprone-string-constructor]
+  // CHECK-FIXES: std::string swapped5((int)'x', 'x');
+  std::string swapped6(getChar(), 10);
+  // CHECK-MESSAGES: [[@LINE-1]]:15: warning: string constructor arguments are probably swapped; expecting string(count, character) [bugprone-string-constructor]
+  // CHECK-FIXES: std::string swapped6(10, getChar());
+  std::string swapped7((('x')), ( i ));
+  // CHECK-MESSAGES: [[@LINE-1]]:15: warning: string constructor arguments are probably swapped; expecting string(count, character) [bugprone-string-constructor]
+  // CHECK-FIXES: std::string swapped7(( i ), (('x')));
+  std::string swapped8((ch), (i));
+  // CHECK-MESSAGES: [[@LINE-1]]:15: warning: string constructor arguments are probably swapped; expecting string(count, character) [bugprone-string-constructor]
+  // CHECK-FIXES: std::string swapped8((i), (ch));
+  std::string swapped9((getChar()), (i));
+  // CHECK-MESSAGES: [[@LINE-1]]:15: warning: string constructor arguments are probably swapped; expecting string(count, character) [bugprone-string-constructor]
+  // CHECK-FIXES: std::string swapped9((i), (getChar()));
   std::string s0(0, 'x');
   // CHECK-MESSAGES: [[@LINE-1]

[PATCH] D143971: [clang-tidy] Flag more buggy string constructor cases

2023-06-10 Thread Chris Cotter via Phabricator via cfe-commits
ccotter added a comment.

bump please?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D143971

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


[PATCH] D141892: Implement modernize-use-constraints

2023-05-21 Thread Chris Cotter via Phabricator via cfe-commits
ccotter added a comment.

bump - @njames93 let me know if you have any further feedback. thanks!


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D141892

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


[PATCH] D140760: [clang-tidy] Support begin/end free functions in modernize-loop-convert

2023-05-07 Thread Chris Cotter via Phabricator via cfe-commits
ccotter updated this revision to Diff 520237.
ccotter marked an inline comment as done.
ccotter added a comment.

- Fix compile for non-libc++


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D140760

Files:
  clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/modernize/loop-convert.rst
  
clang-tools-extra/test/clang-tidy/checkers/modernize/Inputs/loop-convert/structures.h
  clang-tools-extra/test/clang-tidy/checkers/modernize/loop-convert-basic.cpp
  clang-tools-extra/test/clang-tidy/checkers/modernize/loop-convert-negative.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/modernize/loop-convert-negative.cpp
===
--- clang-tools-extra/test/clang-tidy/checkers/modernize/loop-convert-negative.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/modernize/loop-convert-negative.cpp
@@ -5,6 +5,22 @@
 // CHECK-FIXES-NOT: for ({{.*[^:]:[^:].*}})
 // CHECK-MESSAGES-NOT: modernize-loop-convert
 
+namespace somenamespace {
+  template  auto begin(T& t) -> decltype(t.begin());
+  template  auto begin(const T& t) -> decltype(t.begin());
+  template  auto end(T& t) -> decltype(t.end());
+  template  auto end(const T& t) -> decltype(t.end());
+  template  auto size(const T& t) -> decltype(t.size());
+} // namespace somenamespace
+
+struct SomeClass {
+  template  static auto begin(T& t) -> decltype(t.begin());
+  template  static auto begin(const T& t) -> decltype(t.begin());
+  template  static auto end(T& t) -> decltype(t.end());
+  template  static auto end(const T& t) -> decltype(t.end());
+  template  static auto size(const T& t) -> decltype(t.size());
+};
+
 namespace Negative {
 
 const int N = 6;
@@ -92,7 +108,7 @@
   }
 }
 
-}
+} // namespace Negative
 
 namespace NegativeIterator {
 
@@ -103,6 +119,10 @@
 struct BadBeginEnd : T {
   iterator notBegin();
   iterator notEnd();
+  iterator begin(int);
+  iterator end(int);
+  iterator begin();
+  iterator end();
 };
 
 void notBeginOrEnd() {
@@ -112,6 +132,9 @@
 
   for (T::iterator I = Bad.begin(), E = Bad.notEnd();  I != E; ++I)
 int K = *I;
+
+  for (T::iterator I = Bad.begin(0), E = Bad.end(0);  I != E; ++I)
+int K = *I;
 }
 
 void badLoopShapes() {
@@ -202,6 +225,8 @@
   T Other;
   for (T::iterator I = Tt.begin(), E = Other.end();  I != E; ++I)
 int K = *I;
+  for (T::iterator I = begin(Tt), E = end(Other);  I != E; ++I)
+int K = *I;
 
   for (T::iterator I = Other.begin(), E = Tt.end();  I != E; ++I)
 int K = *I;
@@ -214,6 +239,24 @@
 MutableVal K = *I;
 }
 
+void mixedMemberAndADL() {
+  for (T::iterator I = Tt.begin(), E = end(Tt);  I != E; ++I)
+int K = *I;
+  for (T::iterator I = begin(Tt), E = Tt.end();  I != E; ++I)
+int K = *I;
+  for (T::iterator I = std::begin(Tt), E = Tt.end();  I != E; ++I)
+int K = *I;
+  for (T::iterator I = std::begin(Tt), E = end(Tt);  I != E; ++I)
+int K = *I;
+}
+
+void nonADLOrStdCalls() {
+  for (T::iterator I = SomeClass::begin(Tt), E = SomeClass::end(Tt);  I != E; ++I)
+int K = *I;
+  for (T::iterator I = somenamespace::begin(Tt), E = somenamespace::end(Tt);  I != E; ++I)
+int K = *I;
+}
+
 void wrongIterators() {
   T::iterator Other;
   for (T::iterator I = Tt.begin(), E = Tt.end(); I != Other; ++I)
@@ -379,6 +422,13 @@
 Sum += V[I];
 }
 
+void nonADLOrStdCalls() {
+  for (int I = 0, E = somenamespace::size(V); E != I; ++I)
+printf("Fibonacci number is %d\n", V[I]);
+  for (int I = 0, E = SomeClass::size(V); E != I; ++I)
+printf("Fibonacci number is %d\n", V[I]);
+}
+
 // Checks to see that non-const member functions are not called on the container
 // object.
 // These could be conceivably allowed with a lower required confidence level.
Index: clang-tools-extra/test/clang-tidy/checkers/modernize/loop-convert-basic.cpp
===
--- clang-tools-extra/test/clang-tidy/checkers/modernize/loop-convert-basic.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/modernize/loop-convert-basic.cpp
@@ -445,6 +445,41 @@
   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
   // CHECK-FIXES: for (auto & I : Dpp)
   // CHECK-FIXES-NEXT: printf("%d\n", I->X);
+
+  for (S::iterator It = begin(Ss), E = end(Ss); It != E; ++It) {
+printf("s0 has value %d\n", (*It).X);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto & It : Ss)
+  // CHECK-FIXES-NEXT: printf("s0 has value %d\n", It.X);
+
+  for (S::iterator It = std::begin(Ss), E = std::end(Ss); It != E; ++It) {
+printf("s1 has value %d\n", (*It).X);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto & It : Ss)
+  // CHECK-FIXES-NEXT: printf("s1 has value %d\n", It.X);
+

[PATCH] D140760: [clang-tidy] Support begin/end free functions in modernize-loop-convert

2023-05-07 Thread Chris Cotter via Phabricator via cfe-commits
ccotter marked an inline comment as done.
ccotter added inline comments.



Comment at: 
clang-tools-extra/test/clang-tidy/checkers/modernize/loop-convert-basic.cpp:481
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto It : Ss)
+  // CHECK-FIXES-NEXT: printf("s4 has value %d\n", It.X);

PiotrZSL wrote:
> shouldnt it be `const& It` ?
Looks like when the object is trivial to copy (`IsCheapToCopy` logic in the 
check), `auto It` is used instead of `const auto& It`


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D140760

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


[PATCH] D140760: [clang-tidy] Support begin/end free functions in modernize-loop-convert

2023-05-07 Thread Chris Cotter via Phabricator via cfe-commits
ccotter updated this revision to Diff 520232.
ccotter added a comment.

Feedback and rebase


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D140760

Files:
  clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/modernize/loop-convert.rst
  
clang-tools-extra/test/clang-tidy/checkers/modernize/Inputs/loop-convert/structures.h
  clang-tools-extra/test/clang-tidy/checkers/modernize/loop-convert-basic.cpp
  clang-tools-extra/test/clang-tidy/checkers/modernize/loop-convert-negative.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/modernize/loop-convert-negative.cpp
===
--- clang-tools-extra/test/clang-tidy/checkers/modernize/loop-convert-negative.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/modernize/loop-convert-negative.cpp
@@ -5,6 +5,22 @@
 // CHECK-FIXES-NOT: for ({{.*[^:]:[^:].*}})
 // CHECK-MESSAGES-NOT: modernize-loop-convert
 
+namespace somenamespace {
+  template  auto begin(T& t) -> decltype(t.begin());
+  template  auto begin(const T& t) -> decltype(t.begin());
+  template  auto end(T& t) -> decltype(t.end());
+  template  auto end(const T& t) -> decltype(t.end());
+  template  auto size(const T& t) -> decltype(t.size());
+} // namespace somenamespace
+
+struct SomeClass {
+  template  static auto begin(T& t) -> decltype(t.begin());
+  template  static auto begin(const T& t) -> decltype(t.begin());
+  template  static auto end(T& t) -> decltype(t.end());
+  template  static auto end(const T& t) -> decltype(t.end());
+  template  static auto size(const T& t) -> decltype(t.size());
+};
+
 namespace Negative {
 
 const int N = 6;
@@ -92,7 +108,7 @@
   }
 }
 
-}
+} // namespace Negative
 
 namespace NegativeIterator {
 
@@ -103,6 +119,10 @@
 struct BadBeginEnd : T {
   iterator notBegin();
   iterator notEnd();
+  iterator begin(int);
+  iterator end(int);
+  iterator begin();
+  iterator end();
 };
 
 void notBeginOrEnd() {
@@ -112,6 +132,9 @@
 
   for (T::iterator I = Bad.begin(), E = Bad.notEnd();  I != E; ++I)
 int K = *I;
+
+  for (T::iterator I = Bad.begin(0), E = Bad.end(0);  I != E; ++I)
+int K = *I;
 }
 
 void badLoopShapes() {
@@ -202,6 +225,8 @@
   T Other;
   for (T::iterator I = Tt.begin(), E = Other.end();  I != E; ++I)
 int K = *I;
+  for (T::iterator I = begin(Tt), E = end(Other);  I != E; ++I)
+int K = *I;
 
   for (T::iterator I = Other.begin(), E = Tt.end();  I != E; ++I)
 int K = *I;
@@ -214,6 +239,24 @@
 MutableVal K = *I;
 }
 
+void mixedMemberAndADL() {
+  for (T::iterator I = Tt.begin(), E = end(Tt);  I != E; ++I)
+int K = *I;
+  for (T::iterator I = begin(Tt), E = Tt.end();  I != E; ++I)
+int K = *I;
+  for (T::iterator I = std::begin(Tt), E = Tt.end();  I != E; ++I)
+int K = *I;
+  for (T::iterator I = std::begin(Tt), E = end(Tt);  I != E; ++I)
+int K = *I;
+}
+
+void nonADLOrStdCalls() {
+  for (T::iterator I = SomeClass::begin(Tt), E = SomeClass::end(Tt);  I != E; ++I)
+int K = *I;
+  for (T::iterator I = somenamespace::begin(Tt), E = somenamespace::end(Tt);  I != E; ++I)
+int K = *I;
+}
+
 void wrongIterators() {
   T::iterator Other;
   for (T::iterator I = Tt.begin(), E = Tt.end(); I != Other; ++I)
@@ -379,6 +422,13 @@
 Sum += V[I];
 }
 
+void nonADLOrStdCalls() {
+  for (int I = 0, E = somenamespace::size(V); E != I; ++I)
+printf("Fibonacci number is %d\n", V[I]);
+  for (int I = 0, E = SomeClass::size(V); E != I; ++I)
+printf("Fibonacci number is %d\n", V[I]);
+}
+
 // Checks to see that non-const member functions are not called on the container
 // object.
 // These could be conceivably allowed with a lower required confidence level.
Index: clang-tools-extra/test/clang-tidy/checkers/modernize/loop-convert-basic.cpp
===
--- clang-tools-extra/test/clang-tidy/checkers/modernize/loop-convert-basic.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/modernize/loop-convert-basic.cpp
@@ -445,6 +445,41 @@
   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
   // CHECK-FIXES: for (auto & I : Dpp)
   // CHECK-FIXES-NEXT: printf("%d\n", I->X);
+
+  for (S::iterator It = begin(Ss), E = end(Ss); It != E; ++It) {
+printf("s0 has value %d\n", (*It).X);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto & It : Ss)
+  // CHECK-FIXES-NEXT: printf("s0 has value %d\n", It.X);
+
+  for (S::iterator It = std::begin(Ss), E = std::end(Ss); It != E; ++It) {
+printf("s1 has value %d\n", (*It).X);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto & It : Ss)
+  // CHECK-FIXES-NEXT: printf("s1 has value %d\n", It.X);
+
+  for (S::iterator It = begin(*Ps), E = end(*Ps); 

[PATCH] D140760: [clang-tidy] Support begin/end free functions in modernize-loop-convert

2023-05-07 Thread Chris Cotter via Phabricator via cfe-commits
ccotter marked 10 inline comments as done.
ccotter added inline comments.



Comment at: 
clang-tools-extra/test/clang-tidy/checkers/modernize/loop-convert-basic.cpp:477
+
+  for (S::const_iterator It = cbegin(Ss), E = cend(Ss); It != E; ++It) {
+printf("s4 has value %d\n", (*It).X);

PiotrZSL wrote:
> what if begin,end is missing, and there is only cbegin, cend then it will 
> fail with:
> "error: invalid range expression of type 'const A'; no viable 'begin' 
> function available|
> 
This looks to be an already existing bug in the check - mind if I fix that in a 
separate phab?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D140760

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


[PATCH] D143971: [clang-tidy] Flag more buggy string constructor cases

2023-05-06 Thread Chris Cotter via Phabricator via cfe-commits
ccotter added a comment.

bump please?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D143971

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


[PATCH] D143971: [clang-tidy] Flag more buggy string constructor cases

2023-05-06 Thread Chris Cotter via Phabricator via cfe-commits
ccotter updated this revision to Diff 520143.
ccotter added a comment.

rebase


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D143971

Files:
  clang-tools-extra/clang-tidy/bugprone/StringConstructorCheck.cpp
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/bugprone/string-constructor.rst
  clang-tools-extra/test/clang-tidy/checkers/bugprone/string-constructor.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/bugprone/string-constructor.cpp
===
--- clang-tools-extra/test/clang-tidy/checkers/bugprone/string-constructor.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/bugprone/string-constructor.cpp
@@ -5,12 +5,13 @@
 class allocator {};
 template 
 class char_traits {};
-template , typename A = std::allocator >
+template , typename A = std::allocator>
 struct basic_string {
   basic_string();
-  basic_string(const C*, unsigned int size);
-  basic_string(const C *, const A &allocator = A());
-  basic_string(unsigned int size, C c);
+  basic_string(const basic_string&, unsigned int, unsigned int, const A & = A());
+  basic_string(const C*, unsigned int);
+  basic_string(const C*, const A& = A());
+  basic_string(unsigned int, C);
 };
 typedef basic_string string;
 typedef basic_string wstring;
@@ -18,7 +19,7 @@
 template >
 struct basic_string_view {
   basic_string_view();
-  basic_string_view(const C *, unsigned int size);
+  basic_string_view(const C *, unsigned int);
   basic_string_view(const C *);
 };
 typedef basic_string_view string_view;
@@ -28,20 +29,74 @@
 const char* kText = "";
 const char kText2[] = "";
 extern const char kText3[];
+char getChar();
+const char* getCharPtr();
+
+struct CharLikeObj {
+  operator char() const;
+};
 
 void Test() {
-  std::string str('x', 4);
-  // CHECK-MESSAGES: [[@LINE-1]]:15: warning: string constructor parameters are probably swapped; expecting string(count, character) [bugprone-string-constructor]
-  // CHECK-FIXES: std::string str(4, 'x');
-  std::wstring wstr(L'x', 4);
-  // CHECK-MESSAGES: [[@LINE-1]]:16: warning: string constructor parameters are probably swapped
-  // CHECK-FIXES: std::wstring wstr(4, L'x');
+  short sh;
+  int i;
+  int& ref_i = i;
+  char ch;
+  CharLikeObj char_like_obj;
+
+  std::string swapped('x', 4);
+  // CHECK-MESSAGES: [[@LINE-1]]:15: warning: string constructor arguments are probably swapped; expecting string(count, character) [bugprone-string-constructor]
+  // CHECK-FIXES: std::string swapped(4, 'x');
+  std::wstring wswapped(L'x', 4);
+  // CHECK-MESSAGES: [[@LINE-1]]:16: warning: string constructor arguments are probably swapped; expecting string(count, character) [bugprone-string-constructor]
+  // CHECK-FIXES: std::wstring wswapped(4, L'x');
+  std::string swapped2('x', i);
+  // CHECK-MESSAGES: [[@LINE-1]]:15: warning: string constructor arguments are probably swapped; expecting string(count, character) [bugprone-string-constructor]
+  // CHECK-FIXES: std::string swapped2(i, 'x');
+  std::string swapped3(ch, 4);
+  // CHECK-MESSAGES: [[@LINE-1]]:15: warning: string constructor arguments are probably swapped; expecting string(count, character) [bugprone-string-constructor]
+  // CHECK-FIXES: std::string swapped3(4, ch);
+  std::string swapped4(ch, i);
+  // CHECK-MESSAGES: [[@LINE-1]]:15: warning: string constructor arguments are probably swapped; expecting string(count, character) [bugprone-string-constructor]
+  // CHECK-FIXES: std::string swapped4(i, ch);
+  std::string swapped5('x', (int)'x');
+  // CHECK-MESSAGES: [[@LINE-1]]:15: warning: string constructor arguments are probably swapped; expecting string(count, character) [bugprone-string-constructor]
+  // CHECK-FIXES: std::string swapped5((int)'x', 'x');
+  std::string swapped6(getChar(), 10);
+  // CHECK-MESSAGES: [[@LINE-1]]:15: warning: string constructor arguments are probably swapped; expecting string(count, character) [bugprone-string-constructor]
+  // CHECK-FIXES: std::string swapped6(10, getChar());
+  std::string swapped7((('x')), ( i ));
+  // CHECK-MESSAGES: [[@LINE-1]]:15: warning: string constructor arguments are probably swapped; expecting string(count, character) [bugprone-string-constructor]
+  // CHECK-FIXES: std::string swapped7(( i ), (('x')));
+  std::string swapped8((ch), (i));
+  // CHECK-MESSAGES: [[@LINE-1]]:15: warning: string constructor arguments are probably swapped; expecting string(count, character) [bugprone-string-constructor]
+  // CHECK-FIXES: std::string swapped8((i), (ch));
+  std::string swapped9((getChar()), (i));
+  // CHECK-MESSAGES: [[@LINE-1]]:15: warning: string constructor arguments are probably swapped; expecting string(count, character) [bugprone-string-constructor]
+  // CHECK-FIXES: std::string swapped9((i), (getChar()));
   std::string s0(0, 'x');
   // CHECK-MESSAGES: [[@LINE-1]]:15: warning: constructor creating an empty st

[PATCH] D141892: Implement modernize-use-constraints

2023-05-06 Thread Chris Cotter via Phabricator via cfe-commits
ccotter added a comment.

Addressed all comments except for the `handleReturnType` one which I responded 
to - let me know your thoughts, thanks!


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D141892

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


[PATCH] D141892: Implement modernize-use-constraints

2023-05-06 Thread Chris Cotter via Phabricator via cfe-commits
ccotter updated this revision to Diff 520125.
ccotter added a comment.

- Better handling for ctor inits


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D141892

Files:
  clang-tools-extra/clang-tidy/modernize/CMakeLists.txt
  clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp
  clang-tools-extra/clang-tidy/modernize/UseConstraintsCheck.cpp
  clang-tools-extra/clang-tidy/modernize/UseConstraintsCheck.h
  clang-tools-extra/clang-tidy/utils/LexerUtils.cpp
  clang-tools-extra/clang-tidy/utils/LexerUtils.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-constraints.rst
  
clang-tools-extra/test/clang-tidy/checkers/modernize/use-constraints-first-greatergreater.cpp
  clang-tools-extra/test/clang-tidy/checkers/modernize/use-constraints.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/modernize/use-constraints.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/modernize/use-constraints.cpp
@@ -0,0 +1,726 @@
+// RUN: %check_clang_tidy -std=c++20 %s modernize-use-constraints %t -- -- -fno-delayed-template-parsing
+
+// NOLINTBEGIN
+namespace std {
+template  struct enable_if { };
+
+template  struct enable_if { typedef T type; };
+
+template 
+using enable_if_t = typename enable_if::type;
+
+} // namespace std
+// NOLINTEND
+
+template 
+struct ConsumeVariadic;
+
+struct Obj {
+};
+
+namespace enable_if_in_return_type {
+
+
+// Section 1: enable_if in return type of function
+
+
+
+// General tests
+
+
+template 
+typename std::enable_if::type basic() {
+  return Obj{};
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
+// CHECK-FIXES: {{^}}Obj basic() requires T::some_value {{{$}}
+
+template 
+std::enable_if_t basic_t() {
+  return Obj{};
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
+// CHECK-FIXES: {{^}}Obj basic_t() requires T::some_value {{{$}}
+
+template 
+auto basic_trailing() -> typename std::enable_if::type {
+  return Obj{};
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:26: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
+// CHECK-FIXES: {{^}}auto basic_trailing() -> Obj requires T::some_value {{{$}}
+
+template 
+typename std::enable_if::type existing_constraint() requires (T::another_value) {
+  return Obj{};
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
+// CHECK-FIXES: {{^}}typename std::enable_if::type existing_constraint() requires (T::another_value) {{{$}}
+
+template 
+typename std::enable_if::type decl_without_def();
+
+template 
+typename std::enable_if::type decl_with_separate_def();
+
+template 
+typename std::enable_if::type decl_with_separate_def() {
+  return Obj{};
+}
+// FIXME - Support definitions with separate decls
+
+template 
+std::enable_if_t no_dependent_type(U) {
+  return Obj{};
+}
+// FIXME - Support non-dependent enable_ifs. Low priority though...
+
+template 
+typename std::enable_if::type* pointer_of_enable_if() {
+  return nullptr;
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
+// CHECK-FIXES: {{^}}template {{$}}
+// CHECK-FIXES-NEXT: {{^}}int* pointer_of_enable_if() requires T::some_value {{{$}}
+
+template 
+std::enable_if_t* pointer_of_enable_if_t() {
+  return nullptr;
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
+// CHECK-FIXES: {{^}}template {{$}}
+// CHECK-FIXES-NEXT: {{^}}int* pointer_of_enable_if_t() requires T::some_value {{{$}}
+
+template 
+const std::enable_if_t* const_pointer_of_enable_if_t() {
+  return nullptr;
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:7: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
+// CHECK-FIXES: {{^}}template {{$}}
+// CHECK-FIXES-NEXT: {{^}}const int* const_pointer_of_enable_if_t() requires T::some_value {{{$}}
+
+template 
+std::enable_if_t const * const_pointer_of_enable_if_t2() {
+  return nullptr;
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
+// CHECK-FIXES: {{^}}template {{$}}
+// CHECK-FIXES-NEXT: {{^}}int const * const_pointer_of_enable_if_t2() requires T::some_value {{{$}}
+
+
+template 
+std::enable_if_t& reference_of_enable_if_t() {
+  static int x; return x;
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-u

[PATCH] D141892: Implement modernize-use-constraints

2023-05-06 Thread Chris Cotter via Phabricator via cfe-commits
ccotter marked an inline comment as done.
ccotter added inline comments.



Comment at: 
clang-tools-extra/clang-tidy/modernize/UseConstraintsCheck.cpp:247-248
+ParamsRange.getEnd(), SM, LangOpts, tok::r_paren, tok::r_paren);
+return utils::lexer::findNextAnyTokenKind(EndParens, SM, LangOpts,
+  tok::equal, tok::equal);
+  }

njames93 wrote:
> Super contrived, but looking for the `= delete` like this could be problematic
> ```lang=c++
> template
> std::enable_if_t> Foo() noexcept(requires (T a) { a = 4; 
> }) = delete;
> ```
> Here I'd imagine it would return the `=` in the noexcept requires clause.
> I'd imagine the safest bet would be to work from the function end loc looking 
> for the delete, then the equals.
Good catch. Added a test case for this. Looks like getSourceRange() returns the 
location after the parameter list and noexcept (if any), but before the `= 
delete`, so I went with that.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D141892

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


[PATCH] D141892: Implement modernize-use-constraints

2023-05-06 Thread Chris Cotter via Phabricator via cfe-commits
ccotter updated this revision to Diff 520104.
ccotter marked 3 inline comments as done.
ccotter added a comment.

Fix bug, other cleanups, rebase


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D141892

Files:
  clang-tools-extra/clang-tidy/modernize/CMakeLists.txt
  clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp
  clang-tools-extra/clang-tidy/modernize/UseConstraintsCheck.cpp
  clang-tools-extra/clang-tidy/modernize/UseConstraintsCheck.h
  clang-tools-extra/clang-tidy/utils/LexerUtils.cpp
  clang-tools-extra/clang-tidy/utils/LexerUtils.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-constraints.rst
  
clang-tools-extra/test/clang-tidy/checkers/modernize/use-constraints-first-greatergreater.cpp
  clang-tools-extra/test/clang-tidy/checkers/modernize/use-constraints.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/modernize/use-constraints.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/modernize/use-constraints.cpp
@@ -0,0 +1,699 @@
+// RUN: %check_clang_tidy -std=c++20 %s modernize-use-constraints %t -- -- -fno-delayed-template-parsing
+
+// NOLINTBEGIN
+namespace std {
+template  struct enable_if { };
+
+template  struct enable_if { typedef T type; };
+
+template 
+using enable_if_t = typename enable_if::type;
+
+} // namespace std
+// NOLINTEND
+
+template 
+struct ConsumeVariadic;
+
+struct Obj {
+};
+
+namespace enable_if_in_return_type {
+
+
+// Section 1: enable_if in return type of function
+
+
+
+// General tests
+
+
+template 
+typename std::enable_if::type basic() {
+  return Obj{};
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
+// CHECK-FIXES: {{^}}Obj basic() requires T::some_value {{{$}}
+
+template 
+std::enable_if_t basic_t() {
+  return Obj{};
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
+// CHECK-FIXES: {{^}}Obj basic_t() requires T::some_value {{{$}}
+
+template 
+auto basic_trailing() -> typename std::enable_if::type {
+  return Obj{};
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:26: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
+// CHECK-FIXES: {{^}}auto basic_trailing() -> Obj requires T::some_value {{{$}}
+
+template 
+typename std::enable_if::type existing_constraint() requires (T::another_value) {
+  return Obj{};
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
+// CHECK-FIXES: {{^}}typename std::enable_if::type existing_constraint() requires (T::another_value) {{{$}}
+
+template 
+typename std::enable_if::type decl_without_def();
+
+template 
+typename std::enable_if::type decl_with_separate_def();
+
+template 
+typename std::enable_if::type decl_with_separate_def() {
+  return Obj{};
+}
+// FIXME - Support definitions with separate decls
+
+template 
+std::enable_if_t no_dependent_type(U) {
+  return Obj{};
+}
+// FIXME - Support non-dependent enable_ifs. Low priority though...
+
+template 
+typename std::enable_if::type* pointer_of_enable_if() {
+  return nullptr;
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
+// CHECK-FIXES: {{^}}template {{$}}
+// CHECK-FIXES-NEXT: {{^}}int* pointer_of_enable_if() requires T::some_value {{{$}}
+
+template 
+std::enable_if_t* pointer_of_enable_if_t() {
+  return nullptr;
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
+// CHECK-FIXES: {{^}}template {{$}}
+// CHECK-FIXES-NEXT: {{^}}int* pointer_of_enable_if_t() requires T::some_value {{{$}}
+
+template 
+const std::enable_if_t* const_pointer_of_enable_if_t() {
+  return nullptr;
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:7: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
+// CHECK-FIXES: {{^}}template {{$}}
+// CHECK-FIXES-NEXT: {{^}}const int* const_pointer_of_enable_if_t() requires T::some_value {{{$}}
+
+template 
+std::enable_if_t const * const_pointer_of_enable_if_t2() {
+  return nullptr;
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
+// CHECK-FIXES: {{^}}template {{$}}
+// CHECK-FIXES-NEXT: {{^}}int const * const_pointer_of_enable_if_t2() requires T::some_value {{{$}}
+
+
+template 
+std::enable_if_t& reference_of_enable_if_t() {
+  static int x; return x;
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:1: warning: use C++20 requires cons

[PATCH] D146921: [clang-tidy] Implement cppcoreguidelines F.19

2023-05-05 Thread Chris Cotter via Phabricator via cfe-commits
ccotter updated this revision to Diff 520032.
ccotter added a comment.

- fix merge


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146921

Files:
  clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt
  clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp
  clang-tools-extra/clang-tidy/cppcoreguidelines/MissingStdForwardCheck.cpp
  clang-tools-extra/clang-tidy/cppcoreguidelines/MissingStdForwardCheck.h
  clang-tools-extra/docs/ReleaseNotes.rst
  
clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/missing-std-forward.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  
clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/missing-std-forward.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/missing-std-forward.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/missing-std-forward.cpp
@@ -0,0 +1,150 @@
+// RUN: %check_clang_tidy %s cppcoreguidelines-missing-std-forward %t
+
+// NOLINTBEGIN
+namespace std {
+
+template  struct remove_reference  { using type = T; };
+template  struct remove_reference  { using type = T; };
+template  struct remove_reference { using type = T; };
+
+template  using remove_reference_t = typename remove_reference::type;
+
+template  constexpr T &&forward(remove_reference_t &t) noexcept;
+template  constexpr T &&forward(remove_reference_t &&t) noexcept;
+template  constexpr remove_reference_t &&move(T &&x);
+
+} // namespace std
+// NOLINTEND
+
+struct S {
+  S();
+  S(const S&);
+  S(S&&) noexcept;
+  S& operator=(const S&);
+  S& operator=(S&&) noexcept;
+};
+
+template 
+void consumes_all(Ts&&...);
+
+namespace positive_cases {
+
+template 
+void does_not_forward(T&& t) {
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: forwarding reference parameter 't' is never forwarded inside the function body [cppcoreguidelines-missing-std-forward]
+  T other = t;
+}
+
+template 
+void does_not_forward_invoked(T&& t) {
+  // CHECK-MESSAGES: :[[@LINE-1]]:35: warning: forwarding reference parameter 't' is never forwarded inside the function body [cppcoreguidelines-missing-std-forward]
+  T other = t();
+}
+
+template 
+void forwards_pairwise(T&& t) {
+  // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: forwarding reference parameter 't' is never forwarded inside the function body [cppcoreguidelines-missing-std-forward]
+  auto first = std::forward(t.first);
+  auto second = std::forward(t.second);
+}
+
+template 
+void does_not_forward_pack(Ts&&... ts) {
+  // CHECK-MESSAGES: :[[@LINE-1]]:36: warning: forwarding reference parameter 'ts' is never forwarded inside the function body [cppcoreguidelines-missing-std-forward]
+  consumes_all(ts...);
+}
+
+template 
+class AClass {
+
+  template 
+  AClass(U&& u) : data(u) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: forwarding reference parameter 'u' is never forwarded inside the function body [cppcoreguidelines-missing-std-forward]
+
+  template 
+  AClass& operator=(U&& u) { }
+  // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: forwarding reference parameter 'u' is never forwarded inside the function body [cppcoreguidelines-missing-std-forward]
+
+  template 
+  void mixed_params(T&& t, U&& u) {
+// CHECK-MESSAGES: :[[@LINE-1]]:32: warning: forwarding reference parameter 'u' is never forwarded inside the function body [cppcoreguidelines-missing-std-forward]
+T other1 = std::move(t);
+U other2 = std::move(u);
+  }
+
+  T data;
+};
+
+template 
+void does_not_forward_in_evaluated_code(T&& t) {
+  // CHECK-MESSAGES: :[[@LINE-1]]:45: warning: forwarding reference parameter 't' is never forwarded inside the function body [cppcoreguidelines-missing-std-forward]
+  using result_t = decltype(std::forward(t));
+  unsigned len = sizeof(std::forward(t));
+  T other = t;
+}
+
+template 
+void lambda_value_capture(T&& t) {
+  // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: forwarding reference parameter 't' is never forwarded inside the function body [cppcoreguidelines-missing-std-forward]
+  [=]() { T other = std::forward(t); };
+}
+
+template 
+void lambda_value_reference(T&& t) {
+  // CHECK-MESSAGES: :[[@LINE-1]]:33: warning: forwarding reference parameter 't' is never forwarded inside the function body [cppcoreguidelines-missing-std-forward]
+  [&]() { T other = std::forward(t); };
+}
+
+} // namespace positive_cases
+
+namespace negative_cases {
+
+template 
+void just_a_decl(T&&t);
+
+template 
+void does_forward(T&& t) {
+  T other = std::forward(t);
+}
+
+template 
+void does_forward_pack(Ts&&... ts) {
+  consumes_all(std::forward(ts)...);
+}
+
+void pass_by_value(S s) {
+  S other = std::move(s);
+}
+
+void lvalue_ref(S& s) {
+  S other = std::move(s);
+}
+
+void rvalue_ref(S&& s) {
+  S other = std::move(s);
+}
+
+template 
+void templated_rvalue_ref(std::remove_reference_t&& t) {

[PATCH] D146921: [clang-tidy] Implement cppcoreguidelines F.19

2023-05-05 Thread Chris Cotter via Phabricator via cfe-commits
ccotter added a comment.

Note, @PiotrZSL I don't have commit access, so if you're happy with the 
updates, could you please land this for me?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146921

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


[PATCH] D146921: [clang-tidy] Implement cppcoreguidelines F.19

2023-05-05 Thread Chris Cotter via Phabricator via cfe-commits
ccotter updated this revision to Diff 520027.
ccotter added a comment.

rebase


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146921

Files:
  clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt
  clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp
  clang-tools-extra/clang-tidy/cppcoreguidelines/MissingStdForwardCheck.cpp
  clang-tools-extra/clang-tidy/cppcoreguidelines/MissingStdForwardCheck.h
  clang-tools-extra/docs/ReleaseNotes.rst
  
clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/missing-std-forward.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  
clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/missing-std-forward.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/missing-std-forward.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/missing-std-forward.cpp
@@ -0,0 +1,150 @@
+// RUN: %check_clang_tidy %s cppcoreguidelines-missing-std-forward %t
+
+// NOLINTBEGIN
+namespace std {
+
+template  struct remove_reference  { using type = T; };
+template  struct remove_reference  { using type = T; };
+template  struct remove_reference { using type = T; };
+
+template  using remove_reference_t = typename remove_reference::type;
+
+template  constexpr T &&forward(remove_reference_t &t) noexcept;
+template  constexpr T &&forward(remove_reference_t &&t) noexcept;
+template  constexpr remove_reference_t &&move(T &&x);
+
+} // namespace std
+// NOLINTEND
+
+struct S {
+  S();
+  S(const S&);
+  S(S&&) noexcept;
+  S& operator=(const S&);
+  S& operator=(S&&) noexcept;
+};
+
+template 
+void consumes_all(Ts&&...);
+
+namespace positive_cases {
+
+template 
+void does_not_forward(T&& t) {
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: forwarding reference parameter 't' is never forwarded inside the function body [cppcoreguidelines-missing-std-forward]
+  T other = t;
+}
+
+template 
+void does_not_forward_invoked(T&& t) {
+  // CHECK-MESSAGES: :[[@LINE-1]]:35: warning: forwarding reference parameter 't' is never forwarded inside the function body [cppcoreguidelines-missing-std-forward]
+  T other = t();
+}
+
+template 
+void forwards_pairwise(T&& t) {
+  // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: forwarding reference parameter 't' is never forwarded inside the function body [cppcoreguidelines-missing-std-forward]
+  auto first = std::forward(t.first);
+  auto second = std::forward(t.second);
+}
+
+template 
+void does_not_forward_pack(Ts&&... ts) {
+  // CHECK-MESSAGES: :[[@LINE-1]]:36: warning: forwarding reference parameter 'ts' is never forwarded inside the function body [cppcoreguidelines-missing-std-forward]
+  consumes_all(ts...);
+}
+
+template 
+class AClass {
+
+  template 
+  AClass(U&& u) : data(u) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: forwarding reference parameter 'u' is never forwarded inside the function body [cppcoreguidelines-missing-std-forward]
+
+  template 
+  AClass& operator=(U&& u) { }
+  // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: forwarding reference parameter 'u' is never forwarded inside the function body [cppcoreguidelines-missing-std-forward]
+
+  template 
+  void mixed_params(T&& t, U&& u) {
+// CHECK-MESSAGES: :[[@LINE-1]]:32: warning: forwarding reference parameter 'u' is never forwarded inside the function body [cppcoreguidelines-missing-std-forward]
+T other1 = std::move(t);
+U other2 = std::move(u);
+  }
+
+  T data;
+};
+
+template 
+void does_not_forward_in_evaluated_code(T&& t) {
+  // CHECK-MESSAGES: :[[@LINE-1]]:45: warning: forwarding reference parameter 't' is never forwarded inside the function body [cppcoreguidelines-missing-std-forward]
+  using result_t = decltype(std::forward(t));
+  unsigned len = sizeof(std::forward(t));
+  T other = t;
+}
+
+template 
+void lambda_value_capture(T&& t) {
+  // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: forwarding reference parameter 't' is never forwarded inside the function body [cppcoreguidelines-missing-std-forward]
+  [=]() { T other = std::forward(t); };
+}
+
+template 
+void lambda_value_reference(T&& t) {
+  // CHECK-MESSAGES: :[[@LINE-1]]:33: warning: forwarding reference parameter 't' is never forwarded inside the function body [cppcoreguidelines-missing-std-forward]
+  [&]() { T other = std::forward(t); };
+}
+
+} // namespace positive_cases
+
+namespace negative_cases {
+
+template 
+void just_a_decl(T&&t);
+
+template 
+void does_forward(T&& t) {
+  T other = std::forward(t);
+}
+
+template 
+void does_forward_pack(Ts&&... ts) {
+  consumes_all(std::forward(ts)...);
+}
+
+void pass_by_value(S s) {
+  S other = std::move(s);
+}
+
+void lvalue_ref(S& s) {
+  S other = std::move(s);
+}
+
+void rvalue_ref(S&& s) {
+  S other = std::move(s);
+}
+
+template 
+void templated_rvalue_ref(std::remove_reference_t&& t) {
+  T

[PATCH] D146921: [clang-tidy] Implement cppcoreguidelines F.19

2023-05-05 Thread Chris Cotter via Phabricator via cfe-commits
ccotter added inline comments.



Comment at: 
clang-tools-extra/clang-tidy/cppcoreguidelines/MissingStdForwardCheck.cpp:70
+  Finder->addMatcher(
+  parmVarDecl(
+  parmVarDecl().bind("param"), isTemplateTypeOfFunction(),

PiotrZSL wrote:
> maybe think like: "functionDecl(forEachDescendant(parmVarDecl" could work.
Not sure if I see any advantages of `forEachDescendant` over what I have here - 
I think I'll leave it as is.



Comment at: 
clang-tools-extra/clang-tidy/cppcoreguidelines/MissingStdForwardCheck.cpp:71
+  parmVarDecl(
+  parmVarDecl().bind("param"), isTemplateTypeOfFunction(),
+  hasAncestor(functionDecl(isDefinition(), ToParam,

PiotrZSL wrote:
> PiotrZSL wrote:
> > probably this could be named like isTemplateTypeParameter, current name 
> > suggest more that it's a FunctionDecl matcher, not ParmVarDecl.
> consider excluding system code, or code inside std namespace.
Why specifically do this in this check, but not others (very few seem to do 
this)?



Comment at: 
clang-tools-extra/clang-tidy/cppcoreguidelines/MissingStdForwardCheck.cpp:72
+  parmVarDecl().bind("param"), isTemplateTypeOfFunction(),
+  hasAncestor(functionDecl(isDefinition(), ToParam,
+   
unless(hasDescendant(ForwardCallMatcher),

PiotrZSL wrote:
> maybe we should skip also template instances.
Not sure I follow. Can you give an example?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146921

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


[PATCH] D146921: [clang-tidy] Implement cppcoreguidelines F.19

2023-05-05 Thread Chris Cotter via Phabricator via cfe-commits
ccotter updated this revision to Diff 520026.
ccotter marked 6 inline comments as done.
ccotter added a comment.

- feedback


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146921

Files:
  clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt
  clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp
  clang-tools-extra/clang-tidy/cppcoreguidelines/MissingStdForwardCheck.cpp
  clang-tools-extra/clang-tidy/cppcoreguidelines/MissingStdForwardCheck.h
  clang-tools-extra/docs/ReleaseNotes.rst
  
clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/missing-std-forward.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  
clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/missing-std-forward.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/missing-std-forward.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/missing-std-forward.cpp
@@ -0,0 +1,150 @@
+// RUN: %check_clang_tidy %s cppcoreguidelines-missing-std-forward %t
+
+// NOLINTBEGIN
+namespace std {
+
+template  struct remove_reference  { using type = T; };
+template  struct remove_reference  { using type = T; };
+template  struct remove_reference { using type = T; };
+
+template  using remove_reference_t = typename remove_reference::type;
+
+template  constexpr T &&forward(remove_reference_t &t) noexcept;
+template  constexpr T &&forward(remove_reference_t &&t) noexcept;
+template  constexpr remove_reference_t &&move(T &&x);
+
+} // namespace std
+// NOLINTEND
+
+struct S {
+  S();
+  S(const S&);
+  S(S&&) noexcept;
+  S& operator=(const S&);
+  S& operator=(S&&) noexcept;
+};
+
+template 
+void consumes_all(Ts&&...);
+
+namespace positive_cases {
+
+template 
+void does_not_forward(T&& t) {
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: forwarding reference parameter 't' is never forwarded inside the function body [cppcoreguidelines-missing-std-forward]
+  T other = t;
+}
+
+template 
+void does_not_forward_invoked(T&& t) {
+  // CHECK-MESSAGES: :[[@LINE-1]]:35: warning: forwarding reference parameter 't' is never forwarded inside the function body [cppcoreguidelines-missing-std-forward]
+  T other = t();
+}
+
+template 
+void forwards_pairwise(T&& t) {
+  // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: forwarding reference parameter 't' is never forwarded inside the function body [cppcoreguidelines-missing-std-forward]
+  auto first = std::forward(t.first);
+  auto second = std::forward(t.second);
+}
+
+template 
+void does_not_forward_pack(Ts&&... ts) {
+  // CHECK-MESSAGES: :[[@LINE-1]]:36: warning: forwarding reference parameter 'ts' is never forwarded inside the function body [cppcoreguidelines-missing-std-forward]
+  consumes_all(ts...);
+}
+
+template 
+class AClass {
+
+  template 
+  AClass(U&& u) : data(u) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: forwarding reference parameter 'u' is never forwarded inside the function body [cppcoreguidelines-missing-std-forward]
+
+  template 
+  AClass& operator=(U&& u) { }
+  // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: forwarding reference parameter 'u' is never forwarded inside the function body [cppcoreguidelines-missing-std-forward]
+
+  template 
+  void mixed_params(T&& t, U&& u) {
+// CHECK-MESSAGES: :[[@LINE-1]]:32: warning: forwarding reference parameter 'u' is never forwarded inside the function body [cppcoreguidelines-missing-std-forward]
+T other1 = std::move(t);
+U other2 = std::move(u);
+  }
+
+  T data;
+};
+
+template 
+void does_not_forward_in_evaluated_code(T&& t) {
+  // CHECK-MESSAGES: :[[@LINE-1]]:45: warning: forwarding reference parameter 't' is never forwarded inside the function body [cppcoreguidelines-missing-std-forward]
+  using result_t = decltype(std::forward(t));
+  unsigned len = sizeof(std::forward(t));
+  T other = t;
+}
+
+template 
+void lambda_value_capture(T&& t) {
+  // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: forwarding reference parameter 't' is never forwarded inside the function body [cppcoreguidelines-missing-std-forward]
+  [=]() { T other = std::forward(t); };
+}
+
+template 
+void lambda_value_reference(T&& t) {
+  // CHECK-MESSAGES: :[[@LINE-1]]:33: warning: forwarding reference parameter 't' is never forwarded inside the function body [cppcoreguidelines-missing-std-forward]
+  [&]() { T other = std::forward(t); };
+}
+
+} // namespace positive_cases
+
+namespace negative_cases {
+
+template 
+void just_a_decl(T&&t);
+
+template 
+void does_forward(T&& t) {
+  T other = std::forward(t);
+}
+
+template 
+void does_forward_pack(Ts&&... ts) {
+  consumes_all(std::forward(ts)...);
+}
+
+void pass_by_value(S s) {
+  S other = std::move(s);
+}
+
+void lvalue_ref(S& s) {
+  S other = std::move(s);
+}
+
+void rvalue_ref(S&& s) {
+  S other = std::move(s);
+}
+
+template 
+void templated_

[PATCH] D146921: [clang-tidy] Implement cppcoreguidelines F.19

2023-05-01 Thread Chris Cotter via Phabricator via cfe-commits
ccotter added a comment.

bump?


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

https://reviews.llvm.org/D146921

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


[PATCH] D146921: [clang-tidy] Implement cppcoreguidelines F.19

2023-04-11 Thread Chris Cotter via Phabricator via cfe-commits
ccotter updated this revision to Diff 512455.
ccotter marked an inline comment as done.
ccotter added a comment.

Fix tests


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

https://reviews.llvm.org/D146921

Files:
  clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt
  clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp
  clang-tools-extra/clang-tidy/cppcoreguidelines/MissingStdForwardCheck.cpp
  clang-tools-extra/clang-tidy/cppcoreguidelines/MissingStdForwardCheck.h
  clang-tools-extra/docs/ReleaseNotes.rst
  
clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/missing-std-forward.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  
clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/missing-std-forward.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/missing-std-forward.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/missing-std-forward.cpp
@@ -0,0 +1,138 @@
+// RUN: %check_clang_tidy %s cppcoreguidelines-missing-std-forward %t -- -- -fno-delayed-template-parsing
+
+// NOLINTBEGIN
+namespace std {
+
+template  struct remove_reference  { using type = T; };
+template  struct remove_reference  { using type = T; };
+template  struct remove_reference { using type = T; };
+
+template  using remove_reference_t = typename remove_reference::type;
+
+template  constexpr T &&forward(remove_reference_t &t) noexcept;
+template  constexpr T &&forward(remove_reference_t &&t) noexcept;
+template  constexpr remove_reference_t &&move(T &&x);
+
+} // namespace std
+// NOLINTEND
+
+struct S {
+  S();
+  S(const S&);
+  S(S&&) noexcept;
+  S& operator=(const S&);
+  S& operator=(S&&) noexcept;
+};
+
+template 
+void consumes_all(Ts&&...);
+
+namespace positive_cases {
+
+template 
+void does_not_forward(T&& t) {
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: forwarding reference parameter 't' is never forwarded inside the function body [cppcoreguidelines-missing-std-forward]
+  T other = t;
+}
+
+template 
+void does_not_forward_invoked(T&& t) {
+  // CHECK-MESSAGES: :[[@LINE-1]]:35: warning: forwarding reference parameter 't' is never forwarded inside the function body [cppcoreguidelines-missing-std-forward]
+  T other = t();
+}
+
+template 
+void forwards_pairwise(T&& t) {
+  // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: forwarding reference parameter 't' is never forwarded inside the function body [cppcoreguidelines-missing-std-forward]
+  auto first = std::forward(t.first);
+  auto second = std::forward(t.second);
+}
+
+template 
+void does_not_forward_pack(Ts&&... ts) {
+  // CHECK-MESSAGES: :[[@LINE-1]]:36: warning: forwarding reference parameter 'ts' is never forwarded inside the function body [cppcoreguidelines-missing-std-forward]
+  consumes_all(ts...);
+}
+
+template 
+class AClass {
+
+  template 
+  AClass(U&& u) : data(u) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: forwarding reference parameter 'u' is never forwarded inside the function body [cppcoreguidelines-missing-std-forward]
+
+  template 
+  AClass& operator=(U&& u) { }
+  // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: forwarding reference parameter 'u' is never forwarded inside the function body [cppcoreguidelines-missing-std-forward]
+
+  template 
+  void mixed_params(T&& t, U&& u) {
+// CHECK-MESSAGES: :[[@LINE-1]]:32: warning: forwarding reference parameter 'u' is never forwarded inside the function body [cppcoreguidelines-missing-std-forward]
+T other1 = std::move(t);
+U other2 = std::move(u);
+  }
+
+  T data;
+};
+
+template 
+void does_not_forward_in_evaluated_code(T&& t) {
+  // CHECK-MESSAGES: :[[@LINE-1]]:45: warning: forwarding reference parameter 't' is never forwarded inside the function body [cppcoreguidelines-missing-std-forward]
+  using result_t = decltype(std::forward(t));
+  unsigned len = sizeof(std::forward(t));
+  T other = t;
+}
+
+} // namespace positive_cases
+
+namespace negative_cases {
+
+template 
+void just_a_decl(T&&t);
+
+template 
+void does_forward(T&& t) {
+  T other = std::forward(t);
+}
+
+template 
+void does_forward_pack(Ts&&... ts) {
+  consumes_all(std::forward(ts)...);
+}
+
+void pass_by_value(S s) {
+  S other = std::move(s);
+}
+
+void lvalue_ref(S& s) {
+  S other = std::move(s);
+}
+
+void rvalue_ref(S&& s) {
+  S other = std::move(s);
+}
+
+template 
+void templated_rvalue_ref(std::remove_reference_t&& t) {
+  T other = std::move(t);
+}
+
+template 
+class AClass {
+
+  template 
+  AClass(U&& u) : data(std::forward(u)) {}
+
+  template 
+  AClass& operator=(U&& u) {
+data = std::forward(u);
+  }
+
+  void rvalue_ref(T&& t) {
+T other = std::move(t);
+  }
+
+  T data;
+};
+
+} // namespace negative_cases
Index: clang-tools-extra/docs/clang-tidy/checks/list.rst
===
--- clang-tools-extra/docs/clang-tidy/checks/lis

[PATCH] D146921: [clang-tidy] Implement cppcoreguidelines F.19

2023-04-11 Thread Chris Cotter via Phabricator via cfe-commits
ccotter marked 2 inline comments as done.
ccotter added inline comments.



Comment at: 
clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/forwarding-reference-param-not-forwarded.cpp:138
+
+} // namespace negative_cases

PiotrZSL wrote:
> ccotter wrote:
> > ccotter wrote:
> > > PiotrZSL wrote:
> > > > what about when someone uses std::move instead of std::format ?
> > > > maybe some "note" for such issue ?
> > > Are you suggesting to have the tool add a special note in something like
> > > 
> > > ```
> > > template 
> > > void foo(T&& t) { T other = std::move(t); }
> > > ```
> > > 
> > > I'm not sure I completely followed what you were saying. Or perhaps a 
> > > fixit for this specific case of using move on a forwarding reference 
> > > (fixit to replace `move` with `forward`).
> > @PiotrZSL - I wasn't sure what you meant here.
> Yes, I meant that situation. But only because "forwarding reference parameter 
> 't' is never forwarded inside the function body" could be confused in such 
> case, where there is std::move instead of std::forward.
> But that could be ignored, or covered by other check that would simply detect 
> that you doing move when you should do forward.
Ya, 
https://clang.llvm.org/extra/clang-tidy/checks/bugprone/move-forwarding-reference.html
 should cover this. This new check missing-std-forward only knows how to find 
code that is missing `forward`


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146921

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


[PATCH] D146921: [clang-tidy] Implement cppcoreguidelines F.19

2023-04-10 Thread Chris Cotter via Phabricator via cfe-commits
ccotter updated this revision to Diff 512318.
ccotter added a comment.

- format


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146921

Files:
  clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt
  clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp
  clang-tools-extra/clang-tidy/cppcoreguidelines/MissingStdForwardCheck.cpp
  clang-tools-extra/clang-tidy/cppcoreguidelines/MissingStdForwardCheck.h
  clang-tools-extra/docs/ReleaseNotes.rst
  
clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/missing-std-forward.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  
clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/missing-std-forward.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/missing-std-forward.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/missing-std-forward.cpp
@@ -0,0 +1,138 @@
+// RUN: %check_clang_tidy %s cppcoreguidelines-missing-std-forward %t
+
+// NOLINTBEGIN
+namespace std {
+
+template  struct remove_reference  { using type = T; };
+template  struct remove_reference  { using type = T; };
+template  struct remove_reference { using type = T; };
+
+template  using remove_reference_t = typename remove_reference::type;
+
+template  constexpr T &&forward(remove_reference_t &t) noexcept;
+template  constexpr T &&forward(remove_reference_t &&t) noexcept;
+template  constexpr remove_reference_t &&move(T &&x);
+
+} // namespace std
+// NOLINTEND
+
+struct S {
+  S();
+  S(const S&);
+  S(S&&) noexcept;
+  S& operator=(const S&);
+  S& operator=(S&&) noexcept;
+};
+
+template 
+void consumes_all(Ts&&...);
+
+namespace positive_cases {
+
+template 
+void does_not_forward(T&& t) {
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: forwarding reference parameter 't' is never forwarded inside the function body [cppcoreguidelines-missing-std-forward]
+  T other = t;
+}
+
+template 
+void does_not_forward_invoked(T&& t) {
+  // CHECK-MESSAGES: :[[@LINE-1]]:35: warning: forwarding reference parameter 't' is never forwarded inside the function body [cppcoreguidelines-missing-std-forward]
+  T other = t();
+}
+
+template 
+void forwards_pairwise(T&& t) {
+  // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: forwarding reference parameter 't' is never forwarded inside the function body [cppcoreguidelines-missing-std-forward]
+  auto first = std::forward(t.first);
+  auto second = std::forward(t.second);
+}
+
+template 
+void does_not_forward_pack(Ts&&... ts) {
+  // CHECK-MESSAGES: :[[@LINE-1]]:36: warning: forwarding reference parameter 'ts' is never forwarded inside the function body [cppcoreguidelines-missing-std-forward]
+  consumes_all(ts...);
+}
+
+template 
+class AClass {
+
+  template 
+  AClass(U&& u) : data(u) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: forwarding reference parameter 'u' is never forwarded inside the function body [cppcoreguidelines-missing-std-forward]
+
+  template 
+  AClass& operator=(U&& u) { }
+  // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: forwarding reference parameter 'u' is never forwarded inside the function body [cppcoreguidelines-missing-std-forward]
+
+  template 
+  void mixed_params(T&& t, U&& u) {
+// CHECK-MESSAGES: :[[@LINE-1]]:32: warning: forwarding reference parameter 'u' is never forwarded inside the function body [cppcoreguidelines-missing-std-forward]
+T other1 = std::move(t);
+U other2 = std::move(u);
+  }
+
+  T data;
+};
+
+template 
+void does_not_forward_in_evaluated_code(T&& t) {
+  // CHECK-MESSAGES: :[[@LINE-1]]:45: warning: forwarding reference parameter 't' is never forwarded inside the function body [cppcoreguidelines-missing-std-forward]
+  using result_t = decltype(std::forward(t));
+  unsigned len = sizeof(std::forward(t));
+  T other = t;
+}
+
+} // namespace positive_cases
+
+namespace negative_cases {
+
+template 
+void just_a_decl(T&&t);
+
+template 
+void does_forward(T&& t) {
+  T other = std::forward(t);
+}
+
+template 
+void does_forward_pack(Ts&&... ts) {
+  consumes_all(std::forward(ts)...);
+}
+
+void pass_by_value(S s) {
+  S other = std::move(s);
+}
+
+void lvalue_ref(S& s) {
+  S other = std::move(s);
+}
+
+void rvalue_ref(S&& s) {
+  S other = std::move(s);
+}
+
+template 
+void templated_rvalue_ref(std::remove_reference_t&& t) {
+  T other = std::move(t);
+}
+
+template 
+class AClass {
+
+  template 
+  AClass(U&& u) : data(std::forward(u)) {}
+
+  template 
+  AClass& operator=(U&& u) {
+data = std::forward(u);
+  }
+
+  void rvalue_ref(T&& t) {
+T other = std::move(t);
+  }
+
+  T data;
+};
+
+} // namespace negative_cases
Index: clang-tools-extra/docs/clang-tidy/checks/list.rst
===
--- clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ clang-tools-extra/docs/clang-t

[PATCH] D141892: Implement modernize-use-constraints

2023-04-10 Thread Chris Cotter via Phabricator via cfe-commits
ccotter updated this revision to Diff 512315.
ccotter added a comment.

arc diff properly


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D141892

Files:
  clang-tools-extra/clang-tidy/modernize/CMakeLists.txt
  clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp
  clang-tools-extra/clang-tidy/modernize/UseConstraintsCheck.cpp
  clang-tools-extra/clang-tidy/modernize/UseConstraintsCheck.h
  clang-tools-extra/clang-tidy/utils/LexerUtils.cpp
  clang-tools-extra/clang-tidy/utils/LexerUtils.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-constraints.rst
  
clang-tools-extra/test/clang-tidy/checkers/modernize/use-constraints-first-greatergreater.cpp
  clang-tools-extra/test/clang-tidy/checkers/modernize/use-constraints.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/modernize/use-constraints.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/modernize/use-constraints.cpp
@@ -0,0 +1,693 @@
+// RUN: %check_clang_tidy -std=c++20 %s modernize-use-constraints %t -- -- -fno-delayed-template-parsing
+
+// NOLINTBEGIN
+namespace std {
+template  struct enable_if { };
+
+template  struct enable_if { typedef T type; };
+
+template 
+using enable_if_t = typename enable_if::type;
+
+} // namespace std
+// NOLINTEND
+
+template 
+struct ConsumeVariadic;
+
+struct Obj {
+};
+
+namespace enable_if_in_return_type {
+
+
+// Section 1: enable_if in return type of function
+
+
+
+// General tests
+
+
+template 
+typename std::enable_if::type basic() {
+  return Obj{};
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
+// CHECK-FIXES: {{^}}Obj basic() requires T::some_value {{{$}}
+
+template 
+std::enable_if_t basic_t() {
+  return Obj{};
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
+// CHECK-FIXES: {{^}}Obj basic_t() requires T::some_value {{{$}}
+
+template 
+auto basic_trailing() -> typename std::enable_if::type {
+  return Obj{};
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:26: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
+// CHECK-FIXES: {{^}}auto basic_trailing() -> Obj requires T::some_value {{{$}}
+
+template 
+typename std::enable_if::type existing_constraint() requires (T::another_value) {
+  return Obj{};
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
+// CHECK-FIXES: {{^}}typename std::enable_if::type existing_constraint() requires (T::another_value) {{{$}}
+
+template 
+typename std::enable_if::type decl_without_def();
+
+template 
+typename std::enable_if::type decl_with_separate_def();
+
+template 
+typename std::enable_if::type decl_with_separate_def() {
+  return Obj{};
+}
+// FIXME - Support definitions with separate decls
+
+template 
+std::enable_if_t no_dependent_type(U) {
+  return Obj{};
+}
+// FIXME - Support non-dependent enable_ifs. Low priority though...
+
+template 
+typename std::enable_if::type* pointer_of_enable_if() {
+  return nullptr;
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
+// CHECK-FIXES: {{^}}template {{$}}
+// CHECK-FIXES-NEXT: {{^}}int* pointer_of_enable_if() requires T::some_value {{{$}}
+
+template 
+std::enable_if_t* pointer_of_enable_if_t() {
+  return nullptr;
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
+// CHECK-FIXES: {{^}}template {{$}}
+// CHECK-FIXES-NEXT: {{^}}int* pointer_of_enable_if_t() requires T::some_value {{{$}}
+
+template 
+const std::enable_if_t* const_pointer_of_enable_if_t() {
+  return nullptr;
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:7: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
+// CHECK-FIXES: {{^}}template {{$}}
+// CHECK-FIXES-NEXT: {{^}}const int* const_pointer_of_enable_if_t() requires T::some_value {{{$}}
+
+template 
+std::enable_if_t const * const_pointer_of_enable_if_t2() {
+  return nullptr;
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
+// CHECK-FIXES: {{^}}template {{$}}
+// CHECK-FIXES-NEXT: {{^}}int const * const_pointer_of_enable_if_t2() requires T::some_value {{{$}}
+
+
+template 
+std::enable_if_t& reference_of_enable_if_t() {
+  static int x; return x;
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]

[PATCH] D141892: Implement modernize-use-constraints

2023-04-10 Thread Chris Cotter via Phabricator via cfe-commits
ccotter updated this revision to Diff 512314.
ccotter added a comment.

rebase


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D141892

Files:
  clang-tools-extra/clang-tidy/modernize/UseConstraintsCheck.cpp
  clang-tools-extra/clang-tidy/utils/LexerUtils.cpp
  clang-tools-extra/clang-tidy/utils/LexerUtils.h

Index: clang-tools-extra/clang-tidy/utils/LexerUtils.h
===
--- clang-tools-extra/clang-tidy/utils/LexerUtils.h
+++ clang-tools-extra/clang-tidy/utils/LexerUtils.h
@@ -13,6 +13,7 @@
 #include "clang/Basic/TokenKinds.h"
 #include "clang/Lex/Lexer.h"
 #include 
+#include 
 
 namespace clang {
 
@@ -23,6 +24,9 @@
 /// Returns previous token or ``tok::unknown`` if not found.
 Token getPreviousToken(SourceLocation Location, const SourceManager &SM,
const LangOptions &LangOpts, bool SkipComments = true);
+std::pair
+getPreviousTokenAndStart(SourceLocation Location, const SourceManager &SM,
+ const LangOptions &LangOpts, bool SkipComments = true);
 
 SourceLocation findPreviousTokenStart(SourceLocation Start,
   const SourceManager &SM,
Index: clang-tools-extra/clang-tidy/utils/LexerUtils.cpp
===
--- clang-tools-extra/clang-tidy/utils/LexerUtils.cpp
+++ clang-tools-extra/clang-tidy/utils/LexerUtils.cpp
@@ -10,17 +10,19 @@
 #include "clang/AST/AST.h"
 #include "clang/Basic/SourceManager.h"
 #include 
+#include 
 
 namespace clang::tidy::utils::lexer {
 
-Token getPreviousToken(SourceLocation Location, const SourceManager &SM,
-   const LangOptions &LangOpts, bool SkipComments) {
+std::pair
+getPreviousTokenAndStart(SourceLocation Location, const SourceManager &SM,
+ const LangOptions &LangOpts, bool SkipComments) {
   Token Token;
   Token.setKind(tok::unknown);
 
   Location = Location.getLocWithOffset(-1);
   if (Location.isInvalid())
-  return Token;
+return {Token, Location};
 
   auto StartOfFile = SM.getLocForStartOfFile(SM.getFileID(Location));
   while (Location != StartOfFile) {
@@ -31,6 +33,13 @@
 }
 Location = Location.getLocWithOffset(-1);
   }
+  return {Token, Location};
+}
+
+Token getPreviousToken(SourceLocation Location, const SourceManager &SM,
+   const LangOptions &LangOpts, bool SkipComments) {
+  auto [Token, Start] =
+  getPreviousTokenAndStart(Location, SM, LangOpts, SkipComments);
   return Token;
 }
 
Index: clang-tools-extra/clang-tidy/modernize/UseConstraintsCheck.cpp
===
--- clang-tools-extra/clang-tidy/modernize/UseConstraintsCheck.cpp
+++ clang-tools-extra/clang-tidy/modernize/UseConstraintsCheck.cpp
@@ -254,28 +254,6 @@
   return Body->getBeginLoc();
 }
 
-static Token getPreviousToken(SourceLocation &Location, const SourceManager &SM,
-  const LangOptions &LangOpts,
-  bool SkipComments = false) {
-  Token Token;
-  Token.setKind(tok::unknown);
-
-  Location = Location.getLocWithOffset(-1);
-  if (Location.isInvalid())
-return Token;
-
-  auto StartOfFile = SM.getLocForStartOfFile(SM.getFileID(Location));
-  while (Location != StartOfFile) {
-Location = Lexer::GetBeginningOfToken(Location, SM, LangOpts);
-if (!Lexer::getRawToken(Location, Token, SM, LangOpts) &&
-(!SkipComments || !Token.is(tok::comment))) {
-  break;
-}
-Location = Location.getLocWithOffset(-1);
-  }
-  return Token;
-}
-
 bool isPrimaryExpression(const Expr *Expression) {
   // This function is an incomplete approximation of checking whether
   // an Expr is a primary expression. In particular, if this function
@@ -300,7 +278,10 @@
   if (PrevTokenLoc.isInvalid())
 return std::nullopt;
 
-  Token PrevToken = getPreviousToken(PrevTokenLoc, SM, LangOpts);
+  const bool SkipComments = false;
+  Token PrevToken;
+  std::tie(PrevToken, PrevTokenLoc) = utils::lexer::getPreviousTokenAndStart(
+  PrevTokenLoc, SM, LangOpts, SkipComments);
   bool EndsWithDoubleSlash =
   PrevToken.is(tok::comment) &&
   Lexer::getSourceText(CharSourceRange::getCharRange(
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D141892: Implement modernize-use-constraints

2023-04-10 Thread Chris Cotter via Phabricator via cfe-commits
ccotter updated this revision to Diff 512313.
ccotter added a comment.

refactor


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D141892

Files:
  clang-tools-extra/clang-tidy/modernize/UseConstraintsCheck.cpp
  clang-tools-extra/clang-tidy/utils/LexerUtils.cpp
  clang-tools-extra/clang-tidy/utils/LexerUtils.h

Index: clang-tools-extra/clang-tidy/utils/LexerUtils.h
===
--- clang-tools-extra/clang-tidy/utils/LexerUtils.h
+++ clang-tools-extra/clang-tidy/utils/LexerUtils.h
@@ -13,6 +13,7 @@
 #include "clang/Basic/TokenKinds.h"
 #include "clang/Lex/Lexer.h"
 #include 
+#include 
 
 namespace clang {
 
@@ -23,6 +24,9 @@
 /// Returns previous token or ``tok::unknown`` if not found.
 Token getPreviousToken(SourceLocation Location, const SourceManager &SM,
const LangOptions &LangOpts, bool SkipComments = true);
+std::pair
+getPreviousTokenAndStart(SourceLocation Location, const SourceManager &SM,
+ const LangOptions &LangOpts, bool SkipComments = true);
 
 SourceLocation findPreviousTokenStart(SourceLocation Start,
   const SourceManager &SM,
Index: clang-tools-extra/clang-tidy/utils/LexerUtils.cpp
===
--- clang-tools-extra/clang-tidy/utils/LexerUtils.cpp
+++ clang-tools-extra/clang-tidy/utils/LexerUtils.cpp
@@ -10,17 +10,19 @@
 #include "clang/AST/AST.h"
 #include "clang/Basic/SourceManager.h"
 #include 
+#include 
 
 namespace clang::tidy::utils::lexer {
 
-Token getPreviousToken(SourceLocation Location, const SourceManager &SM,
-   const LangOptions &LangOpts, bool SkipComments) {
+std::pair
+getPreviousTokenAndStart(SourceLocation Location, const SourceManager &SM,
+ const LangOptions &LangOpts, bool SkipComments) {
   Token Token;
   Token.setKind(tok::unknown);
 
   Location = Location.getLocWithOffset(-1);
   if (Location.isInvalid())
-  return Token;
+return {Token, Location};
 
   auto StartOfFile = SM.getLocForStartOfFile(SM.getFileID(Location));
   while (Location != StartOfFile) {
@@ -31,6 +33,13 @@
 }
 Location = Location.getLocWithOffset(-1);
   }
+  return {Token, Location};
+}
+
+Token getPreviousToken(SourceLocation Location, const SourceManager &SM,
+   const LangOptions &LangOpts, bool SkipComments) {
+  auto [Token, Start] =
+  getPreviousTokenAndStart(Location, SM, LangOpts, SkipComments);
   return Token;
 }
 
Index: clang-tools-extra/clang-tidy/modernize/UseConstraintsCheck.cpp
===
--- clang-tools-extra/clang-tidy/modernize/UseConstraintsCheck.cpp
+++ clang-tools-extra/clang-tidy/modernize/UseConstraintsCheck.cpp
@@ -254,28 +254,6 @@
   return Body->getBeginLoc();
 }
 
-static Token getPreviousToken(SourceLocation &Location, const SourceManager &SM,
-  const LangOptions &LangOpts,
-  bool SkipComments = false) {
-  Token Token;
-  Token.setKind(tok::unknown);
-
-  Location = Location.getLocWithOffset(-1);
-  if (Location.isInvalid())
-return Token;
-
-  auto StartOfFile = SM.getLocForStartOfFile(SM.getFileID(Location));
-  while (Location != StartOfFile) {
-Location = Lexer::GetBeginningOfToken(Location, SM, LangOpts);
-if (!Lexer::getRawToken(Location, Token, SM, LangOpts) &&
-(!SkipComments || !Token.is(tok::comment))) {
-  break;
-}
-Location = Location.getLocWithOffset(-1);
-  }
-  return Token;
-}
-
 bool isPrimaryExpression(const Expr *Expression) {
   // This function is an incomplete approximation of checking whether
   // an Expr is a primary expression. In particular, if this function
@@ -300,7 +278,10 @@
   if (PrevTokenLoc.isInvalid())
 return std::nullopt;
 
-  Token PrevToken = getPreviousToken(PrevTokenLoc, SM, LangOpts);
+  const bool SkipComments = false;
+  Token PrevToken;
+  std::tie(PrevToken, PrevTokenLoc) = utils::lexer::getPreviousTokenAndStart(
+  PrevTokenLoc, SM, LangOpts, SkipComments);
   bool EndsWithDoubleSlash =
   PrevToken.is(tok::comment) &&
   Lexer::getSourceText(CharSourceRange::getCharRange(
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D141892: Implement modernize-use-constraints

2023-04-10 Thread Chris Cotter via Phabricator via cfe-commits
ccotter added a comment.

> Would you consider supporting enable_if via parameters

I was planning to support those too, but in a subsequent commit / review since 
this review is rather large. Is that OK?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D141892

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


[PATCH] D141892: Implement modernize-use-constraints

2023-04-10 Thread Chris Cotter via Phabricator via cfe-commits
ccotter added inline comments.



Comment at: 
clang-tools-extra/clang-tidy/modernize/UseConstraintsCheck.cpp:157-160
+return std::make_tuple(
+matchEnableIfSpecialization(
+LastTemplateParam->getTypeSourceInfo()->getTypeLoc()),
+LastTemplateParam);

njames93 wrote:
> Prefer braced initialization rather than the factory make_tuple(or 
> make_pair). Same goes below.
I've seen this feedback twice now - is this (or others, like preferring tuple 
over pair) written down somewhere? I didn't see anything on 
https://llvm.org/docs/CodingStandards.htm (or it wasn't obvious to me). Thanks!



Comment at: clang-tools-extra/clang-tidy/modernize/UseConstraintsCheck.cpp:266
+
+static Token getPreviousToken(SourceLocation &Location, const SourceManager 
&SM,
+  const LangOptions &LangOpts,

njames93 wrote:
> Isn't there a copy of this function in `clang::tidy::utils`?
Ah, this version that I copied takes the `Location` by modifiable reference so 
it can be updated. I will update the original version



Comment at: 
clang-tools-extra/clang-tidy/modernize/UseConstraintsCheck.cpp:462-466
+std::vector FixIts =
+handleReturnType(Function, *ReturnType, *EnableIf, *Result.Context);
+diag(ReturnType->getBeginLoc(),
+ "use C++20 requires constraints instead of enable_if")
+<< FixIts;

njames93 wrote:
> Though a different approach of passing the `DiagnosticBuilder` to the 
> `handleReturnType` function and just appending the fixits in place would be a 
> nicer solution.
> Maybe change the function name to `addReturnTypeFixes(DiagnosticBuilder&, 
> const FunctionDecl *, const TypeLoc &, const EnableIfData &, ASTContext &);`
> 
> Same transformation can be made below.
Updated to apply your first suggestion.

For the `addReturnTypeFixes` suggestion, I find that `handleReturnType` 
returning the `vector` of `FixItHints` simpler since it has less responsibility 
or knowledge about how the `FixItHints` are to be applied - it's main purpose 
is to compute them, so why have the function also know how to apply them? 
Practically speaking, maybe this is not really useful since this function is 
not say, exposed as a library function to other code (it's just used as an 
implementation detail of this check).

Can you clarify what makes the application in place a nicer solution? 


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D141892

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


[PATCH] D141892: Implement modernize-use-constraints

2023-04-10 Thread Chris Cotter via Phabricator via cfe-commits
ccotter updated this revision to Diff 512308.
ccotter marked 12 inline comments as done.
ccotter added a comment.

feedback+rebase


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D141892

Files:
  clang-tools-extra/clang-tidy/modernize/UseConstraintsCheck.cpp

Index: clang-tools-extra/clang-tidy/modernize/UseConstraintsCheck.cpp
===
--- clang-tools-extra/clang-tidy/modernize/UseConstraintsCheck.cpp
+++ clang-tools-extra/clang-tidy/modernize/UseConstraintsCheck.cpp
@@ -14,7 +14,7 @@
 #include "../utils/LexerUtils.h"
 
 #include 
-#include 
+#include 
 
 using namespace clang::ast_matchers;
 
@@ -68,7 +68,7 @@
 if (NumArgs != 1 && NumArgs != 2)
   return std::nullopt;
 
-return std::make_optional(Specialization);
+return Specialization;
   }
   return std::nullopt;
 }
@@ -86,7 +86,7 @@
 if (!Specialization.getTypePtr()->isTypeAlias())
   return std::nullopt;
 
-if (const auto *AliasedType = llvm::dyn_cast(
+if (const auto *AliasedType = dyn_cast(
 Specialization.getTypePtr()->getAliasedType())) {
   if (AliasedType->getIdentifier()->getName() != "type" ||
   AliasedType->getKeyword() != ETK_Typename) {
@@ -99,16 +99,14 @@
 if (NumArgs != 1 && NumArgs != 2)
   return std::nullopt;
 
-return std::make_optional(Specialization);
+return Specialization;
   }
   return std::nullopt;
 }
 
 static std::optional
 matchEnableIfSpecializationImpl(TypeLoc TheType) {
-  std::optional EnableIf;
-  EnableIf = matchEnableIfSpecializationImplTypename(TheType);
-  if (EnableIf)
+  if (auto EnableIf = matchEnableIfSpecializationImplTypename(TheType))
 return EnableIf;
   return matchEnableIfSpecializationImplTrait(TheType);
 }
@@ -122,15 +120,12 @@
   if (const auto Qualified = TheType.getAs())
 TheType = Qualified.getUnqualifiedLoc();
 
-  std::optional EnableIf =
-  matchEnableIfSpecializationImpl(TheType);
-  if (EnableIf)
-return std::make_optional(EnableIfData{std::move(*EnableIf), TheType});
-  else
-return std::nullopt;
+  if (auto EnableIf = matchEnableIfSpecializationImpl(TheType))
+return EnableIfData{std::move(*EnableIf), TheType};
+  return std::nullopt;
 }
 
-static std::tuple, const Decl *>
+static std::pair, const Decl *>
 matchTrailingTemplateParam(const FunctionTemplateDecl *FunctionTemplate) {
   // For non-type trailing param, match very specifically
   // 'template <..., enable_if_type = Default>' where
@@ -148,24 +143,22 @@
   const NamedDecl *LastParam =
   TemplateParams->getParam(TemplateParams->size() - 1);
   if (const auto *LastTemplateParam =
-  llvm::dyn_cast(LastParam)) {
+  dyn_cast(LastParam)) {
 
 if (!LastTemplateParam->hasDefaultArgument() ||
 !LastTemplateParam->getName().empty())
   return {};
 
-return std::make_tuple(
-matchEnableIfSpecialization(
-LastTemplateParam->getTypeSourceInfo()->getTypeLoc()),
-LastTemplateParam);
+return {matchEnableIfSpecialization(
+LastTemplateParam->getTypeSourceInfo()->getTypeLoc()),
+LastTemplateParam};
   } else if (const auto *LastTemplateParam =
- llvm::dyn_cast(LastParam)) {
+ dyn_cast(LastParam)) {
 if (LastTemplateParam->hasDefaultArgument() &&
 LastTemplateParam->getIdentifier() == nullptr) {
-  return std::make_tuple(
-  matchEnableIfSpecialization(
-  LastTemplateParam->getDefaultArgumentInfo()->getTypeLoc()),
-  LastTemplateParam);
+  return {matchEnableIfSpecialization(
+  LastTemplateParam->getDefaultArgumentInfo()->getTypeLoc()),
+  LastTemplateParam};
 }
   }
   return {};
@@ -212,26 +205,24 @@
   getRAngleFileLoc(SM, EnableIf));
 }
 
-static std::optional
+static std::optional
 getTypeText(ASTContext &Context,
 const TemplateSpecializationTypeLoc &EnableIf) {
   if (EnableIf.getNumArgs() > 1) {
 const LangOptions &LangOpts = Context.getLangOpts();
 const SourceManager &SM = Context.getSourceManager();
 bool Invalid = false;
-std::string Text =
-Lexer::getSourceText(
-CharSourceRange::getCharRange(getTypeRange(Context, EnableIf)), SM,
-LangOpts, &Invalid)
-.trim()
-.str();
+StringRef Text = Lexer::getSourceText(CharSourceRange::getCharRange(
+  getTypeRange(Context, EnableIf)),
+  SM, LangOpts, &Invalid)
+ .trim();
 if (Invalid)
   return std::nullopt;
 
-return std::make_optional(std::move(Text));
-  } else {
-return std::make_optional("void");
+return std::move(Text);
   }
+
+  return "void";
 }
 
 static std::optional
@@ -239,7 +230,7 @@
   SourceManager &SM = Context.getSour

[PATCH] D140760: [clang-tidy] Support begin/end free functions in modernize-loop-convert

2023-04-09 Thread Chris Cotter via Phabricator via cfe-commits
ccotter added a comment.

bump - any other feedback?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D140760

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


[PATCH] D146921: [clang-tidy] Implement cppcoreguidelines F.19

2023-04-07 Thread Chris Cotter via Phabricator via cfe-commits
ccotter added inline comments.



Comment at: 
clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/forwarding-reference-param-not-forwarded.cpp:138
+
+} // namespace negative_cases

ccotter wrote:
> PiotrZSL wrote:
> > what about when someone uses std::move instead of std::format ?
> > maybe some "note" for such issue ?
> Are you suggesting to have the tool add a special note in something like
> 
> ```
> template 
> void foo(T&& t) { T other = std::move(t); }
> ```
> 
> I'm not sure I completely followed what you were saying. Or perhaps a fixit 
> for this specific case of using move on a forwarding reference (fixit to 
> replace `move` with `forward`).
@PiotrZSL - I wasn't sure what you meant here.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146921

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


[PATCH] D146921: [clang-tidy] Implement cppcoreguidelines F.19

2023-04-07 Thread Chris Cotter via Phabricator via cfe-commits
ccotter updated this revision to Diff 511847.
ccotter added a comment.

- Rename


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146921

Files:
  clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt
  clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp
  clang-tools-extra/clang-tidy/cppcoreguidelines/MissingStdForwardCheck.cpp
  clang-tools-extra/clang-tidy/cppcoreguidelines/MissingStdForwardCheck.h
  clang-tools-extra/docs/ReleaseNotes.rst
  
clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/missing-std-forward.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  
clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/missing-std-forward.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/missing-std-forward.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/missing-std-forward.cpp
@@ -0,0 +1,138 @@
+// RUN: %check_clang_tidy %s cppcoreguidelines-missing-std-forward %t
+
+// NOLINTBEGIN
+namespace std {
+
+template  struct remove_reference  { using type = T; };
+template  struct remove_reference  { using type = T; };
+template  struct remove_reference { using type = T; };
+
+template  using remove_reference_t = typename remove_reference::type;
+
+template  constexpr T &&forward(remove_reference_t &t) noexcept;
+template  constexpr T &&forward(remove_reference_t &&t) noexcept;
+template  constexpr remove_reference_t &&move(T &&x);
+
+} // namespace std
+// NOLINTEND
+
+struct S {
+  S();
+  S(const S&);
+  S(S&&) noexcept;
+  S& operator=(const S&);
+  S& operator=(S&&) noexcept;
+};
+
+template 
+void consumes_all(Ts&&...);
+
+namespace positive_cases {
+
+template 
+void does_not_forward(T&& t) {
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: forwarding reference parameter 't' is never forwarded inside the function body [cppcoreguidelines-missing-std-forward]
+  T other = t;
+}
+
+template 
+void does_not_forward_invoked(T&& t) {
+  // CHECK-MESSAGES: :[[@LINE-1]]:35: warning: forwarding reference parameter 't' is never forwarded inside the function body [cppcoreguidelines-missing-std-forward]
+  T other = t();
+}
+
+template 
+void forwards_pairwise(T&& t) {
+  // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: forwarding reference parameter 't' is never forwarded inside the function body [cppcoreguidelines-missing-std-forward]
+  auto first = std::forward(t.first);
+  auto second = std::forward(t.second);
+}
+
+template 
+void does_not_forward_pack(Ts&&... ts) {
+  // CHECK-MESSAGES: :[[@LINE-1]]:36: warning: forwarding reference parameter 'ts' is never forwarded inside the function body [cppcoreguidelines-missing-std-forward]
+  consumes_all(ts...);
+}
+
+template 
+class AClass {
+
+  template 
+  AClass(U&& u) : data(u) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: forwarding reference parameter 'u' is never forwarded inside the function body [cppcoreguidelines-missing-std-forward]
+
+  template 
+  AClass& operator=(U&& u) { }
+  // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: forwarding reference parameter 'u' is never forwarded inside the function body [cppcoreguidelines-missing-std-forward]
+
+  template 
+  void mixed_params(T&& t, U&& u) {
+// CHECK-MESSAGES: :[[@LINE-1]]:32: warning: forwarding reference parameter 'u' is never forwarded inside the function body [cppcoreguidelines-missing-std-forward]
+T other1 = std::move(t);
+U other2 = std::move(u);
+  }
+
+  T data;
+};
+
+template 
+void does_not_forward_in_evaluated_code(T&& t) {
+  // CHECK-MESSAGES: :[[@LINE-1]]:45: warning: forwarding reference parameter 't' is never forwarded inside the function body [cppcoreguidelines-missing-std-forward]
+  using result_t = decltype(std::forward(t));
+  unsigned len = sizeof(std::forward(t));
+  T other = t;
+}
+
+} // namespace positive_cases
+
+namespace negative_cases {
+
+template 
+void just_a_decl(T&&t);
+
+template 
+void does_forward(T&& t) {
+  T other = std::forward(t);
+}
+
+template 
+void does_forward_pack(Ts&&... ts) {
+  consumes_all(std::forward(ts)...);
+}
+
+void pass_by_value(S s) {
+  S other = std::move(s);
+}
+
+void lvalue_ref(S& s) {
+  S other = std::move(s);
+}
+
+void rvalue_ref(S&& s) {
+  S other = std::move(s);
+}
+
+template 
+void templated_rvalue_ref(std::remove_reference_t&& t) {
+  T other = std::move(t);
+}
+
+template 
+class AClass {
+
+  template 
+  AClass(U&& u) : data(std::forward(u)) {}
+
+  template 
+  AClass& operator=(U&& u) {
+data = std::forward(u);
+  }
+
+  void rvalue_ref(T&& t) {
+T other = std::move(t);
+  }
+
+  T data;
+};
+
+} // namespace negative_cases
Index: clang-tools-extra/docs/clang-tidy/checks/list.rst
===
--- clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ clang-tools-extra/docs/clang-t

[PATCH] D147551: [clang-tidy] Fix init-list handling in readability-implicit-bool-conversion

2023-04-04 Thread Chris Cotter via Phabricator via cfe-commits
ccotter accepted this revision.
ccotter added a comment.
This revision is now accepted and ready to land.

lgtm


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D147551

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


[PATCH] D145138: [clang-tidy] Implement FixIts for C arrays

2023-04-01 Thread Chris Cotter via Phabricator via cfe-commits
ccotter marked 5 inline comments as done.
ccotter added inline comments.



Comment at: clang-tools-extra/clang-tidy/modernize/AvoidCArraysCheck.cpp:496
+  const Expr *SpelledExpr = E->IgnoreUnlessSpelledInSource();
+  if (dyn_cast(SpelledExpr))
+return false;

PiotrZSL wrote:
> InitListExpr::classof(SpelledExpr)
Why `classof` vs `dyn_cast`? The codebase seems to overwhelmingly use 
`dyn_cst`, and I need to use the downcast type anyway..



Comment at: clang-tools-extra/clang-tidy/modernize/AvoidCArraysCheck.cpp:531
+return {};
+  // TODO: How can I get FileCheck to accept '{{}}' as a non-regex match?
+  FixIts.push_back(FixItHint::CreateInsertion(InitRange.getBegin(), "{ "));

PiotrZSL wrote:
> https://www.llvm.org/docs/CommandGuide/FileCheck.html
> "In the rare case that you want to match double braces explicitly from the 
> input, you can use something ugly like {{[}][}]}} as your pattern."
Thanks..fixed!


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D145138

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


[PATCH] D145138: [clang-tidy] Implement FixIts for C arrays

2023-04-01 Thread Chris Cotter via Phabricator via cfe-commits
ccotter updated this revision to Diff 510270.
ccotter added a comment.

- format


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D145138

Files:
  clang-tools-extra/clang-tidy/modernize/AvoidCArraysCheck.cpp
  clang-tools-extra/clang-tidy/modernize/AvoidCArraysCheck.h
  clang-tools-extra/clang-tidy/modernize/UseTrailingReturnTypeCheck.cpp
  clang-tools-extra/clang-tidy/modernize/UseTrailingReturnTypeCheck.h
  clang-tools-extra/clang-tidy/utils/CMakeLists.txt
  clang-tools-extra/clang-tidy/utils/LexerUtils.cpp
  clang-tools-extra/clang-tidy/utils/TypeUtils.cpp
  clang-tools-extra/clang-tidy/utils/TypeUtils.h
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/modernize/avoid-c-arrays.rst
  clang-tools-extra/test/clang-tidy/checkers/modernize/avoid-c-arrays-cxx17.cpp
  clang-tools-extra/test/clang-tidy/checkers/modernize/avoid-c-arrays.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/modernize/avoid-c-arrays.cpp
===
--- clang-tools-extra/test/clang-tidy/checkers/modernize/avoid-c-arrays.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/modernize/avoid-c-arrays.cpp
@@ -1,4 +1,6 @@
-// RUN: %check_clang_tidy %s modernize-avoid-c-arrays %t
+// RUN: %check_clang_tidy -std=c++11 %s modernize-avoid-c-arrays %t
+
+//CHECK-FIXES: #include 
 
 int a[] = {1, 2};
 // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: do not declare C-style arrays, use std::array<> instead
@@ -86,3 +88,280 @@
   int j[1];
 };
 }
+
+template  struct TStruct {};
+
+void replacements() {
+  int ar[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: std::array ar;
+  TStruct ar2[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: std::array, 10> ar2;
+  TStruct< int > ar3[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: std::array, 10> ar3;
+  int * ar4[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: std::array ar4;
+  int * /*comment*/ar5[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: std::array /*comment*/ar5;
+  volatile const int * ar6[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: std::array ar6;
+  volatile int ar7[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: volatile std::array ar7;
+  int const * ar8[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: std::array ar8;
+  int ar9[1];
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: std::array ar9;
+  static int volatile constexpr ar10[10] = {};
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: static volatile constexpr std::array ar10 = {{[{][{]}}{{[}][}]}};
+  thread_local int ar11[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: thread_local std::array ar11;
+  thread_local/*a*/int/*b*/ar12[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: thread_local/*a*/std::array/*b*/ar12;
+  /*a*/ int/*b*/ /*c*/*/*d*/ /*e*/ /*f*/ar13[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: /*a*/ std::array/*d*/ /*e*/ /*f*/ar13;
+  TStruct ar14[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: std::array, 10> ar14;
+  volatile TStruct ar15[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: volatile std::array, 10> ar15;
+  TStruct ar16[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: std::array, 10> ar16;
+  TStruct ar17[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: std::array, 10> ar17;
+  volatile int static thread_local * ar18[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: static thread_local std::array ar18;
+
+  // Note, there is a tab '\t' before the semicolon in the declaration below.
+  int ar19[3]	;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning:

[PATCH] D145138: [clang-tidy] Implement FixIts for C arrays

2023-04-01 Thread Chris Cotter via Phabricator via cfe-commits
ccotter marked an inline comment as done.
ccotter added inline comments.



Comment at: 
clang-tools-extra/test/clang-tidy/checkers/modernize/avoid-c-arrays.cpp:170-172
+  char init4[] = "abcdef";
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare C-style arrays, 
use std::array<> instead
+  // CHECK-FIXES: std::array init4 = { "abcdef" };

PiotrZSL wrote:
> I don't think this check should replace those strings, simply that could 
> break code, image someone is using this later as an argument to some function 
> that expect pointer.
> For strings std::string_view would be better alternative (at least add a 
> bypass for this).
> And all those changes are not safe if variable is used for pointer arithmetic.
> 
> 
The logic I implemented should fix pointer arithmetic (e.g., `str + 1` is 
replaced by `str.begin() + 1`. I have tests for this for `int[]`, but added 
more for `char[]`. string_view is not appropriate conversion here since the 
arrays may be modified etc.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D145138

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


[PATCH] D145138: [clang-tidy] Implement FixIts for C arrays

2023-04-01 Thread Chris Cotter via Phabricator via cfe-commits
ccotter updated this revision to Diff 510267.
ccotter added a comment.

- Add tests for char[]


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D145138

Files:
  clang-tools-extra/clang-tidy/modernize/AvoidCArraysCheck.cpp
  clang-tools-extra/clang-tidy/modernize/AvoidCArraysCheck.h
  clang-tools-extra/clang-tidy/modernize/UseTrailingReturnTypeCheck.cpp
  clang-tools-extra/clang-tidy/modernize/UseTrailingReturnTypeCheck.h
  clang-tools-extra/clang-tidy/utils/CMakeLists.txt
  clang-tools-extra/clang-tidy/utils/LexerUtils.cpp
  clang-tools-extra/clang-tidy/utils/TypeUtils.cpp
  clang-tools-extra/clang-tidy/utils/TypeUtils.h
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/modernize/avoid-c-arrays.rst
  clang-tools-extra/test/clang-tidy/checkers/modernize/avoid-c-arrays-cxx17.cpp
  clang-tools-extra/test/clang-tidy/checkers/modernize/avoid-c-arrays.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/modernize/avoid-c-arrays.cpp
===
--- clang-tools-extra/test/clang-tidy/checkers/modernize/avoid-c-arrays.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/modernize/avoid-c-arrays.cpp
@@ -1,4 +1,6 @@
-// RUN: %check_clang_tidy %s modernize-avoid-c-arrays %t
+// RUN: %check_clang_tidy -std=c++11 %s modernize-avoid-c-arrays %t
+
+//CHECK-FIXES: #include 
 
 int a[] = {1, 2};
 // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: do not declare C-style arrays, use std::array<> instead
@@ -86,3 +88,280 @@
   int j[1];
 };
 }
+
+template  struct TStruct {};
+
+void replacements() {
+  int ar[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: std::array ar;
+  TStruct ar2[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: std::array, 10> ar2;
+  TStruct< int > ar3[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: std::array, 10> ar3;
+  int * ar4[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: std::array ar4;
+  int * /*comment*/ar5[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: std::array /*comment*/ar5;
+  volatile const int * ar6[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: std::array ar6;
+  volatile int ar7[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: volatile std::array ar7;
+  int const * ar8[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: std::array ar8;
+  int ar9[1];
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: std::array ar9;
+  static int volatile constexpr ar10[10] = {};
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: static volatile constexpr std::array ar10 = {{[{][{]}}{{[}][}]}};
+  thread_local int ar11[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: thread_local std::array ar11;
+  thread_local/*a*/int/*b*/ar12[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: thread_local/*a*/std::array/*b*/ar12;
+  /*a*/ int/*b*/ /*c*/*/*d*/ /*e*/ /*f*/ar13[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: /*a*/ std::array/*d*/ /*e*/ /*f*/ar13;
+  TStruct ar14[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: std::array, 10> ar14;
+  volatile TStruct ar15[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: volatile std::array, 10> ar15;
+  TStruct ar16[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: std::array, 10> ar16;
+  TStruct ar17[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: std::array, 10> ar17;
+  volatile int static thread_local * ar18[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: static thread_local std::array ar18;
+
+  // Note, there is a tab '\t' before the semicolon in the declaration below.
+  int ar19[3]	;
+  // CHECK-MESSAGES: :[[@LINE-1

[PATCH] D145138: [clang-tidy] Implement FixIts for C arrays

2023-04-01 Thread Chris Cotter via Phabricator via cfe-commits
ccotter updated this revision to Diff 510262.
ccotter added a comment.

- Fix double curly brace matching in tests


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D145138

Files:
  clang-tools-extra/clang-tidy/modernize/AvoidCArraysCheck.cpp
  clang-tools-extra/clang-tidy/modernize/AvoidCArraysCheck.h
  clang-tools-extra/clang-tidy/modernize/UseTrailingReturnTypeCheck.cpp
  clang-tools-extra/clang-tidy/modernize/UseTrailingReturnTypeCheck.h
  clang-tools-extra/clang-tidy/utils/CMakeLists.txt
  clang-tools-extra/clang-tidy/utils/LexerUtils.cpp
  clang-tools-extra/clang-tidy/utils/TypeUtils.cpp
  clang-tools-extra/clang-tidy/utils/TypeUtils.h
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/modernize/avoid-c-arrays.rst
  clang-tools-extra/test/clang-tidy/checkers/modernize/avoid-c-arrays-cxx17.cpp
  clang-tools-extra/test/clang-tidy/checkers/modernize/avoid-c-arrays.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/modernize/avoid-c-arrays.cpp
===
--- clang-tools-extra/test/clang-tidy/checkers/modernize/avoid-c-arrays.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/modernize/avoid-c-arrays.cpp
@@ -1,4 +1,6 @@
-// RUN: %check_clang_tidy %s modernize-avoid-c-arrays %t
+// RUN: %check_clang_tidy -std=c++11 %s modernize-avoid-c-arrays %t
+
+//CHECK-FIXES: #include 
 
 int a[] = {1, 2};
 // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: do not declare C-style arrays, use std::array<> instead
@@ -86,3 +88,262 @@
   int j[1];
 };
 }
+
+template  struct TStruct {};
+
+void replacements() {
+  int ar[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: std::array ar;
+  TStruct ar2[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: std::array, 10> ar2;
+  TStruct< int > ar3[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: std::array, 10> ar3;
+  int * ar4[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: std::array ar4;
+  int * /*comment*/ar5[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: std::array /*comment*/ar5;
+  volatile const int * ar6[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: std::array ar6;
+  volatile int ar7[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: volatile std::array ar7;
+  int const * ar8[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: std::array ar8;
+  int ar9[1];
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: std::array ar9;
+  static int volatile constexpr ar10[10] = {};
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: static volatile constexpr std::array ar10 = {{[{][{]}}{{[}][}]}};
+  thread_local int ar11[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: thread_local std::array ar11;
+  thread_local/*a*/int/*b*/ar12[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: thread_local/*a*/std::array/*b*/ar12;
+  /*a*/ int/*b*/ /*c*/*/*d*/ /*e*/ /*f*/ar13[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: /*a*/ std::array/*d*/ /*e*/ /*f*/ar13;
+  TStruct ar14[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: std::array, 10> ar14;
+  volatile TStruct ar15[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: volatile std::array, 10> ar15;
+  TStruct ar16[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: std::array, 10> ar16;
+  TStruct ar17[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: std::array, 10> ar17;
+  volatile int static thread_local * ar18[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: static thread_local std::array ar18;
+
+  // Note, there is a tab '\t' before the semicolon in the declaration below.
+  int ar19[3]	;
+  // CHECK-

[PATCH] D144347: [clang-tidy] Add readability-forward-usage check

2023-03-31 Thread Chris Cotter via Phabricator via cfe-commits
ccotter added inline comments.



Comment at: clang-tools-extra/clang-tidy/readability/ForwardUsageCheck.cpp:99
+  unless(isExpansionInSystemHeader()), argumentCountIs(1U),
+  IgnoreDependentExpresions
+  ? expr(unless(isInstantiationDependent()))

I think we might need more tests when `IgnoreDependentExpresions` is true. When 
I was playing around and hardcoded IgnoreDependentExpresions to false on line 
99, the tests still pass.



Comment at: clang-tools-extra/docs/ReleaseNotes.rst:126
+
+  Suggests removing or replacing ``std::forward`` with ``std::move`` or
+  ``static_cast`` in cases where the template argument type is invariant and

Would you see use in expanding use of this check to cases that (broadly, 
cppcoreguiideline ES.56) apply `forward` when the argument is not a forwarding 
reference? Or separate check (as the one I proposed in 
https://reviews.llvm.org/D146888)? Specifically, when the template parameter is 
deduced:

```
template  void forwards_incorrectly(T& t) { T other = 
std::forward(t); } // ignored by readability-forward-usage
```


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D144347

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


[PATCH] D144347: [clang-tidy] Add readability-forward-usage check

2023-03-31 Thread Chris Cotter via Phabricator via cfe-commits
ccotter accepted this revision.
ccotter added inline comments.
This revision is now accepted and ready to land.



Comment at: clang-tools-extra/clang-tidy/readability/ForwardUsageCheck.cpp:98
+  callExpr(
+  unless(isExpansionInSystemHeader()), argumentCountIs(1U),
+  IgnoreDependentExpresions

Curious, why have `isExpansionInSystemHeader` here, rather than rely on the 
`system-headers` command line option. Is that a matter of performance (this 
tool is not likely to apply for system headers)?



Comment at: 
clang-tools-extra/docs/clang-tidy/checks/readability/forward-usage.rst:98
+
+.. option:: DisableTypeMismatchSuggestion
+

PiotrZSL wrote:
> ccotter wrote:
> > Curious what others thing but I think the tool should by default not remove 
> > or replace `forward` with static_cast.  When an author has written 
> > `forward`, there is a good chance they intended to forward something (e.g., 
> > they forgot to use `&&` in the parameter declaration). My hypothesis is 
> > that it's more likely the author intended to forward something, rather than 
> > than they were trying to use it as a cast (but had not intention of forward 
> > - why else would they have typed it out?). In this case, I think it merits 
> > manual review by default (so the tool should always warn, but without the 
> > fixits by default).
> No, in this case if they used forward, they used this with different type, 
> not adding & is not sufficient to trigger this case.
> 
> In theory we could, create alias bugprone-std-forward that would redirect to 
> this check, but would set DisableTypeMismatchSuggestion to false, and would 
> set DisableRemoveSuggestion & DisableMoveSuggestion to true.
> 
> In such case we could have readability check that would just suggest remove 
> of std::forward or usage of std::move, and bugprone check that would only 
> warn of casts between different types.
> 
Makes sense to me. Happy to work on that once this is merged.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D144347

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


[PATCH] D140760: [clang-tidy] Support begin/end free functions in modernize-loop-convert

2023-03-30 Thread Chris Cotter via Phabricator via cfe-commits
ccotter added inline comments.



Comment at: clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp:158-159
+   
callee(cxxMethodDecl(BeginNameMatcher))),
+ callExpr(argumentCountIs(1),
+  callee(functionDecl(BeginNameMatcher)
   .bind(BeginCallName);

PiotrZSL wrote:
> Now it will also catch calls to single parameter methods...
> maybe `unless(cxxMethodDecl())`, after all we want to catch only functions
I think `usesADL()` accomplishes the same thing here.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D140760

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


[PATCH] D140760: [clang-tidy] Support begin/end free functions in modernize-loop-convert

2023-03-30 Thread Chris Cotter via Phabricator via cfe-commits
ccotter updated this revision to Diff 509874.
ccotter marked 3 inline comments as done.
ccotter added a comment.

- format


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D140760

Files:
  clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/modernize/loop-convert.rst
  
clang-tools-extra/test/clang-tidy/checkers/modernize/Inputs/loop-convert/structures.h
  clang-tools-extra/test/clang-tidy/checkers/modernize/loop-convert-basic.cpp
  clang-tools-extra/test/clang-tidy/checkers/modernize/loop-convert-negative.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/modernize/loop-convert-negative.cpp
===
--- clang-tools-extra/test/clang-tidy/checkers/modernize/loop-convert-negative.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/modernize/loop-convert-negative.cpp
@@ -5,6 +5,22 @@
 // CHECK-FIXES-NOT: for ({{.*[^:]:[^:].*}})
 // CHECK-MESSAGES-NOT: modernize-loop-convert
 
+namespace somenamespace {
+  template  auto begin(T& t) -> decltype(t.begin());
+  template  auto begin(const T& t) -> decltype(t.begin());
+  template  auto end(T& t) -> decltype(t.end());
+  template  auto end(const T& t) -> decltype(t.end());
+  template  auto size(const T& t) -> decltype(t.size());
+} // namespace somenamespace
+
+struct SomeClass {
+  template  static auto begin(T& t) -> decltype(t.begin());
+  template  static auto begin(const T& t) -> decltype(t.begin());
+  template  static auto end(T& t) -> decltype(t.end());
+  template  static auto end(const T& t) -> decltype(t.end());
+  template  static auto size(const T& t) -> decltype(t.size());
+};
+
 namespace Negative {
 
 const int N = 6;
@@ -92,7 +108,7 @@
   }
 }
 
-}
+} // namespace Negative
 
 namespace NegativeIterator {
 
@@ -103,6 +119,10 @@
 struct BadBeginEnd : T {
   iterator notBegin();
   iterator notEnd();
+  iterator begin(int);
+  iterator end(int);
+  iterator begin();
+  iterator end();
 };
 
 void notBeginOrEnd() {
@@ -112,6 +132,9 @@
 
   for (T::iterator I = Bad.begin(), E = Bad.notEnd();  I != E; ++I)
 int K = *I;
+
+  for (T::iterator I = Bad.begin(0), E = Bad.end(0);  I != E; ++I)
+int K = *I;
 }
 
 void badLoopShapes() {
@@ -202,6 +225,8 @@
   T Other;
   for (T::iterator I = Tt.begin(), E = Other.end();  I != E; ++I)
 int K = *I;
+  for (T::iterator I = begin(Tt), E = end(Other);  I != E; ++I)
+int K = *I;
 
   for (T::iterator I = Other.begin(), E = Tt.end();  I != E; ++I)
 int K = *I;
@@ -214,6 +239,24 @@
 MutableVal K = *I;
 }
 
+void mixedMemberAndADL() {
+  for (T::iterator I = Tt.begin(), E = end(Tt);  I != E; ++I)
+int K = *I;
+  for (T::iterator I = begin(Tt), E = Tt.end();  I != E; ++I)
+int K = *I;
+  for (T::iterator I = std::begin(Tt), E = Tt.end();  I != E; ++I)
+int K = *I;
+  for (T::iterator I = std::begin(Tt), E = end(Tt);  I != E; ++I)
+int K = *I;
+}
+
+void nonADLOrStdCalls() {
+  for (T::iterator I = SomeClass::begin(Tt), E = SomeClass::end(Tt);  I != E; ++I)
+int K = *I;
+  for (T::iterator I = somenamespace::begin(Tt), E = somenamespace::end(Tt);  I != E; ++I)
+int K = *I;
+}
+
 void wrongIterators() {
   T::iterator Other;
   for (T::iterator I = Tt.begin(), E = Tt.end(); I != Other; ++I)
@@ -379,6 +422,13 @@
 Sum += V[I];
 }
 
+void nonADLOrStdCalls() {
+  for (int I = 0, E = somenamespace::size(V); E != I; ++I)
+printf("Fibonacci number is %d\n", V[I]);
+  for (int I = 0, E = SomeClass::size(V); E != I; ++I)
+printf("Fibonacci number is %d\n", V[I]);
+}
+
 // Checks to see that non-const member functions are not called on the container
 // object.
 // These could be conceivably allowed with a lower required confidence level.
Index: clang-tools-extra/test/clang-tidy/checkers/modernize/loop-convert-basic.cpp
===
--- clang-tools-extra/test/clang-tidy/checkers/modernize/loop-convert-basic.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/modernize/loop-convert-basic.cpp
@@ -445,6 +445,41 @@
   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
   // CHECK-FIXES: for (auto & I : Dpp)
   // CHECK-FIXES-NEXT: printf("%d\n", I->X);
+
+  for (S::iterator It = begin(Ss), E = end(Ss); It != E; ++It) {
+printf("s0 has value %d\n", (*It).X);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto & It : Ss)
+  // CHECK-FIXES-NEXT: printf("s0 has value %d\n", It.X);
+
+  for (S::iterator It = std::begin(Ss), E = std::end(Ss); It != E; ++It) {
+printf("s1 has value %d\n", (*It).X);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto & It : Ss)
+  // CHECK-FIXES-NEXT: printf("s1 has value %d\n", It.X);
+
+  for (S::iterator 

[PATCH] D141892: Implement modernize-use-constraints

2023-03-29 Thread Chris Cotter via Phabricator via cfe-commits
ccotter updated this revision to Diff 509544.
ccotter added a comment.

- format


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D141892

Files:
  clang-tools-extra/clang-tidy/modernize/CMakeLists.txt
  clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp
  clang-tools-extra/clang-tidy/modernize/UseConstraintsCheck.cpp
  clang-tools-extra/clang-tidy/modernize/UseConstraintsCheck.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-constraints.rst
  
clang-tools-extra/test/clang-tidy/checkers/modernize/use-constraints-first-greatergreater.cpp
  clang-tools-extra/test/clang-tidy/checkers/modernize/use-constraints.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/modernize/use-constraints.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/modernize/use-constraints.cpp
@@ -0,0 +1,693 @@
+// RUN: %check_clang_tidy -std=c++20 %s modernize-use-constraints %t -- -- -fno-delayed-template-parsing
+
+// NOLINTBEGIN
+namespace std {
+template  struct enable_if { };
+
+template  struct enable_if { typedef T type; };
+
+template 
+using enable_if_t = typename enable_if::type;
+
+} // namespace std
+// NOLINTEND
+
+template 
+struct ConsumeVariadic;
+
+struct Obj {
+};
+
+namespace enable_if_in_return_type {
+
+
+// Section 1: enable_if in return type of function
+
+
+
+// General tests
+
+
+template 
+typename std::enable_if::type basic() {
+  return Obj{};
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
+// CHECK-FIXES: {{^}}Obj basic() requires T::some_value {{{$}}
+
+template 
+std::enable_if_t basic_t() {
+  return Obj{};
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
+// CHECK-FIXES: {{^}}Obj basic_t() requires T::some_value {{{$}}
+
+template 
+auto basic_trailing() -> typename std::enable_if::type {
+  return Obj{};
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:26: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
+// CHECK-FIXES: {{^}}auto basic_trailing() -> Obj requires T::some_value {{{$}}
+
+template 
+typename std::enable_if::type existing_constraint() requires (T::another_value) {
+  return Obj{};
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
+// CHECK-FIXES: {{^}}typename std::enable_if::type existing_constraint() requires (T::another_value) {{{$}}
+
+template 
+typename std::enable_if::type decl_without_def();
+
+template 
+typename std::enable_if::type decl_with_separate_def();
+
+template 
+typename std::enable_if::type decl_with_separate_def() {
+  return Obj{};
+}
+// FIXME - Support definitions with separate decls
+
+template 
+std::enable_if_t no_dependent_type(U) {
+  return Obj{};
+}
+// FIXME - Support non-dependent enable_ifs. Low priority though...
+
+template 
+typename std::enable_if::type* pointer_of_enable_if() {
+  return nullptr;
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
+// CHECK-FIXES: {{^}}template {{$}}
+// CHECK-FIXES-NEXT: {{^}}int* pointer_of_enable_if() requires T::some_value {{{$}}
+
+template 
+std::enable_if_t* pointer_of_enable_if_t() {
+  return nullptr;
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
+// CHECK-FIXES: {{^}}template {{$}}
+// CHECK-FIXES-NEXT: {{^}}int* pointer_of_enable_if_t() requires T::some_value {{{$}}
+
+template 
+const std::enable_if_t* const_pointer_of_enable_if_t() {
+  return nullptr;
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:7: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
+// CHECK-FIXES: {{^}}template {{$}}
+// CHECK-FIXES-NEXT: {{^}}const int* const_pointer_of_enable_if_t() requires T::some_value {{{$}}
+
+template 
+std::enable_if_t const * const_pointer_of_enable_if_t2() {
+  return nullptr;
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
+// CHECK-FIXES: {{^}}template {{$}}
+// CHECK-FIXES-NEXT: {{^}}int const * const_pointer_of_enable_if_t2() requires T::some_value {{{$}}
+
+
+template 
+std::enable_if_t& reference_of_enable_if_t() {
+  static int x; return x;
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
+// CHECK-FIXES: {{^}}template {{$}}
+// CHECK-FIXES-NEXT: {{^}}int& reference_of_enable_if_t() requires T::so

[PATCH] D141892: Implement modernize-use-constraints

2023-03-29 Thread Chris Cotter via Phabricator via cfe-commits
ccotter updated this revision to Diff 509543.
ccotter added a comment.

rebase


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D141892

Files:
  clang-tools-extra/clang-tidy/modernize/CMakeLists.txt
  clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp
  clang-tools-extra/clang-tidy/modernize/UseConstraintsCheck.cpp
  clang-tools-extra/clang-tidy/modernize/UseConstraintsCheck.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-constraints.rst
  
clang-tools-extra/test/clang-tidy/checkers/modernize/use-constraints-first-greatergreater.cpp
  clang-tools-extra/test/clang-tidy/checkers/modernize/use-constraints.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/modernize/use-constraints.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/modernize/use-constraints.cpp
@@ -0,0 +1,693 @@
+// RUN: %check_clang_tidy -std=c++20 %s modernize-use-constraints %t -- -- -fno-delayed-template-parsing
+
+// NOLINTBEGIN
+namespace std {
+template  struct enable_if { };
+
+template  struct enable_if { typedef T type; };
+
+template 
+using enable_if_t = typename enable_if::type;
+
+} // namespace std
+// NOLINTEND
+
+template 
+struct ConsumeVariadic;
+
+struct Obj {
+};
+
+namespace enable_if_in_return_type {
+
+
+// Section 1: enable_if in return type of function
+
+
+
+// General tests
+
+
+template 
+typename std::enable_if::type basic() {
+  return Obj{};
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
+// CHECK-FIXES: {{^}}Obj basic() requires T::some_value {{{$}}
+
+template 
+std::enable_if_t basic_t() {
+  return Obj{};
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
+// CHECK-FIXES: {{^}}Obj basic_t() requires T::some_value {{{$}}
+
+template 
+auto basic_trailing() -> typename std::enable_if::type {
+  return Obj{};
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:26: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
+// CHECK-FIXES: {{^}}auto basic_trailing() -> Obj requires T::some_value {{{$}}
+
+template 
+typename std::enable_if::type existing_constraint() requires (T::another_value) {
+  return Obj{};
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
+// CHECK-FIXES: {{^}}typename std::enable_if::type existing_constraint() requires (T::another_value) {{{$}}
+
+template 
+typename std::enable_if::type decl_without_def();
+
+template 
+typename std::enable_if::type decl_with_separate_def();
+
+template 
+typename std::enable_if::type decl_with_separate_def() {
+  return Obj{};
+}
+// FIXME - Support definitions with separate decls
+
+template 
+std::enable_if_t no_dependent_type(U) {
+  return Obj{};
+}
+// FIXME - Support non-dependent enable_ifs. Low priority though...
+
+template 
+typename std::enable_if::type* pointer_of_enable_if() {
+  return nullptr;
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
+// CHECK-FIXES: {{^}}template {{$}}
+// CHECK-FIXES-NEXT: {{^}}int* pointer_of_enable_if() requires T::some_value {{{$}}
+
+template 
+std::enable_if_t* pointer_of_enable_if_t() {
+  return nullptr;
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
+// CHECK-FIXES: {{^}}template {{$}}
+// CHECK-FIXES-NEXT: {{^}}int* pointer_of_enable_if_t() requires T::some_value {{{$}}
+
+template 
+const std::enable_if_t* const_pointer_of_enable_if_t() {
+  return nullptr;
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:7: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
+// CHECK-FIXES: {{^}}template {{$}}
+// CHECK-FIXES-NEXT: {{^}}const int* const_pointer_of_enable_if_t() requires T::some_value {{{$}}
+
+template 
+std::enable_if_t const * const_pointer_of_enable_if_t2() {
+  return nullptr;
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
+// CHECK-FIXES: {{^}}template {{$}}
+// CHECK-FIXES-NEXT: {{^}}int const * const_pointer_of_enable_if_t2() requires T::some_value {{{$}}
+
+
+template 
+std::enable_if_t& reference_of_enable_if_t() {
+  static int x; return x;
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
+// CHECK-FIXES: {{^}}template {{$}}
+// CHECK-FIXES-NEXT: {{^}}int& reference_of_enable_if_t() requires T::some

[PATCH] D143971: [clang-tidy] Flag more buggy string constructor cases

2023-03-29 Thread Chris Cotter via Phabricator via cfe-commits
ccotter updated this revision to Diff 509541.
ccotter added a comment.

rebase


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D143971

Files:
  clang-tools-extra/clang-tidy/modernize/AvoidCArraysCheck.cpp
  clang-tools-extra/clang-tidy/modernize/AvoidCArraysCheck.h
  clang-tools-extra/clang-tidy/modernize/UseTrailingReturnTypeCheck.cpp
  clang-tools-extra/clang-tidy/modernize/UseTrailingReturnTypeCheck.h
  clang-tools-extra/clang-tidy/utils/CMakeLists.txt
  clang-tools-extra/clang-tidy/utils/LexerUtils.cpp
  clang-tools-extra/clang-tidy/utils/TypeUtils.cpp
  clang-tools-extra/clang-tidy/utils/TypeUtils.h
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/modernize/avoid-c-arrays.rst
  clang-tools-extra/test/clang-tidy/checkers/modernize/avoid-c-arrays-cxx17.cpp
  clang-tools-extra/test/clang-tidy/checkers/modernize/avoid-c-arrays.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/modernize/avoid-c-arrays.cpp
===
--- clang-tools-extra/test/clang-tidy/checkers/modernize/avoid-c-arrays.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/modernize/avoid-c-arrays.cpp
@@ -1,4 +1,6 @@
-// RUN: %check_clang_tidy %s modernize-avoid-c-arrays %t
+// RUN: %check_clang_tidy -std=c++11 %s modernize-avoid-c-arrays %t
+
+//CHECK-FIXES: #include 
 
 int a[] = {1, 2};
 // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: do not declare C-style arrays, use std::array<> instead
@@ -86,3 +88,262 @@
   int j[1];
 };
 }
+
+template  struct TStruct {};
+
+void replacements() {
+  int ar[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: std::array ar;
+  TStruct ar2[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: std::array, 10> ar2;
+  TStruct< int > ar3[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: std::array, 10> ar3;
+  int * ar4[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: std::array ar4;
+  int * /*comment*/ar5[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: std::array /*comment*/ar5;
+  volatile const int * ar6[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: std::array ar6;
+  volatile int ar7[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: volatile std::array ar7;
+  int const * ar8[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: std::array ar8;
+  int ar9[1];
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: std::array ar9;
+  static int volatile constexpr ar10[10] = {};
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: static volatile constexpr std::array ar10 = { {} };
+  thread_local int ar11[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: thread_local std::array ar11;
+  thread_local/*a*/int/*b*/ar12[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: thread_local/*a*/std::array/*b*/ar12;
+  /*a*/ int/*b*/ /*c*/*/*d*/ /*e*/ /*f*/ar13[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: /*a*/ std::array/*d*/ /*e*/ /*f*/ar13;
+  TStruct ar14[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: std::array, 10> ar14;
+  volatile TStruct ar15[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: volatile std::array, 10> ar15;
+  TStruct ar16[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: std::array, 10> ar16;
+  TStruct ar17[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: std::array, 10> ar17;
+  volatile int static thread_local * ar18[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: static thread_local std::array ar18;
+
+  // Note, there is a tab '\t' before the semicolon in the declaration below.
+  int ar19[3]	;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare 

[PATCH] D146921: [clang-tidy] Implement cppcoreguidelines F.19

2023-03-29 Thread Chris Cotter via Phabricator via cfe-commits
ccotter updated this revision to Diff 509539.
ccotter added a comment.

- Use common function


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146921

Files:
  clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt
  clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp
  
clang-tools-extra/clang-tidy/cppcoreguidelines/ForwardingReferenceParamNotForwardedCheck.cpp
  
clang-tools-extra/clang-tidy/cppcoreguidelines/ForwardingReferenceParamNotForwardedCheck.h
  clang-tools-extra/docs/ReleaseNotes.rst
  
clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/forwarding-reference-param-not-forwarded.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  
clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/forwarding-reference-param-not-forwarded.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/forwarding-reference-param-not-forwarded.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/forwarding-reference-param-not-forwarded.cpp
@@ -0,0 +1,138 @@
+// RUN: %check_clang_tidy %s cppcoreguidelines-forwarding-reference-param-not-forwarded %t -- -- -fno-delayed-template-parsing
+
+// NOLINTBEGIN
+namespace std {
+
+template  struct remove_reference  { using type = T; };
+template  struct remove_reference  { using type = T; };
+template  struct remove_reference { using type = T; };
+
+template  using remove_reference_t = typename remove_reference::type;
+
+template  constexpr T &&forward(remove_reference_t &t) noexcept;
+template  constexpr T &&forward(remove_reference_t &&t) noexcept;
+template  constexpr remove_reference_t &&move(T &&x);
+
+} // namespace std
+// NOLINTEND
+
+struct S {
+  S();
+  S(const S&);
+  S(S&&) noexcept;
+  S& operator=(const S&);
+  S& operator=(S&&) noexcept;
+};
+
+template 
+void consumes_all(Ts&&...);
+
+namespace positive_cases {
+
+template 
+void does_not_forward(T&& t) {
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: forwarding reference parameter 't' is never forwarded inside the function body [cppcoreguidelines-forwarding-reference-param-not-forwarded]
+  T other = t;
+}
+
+template 
+void does_not_forward_invoked(T&& t) {
+  // CHECK-MESSAGES: :[[@LINE-1]]:35: warning: forwarding reference parameter 't' is never forwarded inside the function body [cppcoreguidelines-forwarding-reference-param-not-forwarded]
+  T other = t();
+}
+
+template 
+void forwards_pairwise(T&& t) {
+  // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: forwarding reference parameter 't' is never forwarded inside the function body [cppcoreguidelines-forwarding-reference-param-not-forwarded]
+  auto first = std::forward(t.first);
+  auto second = std::forward(t.second);
+}
+
+template 
+void does_not_forward_pack(Ts&&... ts) {
+  // CHECK-MESSAGES: :[[@LINE-1]]:36: warning: forwarding reference parameter 'ts' is never forwarded inside the function body [cppcoreguidelines-forwarding-reference-param-not-forwarded]
+  consumes_all(ts...);
+}
+
+template 
+class AClass {
+
+  template 
+  AClass(U&& u) : data(u) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: forwarding reference parameter 'u' is never forwarded inside the function body [cppcoreguidelines-forwarding-reference-param-not-forwarded]
+
+  template 
+  AClass& operator=(U&& u) { }
+  // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: forwarding reference parameter 'u' is never forwarded inside the function body [cppcoreguidelines-forwarding-reference-param-not-forwarded]
+
+  template 
+  void mixed_params(T&& t, U&& u) {
+// CHECK-MESSAGES: :[[@LINE-1]]:32: warning: forwarding reference parameter 'u' is never forwarded inside the function body [cppcoreguidelines-forwarding-reference-param-not-forwarded]
+T other1 = std::move(t);
+U other2 = std::move(u);
+  }
+
+  T data;
+};
+
+template 
+void does_not_forward_in_evaluated_code(T&& t) {
+  // CHECK-MESSAGES: :[[@LINE-1]]:45: warning: forwarding reference parameter 't' is never forwarded inside the function body [cppcoreguidelines-forwarding-reference-param-not-forwarded]
+  using result_t = decltype(std::forward(t));
+  unsigned len = sizeof(std::forward(t));
+  T other = t;
+}
+
+} // namespace positive_cases
+
+namespace negative_cases {
+
+template 
+void just_a_decl(T&&t);
+
+template 
+void does_forward(T&& t) {
+  T other = std::forward(t);
+}
+
+template 
+void does_forward_pack(Ts&&... ts) {
+  consumes_all(std::forward(ts)...);
+}
+
+void pass_by_value(S s) {
+  S other = std::move(s);
+}
+
+void lvalue_ref(S& s) {
+  S other = std::move(s);
+}
+
+void rvalue_ref(S&& s) {
+  S other = std::move(s);
+}
+
+template 
+void templated_rvalue_ref(std::remove_reference_t&& t) {
+  T other = std::move(t);
+}
+
+template 
+class AClass {
+
+  template 
+  AClass(U&& u) : data(std::forward(u)) {}
+
+  template 
+  AClass& operator=(U&& u) {

[PATCH] D147062: [clang-tidy] Add option to ignore capture default by reference in cppcoreguidelines-avoid-capture-default-when-capturing-this

2023-03-28 Thread Chris Cotter via Phabricator via cfe-commits
ccotter accepted this revision.
ccotter added a comment.
This revision is now accepted and ready to land.

If https://github.com/isocpp/CppCoreGuidelines/issues/2060 is accepted to only 
consider `[=]`, then I assume we'd want to change the default value of 
IgnoreCaptureDefaultByReference to be true?  Thanks by the way for this!


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D147062

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


[PATCH] D146929: [clang-tidy] Ignore unevaluated exprs in rvalue-reference-param-not-moved

2023-03-27 Thread Chris Cotter via Phabricator via cfe-commits
ccotter added a comment.

@PiotrZSL if you're happy with these changes, would you mind committing them 
for me? "Chris Cotter "


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146929

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


[PATCH] D140760: [clang-tidy] Support begin/end free functions in modernize-loop-convert

2023-03-27 Thread Chris Cotter via Phabricator via cfe-commits
ccotter added a comment.

In D140760#4222989 , @PiotrZSL wrote:

> What about classes that doesn't have begin/end method but got cbegin/cend ? 
> I thing there is open issue for that.

Should we handle that in a separate patch?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D140760

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


[PATCH] D146921: [clang-tidy] Implement cppcoreguidelines F.19

2023-03-27 Thread Chris Cotter via Phabricator via cfe-commits
ccotter updated this revision to Diff 508869.
ccotter marked 2 inline comments as done.
ccotter added a comment.

- fix docs, fix test


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146921

Files:
  clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt
  clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp
  
clang-tools-extra/clang-tidy/cppcoreguidelines/ForwardingReferenceParamNotForwardedCheck.cpp
  
clang-tools-extra/clang-tidy/cppcoreguidelines/ForwardingReferenceParamNotForwardedCheck.h
  clang-tools-extra/docs/ReleaseNotes.rst
  
clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/forwarding-reference-param-not-forwarded.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  
clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/forwarding-reference-param-not-forwarded.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/forwarding-reference-param-not-forwarded.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/forwarding-reference-param-not-forwarded.cpp
@@ -0,0 +1,138 @@
+// RUN: %check_clang_tidy %s cppcoreguidelines-forwarding-reference-param-not-forwarded %t -- -- -fno-delayed-template-parsing
+
+// NOLINTBEGIN
+namespace std {
+
+template  struct remove_reference  { using type = T; };
+template  struct remove_reference  { using type = T; };
+template  struct remove_reference { using type = T; };
+
+template  using remove_reference_t = typename remove_reference::type;
+
+template  constexpr T &&forward(remove_reference_t &t) noexcept;
+template  constexpr T &&forward(remove_reference_t &&t) noexcept;
+template  constexpr remove_reference_t &&move(T &&x);
+
+} // namespace std
+// NOLINTEND
+
+struct S {
+  S();
+  S(const S&);
+  S(S&&) noexcept;
+  S& operator=(const S&);
+  S& operator=(S&&) noexcept;
+};
+
+template 
+void consumes_all(Ts&&...);
+
+namespace positive_cases {
+
+template 
+void does_not_forward(T&& t) {
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: forwarding reference parameter 't' is never forwarded inside the function body [cppcoreguidelines-forwarding-reference-param-not-forwarded]
+  T other = t;
+}
+
+template 
+void does_not_forward_invoked(T&& t) {
+  // CHECK-MESSAGES: :[[@LINE-1]]:35: warning: forwarding reference parameter 't' is never forwarded inside the function body [cppcoreguidelines-forwarding-reference-param-not-forwarded]
+  T other = t();
+}
+
+template 
+void forwards_pairwise(T&& t) {
+  // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: forwarding reference parameter 't' is never forwarded inside the function body [cppcoreguidelines-forwarding-reference-param-not-forwarded]
+  auto first = std::forward(t.first);
+  auto second = std::forward(t.second);
+}
+
+template 
+void does_not_forward_pack(Ts&&... ts) {
+  // CHECK-MESSAGES: :[[@LINE-1]]:36: warning: forwarding reference parameter 'ts' is never forwarded inside the function body [cppcoreguidelines-forwarding-reference-param-not-forwarded]
+  consumes_all(ts...);
+}
+
+template 
+class AClass {
+
+  template 
+  AClass(U&& u) : data(u) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: forwarding reference parameter 'u' is never forwarded inside the function body [cppcoreguidelines-forwarding-reference-param-not-forwarded]
+
+  template 
+  AClass& operator=(U&& u) { }
+  // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: forwarding reference parameter 'u' is never forwarded inside the function body [cppcoreguidelines-forwarding-reference-param-not-forwarded]
+
+  template 
+  void mixed_params(T&& t, U&& u) {
+// CHECK-MESSAGES: :[[@LINE-1]]:32: warning: forwarding reference parameter 'u' is never forwarded inside the function body [cppcoreguidelines-forwarding-reference-param-not-forwarded]
+T other1 = std::move(t);
+U other2 = std::move(u);
+  }
+
+  T data;
+};
+
+template 
+void does_not_forward_in_evaluated_code(T&& t) {
+  // CHECK-MESSAGES: :[[@LINE-1]]:45: warning: forwarding reference parameter 't' is never forwarded inside the function body [cppcoreguidelines-forwarding-reference-param-not-forwarded]
+  using result_t = decltype(std::forward(t));
+  unsigned len = sizeof(std::forward(t));
+  T other = t;
+}
+
+} // namespace positive_cases
+
+namespace negative_cases {
+
+template 
+void just_a_decl(T&&t);
+
+template 
+void does_forward(T&& t) {
+  T other = std::forward(t);
+}
+
+template 
+void does_forward_pack(Ts&&... ts) {
+  consumes_all(std::forward(ts)...);
+}
+
+void pass_by_value(S s) {
+  S other = std::move(s);
+}
+
+void lvalue_ref(S& s) {
+  S other = std::move(s);
+}
+
+void rvalue_ref(S&& s) {
+  S other = std::move(s);
+}
+
+template 
+void templated_rvalue_ref(std::remove_reference_t&& t) {
+  T other = std::move(t);
+}
+
+template 
+class AClass {
+
+  template 
+  AClass(U&& u) : data(std::forward(u)) {}
+
+

[PATCH] D146921: [clang-tidy] Implement cppcoreguidelines F.19

2023-03-27 Thread Chris Cotter via Phabricator via cfe-commits
ccotter added inline comments.



Comment at: 
clang-tools-extra/clang-tidy/cppcoreguidelines/ForwardingReferenceParamNotForwardedCheck.cpp:20
+
+AST_MATCHER(Expr, hasUnevaluatedContext) {
+  if (isa(Node) || isa(Node))

PiotrZSL wrote:
> move this matcher to some utils/...
> It may be needed by other checks.
> 
Will be done in https://reviews.llvm.org/D146929



Comment at: 
clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/forwarding-reference-param-not-forwarded.cpp:138
+
+} // namespace negative_cases

PiotrZSL wrote:
> what about when someone uses std::move instead of std::format ?
> maybe some "note" for such issue ?
Are you suggesting to have the tool add a special note in something like

```
template 
void foo(T&& t) { T other = std::move(t); }
```

I'm not sure I completely followed what you were saying. Or perhaps a fixit for 
this specific case of using move on a forwarding reference (fixit to replace 
`move` with `forward`).


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146921

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


[PATCH] D146929: [clang-tidy] Ignore unevaluated exprs in rvalue-reference-param-not-moved

2023-03-27 Thread Chris Cotter via Phabricator via cfe-commits
ccotter updated this revision to Diff 508865.
ccotter added a comment.

- move to utility file


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146929

Files:
  clang-tools-extra/clang-tidy/bugprone/UseAfterMoveCheck.cpp
  
clang-tools-extra/clang-tidy/cppcoreguidelines/RvalueReferenceParamNotMovedCheck.cpp
  clang-tools-extra/clang-tidy/utils/Matchers.h
  
clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/rvalue-reference-param-not-moved.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/rvalue-reference-param-not-moved.cpp
===
--- clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/rvalue-reference-param-not-moved.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/rvalue-reference-param-not-moved.cpp
@@ -156,6 +156,13 @@
   Obj moved = std::move((o));
 }
 
+void does_not_move_in_evaluated(Obj&& o) {
+  // CHECK-MESSAGES: :[[@LINE-1]]:39: warning: rvalue reference parameter 'o' is never moved from inside the function body [cppcoreguidelines-rvalue-reference-param-not-moved]
+  using result_t = decltype(std::move(o));
+  unsigned size = sizeof(std::move(o));
+  Obj moved = o;
+}
+
 template 
 struct mypair {
   T1 first;
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
@@ -10,6 +10,7 @@
 #define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_UTILS_MATCHERS_H
 
 #include "TypeTraits.h"
+#include "clang/AST/ExprConcepts.h"
 #include "clang/ASTMatchers/ASTMatchers.h"
 #include 
 
@@ -48,6 +49,23 @@
   return pointerType(pointee(qualType(isConstQualified(;
 }
 
+AST_MATCHER(Expr, hasUnevaluatedContext) {
+  if (isa(Node) || isa(Node))
+return true;
+  if (const auto *UnaryExpr = dyn_cast(&Node)) {
+switch (UnaryExpr->getKind()) {
+case UETT_SizeOf:
+case UETT_AlignOf:
+  return true;
+default:
+  return false;
+}
+  }
+  if (const auto *TypeIDExpr = dyn_cast(&Node))
+return !TypeIDExpr->isPotentiallyEvaluated();
+  return false;
+}
+
 // A matcher implementation that matches a list of type name regular expressions
 // against a NamedDecl. If a regular expression contains the substring "::"
 // matching will occur against the qualified name, otherwise only the typename.
Index: clang-tools-extra/clang-tidy/cppcoreguidelines/RvalueReferenceParamNotMovedCheck.cpp
===
--- clang-tools-extra/clang-tidy/cppcoreguidelines/RvalueReferenceParamNotMovedCheck.cpp
+++ clang-tools-extra/clang-tidy/cppcoreguidelines/RvalueReferenceParamNotMovedCheck.cpp
@@ -7,6 +7,7 @@
 //===--===//
 
 #include "RvalueReferenceParamNotMovedCheck.h"
+#include "../utils/Matchers.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/ASTMatchers/ASTMatchFinder.h"
 
@@ -14,6 +15,8 @@
 
 namespace clang::tidy::cppcoreguidelines {
 
+using matchers::hasUnevaluatedContext;
+
 namespace {
 AST_MATCHER_P(LambdaExpr, valueCapturesVar, DeclarationMatcher, VarMatcher) {
   return std::find_if(Node.capture_begin(), Node.capture_end(),
@@ -39,16 +42,18 @@
 
   StatementMatcher MoveCallMatcher =
   callExpr(
+  argumentCountIs(1),
   anyOf(callee(functionDecl(hasName("::std::move"))),
 callee(unresolvedLookupExpr(hasAnyDeclaration(
 namedDecl(hasUnderlyingDecl(hasName("::std::move"))),
-  argumentCountIs(1),
   hasArgument(
   0, argumentOf(
  AllowPartialMove,
  declRefExpr(to(equalsBoundNode("param"))).bind("ref"))),
   unless(hasAncestor(
-  lambdaExpr(valueCapturesVar(equalsBoundNode("param"))
+  lambdaExpr(valueCapturesVar(equalsBoundNode("param"),
+  unless(anyOf(hasAncestor(typeLoc()),
+   hasAncestor(expr(hasUnevaluatedContext())
   .bind("move-call");
 
   Finder->addMatcher(
Index: clang-tools-extra/clang-tidy/bugprone/UseAfterMoveCheck.cpp
===
--- clang-tools-extra/clang-tidy/bugprone/UseAfterMoveCheck.cpp
+++ clang-tools-extra/clang-tidy/bugprone/UseAfterMoveCheck.cpp
@@ -10,13 +10,13 @@
 
 #include "clang/AST/Expr.h"
 #include "clang/AST/ExprCXX.h"
-#include "clang/AST/ExprConcepts.h"
 #include "clang/ASTMatchers/ASTMatchers.h"
 #include "clang/Analysis/CFG.h"
 #include "clang/Lex/Lexer.h"
 #include "llvm/ADT/STLExtras.h"
 
 #include "../utils/ExprSequence.h"
+#include "../utils/Matchers.h"
 #include 
 
 using namespace clang::ast_matchers;
@@ -24,24 +24,9 @@
 
 namespace clang::tidy::bugprone {
 
-namespace {
+using matchers::hasUnevaluatedContext

[PATCH] D137205: [clang-tidy] Add performance-unnecessary-copy-on-last-use check

2023-03-26 Thread Chris Cotter via Phabricator via cfe-commits
ccotter added a comment.
Herald added a subscriber: PiotrZSL.

@Febbe - checking in. is this still on your radar? I would love to see this 
merged!


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D137205

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


[PATCH] D140760: [clang-tidy] Support begin/end free functions in modernize-loop-convert

2023-03-26 Thread Chris Cotter via Phabricator via cfe-commits
ccotter updated this revision to Diff 508476.
ccotter added a comment.

- alpha


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D140760

Files:
  clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/modernize/loop-convert.rst
  
clang-tools-extra/test/clang-tidy/checkers/modernize/Inputs/loop-convert/structures.h
  clang-tools-extra/test/clang-tidy/checkers/modernize/loop-convert-basic.cpp
  clang-tools-extra/test/clang-tidy/checkers/modernize/loop-convert-negative.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/modernize/loop-convert-negative.cpp
===
--- clang-tools-extra/test/clang-tidy/checkers/modernize/loop-convert-negative.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/modernize/loop-convert-negative.cpp
@@ -5,6 +5,22 @@
 // CHECK-FIXES-NOT: for ({{.*[^:]:[^:].*}})
 // CHECK-MESSAGES-NOT: modernize-loop-convert
 
+namespace somenamespace {
+  template  auto begin(T& t) -> decltype(t.begin());
+  template  auto begin(const T& t) -> decltype(t.begin());
+  template  auto end(T& t) -> decltype(t.end());
+  template  auto end(const T& t) -> decltype(t.end());
+  template  auto size(const T& t) -> decltype(t.size());
+} // namespace somenamespace
+
+struct SomeClass {
+  template  static auto begin(T& t) -> decltype(t.begin());
+  template  static auto begin(const T& t) -> decltype(t.begin());
+  template  static auto end(T& t) -> decltype(t.end());
+  template  static auto end(const T& t) -> decltype(t.end());
+  template  static auto size(const T& t) -> decltype(t.size());
+};
+
 namespace Negative {
 
 const int N = 6;
@@ -92,7 +108,7 @@
   }
 }
 
-}
+} // namespace Negative
 
 namespace NegativeIterator {
 
@@ -103,6 +119,10 @@
 struct BadBeginEnd : T {
   iterator notBegin();
   iterator notEnd();
+  iterator begin(int);
+  iterator end(int);
+  iterator begin();
+  iterator end();
 };
 
 void notBeginOrEnd() {
@@ -112,6 +132,9 @@
 
   for (T::iterator I = Bad.begin(), E = Bad.notEnd();  I != E; ++I)
 int K = *I;
+
+  for (T::iterator I = Bad.begin(0), E = Bad.end(0);  I != E; ++I)
+int K = *I;
 }
 
 void badLoopShapes() {
@@ -202,6 +225,8 @@
   T Other;
   for (T::iterator I = Tt.begin(), E = Other.end();  I != E; ++I)
 int K = *I;
+  for (T::iterator I = begin(Tt), E = end(Other);  I != E; ++I)
+int K = *I;
 
   for (T::iterator I = Other.begin(), E = Tt.end();  I != E; ++I)
 int K = *I;
@@ -214,6 +239,24 @@
 MutableVal K = *I;
 }
 
+void mixedMemberAndADL() {
+  for (T::iterator I = Tt.begin(), E = end(Tt);  I != E; ++I)
+int K = *I;
+  for (T::iterator I = begin(Tt), E = Tt.end();  I != E; ++I)
+int K = *I;
+  for (T::iterator I = std::begin(Tt), E = Tt.end();  I != E; ++I)
+int K = *I;
+  for (T::iterator I = std::begin(Tt), E = end(Tt);  I != E; ++I)
+int K = *I;
+}
+
+void nonADLOrStdCalls() {
+  for (T::iterator I = SomeClass::begin(Tt), E = SomeClass::end(Tt);  I != E; ++I)
+int K = *I;
+  for (T::iterator I = somenamespace::begin(Tt), E = somenamespace::end(Tt);  I != E; ++I)
+int K = *I;
+}
+
 void wrongIterators() {
   T::iterator Other;
   for (T::iterator I = Tt.begin(), E = Tt.end(); I != Other; ++I)
@@ -379,6 +422,13 @@
 Sum += V[I];
 }
 
+void nonADLOrStdCalls() {
+  for (int I = 0, E = somenamespace::size(V); E != I; ++I)
+printf("Fibonacci number is %d\n", V[I]);
+  for (int I = 0, E = SomeClass::size(V); E != I; ++I)
+printf("Fibonacci number is %d\n", V[I]);
+}
+
 // Checks to see that non-const member functions are not called on the container
 // object.
 // These could be conceivably allowed with a lower required confidence level.
Index: clang-tools-extra/test/clang-tidy/checkers/modernize/loop-convert-basic.cpp
===
--- clang-tools-extra/test/clang-tidy/checkers/modernize/loop-convert-basic.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/modernize/loop-convert-basic.cpp
@@ -445,6 +445,41 @@
   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
   // CHECK-FIXES: for (auto & I : Dpp)
   // CHECK-FIXES-NEXT: printf("%d\n", I->X);
+
+  for (S::iterator It = begin(Ss), E = end(Ss); It != E; ++It) {
+printf("s0 has value %d\n", (*It).X);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto & It : Ss)
+  // CHECK-FIXES-NEXT: printf("s0 has value %d\n", It.X);
+
+  for (S::iterator It = std::begin(Ss), E = std::end(Ss); It != E; ++It) {
+printf("s1 has value %d\n", (*It).X);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto & It : Ss)
+  // CHECK-FIXES-NEXT: printf("s1 has value %d\n", It.X);
+
+  for (S::iterator It = begin(*Ps), E = end(*Ps); It != E; ++I

[PATCH] D140760: [clang-tidy] Support begin/end free functions in modernize-loop-convert

2023-03-26 Thread Chris Cotter via Phabricator via cfe-commits
ccotter updated this revision to Diff 508474.
ccotter added a comment.

- fix bad rebase


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D140760

Files:
  clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/modernize/loop-convert.rst
  
clang-tools-extra/test/clang-tidy/checkers/modernize/Inputs/loop-convert/structures.h
  clang-tools-extra/test/clang-tidy/checkers/modernize/loop-convert-basic.cpp
  clang-tools-extra/test/clang-tidy/checkers/modernize/loop-convert-negative.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/modernize/loop-convert-negative.cpp
===
--- clang-tools-extra/test/clang-tidy/checkers/modernize/loop-convert-negative.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/modernize/loop-convert-negative.cpp
@@ -5,6 +5,22 @@
 // CHECK-FIXES-NOT: for ({{.*[^:]:[^:].*}})
 // CHECK-MESSAGES-NOT: modernize-loop-convert
 
+namespace somenamespace {
+  template  auto begin(T& t) -> decltype(t.begin());
+  template  auto begin(const T& t) -> decltype(t.begin());
+  template  auto end(T& t) -> decltype(t.end());
+  template  auto end(const T& t) -> decltype(t.end());
+  template  auto size(const T& t) -> decltype(t.size());
+} // namespace somenamespace
+
+struct SomeClass {
+  template  static auto begin(T& t) -> decltype(t.begin());
+  template  static auto begin(const T& t) -> decltype(t.begin());
+  template  static auto end(T& t) -> decltype(t.end());
+  template  static auto end(const T& t) -> decltype(t.end());
+  template  static auto size(const T& t) -> decltype(t.size());
+};
+
 namespace Negative {
 
 const int N = 6;
@@ -92,7 +108,7 @@
   }
 }
 
-}
+} // namespace Negative
 
 namespace NegativeIterator {
 
@@ -103,6 +119,10 @@
 struct BadBeginEnd : T {
   iterator notBegin();
   iterator notEnd();
+  iterator begin(int);
+  iterator end(int);
+  iterator begin();
+  iterator end();
 };
 
 void notBeginOrEnd() {
@@ -112,6 +132,9 @@
 
   for (T::iterator I = Bad.begin(), E = Bad.notEnd();  I != E; ++I)
 int K = *I;
+
+  for (T::iterator I = Bad.begin(0), E = Bad.end(0);  I != E; ++I)
+int K = *I;
 }
 
 void badLoopShapes() {
@@ -202,6 +225,8 @@
   T Other;
   for (T::iterator I = Tt.begin(), E = Other.end();  I != E; ++I)
 int K = *I;
+  for (T::iterator I = begin(Tt), E = end(Other);  I != E; ++I)
+int K = *I;
 
   for (T::iterator I = Other.begin(), E = Tt.end();  I != E; ++I)
 int K = *I;
@@ -214,6 +239,24 @@
 MutableVal K = *I;
 }
 
+void mixedMemberAndADL() {
+  for (T::iterator I = Tt.begin(), E = end(Tt);  I != E; ++I)
+int K = *I;
+  for (T::iterator I = begin(Tt), E = Tt.end();  I != E; ++I)
+int K = *I;
+  for (T::iterator I = std::begin(Tt), E = Tt.end();  I != E; ++I)
+int K = *I;
+  for (T::iterator I = std::begin(Tt), E = end(Tt);  I != E; ++I)
+int K = *I;
+}
+
+void nonADLOrStdCalls() {
+  for (T::iterator I = SomeClass::begin(Tt), E = SomeClass::end(Tt);  I != E; ++I)
+int K = *I;
+  for (T::iterator I = somenamespace::begin(Tt), E = somenamespace::end(Tt);  I != E; ++I)
+int K = *I;
+}
+
 void wrongIterators() {
   T::iterator Other;
   for (T::iterator I = Tt.begin(), E = Tt.end(); I != Other; ++I)
@@ -379,6 +422,13 @@
 Sum += V[I];
 }
 
+void nonADLOrStdCalls() {
+  for (int I = 0, E = somenamespace::size(V); E != I; ++I)
+printf("Fibonacci number is %d\n", V[I]);
+  for (int I = 0, E = SomeClass::size(V); E != I; ++I)
+printf("Fibonacci number is %d\n", V[I]);
+}
+
 // Checks to see that non-const member functions are not called on the container
 // object.
 // These could be conceivably allowed with a lower required confidence level.
Index: clang-tools-extra/test/clang-tidy/checkers/modernize/loop-convert-basic.cpp
===
--- clang-tools-extra/test/clang-tidy/checkers/modernize/loop-convert-basic.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/modernize/loop-convert-basic.cpp
@@ -445,6 +445,41 @@
   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
   // CHECK-FIXES: for (auto & I : Dpp)
   // CHECK-FIXES-NEXT: printf("%d\n", I->X);
+
+  for (S::iterator It = begin(Ss), E = end(Ss); It != E; ++It) {
+printf("s0 has value %d\n", (*It).X);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto & It : Ss)
+  // CHECK-FIXES-NEXT: printf("s0 has value %d\n", It.X);
+
+  for (S::iterator It = std::begin(Ss), E = std::end(Ss); It != E; ++It) {
+printf("s1 has value %d\n", (*It).X);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto & It : Ss)
+  // CHECK-FIXES-NEXT: printf("s1 has value %d\n", It.X);
+
+  for (S::iterator It = begin(*Ps), E = end(*Ps); It 

[PATCH] D58818: [clang-tidy] added cppcoreguidelines-use-raii-locks check

2023-03-26 Thread Chris Cotter via Phabricator via cfe-commits
ccotter added a comment.
Herald added subscribers: mgehre, shchenz.
Herald added projects: clang-tools-extra, All.

bump - I know this is really old, but @lewmpk do you plan on finishing up the 
last remaining comments?


Repository:
  rCTE Clang Tools Extra

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

https://reviews.llvm.org/D58818

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


[PATCH] D146929: [clang-tidy] Ignore unevaluated exprs in rvalue-reference-param-not-moved

2023-03-26 Thread Chris Cotter via Phabricator via cfe-commits
ccotter added a comment.

I didn't update the release notes since this check is new.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146929

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


[PATCH] D146929: [clang-tidy] Ignore unevaluated exprs in rvalue-reference-param-not-moved

2023-03-26 Thread Chris Cotter via Phabricator via cfe-commits
ccotter created this revision.
Herald added subscribers: PiotrZSL, carlosgalvezp, kbarton, xazax.hun, nemanjai.
Herald added a reviewer: njames93.
Herald added a project: All.
ccotter requested review of this revision.
Herald added a project: clang-tools-extra.
Herald added a subscriber: cfe-commits.

Ignore unevaluated expressions in rvalue-reference-param-not-moved
check since they are not actual uses of a move().


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D146929

Files:
  
clang-tools-extra/clang-tidy/cppcoreguidelines/RvalueReferenceParamNotMovedCheck.cpp
  
clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/rvalue-reference-param-not-moved.cpp


Index: 
clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/rvalue-reference-param-not-moved.cpp
===
--- 
clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/rvalue-reference-param-not-moved.cpp
+++ 
clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/rvalue-reference-param-not-moved.cpp
@@ -156,6 +156,13 @@
   Obj moved = std::move((o));
 }
 
+void does_not_move_in_evaluated(Obj&& o) {
+  // CHECK-MESSAGES: :[[@LINE-1]]:39: warning: rvalue reference parameter 'o' 
is never moved from inside the function body 
[cppcoreguidelines-rvalue-reference-param-not-moved]
+  using result_t = decltype(std::move(o));
+  unsigned size = sizeof(std::move(o));
+  Obj moved = o;
+}
+
 template 
 struct mypair {
   T1 first;
Index: 
clang-tools-extra/clang-tidy/cppcoreguidelines/RvalueReferenceParamNotMovedCheck.cpp
===
--- 
clang-tools-extra/clang-tidy/cppcoreguidelines/RvalueReferenceParamNotMovedCheck.cpp
+++ 
clang-tools-extra/clang-tidy/cppcoreguidelines/RvalueReferenceParamNotMovedCheck.cpp
@@ -8,6 +8,7 @@
 
 #include "RvalueReferenceParamNotMovedCheck.h"
 #include "clang/AST/ASTContext.h"
+#include "clang/AST/ExprConcepts.h"
 #include "clang/ASTMatchers/ASTMatchFinder.h"
 
 using namespace clang::ast_matchers;
@@ -15,6 +16,23 @@
 namespace clang::tidy::cppcoreguidelines {
 
 namespace {
+AST_MATCHER(Expr, hasUnevaluatedContext) {
+  if (isa(Node) || isa(Node))
+return true;
+  if (const auto *UnaryExpr = dyn_cast(&Node)) {
+switch (UnaryExpr->getKind()) {
+case UETT_SizeOf:
+case UETT_AlignOf:
+  return true;
+default:
+  return false;
+}
+  }
+  if (const auto *TypeIDExpr = dyn_cast(&Node))
+return !TypeIDExpr->isPotentiallyEvaluated();
+  return false;
+}
+
 AST_MATCHER_P(LambdaExpr, valueCapturesVar, DeclarationMatcher, VarMatcher) {
   return std::find_if(Node.capture_begin(), Node.capture_end(),
   [&](const LambdaCapture &Capture) {
@@ -39,16 +57,18 @@
 
   StatementMatcher MoveCallMatcher =
   callExpr(
+  argumentCountIs(1),
   anyOf(callee(functionDecl(hasName("::std::move"))),
 callee(unresolvedLookupExpr(hasAnyDeclaration(
 namedDecl(hasUnderlyingDecl(hasName("::std::move"))),
-  argumentCountIs(1),
   hasArgument(
   0, argumentOf(
  AllowPartialMove,
  declRefExpr(to(equalsBoundNode("param"))).bind("ref"))),
   unless(hasAncestor(
-  lambdaExpr(valueCapturesVar(equalsBoundNode("param"))
+  lambdaExpr(valueCapturesVar(equalsBoundNode("param"),
+  unless(anyOf(hasAncestor(typeLoc()),
+   hasAncestor(expr(hasUnevaluatedContext())
   .bind("move-call");
 
   Finder->addMatcher(


Index: clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/rvalue-reference-param-not-moved.cpp
===
--- clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/rvalue-reference-param-not-moved.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/rvalue-reference-param-not-moved.cpp
@@ -156,6 +156,13 @@
   Obj moved = std::move((o));
 }
 
+void does_not_move_in_evaluated(Obj&& o) {
+  // CHECK-MESSAGES: :[[@LINE-1]]:39: warning: rvalue reference parameter 'o' is never moved from inside the function body [cppcoreguidelines-rvalue-reference-param-not-moved]
+  using result_t = decltype(std::move(o));
+  unsigned size = sizeof(std::move(o));
+  Obj moved = o;
+}
+
 template 
 struct mypair {
   T1 first;
Index: clang-tools-extra/clang-tidy/cppcoreguidelines/RvalueReferenceParamNotMovedCheck.cpp
===
--- clang-tools-extra/clang-tidy/cppcoreguidelines/RvalueReferenceParamNotMovedCheck.cpp
+++ clang-tools-extra/clang-tidy/cppcoreguidelines/RvalueReferenceParamNotMovedCheck.cpp
@@ -8,6 +8,7 @@
 
 #include "RvalueReferenceParamNotMovedCheck.h"
 #include "clang/AST/ASTContext.h"
+#include "clang/AST/ExprConcepts.h"
 #include "clang/ASTMatchers/ASTMatchFinder.h"
 
 using namespace clang::ast_matche

[PATCH] D141892: Implement modernize-use-constraints

2023-03-26 Thread Chris Cotter via Phabricator via cfe-commits
ccotter updated this revision to Diff 508452.
ccotter added a comment.

rebase


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D141892

Files:
  clang-tools-extra/clang-tidy/modernize/CMakeLists.txt
  clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp
  clang-tools-extra/clang-tidy/modernize/UseConstraintsCheck.cpp
  clang-tools-extra/clang-tidy/modernize/UseConstraintsCheck.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-constraints.rst
  
clang-tools-extra/test/clang-tidy/checkers/modernize/use-constraints-first-greatergreater.cpp
  clang-tools-extra/test/clang-tidy/checkers/modernize/use-constraints.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/modernize/use-constraints.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/modernize/use-constraints.cpp
@@ -0,0 +1,693 @@
+// RUN: %check_clang_tidy -std=c++20 %s modernize-use-constraints %t -- -- -fno-delayed-template-parsing
+
+// NOLINTBEGIN
+namespace std {
+template  struct enable_if { };
+
+template  struct enable_if { typedef T type; };
+
+template 
+using enable_if_t = typename enable_if::type;
+
+} // namespace std
+// NOLINTEND
+
+template 
+struct ConsumeVariadic;
+
+struct Obj {
+};
+
+namespace enable_if_in_return_type {
+
+
+// Section 1: enable_if in return type of function
+
+
+
+// General tests
+
+
+template 
+typename std::enable_if::type basic() {
+  return Obj{};
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
+// CHECK-FIXES: {{^}}Obj basic() requires T::some_value {{{$}}
+
+template 
+std::enable_if_t basic_t() {
+  return Obj{};
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
+// CHECK-FIXES: {{^}}Obj basic_t() requires T::some_value {{{$}}
+
+template 
+auto basic_trailing() -> typename std::enable_if::type {
+  return Obj{};
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:26: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
+// CHECK-FIXES: {{^}}auto basic_trailing() -> Obj requires T::some_value {{{$}}
+
+template 
+typename std::enable_if::type existing_constraint() requires (T::another_value) {
+  return Obj{};
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
+// CHECK-FIXES: {{^}}typename std::enable_if::type existing_constraint() requires (T::another_value) {{{$}}
+
+template 
+typename std::enable_if::type decl_without_def();
+
+template 
+typename std::enable_if::type decl_with_separate_def();
+
+template 
+typename std::enable_if::type decl_with_separate_def() {
+  return Obj{};
+}
+// FIXME - Support definitions with separate decls
+
+template 
+std::enable_if_t no_dependent_type(U) {
+  return Obj{};
+}
+// FIXME - Support non-dependent enable_ifs. Low priority though...
+
+template 
+typename std::enable_if::type* pointer_of_enable_if() {
+  return nullptr;
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
+// CHECK-FIXES: {{^}}template {{$}}
+// CHECK-FIXES-NEXT: {{^}}int* pointer_of_enable_if() requires T::some_value {{{$}}
+
+template 
+std::enable_if_t* pointer_of_enable_if_t() {
+  return nullptr;
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
+// CHECK-FIXES: {{^}}template {{$}}
+// CHECK-FIXES-NEXT: {{^}}int* pointer_of_enable_if_t() requires T::some_value {{{$}}
+
+template 
+const std::enable_if_t* const_pointer_of_enable_if_t() {
+  return nullptr;
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:7: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
+// CHECK-FIXES: {{^}}template {{$}}
+// CHECK-FIXES-NEXT: {{^}}const int* const_pointer_of_enable_if_t() requires T::some_value {{{$}}
+
+template 
+std::enable_if_t const * const_pointer_of_enable_if_t2() {
+  return nullptr;
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
+// CHECK-FIXES: {{^}}template {{$}}
+// CHECK-FIXES-NEXT: {{^}}int const * const_pointer_of_enable_if_t2() requires T::some_value {{{$}}
+
+
+template 
+std::enable_if_t& reference_of_enable_if_t() {
+  static int x; return x;
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
+// CHECK-FIXES: {{^}}template {{$}}
+// CHECK-FIXES-NEXT: {{^}}int& reference_of_enable_if_t() requires T::some

[PATCH] D145138: [clang-tidy] Implement FixIts for C arrays

2023-03-26 Thread Chris Cotter via Phabricator via cfe-commits
ccotter updated this revision to Diff 508451.
ccotter added a comment.

rebase


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D145138

Files:
  clang-tools-extra/clang-tidy/modernize/AvoidCArraysCheck.cpp
  clang-tools-extra/clang-tidy/modernize/AvoidCArraysCheck.h
  clang-tools-extra/clang-tidy/modernize/UseTrailingReturnTypeCheck.cpp
  clang-tools-extra/clang-tidy/modernize/UseTrailingReturnTypeCheck.h
  clang-tools-extra/clang-tidy/utils/CMakeLists.txt
  clang-tools-extra/clang-tidy/utils/LexerUtils.cpp
  clang-tools-extra/clang-tidy/utils/TypeUtils.cpp
  clang-tools-extra/clang-tidy/utils/TypeUtils.h
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/modernize/avoid-c-arrays.rst
  clang-tools-extra/test/clang-tidy/checkers/modernize/avoid-c-arrays-cxx17.cpp
  clang-tools-extra/test/clang-tidy/checkers/modernize/avoid-c-arrays.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/modernize/avoid-c-arrays.cpp
===
--- clang-tools-extra/test/clang-tidy/checkers/modernize/avoid-c-arrays.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/modernize/avoid-c-arrays.cpp
@@ -1,4 +1,6 @@
-// RUN: %check_clang_tidy %s modernize-avoid-c-arrays %t
+// RUN: %check_clang_tidy -std=c++11 %s modernize-avoid-c-arrays %t
+
+//CHECK-FIXES: #include 
 
 int a[] = {1, 2};
 // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: do not declare C-style arrays, use std::array<> instead
@@ -86,3 +88,262 @@
   int j[1];
 };
 }
+
+template  struct TStruct {};
+
+void replacements() {
+  int ar[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: std::array ar;
+  TStruct ar2[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: std::array, 10> ar2;
+  TStruct< int > ar3[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: std::array, 10> ar3;
+  int * ar4[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: std::array ar4;
+  int * /*comment*/ar5[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: std::array /*comment*/ar5;
+  volatile const int * ar6[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: std::array ar6;
+  volatile int ar7[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: volatile std::array ar7;
+  int const * ar8[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: std::array ar8;
+  int ar9[1];
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: std::array ar9;
+  static int volatile constexpr ar10[10] = {};
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: static volatile constexpr std::array ar10 = { {} };
+  thread_local int ar11[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: thread_local std::array ar11;
+  thread_local/*a*/int/*b*/ar12[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: thread_local/*a*/std::array/*b*/ar12;
+  /*a*/ int/*b*/ /*c*/*/*d*/ /*e*/ /*f*/ar13[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: /*a*/ std::array/*d*/ /*e*/ /*f*/ar13;
+  TStruct ar14[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: std::array, 10> ar14;
+  volatile TStruct ar15[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: volatile std::array, 10> ar15;
+  TStruct ar16[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: std::array, 10> ar16;
+  TStruct ar17[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: std::array, 10> ar17;
+  volatile int static thread_local * ar18[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: static thread_local std::array ar18;
+
+  // Note, there is a tab '\t' before the semicolon in the declaration below.
+  int ar19[3]	;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare 

[PATCH] D146921: [clang-tidy] Implement cppcoreguidelines F.19

2023-03-26 Thread Chris Cotter via Phabricator via cfe-commits
ccotter updated this revision to Diff 508450.
ccotter added a comment.

- add tests, simplify expr, handle unevaluated exprs
- formatting


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146921

Files:
  clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt
  clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp
  
clang-tools-extra/clang-tidy/cppcoreguidelines/ForwardingReferenceParamNotForwardedCheck.cpp
  
clang-tools-extra/clang-tidy/cppcoreguidelines/ForwardingReferenceParamNotForwardedCheck.h
  clang-tools-extra/docs/ReleaseNotes.rst
  
clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/forwarding-reference-param-not-forwarded.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  
clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/forwarding-reference-param-not-forwarded.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/forwarding-reference-param-not-forwarded.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/forwarding-reference-param-not-forwarded.cpp
@@ -0,0 +1,138 @@
+// RUN: %check_clang_tidy %s cppcoreguidelines-forwarding-reference-param-not-forwarded %t
+
+// NOLINTBEGIN
+namespace std {
+
+template  struct remove_reference  { using type = T; };
+template  struct remove_reference  { using type = T; };
+template  struct remove_reference { using type = T; };
+
+template  using remove_reference_t = typename remove_reference::type;
+
+template  constexpr T &&forward(remove_reference_t &t) noexcept;
+template  constexpr T &&forward(remove_reference_t &&t) noexcept;
+template  constexpr remove_reference_t &&move(T &&x);
+
+} // namespace std
+// NOLINTEND
+
+struct S {
+  S();
+  S(const S&);
+  S(S&&) noexcept;
+  S& operator=(const S&);
+  S& operator=(S&&) noexcept;
+};
+
+template 
+void consumes_all(Ts&&...);
+
+namespace positive_cases {
+
+template 
+void does_not_forward(T&& t) {
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: forwarding reference parameter 't' is never forwarded inside the function body [cppcoreguidelines-forwarding-reference-param-not-forwarded]
+  T other = t;
+}
+
+template 
+void does_not_forward_invoked(T&& t) {
+  // CHECK-MESSAGES: :[[@LINE-1]]:35: warning: forwarding reference parameter 't' is never forwarded inside the function body [cppcoreguidelines-forwarding-reference-param-not-forwarded]
+  T other = t();
+}
+
+template 
+void forwards_pairwise(T&& t) {
+  // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: forwarding reference parameter 't' is never forwarded inside the function body [cppcoreguidelines-forwarding-reference-param-not-forwarded]
+  auto first = std::forward(t.first);
+  auto second = std::forward(t.second);
+}
+
+template 
+void does_not_forward_pack(Ts&&... ts) {
+  // CHECK-MESSAGES: :[[@LINE-1]]:36: warning: forwarding reference parameter 'ts' is never forwarded inside the function body [cppcoreguidelines-forwarding-reference-param-not-forwarded]
+  consumes_all(ts...);
+}
+
+template 
+class AClass {
+
+  template 
+  AClass(U&& u) : data(u) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: forwarding reference parameter 'u' is never forwarded inside the function body [cppcoreguidelines-forwarding-reference-param-not-forwarded]
+
+  template 
+  AClass& operator=(U&& u) { }
+  // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: forwarding reference parameter 'u' is never forwarded inside the function body [cppcoreguidelines-forwarding-reference-param-not-forwarded]
+
+  template 
+  void mixed_params(T&& t, U&& u) {
+// CHECK-MESSAGES: :[[@LINE-1]]:32: warning: forwarding reference parameter 'u' is never forwarded inside the function body [cppcoreguidelines-forwarding-reference-param-not-forwarded]
+T other1 = std::move(t);
+U other2 = std::move(u);
+  }
+
+  T data;
+};
+
+template 
+void does_not_forward_in_evaluated_code(T&& t) {
+  // CHECK-MESSAGES: :[[@LINE-1]]:45: warning: forwarding reference parameter 't' is never forwarded inside the function body [cppcoreguidelines-forwarding-reference-param-not-forwarded]
+  using result_t = decltype(std::forward(t));
+  unsigned len = sizeof(std::forward(t));
+  T other = t;
+}
+
+} // namespace positive_cases
+
+namespace negative_cases {
+
+template 
+void just_a_decl(T&&t);
+
+template 
+void does_forward(T&& t) {
+  T other = std::forward(t);
+}
+
+template 
+void does_forward_pack(Ts&&... ts) {
+  consumes_all(std::forward(ts)...);
+}
+
+void pass_by_value(S s) {
+  S other = std::move(s);
+}
+
+void lvalue_ref(S& s) {
+  S other = std::move(s);
+}
+
+void rvalue_ref(S&& s) {
+  S other = std::move(s);
+}
+
+template 
+void templated_rvalue_ref(std::remove_reference_t&& t) {
+  T other = std::move(t);
+}
+
+template 
+class AClass {
+
+  template 
+  AClass(U&& u) : data(std::forward(u)) {}
+
+  template 
+  AClass& operator=(

[PATCH] D146921: [clang-tidy] Implement cppcoreguidelines F.19

2023-03-26 Thread Chris Cotter via Phabricator via cfe-commits
ccotter added inline comments.



Comment at: 
clang-tools-extra/clang-tidy/cppcoreguidelines/ForwardingReferenceParamNotForwardedCheck.cpp:83-84
+
+  if (!Param)
+return;
+

PiotrZSL wrote:
> I thing this can never happen
Another review suggested I check the matched node for nullness, even though it 
was the only possible match (https://reviews.llvm.org/D140793). I'll keep it as 
is since in the spirit of defensive programming and to assist future developers 
who may add more matches that might invalidate the invariant that `Param` is 
always non-null.



Comment at: 
clang-tools-extra/clang-tidy/cppcoreguidelines/ForwardingReferenceParamNotForwardedCheck.h:32
+  }
+};
+

PiotrZSL wrote:
> add here that thing about UnlessSpelledInSource
Sorry, I think I'm missing some context here. Would you mind clarifying your 
comment?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146921

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


[PATCH] D146921: [clang-tidy] Implement cppcoreguidelines F.19

2023-03-26 Thread Chris Cotter via Phabricator via cfe-commits
ccotter updated this revision to Diff 508441.
ccotter marked 4 inline comments as done.
ccotter retitled this revision from "[clang-tidy] Implement cppcoreguidelines 
F.19  " to "[clang-tidy] Implement cppcoreguidelines F.19".
ccotter added a comment.

- add tests, simplify expr, handle unevaluated exprs


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146921

Files:
  clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt
  clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp
  
clang-tools-extra/clang-tidy/cppcoreguidelines/ForwardingReferenceParamNotForwardedCheck.cpp
  
clang-tools-extra/clang-tidy/cppcoreguidelines/ForwardingReferenceParamNotForwardedCheck.h
  clang-tools-extra/docs/ReleaseNotes.rst
  
clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/forwarding-reference-param-not-forwarded.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  
clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/forwarding-reference-param-not-forwarded.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/forwarding-reference-param-not-forwarded.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/forwarding-reference-param-not-forwarded.cpp
@@ -0,0 +1,138 @@
+// RUN: %check_clang_tidy %s cppcoreguidelines-forwarding-reference-param-not-forwarded %t
+
+// NOLINTBEGIN
+namespace std {
+
+template  struct remove_reference  { using type = T; };
+template  struct remove_reference  { using type = T; };
+template  struct remove_reference { using type = T; };
+
+template  using remove_reference_t = typename remove_reference::type;
+
+template  constexpr T &&forward(remove_reference_t &t) noexcept;
+template  constexpr T &&forward(remove_reference_t &&t) noexcept;
+template  constexpr remove_reference_t &&move(T &&x);
+
+} // namespace std
+// NOLINTEND
+
+struct S {
+  S();
+  S(const S&);
+  S(S&&) noexcept;
+  S& operator=(const S&);
+  S& operator=(S&&) noexcept;
+};
+
+template 
+void consumes_all(Ts&&...);
+
+namespace positive_cases {
+
+template 
+void does_not_forward(T&& t) {
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: forwarding reference parameter 't' is never forwarded inside the function body [cppcoreguidelines-forwarding-reference-param-not-forwarded]
+  T other = t;
+}
+
+template 
+void does_not_forward_invoked(T&& t) {
+  // CHECK-MESSAGES: :[[@LINE-1]]:35: warning: forwarding reference parameter 't' is never forwarded inside the function body [cppcoreguidelines-forwarding-reference-param-not-forwarded]
+  T other = t();
+}
+
+template 
+void forwards_pairwise(T&& t) {
+  // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: forwarding reference parameter 't' is never forwarded inside the function body [cppcoreguidelines-forwarding-reference-param-not-forwarded]
+  auto first = std::forward(t.first);
+  auto second = std::forward(t.second);
+}
+
+template 
+void does_not_forward_pack(Ts&&... ts) {
+  // CHECK-MESSAGES: :[[@LINE-1]]:36: warning: forwarding reference parameter 'ts' is never forwarded inside the function body [cppcoreguidelines-forwarding-reference-param-not-forwarded]
+  consumes_all(ts...);
+}
+
+template 
+class AClass {
+
+  template 
+  AClass(U&& u) : data(u) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: forwarding reference parameter 'u' is never forwarded inside the function body [cppcoreguidelines-forwarding-reference-param-not-forwarded]
+
+  template 
+  AClass& operator=(U&& u) { }
+  // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: forwarding reference parameter 'u' is never forwarded inside the function body [cppcoreguidelines-forwarding-reference-param-not-forwarded]
+
+  template 
+  void mixed_params(T&& t, U&& u) {
+// CHECK-MESSAGES: :[[@LINE-1]]:32: warning: forwarding reference parameter 'u' is never forwarded inside the function body [cppcoreguidelines-forwarding-reference-param-not-forwarded]
+T other1 = std::move(t);
+U other2 = std::move(u);
+  }
+
+  T data;
+};
+
+template 
+void does_not_forward_in_evaluated_code(T&& t) {
+  // CHECK-MESSAGES: :[[@LINE-1]]:45: warning: forwarding reference parameter 't' is never forwarded inside the function body [cppcoreguidelines-forwarding-reference-param-not-forwarded]
+  using result_t = decltype(std::forward(t));
+  unsigned len = sizeof(std::forward(t));
+  T other = t;
+}
+
+} // namespace positive_cases
+
+namespace negative_cases {
+
+template 
+void just_a_decl(T&&t);
+
+template 
+void does_forward(T&& t) {
+  T other = std::forward(t);
+}
+
+template 
+void does_forward_pack(Ts&&... ts) {
+  consumes_all(std::forward(ts)...);
+}
+
+void pass_by_value(S s) {
+  S other = std::move(s);
+}
+
+void lvalue_ref(S& s) {
+  S other = std::move(s);
+}
+
+void rvalue_ref(S&& s) {
+  S other = std::move(s);
+}
+
+template 
+void templated_rvalue_ref(std::remove_refer

[PATCH] D146921: Reviewers:

2023-03-26 Thread Chris Cotter via Phabricator via cfe-commits
ccotter created this revision.
Herald added subscribers: PiotrZSL, carlosgalvezp, kbarton, nemanjai.
Herald added a reviewer: njames93.
Herald added a project: All.
ccotter requested review of this revision.
Herald added a project: clang-tools-extra.
Herald added a subscriber: cfe-commits.

Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D146921

Files:
  clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt
  clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp
  
clang-tools-extra/clang-tidy/cppcoreguidelines/ForwardingReferenceParamNotForwardedCheck.cpp
  
clang-tools-extra/clang-tidy/cppcoreguidelines/ForwardingReferenceParamNotForwardedCheck.h
  clang-tools-extra/docs/ReleaseNotes.rst
  
clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/forwarding-reference-param-not-forwarded.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  
clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/forwarding-reference-param-not-forwarded.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/forwarding-reference-param-not-forwarded.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/forwarding-reference-param-not-forwarded.cpp
@@ -0,0 +1,105 @@
+// RUN: %check_clang_tidy %s cppcoreguidelines-forwarding-reference-param-not-forwarded %t
+
+// NOLINTBEGIN
+namespace std {
+
+template  struct remove_reference  { using type = T; };
+template  struct remove_reference  { using type = T; };
+template  struct remove_reference { using type = T; };
+
+template  using remove_reference_t = typename remove_reference::type;
+
+template  constexpr T &&forward(remove_reference_t &t) noexcept;
+template  constexpr T &&forward(remove_reference_t &&t) noexcept;
+template  constexpr remove_reference_t &&move(T &&x);
+
+} // namespace std
+// NOLINTEND
+
+struct S {
+  S();
+  S(const S&);
+  S(S&&) noexcept;
+  S& operator=(const S&);
+  S& operator=(S&&) noexcept;
+};
+
+template 
+void consumes_all(Ts&&...);
+
+namespace positive_cases {
+
+template 
+void does_not_forward(T&& t) {
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: forwarding reference parameter 't' is never forwarded inside the function body [cppcoreguidelines-forwarding-reference-param-not-forwarded]
+  T other = t;
+}
+
+template 
+void does_not_forward_invoked(T&& t) {
+  // CHECK-MESSAGES: :[[@LINE-1]]:35: warning: forwarding reference parameter 't' is never forwarded inside the function body [cppcoreguidelines-forwarding-reference-param-not-forwarded]
+  T other = t();
+}
+
+template 
+void forwards_pairwise(T&& t) {
+  // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: forwarding reference parameter 't' is never forwarded inside the function body [cppcoreguidelines-forwarding-reference-param-not-forwarded]
+  auto first = std::forward(t.first);
+  auto second = std::forward(t.second);
+}
+
+template 
+void does_not_forward_pack(Ts&&... ts) {
+  // CHECK-MESSAGES: :[[@LINE-1]]:36: warning: forwarding reference parameter 'ts' is never forwarded inside the function body [cppcoreguidelines-forwarding-reference-param-not-forwarded]
+  consumes_all(ts...);
+}
+
+template 
+class AClass {
+  template 
+  void mixed_params(T&& t, U&& u) {
+// CHECK-MESSAGES: :[[@LINE-1]]:32: warning: forwarding reference parameter 'u' is never forwarded inside the function body [cppcoreguidelines-forwarding-reference-param-not-forwarded]
+T other1 = std::move(t);
+U other2 = std::move(u);
+  }
+};
+
+} // namespace positive_cases
+
+namespace negative_cases {
+
+template 
+void does_forward(T&& t) {
+  T other = std::forward(t);
+}
+
+template 
+void does_forward_pack(Ts&&... ts) {
+  consumes_all(std::forward(ts)...);
+}
+
+void pass_by_value(S s) {
+  S other = std::move(s);
+}
+
+void lvalue_ref(S& s) {
+  S other = std::move(s);
+}
+
+void rvalue_ref(S&& s) {
+  S other = std::move(s);
+}
+
+template 
+void templated_rvalue_ref(std::remove_reference_t&& t) {
+  T other = std::move(t);
+}
+
+template 
+class AClass {
+  void rvalue_ref(T&& t) {
+T other = std::move(t);
+  }
+};
+
+} // namespace negative_cases
Index: clang-tools-extra/docs/clang-tidy/checks/list.rst
===
--- clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -186,6 +186,7 @@
`cppcoreguidelines-avoid-goto `_,
`cppcoreguidelines-avoid-non-const-global-variables `_,
`cppcoreguidelines-avoid-reference-coroutine-parameters `_,
+   `cppcoreguidelines-forwarding-reference-param-not-forwarded `_, "Yes"
`cppcoreguidelines-init-variables `_, "Yes"
`cppcoreguidelines-interfaces-global-init `_,
`cppcoreguidelines-macro-usage `_,
Index: clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/forwarding-reference-param-not-forwarded.rst
===

[PATCH] D144347: [clang-tidy] Add readability-forward-usage check

2023-03-26 Thread Chris Cotter via Phabricator via cfe-commits
ccotter added a comment.

Is it worth adding a cppcoreguidelines alias (ES.56)?




Comment at: 
clang-tools-extra/docs/clang-tidy/checks/readability/forward-usage.rst:98
+
+.. option:: DisableTypeMismatchSuggestion
+

Curious what others thing but I think the tool should by default not remove or 
replace `forward` with static_cast.  When an author has written `forward`, 
there is a good chance they intended to forward something (e.g., they forgot to 
use `&&` in the parameter declaration). My hypothesis is that it's more likely 
the author intended to forward something, rather than than they were trying to 
use it as a cast (but had not intention of forward - why else would they have 
typed it out?). In this case, I think it merits manual review by default (so 
the tool should always warn, but without the fixits by default).


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D144347

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


[PATCH] D146888: [clang-tidy] Flag std::forward on non-forwarding references

2023-03-26 Thread Chris Cotter via Phabricator via cfe-commits
ccotter abandoned this revision.
ccotter added a comment.

Indeed - sorry i missed that


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146888

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


[PATCH] D145138: [clang-tidy] Implement FixIts for C arrays

2023-03-25 Thread Chris Cotter via Phabricator via cfe-commits
ccotter updated this revision to Diff 508351.
ccotter marked 8 inline comments as done.
ccotter added a comment.

- feedback


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D145138

Files:
  clang-tools-extra/clang-tidy/modernize/AvoidCArraysCheck.cpp
  clang-tools-extra/clang-tidy/modernize/AvoidCArraysCheck.h
  clang-tools-extra/clang-tidy/modernize/UseTrailingReturnTypeCheck.cpp
  clang-tools-extra/clang-tidy/modernize/UseTrailingReturnTypeCheck.h
  clang-tools-extra/clang-tidy/utils/CMakeLists.txt
  clang-tools-extra/clang-tidy/utils/LexerUtils.cpp
  clang-tools-extra/clang-tidy/utils/TypeUtils.cpp
  clang-tools-extra/clang-tidy/utils/TypeUtils.h
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/modernize/avoid-c-arrays.rst
  clang-tools-extra/test/clang-tidy/checkers/modernize/avoid-c-arrays-cxx17.cpp
  clang-tools-extra/test/clang-tidy/checkers/modernize/avoid-c-arrays.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/modernize/avoid-c-arrays.cpp
===
--- clang-tools-extra/test/clang-tidy/checkers/modernize/avoid-c-arrays.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/modernize/avoid-c-arrays.cpp
@@ -1,4 +1,6 @@
-// RUN: %check_clang_tidy %s modernize-avoid-c-arrays %t
+// RUN: %check_clang_tidy -std=c++11 %s modernize-avoid-c-arrays %t
+
+//CHECK-FIXES: #include 
 
 int a[] = {1, 2};
 // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: do not declare C-style arrays, use std::array<> instead
@@ -86,3 +88,262 @@
   int j[1];
 };
 }
+
+template  struct TStruct {};
+
+void replacements() {
+  int ar[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: std::array ar;
+  TStruct ar2[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: std::array, 10> ar2;
+  TStruct< int > ar3[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: std::array, 10> ar3;
+  int * ar4[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: std::array ar4;
+  int * /*comment*/ar5[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: std::array /*comment*/ar5;
+  volatile const int * ar6[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: std::array ar6;
+  volatile int ar7[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: volatile std::array ar7;
+  int const * ar8[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: std::array ar8;
+  int ar9[1];
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: std::array ar9;
+  static int volatile constexpr ar10[10] = {};
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: static volatile constexpr std::array ar10 = { {} };
+  thread_local int ar11[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: thread_local std::array ar11;
+  thread_local/*a*/int/*b*/ar12[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: thread_local/*a*/std::array/*b*/ar12;
+  /*a*/ int/*b*/ /*c*/*/*d*/ /*e*/ /*f*/ar13[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: /*a*/ std::array/*d*/ /*e*/ /*f*/ar13;
+  TStruct ar14[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: std::array, 10> ar14;
+  volatile TStruct ar15[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: volatile std::array, 10> ar15;
+  TStruct ar16[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: std::array, 10> ar16;
+  TStruct ar17[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: std::array, 10> ar17;
+  volatile int static thread_local * ar18[10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: do not declare C-style arrays, use std::array<> instead
+  // CHECK-FIXES: static thread_local std::array ar18;
+
+  // Note, there is a tab '\t' before the semicolon in the declaration below.
+  int ar19[3]	;
+  // CHECK-MESS

[PATCH] D146888: [clang-tidy] Flag std::forward on non-forwarding references

2023-03-25 Thread Chris Cotter via Phabricator via cfe-commits
ccotter created this revision.
Herald added subscribers: PiotrZSL, carlosgalvezp, kbarton, xazax.hun, nemanjai.
Herald added a reviewer: njames93.
Herald added a project: All.
ccotter requested review of this revision.
Herald added a project: clang-tools-extra.
Herald added a subscriber: cfe-commits.

Implement the std::forward specific enforcement of ES.56.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D146888

Files:
  clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt
  clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp
  
clang-tools-extra/clang-tidy/cppcoreguidelines/ForwardNonForwardingParameterCheck.cpp
  
clang-tools-extra/clang-tidy/cppcoreguidelines/ForwardNonForwardingParameterCheck.h
  clang-tools-extra/docs/ReleaseNotes.rst
  
clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/forward-non-forwarding-parameter.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  
clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/forward-non-forwarding-parameter.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/forward-non-forwarding-parameter.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/forward-non-forwarding-parameter.cpp
@@ -0,0 +1,163 @@
+// RUN: %check_clang_tidy %s cppcoreguidelines-forward-non-forwarding-parameter %t
+
+// NOLINTBEGIN
+namespace std {
+
+template  struct remove_reference  { using type = T; };
+template  struct remove_reference  { using type = T; };
+template  struct remove_reference { using type = T; };
+
+template  using remove_reference_t = typename remove_reference::type;
+
+template  constexpr T &&forward(remove_reference_t &t) noexcept;
+template  constexpr T &&forward(remove_reference_t &&t) noexcept;
+
+} // namespace std
+// NOLINTEND
+
+struct Obj {
+  Obj();
+  Obj(const Obj&);
+  Obj(Obj&&) noexcept;
+  Obj& operator=(const Obj&);
+  Obj& operator=(Obj&&) noexcept;
+};
+
+template 
+void consumes_all(Ts&&...);
+
+namespace positive_cases {
+
+void forward_local_object() {
+  Obj obj;
+  Obj& obj_ref = obj;
+
+  Obj obj2 = std::forward(obj);
+  // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: calling std::forward on non-forwarding reference 'obj' [cppcoreguidelines-forward-non-forwarding-parameter]
+
+  Obj obj3 = std::forward(obj_ref);
+  // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: calling std::forward on non-forwarding reference 'obj_ref' [cppcoreguidelines-forward-non-forwarding-parameter]
+}
+
+void forward_value_param(Obj obj) {
+  Obj obj2 = std::forward(obj);
+  // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: calling std::forward on non-forwarding reference 'obj' [cppcoreguidelines-forward-non-forwarding-parameter]
+}
+
+template 
+void forward_pack_of_values(Ts... ts) {
+  consumes_all(std::forward(ts)...);
+  // CHECK-MESSAGES: :[[@LINE-1]]:33: warning: calling std::forward on non-forwarding reference 'ts' [cppcoreguidelines-forward-non-forwarding-parameter]
+}
+
+template 
+void forward_pack_of_lvalue_refs(Ts&... ts) {
+  consumes_all(std::forward(ts)...);
+  // CHECK-MESSAGES: :[[@LINE-1]]:33: warning: calling std::forward on non-forwarding reference 'ts' [cppcoreguidelines-forward-non-forwarding-parameter]
+}
+
+void forward_lvalue_ref(Obj& obj) {
+  Obj obj2 = std::forward(obj);
+  // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: calling std::forward on non-forwarding reference 'obj' [cppcoreguidelines-forward-non-forwarding-parameter]
+}
+
+void forward_const_lvalue_ref(const Obj& obj) {
+  Obj obj2 = std::forward(obj);
+  // CHECK-MESSAGES: :[[@LINE-1]]:38: warning: calling std::forward on non-forwarding reference 'obj' [cppcoreguidelines-forward-non-forwarding-parameter]
+}
+
+void forward_rvalue_ref(Obj&& obj) {
+  Obj obj2 = std::forward(obj);
+  // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: calling std::forward on rvalue reference 'obj'; use std::move instead [cppcoreguidelines-forward-non-forwarding-parameter]
+  // CHECK-FIXES: Obj obj2 = std::move(obj);
+}
+
+void forward_const_rvalue_ref(const Obj&& obj) {
+  Obj obj2 = std::forward(obj);
+  // CHECK-MESSAGES: :[[@LINE-1]]:38: warning: calling std::forward on non-forwarding reference 'obj' [cppcoreguidelines-forward-non-forwarding-parameter]
+}
+
+template 
+void forward_value_t(T t) {
+  T other = std::forward(t);
+  // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: calling std::forward on non-forwarding reference 't' [cppcoreguidelines-forward-non-forwarding-parameter]
+}
+
+template 
+void forward_lvalue_ref_t(T& t) {
+  T other = std::forward(t);
+  // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: calling std::forward on non-forwarding reference 't' [cppcoreguidelines-forward-non-forwarding-parameter]
+}
+
+template 
+void forward_const_rvalue_ref_t(const T&& t) {
+  T other = std::forward(t);
+  // CHECK-MESSAGES: :[[@LINE-1]]:35: warning: calling std::forward on non-forwarding reference 't' [cppcoreguideline

[PATCH] D143971: [clang-tidy] Flag more buggy string constructor cases

2023-03-25 Thread Chris Cotter via Phabricator via cfe-commits
ccotter marked an inline comment as done.
ccotter added inline comments.



Comment at: 
clang-tools-extra/clang-tidy/bugprone/StringConstructorCheck.cpp:70-74
+  const auto CharExpr = expr(anyOf(
+  ignoringParenImpCasts(characterLiteral()),
+  
declRefExpr(hasDeclaration(varDecl(hasType(qualType(isAnyCharacter()),
+  ignoringParens(callExpr(
+  callee(functionDecl(returns(qualType(isAnyCharacter();

PiotrZSL wrote:
> add a testcase with:
> ```
> char& chRef = ch;
> std::string swapped2(chRef, i);
> 
> char* chPtr = &ch;
> std::string swapped2(*chPtr, i);
> 
> using Character = char;
> Character  c;
> std::string swapped2(c, i);
> ```
> 
> I fear that it may not match those, because here you are trying to match 
> specific use cases, when you should simply match a type of expression. In 
> such case this should be just:
> ```
> const auto CharExpr = 
> expr(hasType(qualType(hasCanonicalType(anyOf(isAnyCharacter(), 
> references(isAnyCharacter()));
> ```
> 
> Only issue would be implicit cast, you can try deal with them by using 
> ignoringImplicit, or in better way just by using:
> 
> ```
> traverse(TK_IgnoreUnlessSpelledInSource,  hasArgument(0, 
> CharExpr.bind("swapped-parameter"))),
> ```
> TK_IgnoreUnlessSpelledInSource will cut of all implicit operations, so you 
> could check if called constructor is actually the wrong one, and check 
> argument types. Because now macher in line 125 may not always work if somehow 
> we would have for example 2 implicit casts, for example from char reference 
> to char, or some other crap.
> 
> It's up to you, but consider more generic approach instead of matching 
> specific use cases like references to variables, or calls.
> 
Thinking about this more, I think we have to keep the "args swapped" case very 
narrow to the existing patterns of the first arg being a char literal, and the 
second being an integer literal. Consider

```
char buffer[] = "abcdef";
char& chRef = ch;
std::string not_swapped(chRef, 4); // Forgot '&' in front of 'chRef'

std::string also_not_swapped(buffer[2], 2); // Forgot '&' in front of 
'buffer[2]'
```

Neither of these are swapped arg bugs, so I don't think we can have the tool 
consider this a swapped arg bug and apply fixits. The `also_not_swapped` is the 
exact bug I wrote a few weeks ago.

I think there are two types of bugs the tool has to be aware of with respect to 
the string fill constructor
 1. swapped args
 2. "confusing" args - where the arguments are both implicitly cast from int to 
char and vice versa.

For swapped args, the existing logic will match when the first arg has 
`isInteger()` type, and the second arg is `characterLiteral()`. At most, I 
think we can only expand the logic to include constructor exprs when the second 
arg is a declRefExpr to a `char`, but not char ref (see the `not_swapped` 
example above), or when the second arg is the result of a function call that 
returns a char. In these cases, we can be sure that the the author did not mean 
to put a `&` in front of the second argument expression.

For "confusing" args, which is not implemented in the existing logic, but I am 
proposing in this change, this is the more general case where I think the logic 
should match any expression as long as both argument expressions are implicitly 
cast. This is "confusing" because int-to-char and char-to-int conversions are 
not obvious to the reader, and it should be rare for both conversions to take 
place when calling the fill constructor (confirmed anecdotally in the codebases 
I've checked). The tool could not offer fixits here since the fix might be to 
swap the args, or to add a `&` in front of the first arg (or even another 
change). At most, we can warn and alert the user to the problem. If this is 
what the author intended, they can use explicit casts to make the intent 
obvious to the reader.



Comment at: clang-tools-extra/clang-tidy/bugprone/StringConstructorCheck.cpp:95
+  const auto NonCharacterInteger =
+  qualType(isInteger(), unless(isAnyCharacter()));
+  const auto CharToIntCastExpr = implicitCastExpr(

PiotrZSL wrote:
> what about references to integer, or typedefs to integers ?
I'll add a test for reference to integer, but I'm matching on the type of the 
source expression that is being cast, which will be of integer type, even if 
the expression is `string str(x, y)` and `y` is an `int&` (the source 
expression in the cast will be of type `int`).



Comment at: clang-tools-extra/clang-tidy/bugprone/StringConstructorCheck.cpp:213
 }
+  } else if (const auto *E =
+ Result.Nodes.getNodeAs("implicit-cast-both-args")) {

PiotrZSL wrote:
> i thing that this case should be matched by "swapped-parameter", no need to 
> add extra one, just first one should be fixed.
See earlier explanation on why we can't treat these all as swapped parameters 
cases.


=

[PATCH] D143971: [clang-tidy] Flag more buggy string constructor cases

2023-03-25 Thread Chris Cotter via Phabricator via cfe-commits
ccotter updated this revision to Diff 508345.
ccotter marked 4 inline comments as done.
ccotter added a comment.

- Add more cases to swapped params
- Change message, add more tests


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D143971

Files:
  clang-tools-extra/clang-tidy/bugprone/StringConstructorCheck.cpp
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/bugprone/string-constructor.rst
  clang-tools-extra/test/clang-tidy/checkers/bugprone/string-constructor.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/bugprone/string-constructor.cpp
===
--- clang-tools-extra/test/clang-tidy/checkers/bugprone/string-constructor.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/bugprone/string-constructor.cpp
@@ -5,12 +5,13 @@
 class allocator {};
 template 
 class char_traits {};
-template , typename A = std::allocator >
+template , typename A = std::allocator>
 struct basic_string {
   basic_string();
-  basic_string(const C*, unsigned int size);
-  basic_string(const C *, const A &allocator = A());
-  basic_string(unsigned int size, C c);
+  basic_string(const basic_string&, unsigned int, unsigned int, const A & = A());
+  basic_string(const C*, unsigned int);
+  basic_string(const C*, const A& = A());
+  basic_string(unsigned int, C);
 };
 typedef basic_string string;
 typedef basic_string wstring;
@@ -18,7 +19,7 @@
 template >
 struct basic_string_view {
   basic_string_view();
-  basic_string_view(const C *, unsigned int size);
+  basic_string_view(const C *, unsigned int);
   basic_string_view(const C *);
 };
 typedef basic_string_view string_view;
@@ -28,20 +29,74 @@
 const char* kText = "";
 const char kText2[] = "";
 extern const char kText3[];
+char getChar();
+const char* getCharPtr();
+
+struct CharLikeObj {
+  operator char() const;
+};
 
 void Test() {
-  std::string str('x', 4);
-  // CHECK-MESSAGES: [[@LINE-1]]:15: warning: string constructor parameters are probably swapped; expecting string(count, character) [bugprone-string-constructor]
-  // CHECK-FIXES: std::string str(4, 'x');
-  std::wstring wstr(L'x', 4);
-  // CHECK-MESSAGES: [[@LINE-1]]:16: warning: string constructor parameters are probably swapped
-  // CHECK-FIXES: std::wstring wstr(4, L'x');
+  short sh;
+  int i;
+  int& ref_i = i;
+  char ch;
+  CharLikeObj char_like_obj;
+
+  std::string swapped('x', 4);
+  // CHECK-MESSAGES: [[@LINE-1]]:15: warning: string constructor arguments are probably swapped; expecting string(count, character) [bugprone-string-constructor]
+  // CHECK-FIXES: std::string swapped(4, 'x');
+  std::wstring wswapped(L'x', 4);
+  // CHECK-MESSAGES: [[@LINE-1]]:16: warning: string constructor arguments are probably swapped; expecting string(count, character) [bugprone-string-constructor]
+  // CHECK-FIXES: std::wstring wswapped(4, L'x');
+  std::string swapped2('x', i);
+  // CHECK-MESSAGES: [[@LINE-1]]:15: warning: string constructor arguments are probably swapped; expecting string(count, character) [bugprone-string-constructor]
+  // CHECK-FIXES: std::string swapped2(i, 'x');
+  std::string swapped3(ch, 4);
+  // CHECK-MESSAGES: [[@LINE-1]]:15: warning: string constructor arguments are probably swapped; expecting string(count, character) [bugprone-string-constructor]
+  // CHECK-FIXES: std::string swapped3(4, ch);
+  std::string swapped4(ch, i);
+  // CHECK-MESSAGES: [[@LINE-1]]:15: warning: string constructor arguments are probably swapped; expecting string(count, character) [bugprone-string-constructor]
+  // CHECK-FIXES: std::string swapped4(i, ch);
+  std::string swapped5('x', (int)'x');
+  // CHECK-MESSAGES: [[@LINE-1]]:15: warning: string constructor arguments are probably swapped; expecting string(count, character) [bugprone-string-constructor]
+  // CHECK-FIXES: std::string swapped5((int)'x', 'x');
+  std::string swapped6(getChar(), 10);
+  // CHECK-MESSAGES: [[@LINE-1]]:15: warning: string constructor arguments are probably swapped; expecting string(count, character) [bugprone-string-constructor]
+  // CHECK-FIXES: std::string swapped6(10, getChar());
+  std::string swapped7((('x')), ( i ));
+  // CHECK-MESSAGES: [[@LINE-1]]:15: warning: string constructor arguments are probably swapped; expecting string(count, character) [bugprone-string-constructor]
+  // CHECK-FIXES: std::string swapped7(( i ), (('x')));
+  std::string swapped8((ch), (i));
+  // CHECK-MESSAGES: [[@LINE-1]]:15: warning: string constructor arguments are probably swapped; expecting string(count, character) [bugprone-string-constructor]
+  // CHECK-FIXES: std::string swapped8((i), (ch));
+  std::string swapped9((getChar()), (i));
+  // CHECK-MESSAGES: [[@LINE-1]]:15: warning: string constructor arguments are probably swapped; expecting string(count, character) [bugprone-string-constructor]
+  // CHECK-FIXES: std::string swapped9((i), (getChar()));
   

[PATCH] D145138: [clang-tidy] Implement FixIts for C arrays

2023-03-25 Thread Chris Cotter via Phabricator via cfe-commits
ccotter added inline comments.
Herald added a subscriber: PiotrZSL.



Comment at: clang-tools-extra/clang-tidy/modernize/AvoidCArraysCheck.cpp:588
+: ClangTidyCheck(Name, Context),
+  IncludeInserter(Options.getLocalOrGlobal("IncludeStyle",
+   utils::IncludeSorter::IS_LLVM),

Eugene.Zelenko wrote:
> ccotter wrote:
> > Eugene.Zelenko wrote:
> > > Should be global option, because it's used in other checks.
> > Could you clarify this a bit? This is how most other tests consume 
> > IncludeStyle (`Options.getLocalOrGlobal("IncludeStyle", 
> > utils::IncludeSorter::IS_LLVM)`.
> @carlosgalvezp is best person to answer because he recently introduced global 
> option for source files and headers.
bump @carlosgalvezp 


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D145138

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


[PATCH] D141892: Implement modernize-use-constraints

2023-03-18 Thread Chris Cotter via Phabricator via cfe-commits
ccotter updated this revision to Diff 506339.
ccotter added a comment.
Herald added a subscriber: PiotrZSL.

rebase


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D141892

Files:
  clang-tools-extra/clang-tidy/modernize/CMakeLists.txt
  clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp
  clang-tools-extra/clang-tidy/modernize/UseConstraintsCheck.cpp
  clang-tools-extra/clang-tidy/modernize/UseConstraintsCheck.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-constraints.rst
  
clang-tools-extra/test/clang-tidy/checkers/modernize/use-constraints-first-greatergreater.cpp
  clang-tools-extra/test/clang-tidy/checkers/modernize/use-constraints.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/modernize/use-constraints.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/modernize/use-constraints.cpp
@@ -0,0 +1,693 @@
+// RUN: %check_clang_tidy -std=c++20 %s modernize-use-constraints %t -- -- -fno-delayed-template-parsing
+
+// NOLINTBEGIN
+namespace std {
+template  struct enable_if { };
+
+template  struct enable_if { typedef T type; };
+
+template 
+using enable_if_t = typename enable_if::type;
+
+} // namespace std
+// NOLINTEND
+
+template 
+struct ConsumeVariadic;
+
+struct Obj {
+};
+
+namespace enable_if_in_return_type {
+
+
+// Section 1: enable_if in return type of function
+
+
+
+// General tests
+
+
+template 
+typename std::enable_if::type basic() {
+  return Obj{};
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
+// CHECK-FIXES: {{^}}Obj basic() requires T::some_value {{{$}}
+
+template 
+std::enable_if_t basic_t() {
+  return Obj{};
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
+// CHECK-FIXES: {{^}}Obj basic_t() requires T::some_value {{{$}}
+
+template 
+auto basic_trailing() -> typename std::enable_if::type {
+  return Obj{};
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:26: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
+// CHECK-FIXES: {{^}}auto basic_trailing() -> Obj requires T::some_value {{{$}}
+
+template 
+typename std::enable_if::type existing_constraint() requires (T::another_value) {
+  return Obj{};
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
+// CHECK-FIXES: {{^}}typename std::enable_if::type existing_constraint() requires (T::another_value) {{{$}}
+
+template 
+typename std::enable_if::type decl_without_def();
+
+template 
+typename std::enable_if::type decl_with_separate_def();
+
+template 
+typename std::enable_if::type decl_with_separate_def() {
+  return Obj{};
+}
+// FIXME - Support definitions with separate decls
+
+template 
+std::enable_if_t no_dependent_type(U) {
+  return Obj{};
+}
+// FIXME - Support non-dependent enable_ifs. Low priority though...
+
+template 
+typename std::enable_if::type* pointer_of_enable_if() {
+  return nullptr;
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
+// CHECK-FIXES: {{^}}template {{$}}
+// CHECK-FIXES-NEXT: {{^}}int* pointer_of_enable_if() requires T::some_value {{{$}}
+
+template 
+std::enable_if_t* pointer_of_enable_if_t() {
+  return nullptr;
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
+// CHECK-FIXES: {{^}}template {{$}}
+// CHECK-FIXES-NEXT: {{^}}int* pointer_of_enable_if_t() requires T::some_value {{{$}}
+
+template 
+const std::enable_if_t* const_pointer_of_enable_if_t() {
+  return nullptr;
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:7: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
+// CHECK-FIXES: {{^}}template {{$}}
+// CHECK-FIXES-NEXT: {{^}}const int* const_pointer_of_enable_if_t() requires T::some_value {{{$}}
+
+template 
+std::enable_if_t const * const_pointer_of_enable_if_t2() {
+  return nullptr;
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
+// CHECK-FIXES: {{^}}template {{$}}
+// CHECK-FIXES-NEXT: {{^}}int const * const_pointer_of_enable_if_t2() requires T::some_value {{{$}}
+
+
+template 
+std::enable_if_t& reference_of_enable_if_t() {
+  static int x; return x;
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
+// CHECK-FIXES: {{^}}template {{$}}
+// CHECK-FIXES-NEXT: {{^}}int& refere

[PATCH] D141569: [clang-tidy] Implement CppCoreGuideline F.18

2023-03-12 Thread Chris Cotter via Phabricator via cfe-commits
ccotter added a comment.

Thanks!


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D141569

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


  1   2   3   >