blob: ea174b57e44d8e9c0b7b0228e419dda1d110c590 [file] [log] [blame]
// RUN: %clang_cc1 %s -fblocks -triple x86_64-apple-darwin -emit-llvm -o - | FileCheck %s
namespace test0 {
// CHECK: define void @_ZN5test04testEi(
// CHECK: define internal void @__test_block_invoke_{{.*}}(
// CHECK: define internal void @__block_global_{{.*}}(
void test(int x) {
^{ ^{ (void) x; }; };
}
}
extern void (^out)();
namespace test1 {
// Capturing const objects doesn't require a local block.
// CHECK: define void @_ZN5test15test1Ev()
// CHECK: store void ()* bitcast ({{.*}} @__block_literal_global{{.*}} to void ()*), void ()** @out
void test1() {
const int NumHorsemen = 4;
out = ^{ (void) NumHorsemen; };
}
// That applies to structs too...
// CHECK: define void @_ZN5test15test2Ev()
// CHECK: store void ()* bitcast ({{.*}} @__block_literal_global{{.*}} to void ()*), void ()** @out
struct loc { double x, y; };
void test2() {
const loc target = { 5, 6 };
out = ^{ (void) target; };
}
// ...unless they have mutable fields...
// CHECK: define void @_ZN5test15test3Ev()
// CHECK: [[BLOCK:%.*]] = alloca [[BLOCK_T:%.*]],
// CHECK: [[T0:%.*]] = bitcast [[BLOCK_T]]* [[BLOCK]] to void ()*
// CHECK: store void ()* [[T0]], void ()** @out
struct mut { mutable int x; };
void test3() {
const mut obj = { 5 };
out = ^{ (void) obj; };
}
// ...or non-trivial destructors...
// CHECK: define void @_ZN5test15test4Ev()
// CHECK: [[OBJ:%.*]] = alloca
// CHECK: [[BLOCK:%.*]] = alloca [[BLOCK_T:%.*]],
// CHECK: [[T0:%.*]] = bitcast [[BLOCK_T]]* [[BLOCK]] to void ()*
// CHECK: store void ()* [[T0]], void ()** @out
struct scope { int x; ~scope(); };
void test4() {
const scope obj = { 5 };
out = ^{ (void) obj; };
}
// ...or non-trivial copy constructors, but it's not clear how to do
// that and still have a constant initializer in '03.
}