// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify -pedantic %s // Test the c++0x-specific reference initialization rules, e.g., the // rules for rvalue references. template<typename T> T prvalue(); template<typename T> T&& xvalue(); template<typename T> T& lvalue(); struct Base { }; struct Derived : Base { }; struct HasArray { int array[5]; }; int f(int); template<typename T> struct ConvertsTo { operator T(); // expected-note 2{{candidate function}} }; void test_rvalue_refs() { // If the initializer expression... // - is an xvalue, class prvalue, array prvalue or function lvalue // and "cv1 T1" is reference-compatible with "cv2 T2", or // xvalue case Base&& base0 = xvalue<Base>(); Base&& base1 = xvalue<Derived>(); int&& int0 = xvalue<int>(); // class prvalue case Base&& base2 = prvalue<Base>(); Base&& base3 = prvalue<Derived>(); // array prvalue case int (&&array0)[5] = HasArray().array; // function lvalue case int (&&function0)(int) = f; // - has a class type (i.e., T2 is a class type), where T1 is not // reference-related to T2, and can be implicitly converted to // an xvalue, class prvalue, or function lvalue of type "cv3 // T3", where "cv1 T1" is reference-compatible with "cv3 T3", // xvalue Base&& base4 = ConvertsTo<Base&&>(); Base&& base5 = ConvertsTo<Derived&&>(); int && int1 = ConvertsTo<int&&>(); // class prvalue Base&& base6 = ConvertsTo<Base>(); Base&& base7 = ConvertsTo<Derived>(); // function lvalue int (&&function1)(int) = ConvertsTo<int(&)(int)>(); // In the second case, if the reference is an rvalue reference and // the second standard conversion sequence of the user-defined // conversion sequence includes an lvalue-to-rvalue conversion, the // program is ill-formed. int &&int2 = ConvertsTo<int&>(); // expected-error{{no viable conversion from 'ConvertsTo<int &>' to 'int'}} int &&int3 = ConvertsTo<float&>(); // expected-error{{no viable conversion from 'ConvertsTo<float &>' to 'int'}} } class NonCopyable { NonCopyable(const NonCopyable&); }; class NonCopyableDerived : public NonCopyable { NonCopyableDerived(const NonCopyableDerived&); }; // Make sure we get direct bindings with no copies. void test_direct_binding() { NonCopyable &&nc0 = prvalue<NonCopyable>(); NonCopyable &&nc1 = prvalue<NonCopyableDerived>(); NonCopyable &&nc2 = xvalue<NonCopyable>(); NonCopyable &&nc3 = xvalue<NonCopyableDerived>(); const NonCopyable &nc4 = prvalue<NonCopyable>(); const NonCopyable &nc5 = prvalue<NonCopyableDerived>(); const NonCopyable &nc6 = xvalue<NonCopyable>(); const NonCopyable &nc7 = xvalue<NonCopyableDerived>(); NonCopyable &&nc8 = ConvertsTo<NonCopyable&&>(); NonCopyable &&nc9 = ConvertsTo<NonCopyableDerived&&>(); const NonCopyable &nc10 = ConvertsTo<NonCopyable&&>(); const NonCopyable &nc11 = ConvertsTo<NonCopyableDerived&&>(); } namespace std_example_1 { double d = 2.0; double& rd = d; const double& rcd = d; struct A { }; struct B : A { operator int&(); } b; A& ra = b; const A& rca = b; int& ir = B(); } namespace std_example_2 { double& rd2 = 2.0; // expected-error{{non-const lvalue reference to type 'double' cannot bind to a temporary of type 'double'}} int i = 2; double& rd3 = i; // expected-error{{non-const lvalue reference to type 'double' cannot bind to a value of unrelated type 'int'}} struct A { }; struct B : A { } b; extern B f(); const A& rca = f(); A&& rra = f(); struct X { operator B(); // expected-note{{candidate function}} operator int&(); // expected-note{{candidate function}} } x; const A& r = x; int&& rri = static_cast<int&&>(i); B&& rrb = x; int&& rri2 = X(); // expected-error{{no viable conversion from 'std_example_2::X' to 'int'}} const double& rcd2 = 2; double&& rrd = 2; const volatile int cvi = 1; const int& r2 = cvi; // expected-error{{binding value of type 'const volatile int' to reference to type 'const int' drops 'volatile' qualifier}} double d; double&& rrd2 = d; // expected-error{{rvalue reference to type 'double' cannot bind to lvalue of type 'double'}} double&& rrd3 = i; } namespace argument_passing { void base_rvalue_ref(Base&&); void int_rvalue_ref(int&&); // expected-note{{candidate function not viable: no known conversion from 'ConvertsTo<int &>' to 'int &&' for 1st argument}} \ // expected-note{{candidate function not viable: no known conversion from 'ConvertsTo<float &>' to 'int &&' for 1st argument}} void array_rvalue_ref(int (&&)[5]); void function_rvalue_ref(int (&&)(int)); void test() { base_rvalue_ref(xvalue<Base>()); base_rvalue_ref(xvalue<Derived>()); int_rvalue_ref(xvalue<int>()); base_rvalue_ref(prvalue<Base>()); base_rvalue_ref(prvalue<Derived>()); array_rvalue_ref(HasArray().array); function_rvalue_ref(f); base_rvalue_ref(ConvertsTo<Base&&>()); base_rvalue_ref(ConvertsTo<Derived&&>()); int_rvalue_ref(ConvertsTo<int&&>()); base_rvalue_ref(ConvertsTo<Base>()); base_rvalue_ref(ConvertsTo<Derived>()); function_rvalue_ref(ConvertsTo<int(&)(int)>()); int_rvalue_ref(ConvertsTo<int&>()); // expected-error{{no matching function for call to 'int_rvalue_ref'}} int_rvalue_ref(ConvertsTo<float&>()); // expected-error{{no matching function for call to 'int_rvalue_ref'}} } } namespace pr10644 { struct string { string(const char* __s); }; class map { int& operator[](const string& __k); public: int& operator[](const string&& __k); }; void foo() { static map key_map; key_map["line"]; } } namespace PR11003 { class Value { }; struct MoveRef { operator Value &() const ; }; MoveRef Move(int); void growTo() { Value x = Move(0); Value y(Move(0)); } } namespace rdar13278115 { struct X { }; struct Y : X { }; X &&f0(X &x) { return x; } // expected-error{{rvalue reference to type 'rdar13278115::X' cannot bind to lvalue of type 'rdar13278115::X'}} X &&f1(Y &y) { return y; } // expected-error{{rvalue reference to type 'rdar13278115::X' cannot bind to lvalue of type 'rdar13278115::Y'}} const X &&f2(Y &y) { return y; } // expected-error{{rvalue reference to type 'const rdar13278115::X' cannot bind to lvalue of type 'rdar13278115::Y'}} } namespace bitfields { struct IntBitfield { int i : 17; // expected-note 3 {{bit-field is declared here}} }; // A simplified version of std::move. template <typename T> T &&move(T &obj) { return static_cast<T &&>(obj); } void test() { int & ir1 = (lvalue<IntBitfield>().i); // expected-error{{non-const reference cannot bind to bit-field 'i'}} int & ir2 = (xvalue<IntBitfield>().i); // expected-error{{non-const lvalue reference to type 'int' cannot bind to a temporary of type 'int'}} int && ir3 = (xvalue<IntBitfield>().i); // no-warning int && ir4 = move(lvalue<IntBitfield>()).i; // no-warning volatile int & vir1 = (lvalue<IntBitfield>().i); // expected-error{{non-const reference cannot bind to bit-field 'i'}} volatile int & vir2 = (xvalue<IntBitfield>().i); // expected-error{{volatile lvalue reference to type 'volatile int' cannot bind to a temporary of type 'int'}} volatile int && vir3 = (xvalue<IntBitfield>().i); // no-warning volatile int && vir4 = move(lvalue<IntBitfield>()).i; // no-warning const int & cir1 = (lvalue<IntBitfield>().i); // no-warning const int & cir2 = (xvalue<IntBitfield>().i); // no-warning const int && cir3 = (xvalue<IntBitfield>().i); // no-warning const int && cir4 = move(lvalue<IntBitfield>()).i; // no-warning const volatile int & cvir1 = (lvalue<IntBitfield>().i); // expected-error{{non-const reference cannot bind to bit-field 'i'}} 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'}} const volatile int && cvir3 = (xvalue<IntBitfield>().i); // no-warning const volatile int && cvir4 = move(lvalue<IntBitfield>()).i; // no-warning } }