Home | History | Annotate | Download | only in CodeGenObjCXX
      1 // RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fobjc-arc -fexceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime-has-weak -o - -fobjc-arc-exceptions %s | FileCheck %s
      2 
      3 @class Ety;
      4 
      5 // These first four tests are all PR11732 / rdar://problem/10667070.
      6 
      7 void test0_helper(void);
      8 void test0(void) {
      9   @try {
     10     test0_helper();
     11   } @catch (Ety *e) {
     12   }
     13 }
     14 // CHECK-LABEL: define void @_Z5test0v()
     15 // CHECK:      [[E:%.*]] = alloca [[ETY:%.*]]*, align 8
     16 // CHECK-NEXT: invoke void @_Z12test0_helperv()
     17 // CHECK:      [[T0:%.*]] = call i8* @objc_begin_catch(
     18 // CHECK-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to [[ETY]]*
     19 // CHECK-NEXT: [[T2:%.*]] = bitcast [[ETY]]* [[T1]] to i8*
     20 // CHECK-NEXT: [[T3:%.*]] = call i8* @objc_retain(i8* [[T2]]) [[NUW:#[0-9]+]]
     21 // CHECK-NEXT: [[T4:%.*]] = bitcast i8* [[T3]] to [[ETY]]*
     22 // CHECK-NEXT: store [[ETY]]* [[T4]], [[ETY]]** [[E]]
     23 // CHECK-NEXT: [[T0:%.*]] = bitcast [[ETY]]** [[E]] to i8**
     24 // CHECK-NEXT: call void @objc_storeStrong(i8** [[T0]], i8* null) [[NUW]]
     25 // CHECK-NEXT: call void @objc_end_catch() [[NUW]]
     26 
     27 void test1_helper(void);
     28 void test1(void) {
     29   @try {
     30     test1_helper();
     31   } @catch (__weak Ety *e) {
     32   }
     33 }
     34 // CHECK-LABEL: define void @_Z5test1v()
     35 // CHECK:      [[E:%.*]] = alloca [[ETY:%.*]]*, align 8
     36 // CHECK-NEXT: invoke void @_Z12test1_helperv()
     37 // CHECK:      [[T0:%.*]] = call i8* @objc_begin_catch(
     38 // CHECK-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to [[ETY]]*
     39 // CHECK-NEXT: [[T2:%.*]] = bitcast [[ETY]]** [[E]] to i8**
     40 // CHECK-NEXT: [[T3:%.*]] = bitcast [[ETY]]* [[T1]] to i8*
     41 // CHECK-NEXT: call i8* @objc_initWeak(i8** [[T2]], i8* [[T3]]) [[NUW]]
     42 // CHECK-NEXT: [[T0:%.*]] = bitcast [[ETY]]** [[E]] to i8**
     43 // CHECK-NEXT: call void @objc_destroyWeak(i8** [[T0]]) [[NUW]]
     44 // CHECK-NEXT: call void @objc_end_catch() [[NUW]]
     45 
     46 void test2_helper(void);
     47 void test2(void) {
     48   try {
     49     test2_helper();
     50   } catch (Ety *e) {
     51   }
     52 }
     53 // CHECK-LABEL: define void @_Z5test2v()
     54 // CHECK:      [[E:%.*]] = alloca [[ETY:%.*]]*, align 8
     55 // CHECK-NEXT: invoke void @_Z12test2_helperv()
     56 // CHECK:      [[T0:%.*]] = call i8* @__cxa_begin_catch(
     57 // CHECK-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to [[ETY]]*
     58 // CHECK-NEXT: [[T2:%.*]] = bitcast [[ETY]]* [[T1]] to i8*
     59 // CHECK-NEXT: [[T3:%.*]] = call i8* @objc_retain(i8* [[T2]]) [[NUW]]
     60 // CHECK-NEXT: [[T4:%.*]] = bitcast i8* [[T3]] to [[ETY]]*
     61 // CHECK-NEXT: store [[ETY]]* [[T4]], [[ETY]]** [[E]]
     62 // CHECK-NEXT: [[T0:%.*]] = bitcast [[ETY]]** [[E]] to i8**
     63 // CHECK-NEXT: call void @objc_storeStrong(i8** [[T0]], i8* null) [[NUW]]
     64 // CHECK-NEXT: call void @__cxa_end_catch() [[NUW]]
     65 
     66 void test3_helper(void);
     67 void test3(void) {
     68   try {
     69     test3_helper();
     70   } catch (Ety * __weak e) {
     71   }
     72 }
     73 // CHECK-LABEL: define void @_Z5test3v()
     74 // CHECK:      [[E:%.*]] = alloca [[ETY:%.*]]*, align 8
     75 // CHECK-NEXT: invoke void @_Z12test3_helperv()
     76 // CHECK:      [[T0:%.*]] = call i8* @__cxa_begin_catch(
     77 // CHECK-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to [[ETY]]*
     78 // CHECK-NEXT: [[T2:%.*]] = bitcast [[ETY]]** [[E]] to i8**
     79 // CHECK-NEXT: [[T3:%.*]] = bitcast [[ETY]]* [[T1]] to i8*
     80 // CHECK-NEXT: call i8* @objc_initWeak(i8** [[T2]], i8* [[T3]]) [[NUW]]
     81 // CHECK-NEXT: [[T0:%.*]] = bitcast [[ETY]]** [[E]] to i8**
     82 // CHECK-NEXT: call void @objc_destroyWeak(i8** [[T0]]) [[NUW]]
     83 // CHECK-NEXT: call void @__cxa_end_catch() [[NUW]]
     84 
     85 namespace test4 {
     86   struct A {
     87     id single;
     88     id array[2][3];
     89 
     90     A();
     91   };
     92 
     93   A::A() {
     94     throw 0;
     95   }
     96   // CHECK-LABEL:    define void @_ZN5test41AC2Ev(
     97   // CHECK:      [[THIS:%.*]] = load [[A:%.*]]*, [[A:%.*]]** {{%.*}}
     98   //   Construct single.
     99   // CHECK-NEXT: [[SINGLE:%.*]] = getelementptr inbounds [[A]], [[A]]* [[THIS]], i32 0, i32 0
    100   // CHECK-NEXT: store i8* null, i8** [[SINGLE]], align 8
    101   //   Construct array.
    102   // CHECK-NEXT: [[ARRAY:%.*]] = getelementptr inbounds [[A]], [[A]]* [[THIS]], i32 0, i32 1
    103   // CHECK-NEXT: [[T0:%.*]] = bitcast [2 x [3 x i8*]]* [[ARRAY]] to i8*
    104   // CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* [[T0]], i8 0, i64 48, i32 8, i1 false)
    105   //   throw 0;
    106   // CHECK:      invoke void @__cxa_throw(
    107   //   Landing pad from throw site:
    108   // CHECK:      landingpad
    109   //     - First, destroy all of array.
    110   // CHECK:      [[ARRAYBEGIN:%.*]] = getelementptr inbounds [2 x [3 x i8*]], [2 x [3 x i8*]]* [[ARRAY]], i32 0, i32 0, i32 0
    111   // CHECK-NEXT: [[ARRAYEND:%.*]] = getelementptr inbounds i8*, i8** [[ARRAYBEGIN]], i64 6
    112   // CHECK-NEXT: br label
    113   // CHECK:      [[AFTER:%.*]] = phi i8** [ [[ARRAYEND]], {{%.*}} ], [ [[ELT:%.*]], {{%.*}} ]
    114   // CHECK-NEXT: [[ELT]] = getelementptr inbounds i8*, i8** [[AFTER]], i64 -1
    115   // CHECK-NEXT: call void @objc_storeStrong(i8** [[ELT]], i8* null) [[NUW]]
    116   // CHECK-NEXT: [[DONE:%.*]] = icmp eq i8** [[ELT]], [[ARRAYBEGIN]]
    117   // CHECK-NEXT: br i1 [[DONE]],
    118   //     - Next, destroy single.
    119   // CHECK:      call void @objc_storeStrong(i8** [[SINGLE]], i8* null) [[NUW]]
    120   // CHECK:      br label
    121   // CHECK:      resume
    122 }
    123 
    124 // rdar://21397946
    125 __attribute__((ns_returns_retained)) id test5_helper(unsigned);
    126 void test5(void) {
    127   id array[][2] = {
    128     test5_helper(0),
    129     test5_helper(1),
    130     test5_helper(2),
    131     test5_helper(3)
    132   };
    133 }
    134 // CHECK-LABEL: define void @_Z5test5v()
    135 // CHECK:       [[ARRAY:%.*]] = alloca [2 x [2 x i8*]], align
    136 // CHECK:       [[A0:%.*]] = getelementptr inbounds [2 x [2 x i8*]], [2 x [2 x i8*]]* [[ARRAY]], i64 0, i64 0
    137 // CHECK-NEXT:  store [2 x i8*]* [[A0]],
    138 // CHECK-NEXT:  [[A00:%.*]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[A0]], i64 0, i64 0
    139 // CHECK-NEXT:  store i8** [[A00]],
    140 // CHECK-NEXT:  [[T0:%.*]] = invoke i8* @_Z12test5_helperj(i32 0)
    141 // CHECK:       store i8* [[T0]], i8** [[A00]], align
    142 // CHECK-NEXT:  [[A01:%.*]] = getelementptr inbounds i8*, i8** [[A00]], i64 1
    143 // CHECK-NEXT:  store i8** [[A01]],
    144 // CHECK-NEXT:  [[T0:%.*]] = invoke i8* @_Z12test5_helperj(i32 1)
    145 // CHECK:       store i8* [[T0]], i8** [[A01]], align
    146 // CHECK-NEXT:  [[A1:%.*]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[A0]], i64 1
    147 // CHECK-NEXT:  store [2 x i8*]* [[A1]],
    148 // CHECK-NEXT:  [[A10:%.*]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[A1]], i64 0, i64 0
    149 // CHECK-NEXT:  store i8** [[A10]],
    150 // CHECK-NEXT:  [[T0:%.*]] = invoke i8* @_Z12test5_helperj(i32 2)
    151 // CHECK:       store i8* [[T0]], i8** [[A10]], align
    152 // CHECK-NEXT:  [[A11:%.*]] = getelementptr inbounds i8*, i8** [[A10]], i64 1
    153 // CHECK-NEXT:  store i8** [[A11]],
    154 // CHECK-NEXT:  [[T0:%.*]] = invoke i8* @_Z12test5_helperj(i32 3)
    155 // CHECK:       store i8* [[T0]], i8** [[A11]], align
    156 
    157 // CHECK: attributes [[NUW]] = { nounwind }
    158