(root)/
gcc-13.2.0/
gcc/
testsuite/
g++.dg/
warn/
Wself-move1.C
// PR c++/81159
// { dg-do compile { target c++11 } }
// { dg-options "-Wself-move" }

// Define std::move.
namespace std {
  template<typename _Tp>
    struct remove_reference
    { typedef _Tp   type; };

  template<typename _Tp>
    struct remove_reference<_Tp&>
    { typedef _Tp   type; };

  template<typename _Tp>
    struct remove_reference<_Tp&&>
    { typedef _Tp   type; };

  template<typename _Tp>
    constexpr typename std::remove_reference<_Tp>::type&&
    move(_Tp&& __t) noexcept
    { return static_cast<typename std::remove_reference<_Tp>::type&&>(__t); }
}

int g;

struct S {
  int x;
  S(S&& o) {
    x = std::move (x); // { dg-warning "moving '\[^\n\r]*S::x' of type .int. to itself" }
    x = std::move (o.x);
    o.x = std::move (x);
    o.x = std::move (o.x); // { dg-warning "moving 'o.S::x' of type .int. to itself" }
  }
  void foo (int x) {
    x = std::move (x); // { dg-warning "moving 'x' of type .int. to itself" }
  }
};

struct X {
  int x;
  X(int x) : x(std::move (x)) { }
};

struct A {};
struct B { A a; };
struct C { C(); ~C(); };
struct D { D(); D(const D&); D(D&&); D& operator=(const D&); };

void
test ()
{
  int i = 42;
  i = std::move (i); // { dg-warning "moving 'i' of type .int. to itself" }
  (i) = std::move (i); // { dg-warning "moving 'i' of type .int. to itself" }

  g = std::move (g); // { dg-warning "moving 'g' of type .int. to itself" }
  (g) = std::move (g); // { dg-warning "moving 'g' of type .int. to itself" }

  A a;
  a = std::move (a); // { dg-warning "moving 'a' of type .A. to itself" }
  (a) = std::move (a); // { dg-warning "moving 'a' of type .A. to itself" }

  B b;
  b = std::move (b); // { dg-warning "moving 'b' of type .B. to itself" }
  (b) = std::move (b); // { dg-warning "moving 'b' of type .B. to itself" }
  b.a = std::move (b.a); // { dg-warning "moving 'b.B::a' of type .A. to itself" }
  (b.a) = std::move (b.a); // { dg-warning "moving 'b.B::a' of type .A. to itself" }

  C c;
  c = std::move (c); // { dg-warning "moving 'c' of type .C. to itself" }
  D d;
  d = std::move (d); // { dg-warning "moving 'd' of type .D. to itself" }
}

template<typename T>
void ttest ()
{
  T t;
  t = std::move (t); // { dg-warning "moving 't' of type .A. to itself" }
}

template void ttest<A>();

void
testref (int &r, int &&rr)
{
  r = std::move (r); // { dg-warning "moving 'r' of type .int. to itself" }
  rr = std::move (rr); // { dg-warning "moving 'rr' of type .int. to itself" }
}

// Test various other arguments to std::move.
template<typename T>
void
testargs (T *Tptr, T **Tpptr, T& Tref, T&& Trref, const T *Tcptr)
{
  Tptr = std::move (Tptr); // { dg-warning "moving 'Tptr' of type 'int\\*' to itself" }
  *Tptr = std::move (*Tptr); // { dg-warning "moving '\\* Tptr' of type 'int' to itself" }
  *Tptr = std::move (*(Tptr)); // { dg-warning "moving '\\* Tptr' of type 'int' to itself" }
  *(Tptr) = std::move (*Tptr); // { dg-warning "moving '\\* Tptr' of type 'int' to itself" }
  *(Tptr + 1) = std::move (*(Tptr + 1)); // { dg-warning "moving '\[^\n\r]*Tptr\[^\n\r]*' of type 'int' to itself" }
  *(Tptr + 1) = std::move (*(Tptr + 2));
  (*(Tptr)) = std::move (*Tptr); // { dg-warning "moving '\\* Tptr' of type 'int' to itself" }
  *Tpptr = std::move (*Tpptr); // { dg-warning "moving '\\* Tpptr' of type 'int\\*' to itself" }
  **Tpptr = std::move (**Tpptr); // { dg-warning "moving '\\* \\* Tpptr' of type 'int' to itself" }
  Tref = std::move (Tref); // { dg-warning "moving 'Tref' of type 'int' to itself" }
  Trref = std::move (Trref); // { dg-warning "moving 'Trref' of type 'int' to itself" }
  Tcptr = std::move (Tcptr); // { dg-warning "moving 'Tcptr' of type 'const int\\*' to itself" }
  (Tptr) = std::move (Tptr); // { dg-warning "moving 'Tptr' of type 'int\\*' to itself" }
  (*Tptr) = std::move (*Tptr); // { dg-warning "moving '\\* Tptr' of type 'int' to itself" }
  (*Tpptr) = std::move (*Tpptr); // { dg-warning "moving '\\* Tpptr' of type 'int\\*' to itself" }
  (**Tpptr) = std::move (**Tpptr); // { dg-warning "moving '\\* \\* Tpptr' of type 'int' to itself" }
  (*(*(Tpptr))) = std::move (**Tpptr); // { dg-warning "moving '\\* \\* Tpptr' of type 'int' to itself" }
  (Tref) = std::move (Tref); // { dg-warning "moving 'Tref' of type 'int' to itself" }
  (Trref) = std::move (Trref); // { dg-warning "moving 'Trref' of type 'int' to itself" }
  (Tcptr) = std::move (Tcptr); // { dg-warning "moving 'Tcptr' of type 'const int\\*' to itself" }
}

void
call_testargs ()
{
  int i = 42;
  int *p = &i;
  testargs<int>(&i, &p, i, 42, &i);
}