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
test_rvalue_refs()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.
test_direct_binding()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 of reference to type 'const int' to a value of type 'const volatile int' drops qualifiers}}
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
test()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 };
foo()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);
growTo()190 void growTo() {
191 Value x = Move(0);
192 Value y(Move(0));
193 }
194 }
195