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