mirror of
https://github.com/llvm/llvm-project.git
synced 2025-05-13 01:36:05 +00:00

constructor. Previously, we did some bogus recursion into the fields of anonymous structs (recursively), which ended up building invalid ASTs that would cause CodeGen to crash due to invalid GEPs. Now, we instead build the default initializations based on the indirect field declarations at the top level, which properly generates the sequence of GEPs needed to initialize the proper member. Fixes PR10512 and <rdar://problem/9924046>. llvm-svn: 137212
182 lines
4.1 KiB
C++
182 lines
4.1 KiB
C++
// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -o - %s | FileCheck %s
|
|
|
|
// rdar://8818236
|
|
namespace rdar8818236 {
|
|
struct S {
|
|
char c2;
|
|
union {
|
|
char c;
|
|
int i;
|
|
};
|
|
};
|
|
|
|
// CHECK: @_ZN11rdar88182363fooE = global i64 4
|
|
char S::*foo = &S::c;
|
|
}
|
|
|
|
struct A {
|
|
union {
|
|
int a;
|
|
void* b;
|
|
};
|
|
|
|
A() : a(0) { }
|
|
};
|
|
|
|
A a;
|
|
|
|
namespace PR7021 {
|
|
struct X
|
|
{
|
|
union { long l; };
|
|
};
|
|
|
|
// CHECK: define void @_ZN6PR70211fENS_1XES0_
|
|
void f(X x, X z) {
|
|
X x1;
|
|
|
|
// CHECK: store i64 1, i64
|
|
x1.l = 1;
|
|
|
|
// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64
|
|
X x2(x1);
|
|
|
|
X x3;
|
|
// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64
|
|
x3 = x1;
|
|
|
|
// CHECK: ret void
|
|
}
|
|
}
|
|
|
|
namespace test2 {
|
|
struct A {
|
|
struct {
|
|
union {
|
|
int b;
|
|
};
|
|
};
|
|
|
|
A();
|
|
};
|
|
|
|
A::A() : b(10) { }
|
|
// CHECK: define void @_ZN5test21AC2Ev(
|
|
// CHECK-NOT: }
|
|
// CHECK: store i32 10
|
|
// CHECK: }
|
|
}
|
|
|
|
namespace PR10512 {
|
|
struct A {
|
|
A();
|
|
A(int);
|
|
A(long);
|
|
|
|
struct {
|
|
struct {int x;};
|
|
struct {int y;};
|
|
};
|
|
};
|
|
|
|
// CHECK: define void @_ZN7PR105121AC2Ev
|
|
// CHECK: [[THISADDR:%[a-zA-z0-9.]+]] = alloca [[A:%"struct[A-Za-z0-9:.]+"]]
|
|
// CHECK-NEXT: store [[A]]* [[THIS:%[a-zA-z0-9.]+]], [[A]]** [[THISADDR]]
|
|
// CHECK-NEXT: [[THIS1:%[a-zA-z0-9.]+]] = load [[A]]** [[THISADDR]]
|
|
// CHECK-NEXT: ret void
|
|
A::A() {}
|
|
|
|
// CHECK: define void @_ZN7PR105121AC2Ei
|
|
// CHECK: [[THISADDR:%[a-zA-z0-9.]+]] = alloca [[A:%"struct[A-Za-z0-9:.]+"]]
|
|
// CHECK-NEXT: [[XADDR:%[a-zA-z0-9.]+]] = alloca i32
|
|
// CHECK-NEXT: store [[A]]* [[THIS:%[a-zA-z0-9.]+]], [[A]]** [[THISADDR]]
|
|
// CHECK-NEXT: store i32 [[X:%[a-zA-z0-9.]+]], i32* [[XADDR]]
|
|
// CHECK-NEXT: [[THIS1:%[a-zA-z0-9.]+]] = load [[A]]** [[THISADDR]]
|
|
// CHECK-NEXT: {{getelementptr inbounds.*i32 0, i32 0}}
|
|
// CHECK-NEXT: {{getelementptr inbounds.*i32 0, i32 0}}
|
|
// CHECK-NEXT: {{getelementptr inbounds.*i32 0, i32 0}}
|
|
// CHECK-NEXT: [[TMP:%[a-zA-z0-9.]+]] = load i32* [[XADDR]]
|
|
// CHECK-NEXT: store i32 [[TMP]]
|
|
// CHECK-NEXT: ret void
|
|
A::A(int x) : x(x) { }
|
|
|
|
// CHECK: define void @_ZN7PR105121AC2El
|
|
// CHECK: [[THISADDR:%[a-zA-z0-9.]+]] = alloca [[A:%"struct[A-Za-z0-9:.]+"]]
|
|
// CHECK-NEXT: [[XADDR:%[a-zA-z0-9.]+]] = alloca i64
|
|
// CHECK-NEXT: store [[A]]* [[THIS:%[a-zA-z0-9.]+]], [[A]]** [[THISADDR]]
|
|
// CHECK-NEXT: store i64 [[X:%[a-zA-z0-9.]+]], i64* [[XADDR]]
|
|
// CHECK-NEXT: [[THIS1:%[a-zA-z0-9.]+]] = load [[A]]** [[THISADDR]]
|
|
// CHECK-NEXT: {{getelementptr inbounds.*i32 0, i32 0}}
|
|
// CHECK-NEXT: {{getelementptr inbounds.*i32 0, i32 1}}
|
|
// CHECK-NEXT: {{getelementptr inbounds.*i32 0, i32 0}}
|
|
// CHECK-NEXT: [[TMP:%[a-zA-z0-9.]+]] = load i64* [[XADDR]]
|
|
// CHECK-NEXT: [[CONV:%[a-zA-z0-9.]+]] = trunc i64 [[TMP]] to i32
|
|
// CHECK-NEXT: store i32 [[CONV]]
|
|
// CHECK-NEXT: ret void
|
|
A::A(long y) : y(y) { }
|
|
}
|
|
|
|
namespace test3 {
|
|
struct A {
|
|
union {
|
|
mutable char fibers[100];
|
|
struct {
|
|
void (*callback)(void*);
|
|
void *callback_value;
|
|
};
|
|
};
|
|
|
|
A();
|
|
};
|
|
|
|
A::A() : callback(0), callback_value(0) {}
|
|
// CHECK: define void @_ZN5test31AC2Ev(
|
|
// CHECK: [[THIS:%.*]] = load
|
|
// CHECK-NEXT: [[UNION:%.*]] = getelementptr inbounds {{.*}} [[THIS]], i32 0, i32 0
|
|
// CHECK-NEXT: [[STRUCT:%.*]] = bitcast {{.*}}* [[UNION]] to
|
|
// CHECK-NEXT: [[CALLBACK:%.*]] = getelementptr inbounds {{.*}} [[STRUCT]], i32 0, i32 0
|
|
// CHECK: store
|
|
// CHECK-NEXT: [[UNION:%.*]] = getelementptr inbounds {{.*}} [[THIS]], i32 0, i32 0
|
|
// CHECK-NEXT: [[STRUCT:%.*]] = bitcast {{.*}}* [[UNION]] to
|
|
// CHECK-NEXT: [[CVALUE:%.*]] = getelementptr inbounds {{.*}} [[STRUCT]], i32 0, i32 1
|
|
// CHECK-NEXT: store i8* null, i8** [[CVALUE]]
|
|
}
|
|
|
|
struct S {
|
|
// CHECK: store i32 42
|
|
// CHECK: store i32 55
|
|
S() : x(42), y(55) {}
|
|
union {
|
|
struct {
|
|
int x;
|
|
union { int y; };
|
|
};
|
|
};
|
|
} s;
|
|
|
|
|
|
//PR8760
|
|
template <typename T> struct Foo {
|
|
Foo() : ptr(__nullptr) {}
|
|
union {
|
|
T *ptr;
|
|
};
|
|
};
|
|
Foo<int> f;
|
|
|
|
namespace PR9683 {
|
|
struct QueueEntry {
|
|
union {
|
|
struct {
|
|
void* mPtr;
|
|
union {
|
|
unsigned mSubmissionTag;
|
|
};
|
|
};
|
|
unsigned mValue;
|
|
};
|
|
QueueEntry() {}
|
|
};
|
|
QueueEntry QE;
|
|
}
|