aboutsummaryrefslogtreecommitdiff
path: root/test/SemaCXX/aggregate-initialization.cpp
blob: 514473f9bcb176c7aad0e10e66c73f80751a046e (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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s 
// RUN: %clang_cc1 -fsyntax-only -verify -std=c++14 %s 
// RUN: %clang_cc1 -fsyntax-only -verify -std=c++17 %s 

// Verify that using an initializer list for a non-aggregate looks for
// constructors..
struct NonAggr1 { // expected-note 2 {{candidate constructor}}
  NonAggr1(int, int) { } // expected-note {{candidate constructor}}

  int m;
};

struct Base { };
struct NonAggr2 : public Base { // expected-note 0-3 {{candidate constructor}}
  int m;
};

class NonAggr3 { // expected-note 3 {{candidate constructor}}
  int m;
};

struct NonAggr4 { // expected-note 3 {{candidate constructor}}
  int m;
  virtual void f();
};

NonAggr1 na1 = { 17 }; // expected-error{{no matching constructor for initialization of 'NonAggr1'}}
NonAggr2 na2 = { 17 };
NonAggr3 na3 = { 17 }; // expected-error{{no matching constructor for initialization of 'NonAggr3'}}
NonAggr4 na4 = { 17 }; // expected-error{{no matching constructor for initialization of 'NonAggr4'}}
#if __cplusplus <= 201402L
// expected-error@-4{{no matching constructor for initialization of 'NonAggr2'}}
#else
// expected-error@-6{{requires explicit braces}}
NonAggr2 na2b = { {}, 17 }; // ok
#endif

// PR5817
typedef int type[][2];
const type foo = {0};

// Vector initialization.
typedef short __v4hi __attribute__ ((__vector_size__ (8)));
__v4hi v1 = { (void *)1, 2, 3 }; // expected-error {{cannot initialize a vector element of type 'short' with an rvalue of type 'void *'}}

// Array initialization.
int a[] = { (void *)1 }; // expected-error {{cannot initialize an array element of type 'int' with an rvalue of type 'void *'}}

// Struct initialization.
struct S { int a; } s = { (void *)1 }; // expected-error {{cannot initialize a member subobject of type 'int' with an rvalue of type 'void *'}}

// Check that we're copy-initializing the structs.
struct A {
  A();
  A(int);
  ~A();
  
  A(const A&) = delete; // expected-note 0-2{{'A' has been explicitly marked deleted here}}
};

struct B {
  A a;
};

struct C {
  const A& a;
};

void f() {
  A as1[1] = { };
  A as2[1] = { 1 };
#if __cplusplus <= 201402L
  // expected-error@-2 {{copying array element of type 'A' invokes deleted constructor}}
#endif

  B b1 = { };
  B b2 = { 1 };
#if __cplusplus <= 201402L
  // expected-error@-2 {{copying member subobject of type 'A' invokes deleted constructor}}
#endif
  
  C c1 = { 1 };
}

class Agg {
public:
  int i, j;
};

class AggAgg {
public:
  Agg agg1;
  Agg agg2;
};

AggAgg aggagg = { 1, 2, 3, 4 };

namespace diff_cpp14_dcl_init_aggr_example {
  struct derived;
  struct base {
    friend struct derived;
  private:
    base();
  };
  struct derived : base {};

  derived d1{};
#if __cplusplus > 201402L
  // expected-error@-2 {{private}}
  // expected-note@-7 {{here}}
#endif
  derived d2;
}

namespace ProtectedBaseCtor {
  // FIXME: It's unclear whether f() and g() should be valid in C++1z. What is
  // the object expression in a constructor call -- the base class subobject or
  // the complete object?
  struct A {
  protected:
    A();
  };

  struct B : public A {
    friend B f();
    friend B g();
    friend B h();
  };

  B f() { return {}; }
#if __cplusplus > 201402L
  // expected-error@-2 {{protected default constructor}}
  // expected-note@-12 {{here}}
#endif

  B g() { return {{}}; }
#if __cplusplus <= 201402L
  // expected-error@-2 {{no matching constructor}}
  // expected-note@-15 3{{candidate}}
#else
  // expected-error@-5 {{protected default constructor}}
  // expected-note@-21 {{here}}
#endif

  B h() { return {A{}}; }
#if __cplusplus <= 201402L
  // expected-error@-2 {{no matching constructor}}
  // expected-note@-24 3{{candidate}}
#endif
  // expected-error@-5 {{protected constructor}}
  // expected-note@-30 {{here}}
}

namespace IdiomaticStdArrayInitDoesNotWarn {
#pragma clang diagnostic push
#pragma clang diagnostic warning "-Wmissing-braces"
  template<typename T, int N> struct StdArray {
    T contents[N];
  };
  StdArray<int, 3> x = {1, 2, 3};
  
  template<typename T, int N> struct ArrayAndSomethingElse {
    T contents[N];
    int something_else;
  };
  ArrayAndSomethingElse<int, 3> y = {1, 2, 3}; // expected-warning {{suggest braces}}

#if __cplusplus >= 201703L
  template<typename T, int N> struct ArrayAndBaseClass : StdArray<int, 3> {
    T contents[N];
  };
  ArrayAndBaseClass<int, 3> z = {1, 2, 3}; // expected-warning {{suggest braces}}

  // It's not clear whether we should be warning in this case. If this
  // pattern becomes idiomatic, it would be reasonable to suppress the
  // warning here too.
  template<typename T, int N> struct JustABaseClass : StdArray<T, N> {};
  JustABaseClass<int, 3> w = {1, 2, 3}; // expected-warning {{suggest braces}}
#endif

#pragma clang diagnostic pop
}