Home | History | Annotate | Download | only in dcl.init.ref
      1 // RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify -pedantic %s
      2 
      3 // Test the c++0x-specific reference initialization rules, e.g., the
      4 // rules for rvalue references.
      5 template<typename T> T prvalue();
      6 template<typename T> T&& xvalue();
      7 template<typename T> T& lvalue();
      8 
      9 struct Base { };
     10 struct Derived : Base { };
     11 
     12 struct HasArray {
     13   int array[5];
     14 };
     15 
     16 int f(int);
     17 
     18 template<typename T>
     19 struct ConvertsTo {
     20   operator T(); // expected-note 2{{candidate function}}
     21 };
     22 
     23 void test_rvalue_refs() {
     24   // If the initializer expression...
     25   //   - is an xvalue, class prvalue, array prvalue or function lvalue
     26   //     and "cv1 T1" is reference-compatible with "cv2 T2", or
     27 
     28   // xvalue case
     29   Base&& base0 = xvalue<Base>();
     30   Base&& base1 = xvalue<Derived>();
     31   int&& int0 = xvalue<int>();
     32 
     33   // class prvalue case
     34   Base&& base2 = prvalue<Base>();
     35   Base&& base3 = prvalue<Derived>();
     36 
     37   // array prvalue case
     38   int (&&array0)[5] = HasArray().array;
     39 
     40   // function lvalue case
     41   int (&&function0)(int) = f;
     42 
     43   //   - has a class type (i.e., T2 is a class type), where T1 is not
     44   //     reference-related to T2, and can be implicitly converted to
     45   //     an xvalue, class prvalue, or function lvalue of type "cv3
     46   //     T3", where "cv1 T1" is reference-compatible with "cv3 T3",
     47 
     48   // xvalue
     49   Base&& base4 = ConvertsTo<Base&&>();
     50   Base&& base5 = ConvertsTo<Derived&&>();
     51   int && int1 = ConvertsTo<int&&>();
     52 
     53   // class prvalue
     54   Base&& base6 = ConvertsTo<Base>();
     55   Base&& base7 = ConvertsTo<Derived>();
     56 
     57   // function lvalue
     58   int (&&function1)(int) = ConvertsTo<int(&)(int)>();
     59 
     60   // In the second case, if the reference is an rvalue reference and
     61   // the second standard conversion sequence of the user-defined
     62   // conversion sequence includes an lvalue-to-rvalue conversion, the
     63   // program is ill-formed.
     64   int &&int2 = ConvertsTo<int&>(); // expected-error{{no viable conversion from 'ConvertsTo<int &>' to 'int'}}
     65   int &&int3 = ConvertsTo<float&>(); // expected-error{{no viable conversion from 'ConvertsTo<float &>' to 'int'}}
     66 }
     67 
     68 class NonCopyable {
     69   NonCopyable(const NonCopyable&);
     70 };
     71 
     72 class NonCopyableDerived : public NonCopyable {
     73   NonCopyableDerived(const NonCopyableDerived&);
     74 };
     75 
     76 // Make sure we get direct bindings with no copies.
     77 void test_direct_binding() {
     78   NonCopyable &&nc0 = prvalue<NonCopyable>();
     79   NonCopyable &&nc1 = prvalue<NonCopyableDerived>();
     80   NonCopyable &&nc2 = xvalue<NonCopyable>();
     81   NonCopyable &&nc3 = xvalue<NonCopyableDerived>();
     82   const NonCopyable &nc4 = prvalue<NonCopyable>();
     83   const NonCopyable &nc5 = prvalue<NonCopyableDerived>();
     84   const NonCopyable &nc6 = xvalue<NonCopyable>();
     85   const NonCopyable &nc7 = xvalue<NonCopyableDerived>();
     86   NonCopyable &&nc8 = ConvertsTo<NonCopyable&&>();
     87   NonCopyable &&nc9 = ConvertsTo<NonCopyableDerived&&>();
     88   const NonCopyable &nc10 = ConvertsTo<NonCopyable&&>();
     89   const NonCopyable &nc11 = ConvertsTo<NonCopyableDerived&&>();
     90 }
     91 
     92 namespace std_example_1 {
     93   double d = 2.0;
     94   double& rd = d;
     95   const double& rcd = d;
     96   struct A { };
     97   struct B : A {
     98     operator int&();
     99   } b;
    100   A& ra = b;
    101   const A& rca = b;
    102   int& ir = B();
    103 }
    104 
    105 namespace std_example_2 {
    106   double& rd2 = 2.0; // expected-error{{non-const lvalue reference to type 'double' cannot bind to a temporary of type 'double'}}
    107   int i = 2;
    108   double& rd3 = i; // expected-error{{non-const lvalue reference to type 'double' cannot bind to a value of unrelated type 'int'}}
    109   struct A { };
    110   struct B : A { } b;
    111   extern B f();
    112   const A& rca = f();
    113   A&& rra = f();
    114   struct X {
    115     operator B();  // expected-note{{candidate function}}
    116     operator int&(); // expected-note{{candidate function}}
    117   } x;
    118   const A& r = x;
    119   int&& rri = static_cast<int&&>(i);
    120   B&& rrb = x;
    121   int&& rri2 = X(); // expected-error{{no viable conversion from 'std_example_2::X' to 'int'}}
    122 
    123   const double& rcd2 = 2;
    124   double&& rrd = 2;
    125   const volatile int cvi = 1;
    126   const int& r2 = cvi; // expected-error{{binding value of type 'const volatile int' to reference to type 'const int' drops 'volatile' qualifier}}
    127 
    128   double d;
    129   double&& rrd2 = d; // expected-error{{rvalue reference to type 'double' cannot bind to lvalue of type 'double'}}
    130   double&& rrd3 = i;
    131 }
    132 
    133 namespace argument_passing {
    134   void base_rvalue_ref(Base&&);
    135   void int_rvalue_ref(int&&); // expected-note{{candidate function not viable: no known conversion from 'ConvertsTo<int &>' to 'int &&' for 1st argument}} \
    136   // expected-note{{candidate function not viable: no known conversion from 'ConvertsTo<float &>' to 'int &&' for 1st argument}}
    137 
    138   void array_rvalue_ref(int (&&)[5]);
    139   void function_rvalue_ref(int (&&)(int));
    140 
    141   void test() {
    142     base_rvalue_ref(xvalue<Base>());
    143     base_rvalue_ref(xvalue<Derived>());
    144     int_rvalue_ref(xvalue<int>());
    145 
    146     base_rvalue_ref(prvalue<Base>());
    147     base_rvalue_ref(prvalue<Derived>());
    148 
    149     array_rvalue_ref(HasArray().array);
    150 
    151     function_rvalue_ref(f);
    152 
    153     base_rvalue_ref(ConvertsTo<Base&&>());
    154     base_rvalue_ref(ConvertsTo<Derived&&>());
    155     int_rvalue_ref(ConvertsTo<int&&>());
    156 
    157     base_rvalue_ref(ConvertsTo<Base>());
    158     base_rvalue_ref(ConvertsTo<Derived>());
    159 
    160     function_rvalue_ref(ConvertsTo<int(&)(int)>());
    161 
    162     int_rvalue_ref(ConvertsTo<int&>()); // expected-error{{no matching function for call to 'int_rvalue_ref'}}
    163     int_rvalue_ref(ConvertsTo<float&>()); // expected-error{{no matching function for call to 'int_rvalue_ref'}}
    164   }
    165 
    166 }
    167 
    168 namespace pr10644 {
    169   struct string {
    170     string(const char* __s);
    171   };
    172   class map {
    173     int& operator[](const string& __k);
    174   public:
    175     int& operator[](const string&& __k);
    176   };
    177   void foo() {
    178     static map key_map;
    179     key_map["line"];
    180   }
    181 }
    182 
    183 namespace PR11003 {
    184   class Value {
    185   };
    186   struct MoveRef {
    187     operator Value &() const ;
    188   };
    189   MoveRef Move(int);
    190   void growTo() {
    191     Value x = Move(0);
    192     Value y(Move(0));
    193   }
    194 }
    195 
    196 namespace rdar13278115 {
    197   struct X { };
    198   struct Y : X { };
    199   X &&f0(X &x) { return x; } // expected-error{{rvalue reference to type 'rdar13278115::X' cannot bind to lvalue of type 'rdar13278115::X'}}
    200   X &&f1(Y &y) { return y; } // expected-error{{rvalue reference to type 'rdar13278115::X' cannot bind to lvalue of type 'rdar13278115::Y'}}
    201   const X &&f2(Y &y) { return y; } // expected-error{{rvalue reference to type 'const rdar13278115::X' cannot bind to lvalue of type 'rdar13278115::Y'}}
    202 }
    203 
    204 namespace bitfields {
    205   struct IntBitfield {
    206     int i : 17; // expected-note 3 {{bit-field is declared here}}
    207   };
    208 
    209   // A simplified version of std::move.
    210   template <typename T>
    211   T &&move(T &obj) {
    212     return static_cast<T &&>(obj);
    213   }
    214 
    215   void test() {
    216     int & ir1 = (lvalue<IntBitfield>().i); // expected-error{{non-const reference cannot bind to bit-field 'i'}}
    217     int & ir2 = (xvalue<IntBitfield>().i); // expected-error{{non-const lvalue reference to type 'int' cannot bind to a temporary of type 'int'}}
    218     int && ir3 = (xvalue<IntBitfield>().i); // no-warning
    219     int && ir4 = move(lvalue<IntBitfield>()).i; // no-warning
    220 
    221     volatile int & vir1 = (lvalue<IntBitfield>().i); // expected-error{{non-const reference cannot bind to bit-field 'i'}}
    222     volatile int & vir2 = (xvalue<IntBitfield>().i); // expected-error{{volatile lvalue reference to type 'volatile int' cannot bind to a temporary of type 'int'}}
    223     volatile int && vir3 = (xvalue<IntBitfield>().i); // no-warning
    224     volatile int && vir4 = move(lvalue<IntBitfield>()).i; // no-warning
    225 
    226     const int & cir1 = (lvalue<IntBitfield>().i); // no-warning
    227     const int & cir2 = (xvalue<IntBitfield>().i); // no-warning
    228     const int && cir3 = (xvalue<IntBitfield>().i); // no-warning
    229     const int && cir4 = move(lvalue<IntBitfield>()).i; // no-warning
    230 
    231     const volatile int & cvir1 = (lvalue<IntBitfield>().i); // expected-error{{non-const reference cannot bind to bit-field 'i'}}
    232     const volatile int & cvir2 = (xvalue<IntBitfield>().i); // expected-error{{volatile lvalue reference to type 'const volatile int' cannot bind to a temporary of type 'int'}}
    233     const volatile int && cvir3 = (xvalue<IntBitfield>().i); // no-warning
    234     const volatile int && cvir4 = move(lvalue<IntBitfield>()).i; // no-warning
    235   }
    236 }
    237