aboutsummaryrefslogtreecommitdiff
path: root/test/SemaCXX/cxx0x-initializer-references.cpp
blob: ce029d7f0732155494b0abd0b0caf0bcf433f532 (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
136
137
138
139
140
141
142
// 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");
  }

  struct X {};

  void edge_cases() {
    int const &b({0}); // expected-error {{cannot initialize reference type 'const int &' with a parenthesized initializer list}}
    const int (&arr)[3] ({1, 2, 3}); // expected-error {{cannot initialize reference type 'const int (&)[3]' with a parenthesized initializer list}}
    const X &x({}); // expected-error {{cannot initialize reference type 'const reference::X &' with a parenthesized initializer list}}
  }

  template<typename T> void dependent_edge_cases() {
    T b({}); // expected-error-re 3{{cannot initialize reference type {{.*}} with a parenthesized init}}
    T({}); // expected-error-re 3{{cannot initialize reference type {{.*}} with a parenthesized init}}
  }
  template void dependent_edge_cases<X>(); // ok
  template void dependent_edge_cases<const int&>(); // expected-note {{instantiation of}}
  template void dependent_edge_cases<const int(&)[1]>(); // expected-note {{instantiation of}}
  template void dependent_edge_cases<const X&>(); // expected-note {{instantiation of}}
}

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