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
5struct Base { };
6struct 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
10struct Unrelated { };
11struct Derived2 : Base { };
12struct Diamond : Derived, Derived2 { };
13
14struct ConvertibleToBaseRef {
15  operator Base&() const;
16};
17
18struct ConvertibleToDerivedRef {
19  operator Derived&() const;
20};
21
22struct ConvertibleToBothDerivedRef {
23  operator Derived&(); // expected-note{{candidate function}}
24  operator Derived2&(); // expected-note{{candidate function}}
25};
26
27struct ConvertibleToIntRef {
28  operator int&();
29};
30
31struct ConvertibleToBase {
32  operator Base() const;
33};
34
35struct ConvertibleToDerived {
36  operator Derived() const;
37};
38
39struct ConvertibleToBothDerived {
40  operator Derived(); // expected-note{{candidate function}}
41  operator Derived2(); // expected-note{{candidate function}}
42};
43
44struct ConvertibleToInt {
45  operator int();
46};
47
48template<typename T> T create();
49
50// First bullet: lvalue references binding to lvalues (the simple cases).
51void 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
67void 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
81void 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
90void 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
95void 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
103void 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
108struct IntBitfield {
109  int i : 17; // expected-note{{bit-field is declared here}}
110};
111
112void 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).
118void 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.
133void bind_const_lvalue_to_class_conv_temporary() {
134  const Base &br1 = ConvertibleToBase();
135  const Base &br2 = ConvertibleToDerived();
136}
137void 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