1 | // RUN: %clang_cc1 -fsyntax-only -verify %s |
2 | // RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s |
3 | int g(int); |
4 | |
5 | void f() { |
6 | int i; |
7 | int &r = i; |
8 | r = 1; |
9 | int *p = &r; |
10 | int &rr = r; |
11 | int (&rg)(int) = g; |
12 | rg(i); |
13 | int a[3]; |
14 | int (&ra)[3] = a; |
15 | ra[1] = i; |
16 | int *Q; |
17 | int *& P = Q; |
18 | P[1] = 1; |
19 | } |
20 | |
21 | typedef int t[1]; |
22 | void test2() { |
23 | t a; |
24 | t& b = a; |
25 | |
26 | |
27 | int c[3]; |
28 | int (&rc)[3] = c; |
29 | } |
30 | |
31 | // C++ [dcl.init.ref]p5b1 |
32 | struct A { }; |
33 | struct B : A { } b; |
34 | |
35 | void test3() { |
36 | double d = 2.0; |
37 | double& rd = d; // rd refers to d |
38 | const double& rcd = d; // rcd refers to d |
39 | |
40 | A& ra = b; // ra refers to A subobject in b |
41 | const A& rca = b; // rca refers to A subobject in b |
42 | } |
43 | |
44 | B fB(); |
45 | |
46 | // C++ [dcl.init.ref]p5b2 |
47 | void test4() { |
48 | double& rd2 = 2.0; // expected-error{{non-const lvalue reference to type 'double' cannot bind to a temporary of type 'double'}} |
49 | int i = 2; |
50 | double& rd3 = i; // expected-error{{non-const lvalue reference to type 'double' cannot bind to a value of unrelated type 'int'}} |
51 | |
52 | const A& rca = fB(); |
53 | } |
54 | |
55 | void test5() { |
56 | // const double& rcd2 = 2; // rcd2 refers to temporary with value 2.0 |
57 | const volatile int cvi = 1; |
58 | const int& r = cvi; // expected-error{{binding value of type 'const volatile int' to reference to type 'const int' drops 'volatile' qualifier}} |
59 | |
60 | #if __cplusplus >= 201103L |
61 | const int& r2{cvi}; // expected-error{{binding value of type 'const volatile int' to reference to type 'const int' drops 'volatile' qualifier}} |
62 | |
63 | const int a = 2; |
64 | int& r3{a}; // expected-error{{binding value of type 'const int' to reference to type 'int' drops 'const'}} |
65 | |
66 | const int&& r4{a}; // expected-error{{rvalue reference to type 'const int' cannot bind to lvalue of type 'const int'}} |
67 | |
68 | void func(); |
69 | void func(int); |
70 | int &ptr1 = {func}; // expected-error{{address of overloaded function 'func' does not match required type 'int'}} |
71 | int &&ptr2{func}; // expected-error{{address of overloaded function 'func' does not match required type 'int'}} |
72 | // expected-note@-4{{candidate function}} |
73 | // expected-note@-4{{candidate function}} |
74 | // expected-note@-6{{candidate function}} |
75 | // expected-note@-6{{candidate function}} |
76 | #endif |
77 | } |
78 | |
79 | // C++ [dcl.init.ref]p3 |
80 | int& test6(int& x) { |
81 | int& yo; // expected-error{{declaration of reference variable 'yo' requires an initializer}} |
82 | |
83 | return x; |
84 | } |
85 | int& not_initialized_error; // expected-error{{declaration of reference variable 'not_initialized_error' requires an initializer}} |
86 | extern int& not_initialized_okay; |
87 | |
88 | class Test6 { // expected-warning{{class 'Test6' does not declare any constructor to initialize its non-modifiable members}} |
89 | int& okay; // expected-note{{reference member 'okay' will never be initialized}} |
90 | }; |
91 | |
92 | struct C : B, A { }; // expected-warning {{direct base 'A' is inaccessible due to ambiguity:\n struct C -> struct B -> struct A\nstruct C -> struct A}} |
93 | |
94 | void test7(C& c) { |
95 | A& a1 = c; // expected-error {{ambiguous conversion from derived class 'C' to base class 'A':}} |
96 | } |
97 | |
98 | // C++ [dcl.ref]p1, C++ [dcl.ref]p4 |
99 | void test8(int& const,// expected-error{{'const' qualifier may not be applied to a reference}} |
100 | |
101 | void&, // expected-error{{cannot form a reference to 'void'}} |
102 | int& &) // expected-error{{type name declared as a reference to a reference}} |
103 | { |
104 | typedef int& intref; |
105 | typedef intref& intrefref; // C++ DR 106: reference collapsing |
106 | |
107 | typedef intref const intref_c; // expected-warning {{'const' qualifier on reference type 'intref' (aka 'int &') has no effect}} |
108 | typedef intref_c intref; // ok, same type |
109 | |
110 | typedef intref volatile intref; // expected-warning {{'volatile' qualifier on reference type 'intref' (aka 'int &') has no effect}} |
111 | typedef intref _Atomic intref; // expected-warning {{'_Atomic' qualifier on reference type 'intref' (aka 'int &') has no effect}} |
112 | |
113 | void restrict_ref(__restrict intref); // ok |
114 | void restrict_ref(int &__restrict); // ok |
115 | } |
116 | |
117 | template<typename T> int const_param(const T) {} |
118 | int const_ref_param = const_param<int&>(const_ref_param); // no-warning |
119 | |
120 | |
121 | class string { |
122 | char *Data; |
123 | unsigned Length; |
124 | public: |
125 | string(); |
126 | ~string(); |
127 | }; |
128 | |
129 | string getInput(); |
130 | |
131 | void test9() { |
132 | string &s = getInput(); // expected-error{{lvalue reference}} |
133 | } |
134 | |
135 | void test10() { |
136 | __attribute((vector_size(16))) typedef int vec4; |
137 | typedef __attribute__(( ext_vector_type(4) )) int ext_vec4; |
138 | |
139 | vec4 v; |
140 | int &a = v[0]; // expected-error{{non-const reference cannot bind to vector element}} |
141 | const int &b = v[0]; |
142 | |
143 | ext_vec4 ev; |
144 | int &c = ev.x; // expected-error{{non-const reference cannot bind to vector element}} |
145 | const int &d = ev.x; |
146 | } |
147 | |
148 | namespace PR7149 { |
149 | template<typename T> struct X0 |
150 | { |
151 | T& first; |
152 | X0(T& p1) : first(p1) { } |
153 | }; |
154 | |
155 | |
156 | void f() |
157 | { |
158 | int p1[1]; |
159 | X0< const int[1]> c(p1); |
160 | } |
161 | } |
162 | |
163 | namespace PR8608 { |
164 | bool& f(unsigned char& c) { return (bool&)c; } |
165 | } |
166 | |
167 | // The following crashed trying to recursively evaluate the LValue. |
168 | const int &do_not_crash = do_not_crash; // expected-warning{{reference 'do_not_crash' is not yet bound to a value when used within its own initialization}} |
169 | |
170 | namespace ExplicitRefInit { |
171 | // This is invalid: we can't copy-initialize an 'A' temporary using an |
172 | // explicit constructor. |
173 | struct A { explicit A(int); }; |
174 | const A &a(0); // expected-error {{reference to type 'const ExplicitRefInit::A' could not bind to an rvalue of type 'int'}} |
175 | } |
176 | |
177 | namespace RefCollapseTypePrinting { |
178 | template<typename T> void add_lref() { |
179 | using X = int(T); // expected-note 4{{previous}} |
180 | using X = const volatile T&; |
181 | // expected-error@-1 {{'int &' vs 'int (int &)'}} |
182 | // expected-error@-2 {{'int &' vs 'int (int &&)'}} |
183 | // expected-error@-3 {{'const int &' vs 'int (const int &)'}} |
184 | // expected-error@-4 {{'const int &' vs 'int (const int &&)'}} |
185 | } |
186 | template void add_lref<int&>(); // expected-note {{instantiation of}} |
187 | template void add_lref<int&&>(); // expected-note {{instantiation of}} |
188 | template void add_lref<const int&>(); // expected-note {{instantiation of}} |
189 | template void add_lref<const int&&>(); // expected-note {{instantiation of}} |
190 | |
191 | template<typename T> void add_rref() { |
192 | using X = int(T); // expected-note 4{{previous}} |
193 | using X = const volatile T&&; |
194 | // expected-error@-1 {{'int &' vs 'int (int &)'}} |
195 | // expected-error@-2 {{'int &&' vs 'int (int &&)'}} |
196 | // expected-error@-3 {{'const int &' vs 'int (const int &)'}} |
197 | // expected-error@-4 {{'const int &&' vs 'int (const int &&)'}} |
198 | } |
199 | template void add_rref<int&>(); // expected-note {{instantiation of}} |
200 | template void add_rref<int&&>(); // expected-note {{instantiation of}} |
201 | template void add_rref<const int&>(); // expected-note {{instantiation of}} |
202 | template void add_rref<const int&&>(); // expected-note {{instantiation of}} |
203 | } |
204 | |