forked from OSchip/llvm-project
				
			
		
			
				
	
	
		
			257 lines
		
	
	
		
			8.2 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			257 lines
		
	
	
		
			8.2 KiB
		
	
	
	
		
			C++
		
	
	
	
| // RUN: %clang_cc1 -fsyntax-only -Wpessimizing-move -std=c++11 -verify %s
 | |
| // RUN: %clang_cc1 -fsyntax-only -Wpessimizing-move -std=c++11 -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s
 | |
| 
 | |
| // definitions for std::move
 | |
| namespace std {
 | |
| inline namespace foo {
 | |
| template <class T> struct remove_reference { typedef T type; };
 | |
| template <class T> struct remove_reference<T&> { typedef T type; };
 | |
| template <class T> struct remove_reference<T&&> { typedef T type; };
 | |
| 
 | |
| template <class T> typename remove_reference<T>::type &&move(T &&t);
 | |
| }
 | |
| }
 | |
| 
 | |
| struct A {};
 | |
| struct B {
 | |
|   B() {}
 | |
|   B(A) {}
 | |
| };
 | |
| 
 | |
| A test1(A a1) {
 | |
|   A a2;
 | |
|   return a1;
 | |
|   return a2;
 | |
|   return std::move(a1);
 | |
|   return std::move(a2);
 | |
|   // expected-warning@-1{{prevents copy elision}}
 | |
|   // expected-note@-2{{remove std::move call}}
 | |
|   // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:20}:""
 | |
|   // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:22-[[@LINE-4]]:23}:""
 | |
| }
 | |
| 
 | |
| B test2(A a1, B b1) {
 | |
|   // Object is different than return type so don't warn.
 | |
|   A a2;
 | |
|   return a1;
 | |
|   return a2;
 | |
|   return std::move(a1);
 | |
|   return std::move(a2);
 | |
| 
 | |
|   B b2;
 | |
|   return b1;
 | |
|   return b2;
 | |
|   return std::move(b1);
 | |
|   return std::move(b2);
 | |
|   // expected-warning@-1{{prevents copy elision}}
 | |
|   // expected-note@-2{{remove std::move call}}
 | |
|   // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:20}:""
 | |
|   // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:22-[[@LINE-4]]:23}:""
 | |
| }
 | |
| 
 | |
| A global_a;
 | |
| A test3() {
 | |
|   // Don't warn when object is not local.
 | |
|   return global_a;
 | |
|   return std::move(global_a);
 | |
|   static A static_a;
 | |
|   return static_a;
 | |
|   return std::move(static_a);
 | |
| 
 | |
| }
 | |
| 
 | |
| A test4() {
 | |
|   return A();
 | |
|   return test3();
 | |
| 
 | |
|   return std::move(A());
 | |
|   // expected-warning@-1{{prevents copy elision}}
 | |
|   // expected-note@-2{{remove std::move call}}
 | |
|   // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:20}:""
 | |
|   // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:23-[[@LINE-4]]:24}:""
 | |
|   return std::move(test3());
 | |
|   // expected-warning@-1{{prevents copy elision}}
 | |
|   // expected-note@-2{{remove std::move call}}
 | |
|   // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:20}:""
 | |
|   // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:27-[[@LINE-4]]:28}:""
 | |
| }
 | |
| 
 | |
| void test5(A) {
 | |
|   test5(A());
 | |
|   test5(test4());
 | |
| 
 | |
|   test5(std::move(A()));
 | |
|   // expected-warning@-1{{prevents copy elision}}
 | |
|   // expected-note@-2{{remove std::move call}}
 | |
|   // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:19}:""
 | |
|   // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:22-[[@LINE-4]]:23}:""
 | |
|   test5(std::move(test4()));
 | |
|   // expected-warning@-1{{prevents copy elision}}
 | |
|   // expected-note@-2{{remove std::move call}}
 | |
|   // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:19}:""
 | |
|   // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:26-[[@LINE-4]]:27}:""
 | |
| }
 | |
| 
 | |
| void test6() {
 | |
|   A a1 = A();
 | |
|   A a2 = test3();
 | |
| 
 | |
|   A a3 = std::move(A());
 | |
|   // expected-warning@-1{{prevents copy elision}}
 | |
|   // expected-note@-2{{remove std::move call}}
 | |
|   // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:20}:""
 | |
|   // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:23-[[@LINE-4]]:24}:""
 | |
|   A a4 = std::move(test3());
 | |
|   // expected-warning@-1{{prevents copy elision}}
 | |
|   // expected-note@-2{{remove std::move call}}
 | |
|   // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:20}:""
 | |
|   // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:27-[[@LINE-4]]:28}:""
 | |
| }
 | |
| 
 | |
| A test7() {
 | |
|   A a1 = std::move(A());
 | |
|   // expected-warning@-1{{prevents copy elision}}
 | |
|   // expected-note@-2{{remove std::move call}}
 | |
|   // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:20}:""
 | |
|   // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:23-[[@LINE-4]]:24}:""
 | |
|   A a2 = std::move((A()));
 | |
|   // expected-warning@-1{{prevents copy elision}}
 | |
|   // expected-note@-2{{remove std::move call}}
 | |
|   // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:20}:""
 | |
|   // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:25-[[@LINE-4]]:26}:""
 | |
|   A a3 = (std::move(A()));
 | |
|   // expected-warning@-1{{prevents copy elision}}
 | |
|   // expected-note@-2{{remove std::move call}}
 | |
|   // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:21}:""
 | |
|   // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:24-[[@LINE-4]]:26}:""
 | |
|   A a4 = (std::move((A())));
 | |
|   // expected-warning@-1{{prevents copy elision}}
 | |
|   // expected-note@-2{{remove std::move call}}
 | |
|   // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:21}:""
 | |
|   // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:26-[[@LINE-4]]:28}:""
 | |
| 
 | |
|   return std::move(a1);
 | |
|   // expected-warning@-1{{prevents copy elision}}
 | |
|   // expected-note@-2{{remove std::move call}}
 | |
|   // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:20}:""
 | |
|   // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:22-[[@LINE-4]]:23}:""
 | |
|   return std::move((a1));
 | |
|   // expected-warning@-1{{prevents copy elision}}
 | |
|   // expected-note@-2{{remove std::move call}}
 | |
|   // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:20}:""
 | |
|   // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:24-[[@LINE-4]]:25}:""
 | |
|   return (std::move(a1));
 | |
|   // expected-warning@-1{{prevents copy elision}}
 | |
|   // expected-note@-2{{remove std::move call}}
 | |
|   // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:21}:""
 | |
|   // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:23-[[@LINE-4]]:25}:""
 | |
|   return (std::move((a1)));
 | |
|   // expected-warning@-1{{prevents copy elision}}
 | |
|   // expected-note@-2{{remove std::move call}}
 | |
|   // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:21}:""
 | |
|   // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:25-[[@LINE-4]]:27}:""
 | |
| }
 | |
| 
 | |
| #define wrap1(x) x
 | |
| #define wrap2(x) x
 | |
| 
 | |
| // Macro test. Since the std::move call is outside the macro, it is
 | |
| // safe to suggest a fix-it.
 | |
| A test8() {
 | |
|   A a;
 | |
|   return std::move(a);
 | |
|   // expected-warning@-1{{prevents copy elision}}
 | |
|   // expected-note@-2{{remove std::move call}}
 | |
|   // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:20}:""
 | |
|   // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:21-[[@LINE-4]]:22}:""
 | |
|   return std::move(wrap1(a));
 | |
|   // expected-warning@-1{{prevents copy elision}}
 | |
|   // expected-note@-2{{remove std::move call}}
 | |
|   // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:20}:""
 | |
|   // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:28-[[@LINE-4]]:29}:""
 | |
|   return std::move(wrap1(wrap2(a)));
 | |
|   // expected-warning@-1{{prevents copy elision}}
 | |
|   // expected-note@-2{{remove std::move call}}
 | |
|   // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:20}:""
 | |
|   // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:35-[[@LINE-4]]:36}:""
 | |
| }
 | |
| 
 | |
| #define test9            \
 | |
|   A test9() {            \
 | |
|     A a;                 \
 | |
|     return std::move(a); \
 | |
|   }
 | |
| 
 | |
| // Macro test.  The std::call is inside the macro, so no fix-it is suggested.
 | |
| test9
 | |
| // expected-warning@-1{{prevents copy elision}}
 | |
| // CHECK-NOT: fix-it
 | |
| 
 | |
| #define return_a return std::move(a)
 | |
| 
 | |
| // Macro test.  The std::call is inside the macro, so no fix-it is suggested.
 | |
| A test10() {
 | |
|   A a;
 | |
|   return_a;
 | |
|   // expected-warning@-1{{prevents copy elision}}
 | |
|   // CHECK-NOT: fix-it
 | |
| }
 | |
| 
 | |
| namespace templates {
 | |
|   struct A {};
 | |
|   struct B { B(A); };
 | |
| 
 | |
|   // Warn once here since the type is not dependent.
 | |
|   template <typename T>
 | |
|   A test1() {
 | |
|     A a;
 | |
|     return std::move(a);
 | |
|     // expected-warning@-1{{prevents copy elision}}
 | |
|     // expected-note@-2{{remove std::move call}}
 | |
|     // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:12-[[@LINE-3]]:22}:""
 | |
|     // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:23-[[@LINE-4]]:24}:""
 | |
|   }
 | |
|   void run_test1() {
 | |
|     test1<A>();
 | |
|     test1<B>();
 | |
|   }
 | |
| 
 | |
|   // T1 and T2 may not be the same, the warning may not always apply.
 | |
|   template <typename T1, typename T2>
 | |
|   T1 test2() {
 | |
|     T2 t;
 | |
|     return std::move(t);
 | |
|   }
 | |
|   void run_test2() {
 | |
|     test2<A, A>();
 | |
|     test2<B, A>();
 | |
|   }
 | |
| }
 | |
| 
 | |
| A init_list() {
 | |
|   A a1;
 | |
|   return { std::move(a1) };
 | |
|   // expected-warning@-1{{prevents copy elision}}
 | |
|   // expected-note@-2{{remove std::move call}}
 | |
|   // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:22}:""
 | |
|   // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:24-[[@LINE-4]]:27}:""
 | |
| 
 | |
|   return { (std::move(a1)) };
 | |
|   // expected-warning@-1{{prevents copy elision}}
 | |
|   // expected-note@-2{{remove std::move call}}
 | |
|   // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:23}:""
 | |
|   // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:25-[[@LINE-4]]:29}:""
 | |
| 
 | |
|   A a2 = { std::move(A()) };
 | |
|   // expected-warning@-1{{prevents copy elision}}
 | |
|   // expected-note@-2{{remove std::move call}}
 | |
|   // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:22}:""
 | |
|   // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:25-[[@LINE-4]]:28}:""
 | |
| 
 | |
|   A a3 = { (std::move(A())) };
 | |
|   // expected-warning@-1{{prevents copy elision}}
 | |
|   // expected-note@-2{{remove std::move call}}
 | |
|   // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:23}:""
 | |
|   // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:26-[[@LINE-4]]:30}:""
 | |
| }
 |