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