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 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
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 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.
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