xref: /aosp_15_r20/external/clang/test/SemaCXX/warn-redundant-move.cpp (revision 67e74705e28f6214e480b399dd47ea732279e315)
1*67e74705SXin Li // RUN: %clang_cc1 -fsyntax-only -Wredundant-move -std=c++11 -verify %s
2*67e74705SXin Li // RUN: %clang_cc1 -fsyntax-only -Wredundant-move -std=c++11 -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s
3*67e74705SXin Li // RUN: %clang_cc1 -fsyntax-only -std=c++11 %s -ast-dump | FileCheck %s --check-prefix=CHECK-AST
4*67e74705SXin Li 
5*67e74705SXin Li // definitions for std::move
6*67e74705SXin Li namespace std {
7*67e74705SXin Li inline namespace foo {
8*67e74705SXin Li template <class T> struct remove_reference { typedef T type; };
9*67e74705SXin Li template <class T> struct remove_reference<T&> { typedef T type; };
10*67e74705SXin Li template <class T> struct remove_reference<T&&> { typedef T type; };
11*67e74705SXin Li 
12*67e74705SXin Li template <class T> typename remove_reference<T>::type &&move(T &&t);
13*67e74705SXin Li }
14*67e74705SXin Li }
15*67e74705SXin Li 
16*67e74705SXin Li // test1 and test2 should not warn until after implementation of DR1579.
17*67e74705SXin Li struct A {};
18*67e74705SXin Li struct B : public A {};
19*67e74705SXin Li 
test1(B b1)20*67e74705SXin Li A test1(B b1) {
21*67e74705SXin Li   B b2;
22*67e74705SXin Li   return b1;
23*67e74705SXin Li   return b2;
24*67e74705SXin Li   return std::move(b1);
25*67e74705SXin Li   return std::move(b2);
26*67e74705SXin Li }
27*67e74705SXin Li 
28*67e74705SXin Li struct C {
CC29*67e74705SXin Li   C() {}
CC30*67e74705SXin Li   C(A) {}
31*67e74705SXin Li };
32*67e74705SXin Li 
test2(A a1,B b1)33*67e74705SXin Li C test2(A a1, B b1) {
34*67e74705SXin Li   A a2;
35*67e74705SXin Li   B b2;
36*67e74705SXin Li 
37*67e74705SXin Li   return a1;
38*67e74705SXin Li   return a2;
39*67e74705SXin Li   return b1;
40*67e74705SXin Li   return b2;
41*67e74705SXin Li 
42*67e74705SXin Li   return std::move(a1);
43*67e74705SXin Li   return std::move(a2);
44*67e74705SXin Li   return std::move(b1);
45*67e74705SXin Li   return std::move(b2);
46*67e74705SXin Li }
47*67e74705SXin Li 
48*67e74705SXin Li // Copy of tests above with types changed to reference types.
test3(B & b1)49*67e74705SXin Li A test3(B& b1) {
50*67e74705SXin Li   B& b2 = b1;
51*67e74705SXin Li   return b1;
52*67e74705SXin Li   return b2;
53*67e74705SXin Li   return std::move(b1);
54*67e74705SXin Li   return std::move(b2);
55*67e74705SXin Li }
56*67e74705SXin Li 
test4(A & a1,B & b1)57*67e74705SXin Li C test4(A& a1, B& b1) {
58*67e74705SXin Li   A& a2 = a1;
59*67e74705SXin Li   B& b2 = b1;
60*67e74705SXin Li 
61*67e74705SXin Li   return a1;
62*67e74705SXin Li   return a2;
63*67e74705SXin Li   return b1;
64*67e74705SXin Li   return b2;
65*67e74705SXin Li 
66*67e74705SXin Li   return std::move(a1);
67*67e74705SXin Li   return std::move(a2);
68*67e74705SXin Li   return std::move(b1);
69*67e74705SXin Li   return std::move(b2);
70*67e74705SXin Li }
71*67e74705SXin Li 
72*67e74705SXin Li // PR23819, case 2
73*67e74705SXin Li struct D {};
test5(D d)74*67e74705SXin Li D test5(D d) {
75*67e74705SXin Li   return d;
76*67e74705SXin Li   // Verify the implicit move from the AST dump
77*67e74705SXin Li   // CHECK-AST: ReturnStmt{{.*}}line:[[@LINE-2]]
78*67e74705SXin Li   // CHECK-AST-NEXT: CXXConstructExpr{{.*}}struct D{{.*}}void (struct D &&)
79*67e74705SXin Li   // CHECK-AST-NEXT: ImplicitCastExpr
80*67e74705SXin Li   // CHECK-AST-NEXT: DeclRefExpr{{.*}}ParmVar{{.*}}'d'
81*67e74705SXin Li 
82*67e74705SXin Li   return std::move(d);
83*67e74705SXin Li   // expected-warning@-1{{redundant move in return statement}}
84*67e74705SXin Li   // expected-note@-2{{remove std::move call here}}
85*67e74705SXin Li   // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:20}:""
86*67e74705SXin Li   // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:21-[[@LINE-4]]:22}:""
87*67e74705SXin Li }
88*67e74705SXin Li 
89*67e74705SXin Li namespace templates {
90*67e74705SXin Li   struct A {};
91*67e74705SXin Li   struct B { B(A); };
92*67e74705SXin Li 
93*67e74705SXin Li   // Warn once here since the type is not dependent.
94*67e74705SXin Li   template <typename T>
test1(A a)95*67e74705SXin Li   A test1(A a) {
96*67e74705SXin Li     return std::move(a);
97*67e74705SXin Li     // expected-warning@-1{{redundant move in return statement}}
98*67e74705SXin Li     // expected-note@-2{{remove std::move call here}}
99*67e74705SXin Li     // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:12-[[@LINE-3]]:22}:""
100*67e74705SXin Li     // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:23-[[@LINE-4]]:24}:""
101*67e74705SXin Li   }
run_test1()102*67e74705SXin Li   void run_test1() {
103*67e74705SXin Li     test1<A>(A());
104*67e74705SXin Li     test1<B>(A());
105*67e74705SXin Li   }
106*67e74705SXin Li 
107*67e74705SXin Li   // T1 and T2 may not be the same, the warning may not always apply.
108*67e74705SXin Li   template <typename T1, typename T2>
test2(T2 t)109*67e74705SXin Li   T1 test2(T2 t) {
110*67e74705SXin Li     return std::move(t);
111*67e74705SXin Li   }
run_test2()112*67e74705SXin Li   void run_test2() {
113*67e74705SXin Li     test2<A, A>(A());
114*67e74705SXin Li     test2<B, A>(A());
115*67e74705SXin Li   }
116*67e74705SXin Li }
117