180 lines
3.4 KiB
C++
180 lines
3.4 KiB
C++
|
// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify -Wno-reorder -Wno-c99-designator -Winitializer-overrides %s
|
||
|
// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify -Wno-reorder -Wno-c99-designator -Woverride-init %s
|
||
|
|
||
|
template <typename T> struct Foo {
|
||
|
struct SubFoo {
|
||
|
int bar1;
|
||
|
int bar2;
|
||
|
};
|
||
|
|
||
|
static void Test() { SubFoo sf = {.bar1 = 10, .bar2 = 20}; } // Expected no warning
|
||
|
};
|
||
|
|
||
|
void foo() {
|
||
|
Foo<int>::Test();
|
||
|
Foo<bool>::Test();
|
||
|
Foo<float>::Test();
|
||
|
}
|
||
|
|
||
|
template <typename T> struct Bar {
|
||
|
struct SubFoo {
|
||
|
int bar1;
|
||
|
int bar2;
|
||
|
};
|
||
|
|
||
|
static void Test() { SubFoo sf = {.bar1 = 10, // expected-note 2 {{previous initialization is here}}
|
||
|
.bar1 = 20}; } // expected-warning 2 {{initializer overrides prior initialization of this subobject}}
|
||
|
};
|
||
|
|
||
|
void bar() {
|
||
|
Bar<int>::Test(); // expected-note {{in instantiation of member function 'Bar<int>::Test' requested here}}
|
||
|
Bar<bool>::Test(); // expected-note {{in instantiation of member function 'Bar<bool>::Test' requested here}}
|
||
|
}
|
||
|
|
||
|
namespace Reorder {
|
||
|
struct X {
|
||
|
X(int n);
|
||
|
private:
|
||
|
int i;
|
||
|
};
|
||
|
|
||
|
struct foo {
|
||
|
X x;
|
||
|
X y;
|
||
|
};
|
||
|
|
||
|
foo n = {.y = 4, .x = 5};
|
||
|
X arr[2] = {[1] = 1, [0] = 2};
|
||
|
}
|
||
|
|
||
|
namespace Reorder2 {
|
||
|
struct S {
|
||
|
S();
|
||
|
S(const S &);
|
||
|
~S();
|
||
|
};
|
||
|
|
||
|
struct EF {
|
||
|
S s;
|
||
|
};
|
||
|
|
||
|
struct PN {
|
||
|
PN(const PN &);
|
||
|
};
|
||
|
extern PN pn;
|
||
|
|
||
|
struct FLN {
|
||
|
EF ef;
|
||
|
int it;
|
||
|
PN pn;
|
||
|
};
|
||
|
|
||
|
void f() {
|
||
|
FLN new_elem = {
|
||
|
.ef = EF(),
|
||
|
.pn = pn,
|
||
|
.it = 0,
|
||
|
};
|
||
|
}
|
||
|
}
|
||
|
|
||
|
namespace Reorder3 {
|
||
|
struct S {
|
||
|
int a, &b, &c; // expected-note 2{{here}}
|
||
|
};
|
||
|
S s1 = {
|
||
|
.a = 1, .c = s1.a, .b = s1.a
|
||
|
};
|
||
|
S s2 = {
|
||
|
.a = 1, .c = s2.a
|
||
|
}; // expected-error {{uninitialized}}
|
||
|
S s3 = {
|
||
|
.b = s3.a, .a = 1,
|
||
|
}; // expected-error {{uninitialized}}
|
||
|
}
|
||
|
|
||
|
// Check that we don't even think about whether holes in a designated
|
||
|
// initializer are zero-initializable if the holes are filled later.
|
||
|
namespace NoCheckingFilledHoles {
|
||
|
template<typename T> struct Error { using type = typename T::type; }; // expected-error 3{{'::'}}
|
||
|
|
||
|
template<int N>
|
||
|
struct DefaultInitIsError {
|
||
|
DefaultInitIsError(Error<int[N]> = {}); // expected-note 3{{instantiation}} expected-note 3{{passing}}
|
||
|
DefaultInitIsError(int, int);
|
||
|
};
|
||
|
|
||
|
template<int N>
|
||
|
struct X {
|
||
|
int a;
|
||
|
DefaultInitIsError<N> e;
|
||
|
int b;
|
||
|
};
|
||
|
X<1> x1 = {
|
||
|
.b = 2,
|
||
|
.a = 1,
|
||
|
{4, 4}
|
||
|
};
|
||
|
X<2> x2 = {
|
||
|
.e = {4, 4},
|
||
|
.b = 2,
|
||
|
.a = 1
|
||
|
};
|
||
|
X<3> x3 = {
|
||
|
.b = 2,
|
||
|
.a = 1
|
||
|
}; // expected-note {{default function argument}}
|
||
|
X<4> x4 = {
|
||
|
.a = 1,
|
||
|
.b = 2
|
||
|
}; // expected-note {{default function argument}}
|
||
|
X<5> x5 = {
|
||
|
.e = {4, 4},
|
||
|
.a = 1,
|
||
|
.b = 2
|
||
|
};
|
||
|
X<6> x6 = {
|
||
|
.a = 1,
|
||
|
.b = 2,
|
||
|
.e = {4, 4}
|
||
|
};
|
||
|
|
||
|
template<int N> struct Y { X<N> x; };
|
||
|
Y<7> y7 = {
|
||
|
.x = {.a = 1, .b = 2}, // expected-note {{default function argument}}
|
||
|
.x.e = {3, 4}
|
||
|
};
|
||
|
Y<8> y8 = {
|
||
|
.x = {.e = {3, 4}},
|
||
|
.x.a = 1,
|
||
|
.x.b = 2
|
||
|
};
|
||
|
}
|
||
|
|
||
|
namespace LargeArrayDesignator {
|
||
|
struct X {
|
||
|
int arr[1000000000];
|
||
|
};
|
||
|
struct Y {
|
||
|
int arr[3];
|
||
|
};
|
||
|
void f(X x);
|
||
|
void f(Y y) = delete;
|
||
|
void g() {
|
||
|
f({.arr[4] = 1});
|
||
|
}
|
||
|
}
|
||
|
|
||
|
namespace ADL {
|
||
|
struct A {};
|
||
|
void f(A, int);
|
||
|
|
||
|
namespace X {
|
||
|
void f(A, int);
|
||
|
// OK. Would fail if checking {} against type A set the type of the
|
||
|
// initializer list to A, because ADL would find ADL::f, resulting in
|
||
|
// ambiguity.
|
||
|
void g() { f({}, {}); }
|
||
|
}
|
||
|
}
|