1// RUN: %clang_cc1 -emit-llvm -triple i686-apple-darwin9 -fobjc-runtime=macosx-fragile-10.5 -o - %s -O2 | FileCheck %s
2
3@interface MyClass
4{
5}
6- (void)method;
7@end
8
9@implementation MyClass
10
11// CHECK: define internal void @"\01-[MyClass method]"
12- (void)method
13{
14  // CHECK: call i32 @objc_sync_enter
15  // CHECK: call void @objc_exception_try_enter
16  // CHECK: call i32 @_setjmp
17  @synchronized(self) {
18  }
19}
20
21@end
22
23// CHECK-LABEL: define void @foo(
24void foo(id a) {
25  // CHECK: [[A:%.*]] = alloca i8*
26  // CHECK: [[SYNC:%.*]] = alloca i8*
27
28  // CHECK:      store i8* [[AVAL:%.*]], i8** [[A]]
29  // CHECK-NEXT: call i32 @objc_sync_enter(i8* [[AVAL]])
30  // CHECK-NEXT: store i8* [[AVAL]], i8** [[SYNC]]
31  // CHECK-NEXT: call void @objc_exception_try_enter
32  // CHECK:      call i32 @_setjmp
33  @synchronized(a) {
34    // This is unreachable, but the optimizers can't know that.
35    // CHECK: call void asm sideeffect "", "=*m,=*m,=*m"(i8** nonnull [[A]], i8** nonnull [[SYNC]]
36    // CHECK: call i32 @objc_sync_exit
37    // CHECK: call i8* @objc_exception_extract
38    // CHECK: call void @objc_exception_throw
39    // CHECK: unreachable
40
41    // CHECK:      call void @objc_exception_try_exit
42    // CHECK:      [[T:%.*]] = load i8*, i8** [[SYNC]]
43    // CHECK-NEXT: call i32 @objc_sync_exit
44    // CHECK: ret void
45    return;
46  }
47
48}
49
50// CHECK-LABEL: define i32 @f0(
51int f0(id a) {
52  // TODO: we can optimize the ret to a constant if we can figure out
53  // either that x isn't stored to within the synchronized block or
54  // that the synchronized block can't longjmp.
55
56  // CHECK: [[X:%.*]] = alloca i32
57  // CHECK: store i32 1, i32* [[X]]
58  int x = 0;
59  @synchronized((x++, a)) {
60  }
61
62  // CHECK: [[T:%.*]] = load i32, i32* [[X]]
63  // CHECK: ret i32 [[T]]
64  return x;
65}
66
67// CHECK-LABEL: define void @f1(
68void f1(id a) {
69  // Check that the return doesn't go through the cleanup.
70  extern void opaque(void);
71  opaque();
72
73  // CHECK: call void @opaque()
74  // CHECK-NEXT: ret void
75
76  @synchronized(({ return; }), a) {
77    return;
78  }
79}
80