1 // RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-runtime=macosx-fragile-10.5 -emit-llvm -fobjc-exceptions -mllvm -simplifycfg-sink-common=false -O2 -o - %s | FileCheck %s
3 // [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-LABEL: define{{.*}} void @f1()
19 extern void foo(void);
22 // CHECK: call void @objc_exception_try_enter
23 // CHECK-NEXT: call i32 @_setjmp(
27 // CHECK: call void asm sideeffect "", "=*m"
28 // CHECK: call void asm sideeffect "", "*m"
29 // CHECK-NEXT: call void @foo()
31 // CHECK: call void @objc_exception_try_exit
39 // Test that modifications to local variables are respected under
42 // CHECK-LABEL: define{{.*}} i32 @f2()
44 extern void foo(void);
46 // CHECK: [[X:%.*]] = alloca i32
47 // CHECK: store i32 5, ptr [[X]]
51 // CHECK: [[SETJMP:%.*]] = call i32 @_setjmp
52 // CHECK-NEXT: [[CAUGHT:%.*]] = icmp eq i32 [[SETJMP]], 0
53 // CHECK-NEXT: br i1 [[CAUGHT]]
55 // Landing pad. Note that we elide the re-enter.
56 // CHECK: call void asm sideeffect "", "=*m,=*m"(ptr nonnull elementtype(i32) [[X]]
57 // CHECK-NEXT: call ptr @objc_exception_extract
58 // CHECK-NEXT: [[T1:%.*]] = load i32, ptr [[X]]
59 // CHECK-NEXT: [[T2:%.*]] = add nsw i32 [[T1]], -1
61 // CHECK: store i32 6, ptr [[X]]
63 // CHECK-NEXT: call void asm sideeffect "", "*m,*m"(ptr nonnull elementtype(i32) [[X]]
64 // CHECK-NEXT: call void @foo()
65 // CHECK-NEXT: call void @objc_exception_try_exit
66 // CHECK-NEXT: [[T:%.*]] = load i32, ptr [[X]]
75 // Test that the cleanup destination is saved when entering a finally
77 // CHECK-LABEL: define{{.*}} void @f3()
79 extern void f3_helper(int, int*);
81 // CHECK: [[X:%.*]] = alloca i32
82 // CHECK: call void @llvm.lifetime.start.p0(i64 4, ptr nonnull [[X]])
83 // CHECK: store i32 0, ptr [[X]]
86 // CHECK: call void @objc_exception_try_enter(
87 // CHECK: call i32 @_setjmp
88 // CHECK-NEXT: [[DEST1:%.*]] = icmp eq
89 // CHECK-NEXT: br i1 [[DEST1]]
92 // CHECK: call void @f3_helper(i32 noundef 0, ptr noundef nonnull [[X]])
93 // CHECK: call void @objc_exception_try_exit(
96 // CHECK: call void @objc_exception_try_enter
97 // CHECK: call i32 @_setjmp
98 // CHECK-NEXT: [[DEST2:%.*]] = icmp eq
99 // CHECK-NEXT: br i1 [[DEST2]]
101 // CHECK: call void @f3_helper(i32 noundef 1, ptr noundef nonnull [[X]])
102 // CHECK: call void @objc_exception_try_exit(
105 // CHECK: call void @f3_helper(i32 noundef 2, ptr noundef nonnull [[X]])
108 // This loop is large enough to dissuade the optimizer from just
109 // duplicating the finally block.
110 while (x) f3_helper(3, &x);
112 // This is a switch or maybe some chained branches, but relying
113 // on a specific result from the optimizer is really unstable.
117 // This is a switch or maybe some chained branches, but relying
118 // on a specific result from the optimizer is really unstable.
122 // CHECK: call void @f3_helper(i32 noundef 4, ptr noundef nonnull [[X]])
123 // CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 4, ptr nonnull [[X]])
124 // CHECK-NEXT: ret void
129 extern void f4_help(int);
131 // CHECK-LABEL: define{{.*}} void @f4()
132 // CHECK: [[EXNDATA:%.*]] = alloca [[EXNDATA_T:%.*]], align
133 // CHECK: call void @objc_exception_try_enter(ptr nonnull [[EXNDATA]])
134 // CHECK: call i32 @_setjmp
136 // CHECK: call void @f4_help(i32 noundef 0)
139 // The finally cleanup has two threaded entrypoints after optimization:
141 // finally.no-call-exit: Predecessor is when the catch throws.
142 // CHECK: call ptr @objc_exception_extract(ptr nonnull [[EXNDATA]])
143 // CHECK-NEXT: call void @f4_help(i32 noundef 2)
144 // CHECK-NEXT: br label
147 // finally.call-exit: Predecessors are the @try and @catch fallthroughs
148 // as well as the no-match case in the catch mechanism. The i1 is whether
149 // to rethrow and should be true only in the last case.
151 // CHECK-NEXT: phi i1
152 // CHECK-NEXT: call void @objc_exception_try_exit(ptr nonnull [[EXNDATA]])
153 // CHECK-NEXT: call void @f4_help(i32 noundef 2)
161 // CHECK: call ptr @objc_exception_extract(ptr nonnull [[EXNDATA]])
162 // CHECK-NEXT: call void @objc_exception_try_enter(ptr nonnull [[EXNDATA]])
163 // CHECK: call i32 @_setjmp
164 // -> next, finally.no-call-exit
165 // CHECK: call i32 @objc_exception_match
166 // -> finally.call-exit, match
167 } @catch (NSArray *a) {
169 // CHECK: call void @f4_help(i32 noundef 1)
170 // CHECK-NEXT: br label
171 // -> finally.call-exit
179 // CHECK-NEXT: call void @objc_exception_throw(ptr
180 // CHECK-NEXT: unreachable