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