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.
5template<typename T> T prvalue();
6template<typename T> T&& xvalue();
7template<typename T> T& lvalue();
8
9struct Base { };
10struct Derived : Base { };
11
12struct HasArray {
13  int array[5];
14};
15
16int f(int);
17
18template<typename T>
19struct ConvertsTo {
20  operator T(); // expected-note 2{{candidate function}}
21};
22
23void 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
68class NonCopyable {
69  NonCopyable(const NonCopyable&);
70};
71
72class NonCopyableDerived : public NonCopyable {
73  NonCopyableDerived(const NonCopyableDerived&);
74};
75
76// Make sure we get direct bindings with no copies.
77void 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
92namespace 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
105namespace 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
133namespace 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
168namespace 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
183namespace 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
196namespace 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
204namespace 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