aboutsummaryrefslogtreecommitdiff
path: root/test/SemaCXX/cxx0x-initializer-references.cpp
blob: 390047ea075214cde84e955ebe30db5e64a4f689 (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
// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s

struct one { char c; };
struct two { char c[2]; };

namespace reference {
  struct A {
    int i1, i2;
  };

  void single_init() {
    const int &cri1a = {1};
    const int &cri1b{1};

    int i = 1;
    int &ri1a = {i};
    int &ri1b{i};

    int &ri2 = {1}; // expected-error {{cannot bind to an initializer list temporary}}

    A a{1, 2};
    A &ra1a = {a};
    A &ra1b{a};
  }

  void reference_to_aggregate() {
    const A &ra1{1, 2};
    A &ra2{1, 2}; // expected-error {{cannot bind to an initializer list temporary}}

    const int (&arrayRef)[] = {1, 2, 3};
    static_assert(sizeof(arrayRef) == 3 * sizeof(int), "bad array size");
  }

  struct B {
    int i1;
  };

  void call() {
    one f(const int&);
    f({1});

    one g(int&); // expected-note {{passing argument}}
    g({1}); // expected-error {{cannot bind to an initializer list temporary}}
    int i = 0;
    g({i});

    void h(const B&);
    h({1});

    void a(B&); // expected-note {{passing argument}}
    a({1}); // expected-error {{cannot bind to an initializer list temporary}}
    B b{1};
    a({b});
  }

  void overloading() {
    one f(const int&);
    two f(const B&);

    // First is identity conversion, second is user-defined conversion.
    static_assert(sizeof(f({1})) == sizeof(one), "bad overload resolution");

    one g(int&);
    two g(const B&);

    static_assert(sizeof(g({1})) == sizeof(two), "bad overload resolution");

    one h(const int&);
    two h(const A&);

    static_assert(sizeof(h({1, 2})) == sizeof(two), "bad overload resolution");
  }

  void edge_cases() {
    // FIXME: very poor error message
    int const &b({0}); // expected-error {{could not bind}}
  }

}

namespace PR12182 {
  void f(int const(&)[3]);

  void g() {
      f({1, 2});
  }
}

namespace PR12660 {
  const int &i { 1 };
  struct S { S(int); } const &s { 2 };
}

namespace b7891773 {
  typedef void (*ptr)();
  template <class T> void f();
  int g(const ptr &);
  int k = g({ f<int> });
}

namespace inner_init {
  struct A { int n; };
  struct B { A &&r; };
  B b1 { 0 }; // expected-error {{reference to type 'inner_init::A' could not bind to an rvalue of type 'int'}}
  B b2 { { 0 } };
  B b3 { { { 0 } } }; // expected-warning {{braces around scalar init}}

  struct C { C(int); };   // expected-note 2{{candidate constructor (the implicit}} \
                          // expected-note {{candidate constructor not viable: cannot convert initializer list argument to 'int'}}
  struct D { C &&r; };
  D d1 { 0 }; // ok, 0 implicitly converts to C
  D d2 { { 0 } }; // ok, { 0 } calls C(0)
  D d3 { { { 0 } } }; // ok, { { 0 } } calls C({ 0 }), expected-warning {{braces around scalar init}}
  D d4 { { { { 0 } } } }; // expected-error {{no matching constructor for initialization of 'inner_init::C &&'}}

  struct E { explicit E(int); }; // expected-note 2{{here}}
  struct F { E &&r; };
  F f1 { 0 }; // expected-error {{could not bind to an rvalue of type 'int'}}
  F f2 { { 0 } }; // expected-error {{chosen constructor is explicit}}
  F f3 { { { 0 } } }; // expected-error {{chosen constructor is explicit}}
}

namespace PR20844 {
  struct A {};
  struct B { operator A&(); } b;
  A &a{b}; // expected-error {{excess elements}} expected-note {{in initialization of temporary of type 'PR20844::A'}}
}

namespace PR21834 {
const int &a = (const int &){0}; // expected-error {{cannot bind to an initializer list}}
}