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).
bind_lvalue_to_lvalue(Base b,Derived d,const Base bc,const Derived dc,Diamond diamond,int i)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 
bind_lvalue_quals(volatile Base b,volatile Derived d,volatile const Base bvc,volatile const Derived dvc,volatile const int ivc)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 reference of type 'volatile Base' to value of type 'const volatile Base' drops 'const' qualifier}}
73   volatile Base &bvr4 = dvc; // expected-error{{binding reference of type 'volatile Base' to value of type 'const volatile Derived' drops 'const' qualifier}}
74 
75   volatile int &ir = ivc; // expected-error{{binding reference of type 'volatile int' to value of type 'const volatile int' drops 'const' qualifier}}
76 
77   const volatile Base &bcvr1 = b;
78   const volatile Base &bcvr2 = d;
79 }
80 
bind_lvalue_to_rvalue()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 
bind_lvalue_to_unrelated(Unrelated ur)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 
bind_lvalue_to_conv_lvalue()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 
bind_lvalue_to_conv_lvalue_ambig(ConvertibleToBothDerivedRef both)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 
test_bitfield(IntBitfield ib)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).
bind_const_lvalue_to_rvalue()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 reference of type 'const Base' to value of type 'const volatile Base' drops 'volatile' qualifier}}
127   const Base &br6 = create<const volatile Derived>(); // expected-error{{binding reference of type 'const Base' to value of type 'const volatile Derived' 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.
bind_const_lvalue_to_class_conv_temporary()133 void bind_const_lvalue_to_class_conv_temporary() {
134   const Base &br1 = ConvertibleToBase();
135   const Base &br2 = ConvertibleToDerived();
136 }
bind_lvalue_to_conv_rvalue_ambig(ConvertibleToBothDerived both)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