
completes support for C1X anonymous struct/union init features: * Indexed anonymous member initializers should not be expanded. Doing so makes little sense and would cause unresolvable semantic ambiguity in valid code (regression introduced by r69153). * Subobject initialization of (possibly nested) anonymous members are now referred to with paths relative to the naming record context, eliminating the synthesis of incorrect implicit InitListExprs that caused CodeGen to assert. * Field lookup was missing a null check in IdentifierInfo comparison which caused lookup for a known (already resolved) field to match the first unnamed data member it encountered leading to silent miscompilation. * Subobject paths are no longer built using the general purpose Sema::BuildAnonymousStructUnionMemberPath(). If any corner cases crop up, we will now assert earlier in Sema instead of passing invalid InitListExprs through to CodeGen. Fixes PR6955, from Alp Toker! llvm-svn: 116098
90 lines
1.7 KiB
C
90 lines
1.7 KiB
C
// RUN: %clang_cc1 -triple i386-unknown-unknown %s -emit-llvm -o - | FileCheck %s
|
|
|
|
struct foo {
|
|
void *a;
|
|
int b;
|
|
};
|
|
|
|
// CHECK: @u = global %union.anon zeroinitializer
|
|
union { int i; float f; } u = { };
|
|
|
|
// CHECK: @u2 = global %1 { i32 0, [4 x i8] undef }
|
|
union { int i; double f; } u2 = { };
|
|
|
|
// CHECK: @u3 = global %2 zeroinitializer
|
|
union { double f; int i; } u3 = { };
|
|
|
|
// CHECK: @b = global [2 x i32] [i32 0, i32 22]
|
|
int b[2] = {
|
|
[1] = 22
|
|
};
|
|
|
|
// PR6955
|
|
|
|
struct ds {
|
|
struct {
|
|
struct {
|
|
short a;
|
|
};
|
|
short b;
|
|
struct {
|
|
short c;
|
|
};
|
|
};
|
|
};
|
|
|
|
// Traditional C anonymous member init
|
|
struct ds ds0 = { { { .a = 0 } } };
|
|
// C1X lookup-based anonymous member init cases
|
|
struct ds ds1 = { { .a = 1 } };
|
|
struct ds ds2 = { { .b = 1 } };
|
|
struct ds ds3 = { .a = 0 };
|
|
// CHECK: @ds4 = global %3 { %4 { %struct.anon zeroinitializer, i16 0, %struct.anon { i16 1 } } }
|
|
struct ds ds4 = { .c = 1 };
|
|
struct ds ds5 = { { { .a = 0 } }, .b = 1 };
|
|
struct ds ds6 = { { .a = 0, .b = 1 } };
|
|
// CHECK: @ds7 = global %3 { %4 { %struct.anon { i16 2 }, i16 3, %struct.anon zeroinitializer } }
|
|
struct ds ds7 = {
|
|
{ {
|
|
.a = 1
|
|
} },
|
|
.a = 2,
|
|
.b = 3
|
|
};
|
|
|
|
void test1(int argc, char **argv)
|
|
{
|
|
// CHECK: internal global %struct.foo { i8* null, i32 1024 }
|
|
static struct foo foo = {
|
|
.b = 1024,
|
|
};
|
|
|
|
// CHECK: bitcast %union.anon* %u2
|
|
// CHECK: call void @llvm.memset
|
|
union { int i; float f; } u2 = { };
|
|
|
|
// CHECK-NOT: call void @llvm.memset
|
|
union { int i; float f; } u3;
|
|
|
|
// CHECK: ret void
|
|
}
|
|
|
|
|
|
// PR7151
|
|
struct S {
|
|
int nkeys;
|
|
int *keys;
|
|
union {
|
|
void *data;
|
|
};
|
|
};
|
|
|
|
void test2() {
|
|
struct S *btkr;
|
|
|
|
*btkr = (struct S) {
|
|
.keys = 0,
|
|
{ .data = 0 },
|
|
};
|
|
}
|