1 // RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fexceptions -O2 -o - %s | FileCheck %s
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
11 } @catch(NSArray *e) {
17 // CHECK: define void @f1()
19 extern void foo(void);
22 // CHECK: call void @objc_exception_try_enter
23 // CHECK-NEXT: getelementptr
24 // CHECK-NEXT: call i32 @_setjmp(
28 // CHECK: call void asm sideeffect "", "*m"
29 // CHECK-NEXT: call void @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
42 // Test that modifications to local variables are respected under
43 // optimization. rdar://problem/8160285
45 // CHECK: define i32 @f2()
47 extern void foo(void);
49 // CHECK: [[X:%.*]] = alloca i32
50 // CHECK: store i32 5, i32* [[X]]
54 // CHECK: [[SETJMP:%.*]] = call i32 @_setjmp
55 // CHECK-NEXT: [[CAUGHT:%.*]] = icmp eq i32 [[SETJMP]], 0
56 // CHECK-NEXT: br i1 [[CAUGHT]]
58 // If the optimizers ever figure out how to make this store 6,
60 // CHECK: [[T1:%.*]] = load i32* [[X]]
61 // CHECK-NEXT: [[T2:%.*]] = add nsw i32 [[T1]], 1
62 // CHECK-NEXT: store i32 [[T2]], i32* [[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]]
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]]
86 // Test that the cleanup destination is saved when entering a finally
87 // block. rdar://problem/8293901
88 // CHECK: define void @f3()
90 extern void f3_helper(int, int*);
92 // CHECK: [[X:%.*]] = alloca i32
93 // CHECK: store i32 0, i32* [[X]]
96 // CHECK: call void @objc_exception_try_enter(
97 // CHECK: call i32 @_setjmp
98 // CHECK-NEXT: icmp eq
102 // CHECK: call void @f3_helper(i32 0, i32* [[X]])
103 // CHECK: call void @objc_exception_try_exit(
106 // CHECK: [[DEST1:%.*]] = phi i32 [ 0, {{%.*}} ], [ 3, {{%.*}} ]
107 // CHECK: call void @objc_exception_try_enter
108 // CHECK: call i32 @_setjmp
110 // CHECK: call void @f3_helper(i32 1, i32* [[X]])
111 // CHECK: call void @objc_exception_try_exit(
114 // CHECK: [[DEST2:%.*]] = phi i32 [ 0, {{%.*}} ], [ 5, {{%.*}} ]
115 // CHECK: call void @f3_helper(i32 2, i32* [[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.
127 // This is a switch or maybe some chained branches, but relying
128 // on a specific result from the optimizer is really unstable.
132 // CHECK: call void @f3_helper(i32 4, i32* [[X]])
133 // CHECK-NEXT: ret void
137 // rdar://problem/8440970
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
146 // CHECK: call void @f4_help(i32 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
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.
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)
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) {
179 // CHECK: call void @f4_help(i32 1)
180 // CHECK-NEXT: br label
181 // -> finally.call-exit
189 // CHECK-NEXT: call void @objc_exception_throw(i8*
190 // CHECK-NEXT: unreachable