brintos

brintos / llvm-project-archived public Read only

0
0
Text · 4.2 KiB · 9f45367 Raw
126 lines · cpp
1// RUN: %check_clang_tidy -std=c++14-or-later %s bugprone-move-forwarding-reference %t -- -- -fno-delayed-template-parsing2 3namespace std {4template <typename> struct remove_reference;5 6template <typename _Tp> struct remove_reference { typedef _Tp type; };7 8template <typename _Tp> struct remove_reference<_Tp &> { typedef _Tp type; };9 10template <typename _Tp> struct remove_reference<_Tp &&> { typedef _Tp type; };11 12template <typename _Tp>13constexpr typename std::remove_reference<_Tp>::type &&move(_Tp &&__t);14 15} // namespace std16 17// Standard case.18template <typename T, typename U> void f1(U &&SomeU) {19  T SomeT(std::move(SomeU));20  // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: forwarding reference passed to21  // CHECK-FIXES: T SomeT(std::forward<U>(SomeU));22}23 24// Ignore parentheses around the argument to std::move().25template <typename T, typename U> void f2(U &&SomeU) {26  T SomeT(std::move((SomeU)));27  // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: forwarding reference passed to28  // CHECK-FIXES: T SomeT(std::forward<U>((SomeU)));29}30 31// Handle the case correctly where std::move() is being used through a using32// declaration.33template <typename T, typename U> void f3(U &&SomeU) {34  using std::move;35  T SomeT(move(SomeU));36  // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: forwarding reference passed to37  // CHECK-FIXES: T SomeT(std::forward<U>(SomeU));38}39 40// Handle the case correctly where a global specifier is prepended to41// std::move().42template <typename T, typename U> void f4(U &&SomeU) {43  T SomeT(::std::move(SomeU));44  // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: forwarding reference passed to45  // CHECK-FIXES: T SomeT(::std::forward<U>(SomeU));46}47 48// Create a correct fix if there are spaces around the scope resolution49// operator.50template <typename T, typename U> void f5(U &&SomeU) {51  {52    T SomeT(::  std  ::  move(SomeU));53    // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: forwarding reference passed to54    // CHECK-FIXES: T SomeT(::std::forward<U>(SomeU));55  }56  {57    T SomeT(std  ::  move(SomeU));58    // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: forwarding reference passed to59    // CHECK-FIXES: T SomeT(std::forward<U>(SomeU));60  }61}62 63// Ignore const rvalue reference parameters.64template <typename T, typename U> void f6(const U &&SomeU) {65  T SomeT(std::move(SomeU));66}67 68// Ignore the case where the argument to std::move() is a lambda parameter (and69// thus not actually a parameter of the function template).70template <typename T, typename U> void f7() {71  [](U &&SomeU) { T SomeT(std::move(SomeU)); };72}73 74// Ignore the case where the argument is a lvalue reference.75template <typename T, typename U> void f8(U &SomeU) {76  T SomeT(std::move(SomeU));77}78 79// Ignore the case where the template parameter is a class template parameter80// (i.e. no template argument deduction is taking place).81template <typename T, typename U> class SomeClass {82  void f(U &&SomeU) { T SomeT(std::move(SomeU)); }83};84 85// Ignore the case where the function parameter in the template isn't an rvalue86// reference but the template argument is explicitly set to be an rvalue87// reference.88class A {};89template <typename T> void foo(T);90void f8() {91  A a;92  foo<A &&>(std::move(a));93}94 95// A warning is output, but no fix is suggested, if a macro is used to rename96// std::move.97#define MOVE(x) std::move((x))98template <typename T, typename U> void f9(U &&SomeU) {99  T SomeT(MOVE(SomeU));100  // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: forwarding reference passed to101}102 103// Same result if the argument is passed outside of the macro.104#undef MOVE105#define MOVE std::move106template <typename T, typename U> void f10(U &&SomeU) {107  T SomeT(MOVE(SomeU));108  // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: forwarding reference passed to109}110 111// Same result if the macro does not include the "std" namespace.112#undef MOVE113#define MOVE move114template <typename T, typename U> void f11(U &&SomeU) {115  T SomeT(std::MOVE(SomeU));116  // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: forwarding reference passed to117}118 119// Handle the case correctly where the forwarding reference is a parameter of a120// generic lambda.121template <typename T> void f12() {122  [] (auto&& x) { T SomeT(std::move(x)); };123  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: forwarding reference passed to124  // CHECK-FIXES: [] (auto&& x) { T SomeT(std::forward<decltype(x)>(x)); };125}126