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 136 137 138 139 140
|
// RUN: %clang_cc1 -fsyntax-only -verify %s
// RUN: %clang_cc1 -fsyntax-only -verify -std=c++98 %s
// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
struct Base { };
struct Derived : Base { }; // expected-note{{candidate constructor (the implicit copy constructor) not viable}}
#if __cplusplus >= 201103L // C++11 or later
// expected-note@-2 {{candidate constructor (the implicit move constructor) not viable}}
#endif
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}}
}
|