return const_cast<InitListExpr *>(this)->getInitializedFieldInUnion();
}
void setInitializedFieldInUnion(FieldDecl *FD) {
+ assert((FD == 0
+ || getInitializedFieldInUnion() == 0
+ || getInitializedFieldInUnion() == FD)
+ && "Only one field of a union may be initialized at a time!");
ArrayFillerOrUnionFieldInit = FD;
}
// the initializer list.
if (RT->getDecl()->isUnion()) {
FieldIndex = 0;
- if (!VerifyOnly)
+ if (!VerifyOnly) {
+ FieldDecl *CurrentField = StructuredList->getInitializedFieldInUnion();
+ if (CurrentField && CurrentField != *Field) {
+ assert(StructuredList->getNumInits() == 1
+ && "A union should never have more than one initializer!");
+
+ // we're about to throw away an initializer, emit warning
+ SemaRef.Diag(D->getFieldLoc(),
+ diag::warn_initializer_overrides)
+ << D->getSourceRange();
+ Expr *ExistingInit = StructuredList->getInit(0);
+ SemaRef.Diag(ExistingInit->getLocStart(),
+ diag::note_previous_initializer)
+ << /*FIXME:has side effects=*/0
+ << ExistingInit->getSourceRange();
+
+ // remove existing initializer
+ StructuredList->resizeInits(SemaRef.Context, 0);
+ StructuredList->setInitializedFieldInUnion(0);
+ }
+
StructuredList->setInitializedFieldInUnion(*Field);
+ }
}
// Make sure we can use this declaration.
// CHECK: [6 x i8] c"foo\00y\00", i32 1
+// CHECK: @u1 = {{.*}} { i32 65535 }
+union u_FFFF { char c; long l; } u1 = { .l = 0xFFFF };
+
+
+/// PR16644
+typedef union u_16644 {
+ struct s_16644 {
+ int zero;
+ int one;
+ int two;
+ int three;
+ } a;
+ int b[4];
+} union_16644_t;
+
+// CHECK: @union_16644_instance_0 = {{.*}} { i32 0, i32 0, i32 0, i32 3 } }
+union_16644_t union_16644_instance_0 =
+{
+ .b[0] = 0,
+ .a.one = 1,
+ .b[2] = 2,
+ .a.three = 3,
+};
+
+// CHECK: @union_16644_instance_1 = {{.*}} [i32 10, i32 0, i32 0, i32 0]
+union_16644_t union_16644_instance_1 =
+{
+ .a.three = 13,
+ .b[2] = 12,
+ .a.one = 11,
+ .b[0] = 10,
+};
+
+// CHECK: @union_16644_instance_2 = {{.*}} [i32 0, i32 20, i32 0, i32 0]
+union_16644_t union_16644_instance_2 =
+{
+ .a.one = 21,
+ .b[1] = 20,
+};
+
+// CHECK: @union_16644_instance_3 = {{.*}} { i32 0, i32 31, i32 0, i32 0 }
+union_16644_t union_16644_instance_3 =
+{
+ .b[1] = 30,
+ .a = {
+ .one = 31
+ }
+};
+
+// CHECK: @union_16644_instance_4 = {{.*}} { i32 5, i32 2, i32 0, i32 0 } {{.*}} [i32 0, i32 4, i32 0, i32 0]
+union_16644_t union_16644_instance_4[2] =
+{
+ [0].a.one = 2,
+ [1].a.zero = 3,
+ [0].a.zero = 5,
+ [1].b[1] = 4
+};
void test1(int argc, char **argv)
{
};
}
-// FIXME: How do we test that this initializes the long properly?
union { char c; long l; } u1 = { .l = 0xFFFF };
extern float global_float;
};
+/// PR16644
+typedef union {
+ struct {
+ int zero;
+ int one;
+ int two;
+ int three;
+ } a;
+ int b[4];
+} union_16644_t;
+
+union_16644_t union_16644_instance_0 =
+{
+ .b[0] = 0, // expected-note{{previous}}
+ .a.one = 1, // expected-warning{{overrides}} expected-note{{previous}}
+ .b[2] = 2, // expected-warning{{overrides}} expected-note{{previous}}
+ .a.three = 3, // expected-warning{{overrides}}
+};
+
+union_16644_t union_16644_instance_1 =
+{
+ .a.three = 13, // expected-note{{previous}}
+ .b[2] = 12, // expected-warning{{overrides}} expected-note{{previous}}
+ .a.one = 11, // expected-warning{{overrides}} expected-note{{previous}}
+ .b[0] = 10, // expected-warning{{overrides}}
+};
+
+union_16644_t union_16644_instance_2 =
+{
+ .a.one = 21, // expected-note{{previous}}
+ .b[1] = 20, // expected-warning{{overrides}}
+};
+
+union_16644_t union_16644_instance_3 =
+{
+ .b[1] = 30, // expected-note{{previous}}
+ .a = { // expected-warning{{overrides}}
+ .one = 31
+ }
+};
+
+union_16644_t union_16644_instance_4[2] =
+{
+ [0].a.one = 2,
+ [1].a.zero = 3,// expected-note{{previous}}
+ [0].a.zero = 5,
+ [1].b[1] = 4 // expected-warning{{overrides}}
+};
+
/// PR4073
/// Should use evaluate to fold aggressively and emit a warning if not an ice.
extern int crazy_x;