aboutsummaryrefslogtreecommitdiff
path: root/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-var.cpp
blob: cb62874b40cd646e22a01dfef49a37dbfd5a7dd3 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
// RUN: %clang_cc1 -fsyntax-only -verify %s

struct Base { };
struct Derived : Base { }; // expected-note{{candidate constructor (the implicit copy constructor) not viable}}
struct Unrelated { };
struct Derived2 : Base { };
struct Diamond : Derived, Derived2 { };

struct ConvertibleToBaseRef {
  operator Base&() const;
};

struct ConvertibleToDerivedRef {
  operator Derived&() const;
};

struct ConvertibleToBothDerivedRef {
  operator Derived&(); // expected-note{{candidate function}}
  operator Derived2&(); // expected-note{{candidate function}}
};

struct ConvertibleToIntRef {
  operator int&();
};

struct ConvertibleToBase {
  operator Base() const;
};

struct ConvertibleToDerived {
  operator Derived() const;
};

struct ConvertibleToBothDerived {
  operator Derived(); // expected-note{{candidate function}}
  operator Derived2(); // expected-note{{candidate function}}
};

struct ConvertibleToInt {
  operator int();
};

template<typename T> T create();

// First bullet: lvalue references binding to lvalues (the simple cases).
void bind_lvalue_to_lvalue(Base b, Derived d, 
                           const Base bc, const Derived dc,
                           Diamond diamond,
                           int i) {
  // Reference-compatible
  Base &br1 = b;
  Base &br2 = d;
  Derived &dr1 = d;
  Derived &dr2 = b; // expected-error{{non-const lvalue reference to type 'Derived' cannot bind to a value of unrelated type 'Base'}}
  Base &br3 = bc; // expected-error{{drops 'const' qualifier}}
  Base &br4 = dc; // expected-error{{drops 'const' qualifier}}
  Base &br5 = diamond; // expected-error{{ambiguous conversion from derived class 'Diamond' to base class 'Base':}}
  int &ir = i;
  long &lr = i; // expected-error{{non-const lvalue reference to type 'long' cannot bind to a value of unrelated type 'int'}}
}

void bind_lvalue_quals(volatile Base b, volatile Derived d,
                       volatile const Base bvc, volatile const Derived dvc,
                       volatile const int ivc) {
  volatile Base &bvr1 = b;
  volatile Base &bvr2 = d;
  volatile Base &bvr3 = bvc; // expected-error{{binding value of type 'const volatile Base' to reference to type 'volatile Base' drops 'const' qualifier}}
  volatile Base &bvr4 = dvc; // expected-error{{binding value of type 'const volatile Derived' to reference to type 'volatile Base' drops 'const' qualifier}}
  
  volatile int &ir = ivc; // expected-error{{binding value of type 'const volatile int' to reference to type 'volatile int' drops 'const' qualifier}}

  const volatile Base &bcvr1 = b;
  const volatile Base &bcvr2 = d;
}

void bind_lvalue_to_rvalue() {
  Base &br1 = Base(); // expected-error{{non-const lvalue reference to type 'Base' cannot bind to a temporary of type 'Base'}}
  Base &br2 = Derived(); // expected-error{{non-const lvalue reference to type 'Base' cannot bind to a temporary of type 'Derived'}}
  const volatile Base &br3 = Base(); // expected-error{{volatile lvalue reference to type 'const volatile Base' cannot bind to a temporary of type 'Base'}}
  const volatile Base &br4 = Derived(); // expected-error{{volatile lvalue reference to type 'const volatile Base' cannot bind to a temporary of type 'Derived'}}

  int &ir = 17; // expected-error{{non-const lvalue reference to type 'int' cannot bind to a temporary of type 'int'}}
}

void bind_lvalue_to_unrelated(Unrelated ur) {
  Base &br1 = ur; // expected-error{{non-const lvalue reference to type 'Base' cannot bind to a value of unrelated type 'Unrelated'}}
  const volatile Base &br2 = ur; // expected-error{{volatile lvalue reference to type 'const volatile Base' cannot bind to a value of unrelated type 'Unrelated'}}
}

void bind_lvalue_to_conv_lvalue() {
  // Not reference-related, but convertible
  Base &nbr1 = ConvertibleToBaseRef();
  Base &nbr2 = ConvertibleToDerivedRef();
  Derived &ndr1 = ConvertibleToDerivedRef();
  int &ir = ConvertibleToIntRef();
}

void bind_lvalue_to_conv_lvalue_ambig(ConvertibleToBothDerivedRef both) {
  Derived &dr1 = both;
  Base &br1 = both; // expected-error{{reference initialization of type 'Base &' with initializer of type 'ConvertibleToBothDerivedRef' is ambiguous}}
}

struct IntBitfield {
  int i : 17; // expected-note{{bit-field is declared here}}
};

void test_bitfield(IntBitfield ib) {
  int & ir1 = (ib.i); // expected-error{{non-const reference cannot bind to bit-field 'i'}}
}

// Second bullet: const lvalue reference binding to an rvalue with
// similar type (both of which are class types).
void bind_const_lvalue_to_rvalue() {
  const Base &br1 = create<Base>();
  const Base &br2 = create<Derived>();
  const Derived &dr1 = create<Base>(); // expected-error{{no viable conversion}}

  const Base &br3 = create<const Base>();
  const Base &br4 = create<const Derived>();

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

  const int &ir = create<int>();
}

// Second bullet: const lvalue reference binds to the result of a conversion.
void bind_const_lvalue_to_class_conv_temporary() {
  const Base &br1 = ConvertibleToBase();
  const Base &br2 = ConvertibleToDerived();
}
void bind_lvalue_to_conv_rvalue_ambig(ConvertibleToBothDerived both) {
  const Derived &dr1 = both;
  const Base &br1 = both; // expected-error{{reference initialization of type 'const Base &' with initializer of type 'ConvertibleToBothDerived' is ambiguous}}
}