]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - test/CodeGenObjC/exceptions.m
Vendor import of clang release_30 branch r142614:
[FreeBSD/FreeBSD.git] / test / CodeGenObjC / exceptions.m
1 // RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-fragile-abi -emit-llvm -fexceptions -fobjc-exceptions -O2 -o - %s | FileCheck %s
2 //
3 // <rdar://problem/7471679> [irgen] [eh] Exception code built with clang (x86_64) crashes
4
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   }
15 }
16
17 // CHECK: define void @f1()
18 void f1() {
19   extern void foo(void);
20
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
33     // CHECK:      call void asm sideeffect "", "=*m"
34     } @finally {
35       break;
36     }
37   }
38 }
39
40 // Test that modifications to local variables are respected under
41 // optimization.  rdar://problem/8160285
42
43 // CHECK: define i32 @f2()
44 int f2() {
45   extern void foo(void);
46
47   // CHECK:        [[X:%.*]] = alloca i32
48   // CHECK:        store i32 5, i32* [[X]]
49   int x = 0;
50   x += 5;
51
52   // CHECK:        [[SETJMP:%.*]] = call i32 @_setjmp
53   // CHECK-NEXT:   [[CAUGHT:%.*]] = icmp eq i32 [[SETJMP]], 0
54   // CHECK-NEXT:   br i1 [[CAUGHT]]
55   @try {
56     // If the optimizers ever figure out how to make this store 6,
57     // that's okay.
58     // CHECK:      [[T1:%.*]] = load i32* [[X]]
59     // CHECK-NEXT: [[T2:%.*]] = add nsw i32 [[T1]], 1
60     // CHECK-NEXT: store i32 [[T2]], i32* [[X]]
61     x++;
62     // CHECK-NEXT: call void asm sideeffect "", "*m,*m"(i32* [[X]]
63     // CHECK-NEXT: call void @foo()
64     // CHECK-NEXT: call void @objc_exception_try_exit
65     // CHECK-NEXT: [[T:%.*]] = load i32* [[X]]
66     foo();
67   } @catch (id) {
68     // Landing pad.  Note that we elide the re-enter.
69     // CHECK:      call void asm sideeffect "", "=*m,=*m"(i32* [[X]]
70     // CHECK-NEXT: call i8* @objc_exception_extract
71     // CHECK-NEXT: [[T1:%.*]] = load i32* [[X]]
72     // CHECK-NEXT: [[T2:%.*]] = add nsw i32 [[T1]], -1
73
74     // This store is dead.
75     // CHECK-NEXT: store i32 [[T2]], i32* [[X]]
76     x--;
77   }
78
79   return x;
80 }
81
82 // Test that the cleanup destination is saved when entering a finally
83 // block.  rdar://problem/8293901
84 // CHECK: define void @f3()
85 void f3() {
86   extern void f3_helper(int, int*);
87
88   // CHECK:      [[X:%.*]] = alloca i32
89   // CHECK:      store i32 0, i32* [[X]]
90   int x = 0;
91
92   // CHECK:      call void @objc_exception_try_enter(
93   // CHECK:      call i32 @_setjmp
94   // CHECK-NEXT: icmp eq
95   // CHECK-NEXT: br i1
96
97   @try {
98     // CHECK:    call void @f3_helper(i32 0, i32* [[X]])
99     // CHECK:    call void @objc_exception_try_exit(
100     f3_helper(0, &x);
101   } @finally {
102     // CHECK:    [[DEST1:%.*]] = phi i32 [ 0, {{%.*}} ], [ 3, {{%.*}} ]
103     // CHECK:    call void @objc_exception_try_enter
104     // CHECK:    call i32 @_setjmp
105     @try {
106       // CHECK:  call void @f3_helper(i32 1, i32* [[X]])
107       // CHECK:  call void @objc_exception_try_exit(
108       f3_helper(1, &x);
109     } @finally {
110       // CHECK:  [[DEST2:%.*]] = phi i32 [ 0, {{%.*}} ], [ 5, {{%.*}} ]
111       // CHECK:  call void @f3_helper(i32 2, i32* [[X]])
112       f3_helper(2, &x);
113
114       // This loop is large enough to dissuade the optimizer from just
115       // duplicating the finally block.
116       while (x) f3_helper(3, &x);
117
118       // This is a switch or maybe some chained branches, but relying
119       // on a specific result from the optimizer is really unstable.
120       // CHECK:  [[DEST2]]
121     }
122
123       // This is a switch or maybe some chained branches, but relying
124       // on a specific result from the optimizer is really unstable.
125     // CHECK:    [[DEST1]]
126   }
127
128   // CHECK:      call void @f3_helper(i32 4, i32* [[X]])
129   // CHECK-NEXT: ret void
130   f3_helper(4, &x);
131 }
132
133 // rdar://problem/8440970
134 void f4() {
135   extern void f4_help(int);
136
137   // CHECK: define void @f4()
138   // CHECK:      [[EXNDATA:%.*]] = alloca [[EXNDATA_T:%.*]], align
139   // CHECK:      call void @objc_exception_try_enter([[EXNDATA_T]]* [[EXNDATA]])
140   // CHECK:      call i32 @_setjmp
141   @try {
142   // CHECK:      call void @f4_help(i32 0)
143     f4_help(0);
144
145   // The finally cleanup has two threaded entrypoints after optimization:
146
147   // finally.no-call-exit:  Predecessor is when the catch throws.
148   // CHECK:      call i8* @objc_exception_extract([[EXNDATA_T]]* [[EXNDATA]])
149   // CHECK-NEXT: call void @f4_help(i32 2)
150   // CHECK-NEXT: br label
151   //   -> rethrow
152
153   // finally.call-exit:  Predecessors are the @try and @catch fallthroughs
154   // as well as the no-match case in the catch mechanism.  The i1 is whether
155   // to rethrow and should be true only in the last case.
156   // CHECK:      phi i1
157   // CHECK-NEXT: phi i8*
158   // CHECK-NEXT: call void @objc_exception_try_exit([[EXNDATA_T]]* [[EXNDATA]])
159   // CHECK-NEXT: call void @f4_help(i32 2)
160   // CHECK-NEXT: br i1
161   //   -> ret, rethrow
162
163   // ret:
164   // CHECK:      ret void
165
166   // Catch mechanism:
167   // CHECK:      call i8* @objc_exception_extract([[EXNDATA_T]]* [[EXNDATA]])
168   // CHECK-NEXT: call void @objc_exception_try_enter([[EXNDATA_T]]* [[EXNDATA]])
169   // CHECK:      call i32 @_setjmp
170   //   -> next, finally.no-call-exit
171   // CHECK:      call i32 @objc_exception_match
172   //   -> finally.call-exit, match
173   } @catch (NSArray *a) {
174   // match:
175   // CHECK:      call void @f4_help(i32 1)
176   // CHECK-NEXT: br label
177   //   -> finally.call-exit
178     f4_help(1);
179   } @finally {
180     f4_help(2);
181   }
182
183   // rethrow:
184   // CHECK:      phi i8*
185   // CHECK-NEXT: call void @objc_exception_throw(i8*
186   // CHECK-NEXT: unreachable
187 }