Add more reference-binding examples from the C++0x working paper, all of which seem...
[clang.git] / test / CodeGenObjC / exceptions.m
blob7cc0c1f25045eb82a5c129de24cb8e504a1e9433
1 // RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fexceptions -O2 -o - %s | FileCheck %s
2 //
3 // <rdar://problem/7471679> [irgen] [eh] Exception code built with clang (x86_64) crashes
5 // Just check that we don't emit any dead blocks.
6 @interface NSArray @end
7 void f0() {
8   @try {
9     @try {
10       @throw @"a";
11     } @catch(NSArray *e) {
12     }
13   } @catch (id e) {
14   }
17 // CHECK: define void @f1()
18 void f1() {
19   extern void foo(void);
21   while (1) {
22     // CHECK:      call void @objc_exception_try_enter
23     // CHECK-NEXT: getelementptr
24     // CHECK-NEXT: call i32 @_setjmp(
25     // CHECK-NEXT: icmp
26     // CHECK-NEXT: br i1
27     @try {
28     // CHECK:      call void asm sideeffect "", "*m"
29     // CHECK-NEXT: call void @foo()
30       foo();
31     // CHECK-NEXT: call void @objc_exception_try_exit
32     // CHECK-NEXT: ret void
34     // CHECK:      call void asm sideeffect "", "=*m"
35     // CHECK-NEXT: ret void
36     } @finally {
37       break;
38     }
39   }
42 // Test that modifications to local variables are respected under
43 // optimization.  rdar://problem/8160285
45 // CHECK: define i32 @f2()
46 int f2() {
47   extern void foo(void);
49   // CHECK:        [[X:%.*]] = alloca i32
50   // CHECK:        store i32 5, i32* [[X]]
51   int x = 0;
52   x += 5;
54   // CHECK:        [[SETJMP:%.*]] = call i32 @_setjmp
55   // CHECK-NEXT:   [[CAUGHT:%.*]] = icmp eq i32 [[SETJMP]], 0
56   // CHECK-NEXT:   br i1 [[CAUGHT]]
57   @try {
58     // If the optimizers ever figure out how to make this store 6,
59     // that's okay.
60     // CHECK:      [[T1:%.*]] = load i32* [[X]]
61     // CHECK-NEXT: [[T2:%.*]] = add nsw i32 [[T1]], 1
62     // CHECK-NEXT: store i32 [[T2]], i32* [[X]]
63     x++;
64     // CHECK-NEXT: call void asm sideeffect "", "*m,*m"(i32* [[X]]
65     // CHECK-NEXT: call void @foo()
66     // CHECK-NEXT: call void @objc_exception_try_exit
67     // CHECK-NEXT: [[T:%.*]] = load i32* [[X]]
68     // CHECK-NEXT: ret i32 [[T]]
69     foo();
70   } @catch (id) {
71     // Landing pad.  Note that we elide the re-enter.
72     // CHECK:      call void asm sideeffect "", "=*m,=*m"(i32* [[X]]
73     // CHECK-NEXT: call i8* @objc_exception_extract
74     // CHECK-NEXT: [[T1:%.*]] = load i32* [[X]]
75     // CHECK-NEXT: [[T2:%.*]] = add nsw i32 [[T1]], -1
77     // This store is dead.
78     // CHECK-NEXT: store i32 [[T2]], i32* [[X]]
80     // CHECK-NEXT: ret i32 [[T2]]
81     x--;
82   }
83   return x;
86 // Test that the cleanup destination is saved when entering a finally
87 // block.  rdar://problem/8293901
88 // CHECK: define void @f3()
89 void f3() {
90   extern void f3_helper(int, int*);
92   // CHECK:      [[X:%.*]] = alloca i32
93   // CHECK:      store i32 0, i32* [[X]]
94   int x = 0;
96   // CHECK:      call void @objc_exception_try_enter(
97   // CHECK:      call i32 @_setjmp
98   // CHECK-NEXT: icmp eq
99   // CHECK-NEXT: br i1
101   @try {
102     // CHECK:    call void @f3_helper(i32 0, i32* [[X]])
103     // CHECK:    call void @objc_exception_try_exit(
104     f3_helper(0, &x);
105   } @finally {
106     // CHECK:    [[DEST1:%.*]] = phi i32 [ 0, {{%.*}} ], [ 3, {{%.*}} ]
107     // CHECK:    call void @objc_exception_try_enter
108     // CHECK:    call i32 @_setjmp
109     @try {
110       // CHECK:  call void @f3_helper(i32 1, i32* [[X]])
111       // CHECK:  call void @objc_exception_try_exit(
112       f3_helper(1, &x);
113     } @finally {
114       // CHECK:  [[DEST2:%.*]] = phi i32 [ 0, {{%.*}} ], [ 5, {{%.*}} ]
115       // CHECK:  call void @f3_helper(i32 2, i32* [[X]])
116       f3_helper(2, &x);
118       // This loop is large enough to dissuade the optimizer from just
119       // duplicating the finally block.
120       while (x) f3_helper(3, &x);
122       // This is a switch or maybe some chained branches, but relying
123       // on a specific result from the optimizer is really unstable.
124       // CHECK:  [[DEST2]]
125     }
127       // This is a switch or maybe some chained branches, but relying
128       // on a specific result from the optimizer is really unstable.
129     // CHECK:    [[DEST1]]
130   }
132   // CHECK:      call void @f3_helper(i32 4, i32* [[X]])
133   // CHECK-NEXT: ret void
134   f3_helper(4, &x);
137 // rdar://problem/8440970
138 void f4() {
139   extern void f4_help(int);
141   // CHECK: define void @f4()
142   // CHECK:      [[EXNDATA:%.*]] = alloca [[EXNDATA_T:%.*]], align
143   // CHECK:      call void @objc_exception_try_enter([[EXNDATA_T]]* [[EXNDATA]])
144   // CHECK:      call i32 @_setjmp
145   @try {
146   // CHECK:      call void @f4_help(i32 0)
147     f4_help(0);
149   // The finally cleanup has two threaded entrypoints after optimization:
151   // finally.no-call-exit:  Predecessor is when the catch throws.
152   // CHECK:      call i8* @objc_exception_extract([[EXNDATA_T]]* [[EXNDATA]])
153   // CHECK-NEXT: call void @f4_help(i32 2)
154   // CHECK-NEXT: br label
155   //   -> rethrow
157   // finally.call-exit:  Predecessors are the @try and @catch fallthroughs
158   // as well as the no-match case in the catch mechanism.  The i1 is whether
159   // to rethrow and should be true only in the last case.
160   // CHECK:      phi i1
161   // CHECK-NEXT: phi i8*
162   // CHECK-NEXT: call void @objc_exception_try_exit([[EXNDATA_T]]* [[EXNDATA]])
163   // CHECK-NEXT: call void @f4_help(i32 2)
164   // CHECK-NEXT: br i1
165   //   -> ret, rethrow
167   // ret:
168   // CHECK:      ret void
170   // Catch mechanism:
171   // CHECK:      call i8* @objc_exception_extract([[EXNDATA_T]]* [[EXNDATA]])
172   // CHECK-NEXT: call void @objc_exception_try_enter([[EXNDATA_T]]* [[EXNDATA]])
173   // CHECK:      call i32 @_setjmp
174   //   -> next, finally.no-call-exit
175   // CHECK:      call i32 @objc_exception_match
176   //   -> finally.call-exit, match
177   } @catch (NSArray *a) {
178   // match:
179   // CHECK:      call void @f4_help(i32 1)
180   // CHECK-NEXT: br label
181   //   -> finally.call-exit
182     f4_help(1);
183   } @finally {
184     f4_help(2);
185   }
187   // rethrow:
188   // CHECK:      phi i8*
189   // CHECK-NEXT: call void @objc_exception_throw(i8*
190   // CHECK-NEXT: unreachable