| // 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 |
| } |
| } |