1// RUN: %clang_cc1 -triple i386-unknown-unknown %s -emit-llvm -o - -fblocks | FileCheck %s
2void (^f)(void) = ^{};
3
4// rdar://6768379
5int f0(int (^a0)()) {
6  return a0(1, 2, 3);
7}
8
9// Verify that attributes on blocks are set correctly.
10typedef struct s0 T;
11struct s0 {
12  int a[64];
13};
14
15// CHECK: define internal void @__f2_block_invoke(%struct.s0* noalias sret {{%.*}}, i8* {{%.*}}, %struct.s0* byval align 4 {{.*}})
16struct s0 f2(struct s0 a0) {
17  return ^(struct s0 a1){ return a1; }(a0);
18}
19
20// This should not crash: rdar://6808051
21void *P = ^{
22  void *Q = __func__;
23};
24
25void (^test1)(void) = ^(void) {
26  __block int i;
27  ^ { i = 1; }();
28};
29
30typedef double ftype(double);
31// It's not clear that we *should* support this syntax, but until that decision
32// is made, we should support it properly and not crash.
33ftype ^test2 = ^ftype {
34  return 0;
35};
36
37// rdar://problem/8605032
38void f3_helper(void (^)(void));
39void f3() {
40  _Bool b = 0;
41  f3_helper(^{ if (b) {} });
42}
43
44// rdar://problem/11322251
45// The bool can fill in between the header and the long long.
46// Add the appropriate amount of padding between them.
47void f4_helper(long long (^)(void));
48// CHECK-LABEL: define void @f4()
49void f4(void) {
50  _Bool b = 0;
51  long long ll = 0;
52  // CHECK: alloca <{ i8*, i32, i32, i8*, {{%.*}}*, i8, [3 x i8], i64 }>, align 8
53  f4_helper(^{ if (b) return ll; return 0LL; });
54}
55
56// rdar://problem/11354538
57// The alignment after rounding up to the align of F5 is actually
58// greater than the required alignment.  Don't assert.
59struct F5 {
60  char buffer[32] __attribute((aligned));
61};
62void f5_helper(void (^)(struct F5 *));
63// CHECK-LABEL: define void @f5()
64void f5(void) {
65  struct F5 value;
66  // CHECK: alloca <{ i8*, i32, i32, i8*, {{%.*}}*, [12 x i8], [[F5:%.*]] }>, align 16
67  f5_helper(^(struct F5 *slot) { *slot = value; });
68}
69
70// rdar://14085217
71void (^b)() = ^{};
72int main() {
73   (b?: ^{})();
74}
75// CHECK: [[ZERO:%.*]] = load void (...)** @b
76// CHECK-NEXT: [[TB:%.*]] = icmp ne void (...)* [[ZERO]], null
77// CHECK-NEXT: br i1 [[TB]], label [[CT:%.*]], label [[CF:%.*]]
78// CHECK: [[ONE:%.*]] = bitcast void (...)* [[ZERO]] to void ()*
79// CHECK-NEXT:   br label [[CE:%.*]]
80
81