1 | // RUN: %clang_cc1 -fsyntax-only -verify %s |
2 | // RUN: %clang_cc1 -fsyntax-only -verify -std=c++98 %s |
3 | // RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s |
4 | |
5 | struct Base { }; |
6 | struct Derived : Base { }; // expected-note{{candidate constructor (the implicit copy constructor) not viable}} |
7 | #if __cplusplus >= 201103L // C++11 or later |
8 | // expected-note@-2 {{candidate constructor (the implicit move constructor) not viable}} |
9 | #endif |
10 | struct Unrelated { }; |
11 | struct Derived2 : Base { }; |
12 | struct Diamond : Derived, Derived2 { }; |
13 | |
14 | struct ConvertibleToBaseRef { |
15 | operator Base&() const; |
16 | }; |
17 | |
18 | struct ConvertibleToDerivedRef { |
19 | operator Derived&() const; |
20 | }; |
21 | |
22 | struct ConvertibleToBothDerivedRef { |
23 | operator Derived&(); // expected-note{{candidate function}} |
24 | operator Derived2&(); // expected-note{{candidate function}} |
25 | }; |
26 | |
27 | struct ConvertibleToIntRef { |
28 | operator int&(); |
29 | }; |
30 | |
31 | struct ConvertibleToBase { |
32 | operator Base() const; |
33 | }; |
34 | |
35 | struct ConvertibleToDerived { |
36 | operator Derived() const; |
37 | }; |
38 | |
39 | struct ConvertibleToBothDerived { |
40 | operator Derived(); // expected-note{{candidate function}} |
41 | operator Derived2(); // expected-note{{candidate function}} |
42 | }; |
43 | |
44 | struct ConvertibleToInt { |
45 | operator int(); |
46 | }; |
47 | |
48 | template<typename T> T create(); |
49 | |
50 | // First bullet: lvalue references binding to lvalues (the simple cases). |
51 | void bind_lvalue_to_lvalue(Base b, Derived d, |
52 | const Base bc, const Derived dc, |
53 | Diamond diamond, |
54 | int i) { |
55 | // Reference-compatible |
56 | Base &br1 = b; |
57 | Base &br2 = d; |
58 | Derived &dr1 = d; |
59 | Derived &dr2 = b; // expected-error{{non-const lvalue reference to type 'Derived' cannot bind to a value of unrelated type 'Base'}} |
60 | Base &br3 = bc; // expected-error{{drops 'const' qualifier}} |
61 | Base &br4 = dc; // expected-error{{drops 'const' qualifier}} |
62 | Base &br5 = diamond; // expected-error{{ambiguous conversion from derived class 'Diamond' to base class 'Base':}} |
63 | int &ir = i; |
64 | long &lr = i; // expected-error{{non-const lvalue reference to type 'long' cannot bind to a value of unrelated type 'int'}} |
65 | } |
66 | |
67 | void bind_lvalue_quals(volatile Base b, volatile Derived d, |
68 | volatile const Base bvc, volatile const Derived dvc, |
69 | volatile const int ivc) { |
70 | volatile Base &bvr1 = b; |
71 | volatile Base &bvr2 = d; |
72 | volatile Base &bvr3 = bvc; // expected-error{{binding value of type 'const volatile Base' to reference to type 'volatile Base' drops 'const' qualifier}} |
73 | volatile Base &bvr4 = dvc; // expected-error{{binding value of type 'const volatile Derived' to reference to type 'volatile Base' drops 'const' qualifier}} |
74 | |
75 | volatile int &ir = ivc; // expected-error{{binding value of type 'const volatile int' to reference to type 'volatile int' drops 'const' qualifier}} |
76 | |
77 | const volatile Base &bcvr1 = b; |
78 | const volatile Base &bcvr2 = d; |
79 | } |
80 | |
81 | void bind_lvalue_to_rvalue() { |
82 | Base &br1 = Base(); // expected-error{{non-const lvalue reference to type 'Base' cannot bind to a temporary of type 'Base'}} |
83 | Base &br2 = Derived(); // expected-error{{non-const lvalue reference to type 'Base' cannot bind to a temporary of type 'Derived'}} |
84 | const volatile Base &br3 = Base(); // expected-error{{volatile lvalue reference to type 'const volatile Base' cannot bind to a temporary of type 'Base'}} |
85 | const volatile Base &br4 = Derived(); // expected-error{{volatile lvalue reference to type 'const volatile Base' cannot bind to a temporary of type 'Derived'}} |
86 | |
87 | int &ir = 17; // expected-error{{non-const lvalue reference to type 'int' cannot bind to a temporary of type 'int'}} |
88 | } |
89 | |
90 | void bind_lvalue_to_unrelated(Unrelated ur) { |
91 | Base &br1 = ur; // expected-error{{non-const lvalue reference to type 'Base' cannot bind to a value of unrelated type 'Unrelated'}} |
92 | const volatile Base &br2 = ur; // expected-error{{volatile lvalue reference to type 'const volatile Base' cannot bind to a value of unrelated type 'Unrelated'}} |
93 | } |
94 | |
95 | void bind_lvalue_to_conv_lvalue() { |
96 | // Not reference-related, but convertible |
97 | Base &nbr1 = ConvertibleToBaseRef(); |
98 | Base &nbr2 = ConvertibleToDerivedRef(); |
99 | Derived &ndr1 = ConvertibleToDerivedRef(); |
100 | int &ir = ConvertibleToIntRef(); |
101 | } |
102 | |
103 | void bind_lvalue_to_conv_lvalue_ambig(ConvertibleToBothDerivedRef both) { |
104 | Derived &dr1 = both; |
105 | Base &br1 = both; // expected-error{{reference initialization of type 'Base &' with initializer of type 'ConvertibleToBothDerivedRef' is ambiguous}} |
106 | } |
107 | |
108 | struct IntBitfield { |
109 | int i : 17; // expected-note{{bit-field is declared here}} |
110 | }; |
111 | |
112 | void test_bitfield(IntBitfield ib) { |
113 | int & ir1 = (ib.i); // expected-error{{non-const reference cannot bind to bit-field 'i'}} |
114 | } |
115 | |
116 | // Second bullet: const lvalue reference binding to an rvalue with |
117 | // similar type (both of which are class types). |
118 | void bind_const_lvalue_to_rvalue() { |
119 | const Base &br1 = create<Base>(); |
120 | const Base &br2 = create<Derived>(); |
121 | const Derived &dr1 = create<Base>(); // expected-error{{no viable conversion}} |
122 | |
123 | const Base &br3 = create<const Base>(); |
124 | const Base &br4 = create<const Derived>(); |
125 | |
126 | const Base &br5 = create<const volatile Base>(); // expected-error{{binding value of type 'const volatile Base' to reference to type 'const Base' drops 'volatile' qualifier}} |
127 | const Base &br6 = create<const volatile Derived>(); // expected-error{{binding value of type 'const volatile Derived' to reference to type 'const Base' drops 'volatile' qualifier}} |
128 | |
129 | const int &ir = create<int>(); |
130 | } |
131 | |
132 | // Second bullet: const lvalue reference binds to the result of a conversion. |
133 | void bind_const_lvalue_to_class_conv_temporary() { |
134 | const Base &br1 = ConvertibleToBase(); |
135 | const Base &br2 = ConvertibleToDerived(); |
136 | } |
137 | void bind_lvalue_to_conv_rvalue_ambig(ConvertibleToBothDerived both) { |
138 | const Derived &dr1 = both; |
139 | const Base &br1 = both; // expected-error{{reference initialization of type 'const Base &' with initializer of type 'ConvertibleToBothDerived' is ambiguous}} |
140 | } |
141 | |