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