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