Home | History | Annotate | Download | only in SemaCXX
      1 // RUN: %clang_cc1 -fsyntax-only -Wpessimizing-move -std=c++11 -verify %s
      2 // RUN: %clang_cc1 -fsyntax-only -Wpessimizing-move -std=c++11 -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s
      3 
      4 // definitions for std::move
      5 namespace std {
      6 inline namespace foo {
      7 template <class T> struct remove_reference { typedef T type; };
      8 template <class T> struct remove_reference<T&> { typedef T type; };
      9 template <class T> struct remove_reference<T&&> { typedef T type; };
     10 
     11 template <class T> typename remove_reference<T>::type &&move(T &&t);
     12 }
     13 }
     14 
     15 struct A {};
     16 struct B {
     17   B() {}
     18   B(A) {}
     19 };
     20 
     21 A test1(A a1) {
     22   A a2;
     23   return a1;
     24   return a2;
     25   return std::move(a1);
     26   return std::move(a2);
     27   // expected-warning@-1{{prevents copy elision}}
     28   // expected-note@-2{{remove std::move call}}
     29   // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:20}:""
     30   // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:22-[[@LINE-4]]:23}:""
     31 }
     32 
     33 B test2(A a1, B b1) {
     34   // Object is different than return type so don't warn.
     35   A a2;
     36   return a1;
     37   return a2;
     38   return std::move(a1);
     39   return std::move(a2);
     40 
     41   B b2;
     42   return b1;
     43   return b2;
     44   return std::move(b1);
     45   return std::move(b2);
     46   // expected-warning@-1{{prevents copy elision}}
     47   // expected-note@-2{{remove std::move call}}
     48   // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:20}:""
     49   // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:22-[[@LINE-4]]:23}:""
     50 }
     51 
     52 A global_a;
     53 A test3() {
     54   // Don't warn when object is not local.
     55   return global_a;
     56   return std::move(global_a);
     57   static A static_a;
     58   return static_a;
     59   return std::move(static_a);
     60 
     61 }
     62 
     63 A test4() {
     64   return A();
     65   return test3();
     66 
     67   return std::move(A());
     68   // expected-warning@-1{{prevents copy elision}}
     69   // expected-note@-2{{remove std::move call}}
     70   // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:20}:""
     71   // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:23-[[@LINE-4]]:24}:""
     72   return std::move(test3());
     73   // expected-warning@-1{{prevents copy elision}}
     74   // expected-note@-2{{remove std::move call}}
     75   // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:20}:""
     76   // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:27-[[@LINE-4]]:28}:""
     77 }
     78 
     79 void test5(A) {
     80   test5(A());
     81   test5(test4());
     82 
     83   test5(std::move(A()));
     84   // expected-warning@-1{{prevents copy elision}}
     85   // expected-note@-2{{remove std::move call}}
     86   // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:19}:""
     87   // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:22-[[@LINE-4]]:23}:""
     88   test5(std::move(test4()));
     89   // expected-warning@-1{{prevents copy elision}}
     90   // expected-note@-2{{remove std::move call}}
     91   // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:19}:""
     92   // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:26-[[@LINE-4]]:27}:""
     93 }
     94 
     95 void test6() {
     96   A a1 = A();
     97   A a2 = test3();
     98 
     99   A a3 = std::move(A());
    100   // expected-warning@-1{{prevents copy elision}}
    101   // expected-note@-2{{remove std::move call}}
    102   // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:20}:""
    103   // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:23-[[@LINE-4]]:24}:""
    104   A a4 = std::move(test3());
    105   // expected-warning@-1{{prevents copy elision}}
    106   // expected-note@-2{{remove std::move call}}
    107   // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:20}:""
    108   // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:27-[[@LINE-4]]:28}:""
    109 }
    110 
    111 A test7() {
    112   A a1 = std::move(A());
    113   // expected-warning@-1{{prevents copy elision}}
    114   // expected-note@-2{{remove std::move call}}
    115   // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:20}:""
    116   // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:23-[[@LINE-4]]:24}:""
    117   A a2 = std::move((A()));
    118   // expected-warning@-1{{prevents copy elision}}
    119   // expected-note@-2{{remove std::move call}}
    120   // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:20}:""
    121   // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:25-[[@LINE-4]]:26}:""
    122   A a3 = (std::move(A()));
    123   // expected-warning@-1{{prevents copy elision}}
    124   // expected-note@-2{{remove std::move call}}
    125   // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:11-[[@LINE-3]]:21}:""
    126   // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:24-[[@LINE-4]]:25}:""
    127   A a4 = (std::move((A())));
    128   // expected-warning@-1{{prevents copy elision}}
    129   // expected-note@-2{{remove std::move call}}
    130   // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:11-[[@LINE-3]]:21}:""
    131   // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:26-[[@LINE-4]]:27}:""
    132 
    133   return std::move(a1);
    134   // expected-warning@-1{{prevents copy elision}}
    135   // expected-note@-2{{remove std::move call}}
    136   // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:20}:""
    137   // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:22-[[@LINE-4]]:23}:""
    138   return std::move((a1));
    139   // expected-warning@-1{{prevents copy elision}}
    140   // expected-note@-2{{remove std::move call}}
    141   // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:20}:""
    142   // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:24-[[@LINE-4]]:25}:""
    143   return (std::move(a1));
    144   // expected-warning@-1{{prevents copy elision}}
    145   // expected-note@-2{{remove std::move call}}
    146   // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:11-[[@LINE-3]]:21}:""
    147   // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:23-[[@LINE-4]]:24}:""
    148   return (std::move((a1)));
    149   // expected-warning@-1{{prevents copy elision}}
    150   // expected-note@-2{{remove std::move call}}
    151   // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:11-[[@LINE-3]]:21}:""
    152   // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:25-[[@LINE-4]]:26}:""
    153 }
    154 
    155 #define wrap1(x) x
    156 #define wrap2(x) x
    157 
    158 // Macro test. Since the std::move call is outside the macro, it is
    159 // safe to suggest a fix-it.
    160 A test8() {
    161   A a;
    162   return std::move(a);
    163   // expected-warning@-1{{prevents copy elision}}
    164   // expected-note@-2{{remove std::move call}}
    165   // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:20}:""
    166   // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:21-[[@LINE-4]]:22}:""
    167   return std::move(wrap1(a));
    168   // expected-warning@-1{{prevents copy elision}}
    169   // expected-note@-2{{remove std::move call}}
    170   // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:20}:""
    171   // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:28-[[@LINE-4]]:29}:""
    172   return std::move(wrap1(wrap2(a)));
    173   // expected-warning@-1{{prevents copy elision}}
    174   // expected-note@-2{{remove std::move call}}
    175   // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:20}:""
    176   // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:35-[[@LINE-4]]:36}:""
    177 }
    178 
    179 #define test9            \
    180   A test9() {            \
    181     A a;                 \
    182     return std::move(a); \
    183   }
    184 
    185 // Macro test.  The std::call is inside the macro, so no fix-it is suggested.
    186 test9
    187 // expected-warning@-1{{prevents copy elision}}
    188 // CHECK-NOT: fix-it
    189 
    190 #define return_a return std::move(a)
    191 
    192 // Macro test.  The std::call is inside the macro, so no fix-it is suggested.
    193 A test10() {
    194   A a;
    195   return_a;
    196   // expected-warning@-1{{prevents copy elision}}
    197   // CHECK-NOT: fix-it
    198 }
    199 
    200 namespace templates {
    201   struct A {};
    202   struct B { B(A); };
    203 
    204   // Warn once here since the type is not dependent.
    205   template <typename T>
    206   A test1() {
    207     A a;
    208     return std::move(a);
    209     // expected-warning@-1{{prevents copy elision}}
    210     // expected-note@-2{{remove std::move call}}
    211     // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:12-[[@LINE-3]]:22}:""
    212     // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:23-[[@LINE-4]]:24}:""
    213   }
    214   void run_test1() {
    215     test1<A>();
    216     test1<B>();
    217   }
    218 
    219   // T1 and T2 may not be the same, the warning may not always apply.
    220   template <typename T1, typename T2>
    221   T1 test2() {
    222     T2 t;
    223     return std::move(t);
    224   }
    225   void run_test2() {
    226     test2<A, A>();
    227     test2<B, A>();
    228   }
    229 }
    230