Home | History | Annotate | Download | only in CodeGen
      1 // RUN: %clang_cc1 %s -triple x86_64-pc-win32 -fms-extensions -emit-llvm -o - | FileCheck %s
      2 
      3 void abort(void) __attribute__((noreturn));
      4 void might_crash(void);
      5 void cleanup(void);
      6 int check_condition(void);
      7 void basic_finally(void) {
      8   __try {
      9     might_crash();
     10   } __finally {
     11     cleanup();
     12   }
     13 }
     14 
     15 // CHECK-LABEL: define void @basic_finally()
     16 // CHECK: invoke void @might_crash()
     17 // CHECK:     to label %[[invoke_cont:[^ ]*]] unwind label %[[lpad:[^ ]*]]
     18 //
     19 // CHECK: [[invoke_cont]]
     20 // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
     21 // CHECK: call void @"\01?fin$0@0@basic_finally@@"(i1 zeroext false, i8* %[[fp]])
     22 // CHECK-NEXT: ret void
     23 //
     24 // CHECK: [[lpad]]
     25 // CHECK-NEXT: landingpad
     26 // CHECK-NEXT: cleanup
     27 // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
     28 // CHECK: call void @"\01?fin$0@0@basic_finally@@"(i1 zeroext true, i8* %[[fp]])
     29 // CHECK: resume { i8*, i32 }
     30 
     31 // CHECK: define internal void @"\01?fin$0@0@basic_finally@@"(i1 zeroext %abnormal_termination, i8* %frame_pointer)
     32 // CHECK: call void @cleanup()
     33 
     34 // Mostly check that we don't double emit 'r' which would crash.
     35 void decl_in_finally(void) {
     36   __try {
     37     might_crash();
     38   } __finally {
     39     int r;
     40   }
     41 }
     42 
     43 // Ditto, don't crash double emitting 'l'.
     44 void label_in_finally(void) {
     45   __try {
     46     might_crash();
     47   } __finally {
     48 l:
     49     cleanup();
     50     if (check_condition())
     51       goto l;
     52   }
     53 }
     54 
     55 // CHECK-LABEL: define void @label_in_finally()
     56 // CHECK: invoke void @might_crash()
     57 // CHECK:     to label %[[invoke_cont:[^ ]*]] unwind label %[[lpad:[^ ]*]]
     58 //
     59 // CHECK: [[invoke_cont]]
     60 // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
     61 // CHECK: call void @"\01?fin$0@0@label_in_finally@@"(i1 zeroext false, i8* %[[fp]])
     62 // CHECK: ret void
     63 
     64 // CHECK: define internal void @"\01?fin$0@0@label_in_finally@@"(i1 zeroext %abnormal_termination, i8* %frame_pointer)
     65 // CHECK: br label %[[l:[^ ]*]]
     66 //
     67 // CHECK: [[l]]
     68 // CHECK: call void @cleanup()
     69 // CHECK: call i32 @check_condition()
     70 // CHECK: br i1 {{.*}}, label
     71 // CHECK: br label %[[l]]
     72 
     73 int crashed;
     74 void use_abnormal_termination(void) {
     75   __try {
     76     might_crash();
     77   } __finally {
     78     crashed = __abnormal_termination();
     79   }
     80 }
     81 
     82 // CHECK-LABEL: define void @use_abnormal_termination()
     83 // CHECK: invoke void @might_crash()
     84 // CHECK:     to label %[[invoke_cont:[^ ]*]] unwind label %[[lpad:[^ ]*]]
     85 //
     86 // CHECK: [[invoke_cont]]
     87 // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
     88 // CHECK: call void @"\01?fin$0@0@use_abnormal_termination@@"(i1 zeroext false, i8* %[[fp]])
     89 // CHECK: ret void
     90 //
     91 // CHECK: [[lpad]]
     92 // CHECK-NEXT: landingpad
     93 // CHECK-NEXT: cleanup
     94 // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
     95 // CHECK: call void @"\01?fin$0@0@use_abnormal_termination@@"(i1 zeroext true, i8* %[[fp]])
     96 // CHECK: resume { i8*, i32 }
     97 
     98 // CHECK: define internal void @"\01?fin$0@0@use_abnormal_termination@@"(i1 zeroext %abnormal_termination, i8* %frame_pointer)
     99 // CHECK: %[[abnormal_zext:[^ ]*]] = zext i1 %abnormal_termination to i32
    100 // CHECK: store i32 %[[abnormal_zext]], i32* @crashed
    101 // CHECK-NEXT: ret void
    102 
    103 void noreturn_noop_finally() {
    104   __try {
    105     __noop();
    106   } __finally {
    107     abort();
    108   }
    109 }
    110 
    111 // CHECK-LABEL: define void @noreturn_noop_finally()
    112 // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
    113 // CHECK: call void @"\01?fin$0@0@noreturn_noop_finally@@"(i1 zeroext false, i8* %[[fp]])
    114 // CHECK: ret void
    115 
    116 // CHECK: define internal void @"\01?fin$0@0@noreturn_noop_finally@@"(i1 zeroext %abnormal_termination, i8* %frame_pointer)
    117 // CHECK: call void @abort()
    118 // CHECK: unreachable
    119 
    120 void noreturn_finally() {
    121   __try {
    122     might_crash();
    123   } __finally {
    124     abort();
    125   }
    126 }
    127 
    128 // CHECK-LABEL: define void @noreturn_finally()
    129 // CHECK: invoke void @might_crash()
    130 // CHECK:     to label %[[cont:[^ ]*]] unwind label %[[lpad:[^ ]*]]
    131 //
    132 // CHECK: [[cont]]
    133 // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
    134 // CHECK: call void @"\01?fin$0@0@noreturn_finally@@"(i1 zeroext false, i8* %[[fp]])
    135 // CHECK: ret void
    136 //
    137 // CHECK: [[lpad]]
    138 // CHECK: landingpad
    139 // CHECK-NEXT: cleanup
    140 // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
    141 // CHECK: call void @"\01?fin$0@0@noreturn_finally@@"(i1 zeroext true, i8* %[[fp]])
    142 // CHECK: resume { i8*, i32 }
    143 
    144 // CHECK: define internal void @"\01?fin$0@0@noreturn_finally@@"(i1 zeroext %abnormal_termination, i8* %frame_pointer)
    145 // CHECK: call void @abort()
    146 // CHECK: unreachable
    147 
    148 int finally_with_return() {
    149   __try {
    150     return 42;
    151   } __finally {
    152   }
    153 }
    154 // CHECK-LABEL: define i32 @finally_with_return()
    155 // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
    156 // CHECK-NEXT: call void @"\01?fin$0@0@finally_with_return@@"(i1 zeroext false, i8* %[[fp]])
    157 // CHECK-NEXT: ret i32 42
    158 
    159 // CHECK: define internal void @"\01?fin$0@0@finally_with_return@@"(i1 zeroext %abnormal_termination, i8* %frame_pointer)
    160 // CHECK-NOT: br i1
    161 // CHECK-NOT: br label
    162 // CHECK: ret void
    163 
    164 int nested___finally___finally() {
    165   __try {
    166     __try {
    167     } __finally {
    168       return 1;
    169     }
    170   } __finally {
    171     // Intentionally no return here.
    172   }
    173   return 0;
    174 }
    175 
    176 // CHECK-LABEL: define i32 @nested___finally___finally
    177 // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
    178 // CHECK: invoke void @"\01?fin$1@0@nested___finally___finally@@"(i1 zeroext false, i8* %[[fp]])
    179 // CHECK:          to label %[[outercont:[^ ]*]] unwind label %[[lpad:[^ ]*]]
    180 //
    181 // CHECK: [[outercont]]
    182 // CHECK-NEXT: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
    183 // CHECK-NEXT: call void @"\01?fin$0@0@nested___finally___finally@@"(i1 zeroext false, i8* %[[fp]])
    184 // CHECK-NEXT: ret i32 0
    185 //
    186 // CHECK: [[lpad]]
    187 // CHECK-NEXT: landingpad
    188 // CHECK-NEXT: cleanup
    189 // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
    190 // CHECK-NEXT: call void @"\01?fin$0@0@nested___finally___finally@@"(i1 zeroext true, i8* %[[fp]])
    191 
    192 // CHECK-LABEL: define internal void @"\01?fin$0@0@nested___finally___finally@@"(i1 zeroext %abnormal_termination, i8* %frame_pointer)
    193 // CHECK: ret void
    194 
    195 // CHECK-LABEL: define internal void @"\01?fin$1@0@nested___finally___finally@@"(i1 zeroext %abnormal_termination, i8* %frame_pointer)
    196 // CHECK: unreachable
    197 
    198 int nested___finally___finally_with_eh_edge() {
    199   __try {
    200     __try {
    201       might_crash();
    202     } __finally {
    203       return 899;
    204     }
    205   } __finally {
    206     // Intentionally no return here.
    207   }
    208   return 912;
    209 }
    210 // CHECK-LABEL: define i32 @nested___finally___finally_with_eh_edge
    211 // CHECK: invoke void @might_crash()
    212 // CHECK-NEXT: to label %[[invokecont:[^ ]*]] unwind label %[[lpad1:[^ ]*]]
    213 //
    214 // [[invokecont]]
    215 // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
    216 // CHECK: invoke void @"\01?fin$1@0@nested___finally___finally_with_eh_edge@@"(i1 zeroext false, i8* %[[fp]])
    217 // CHECK:          to label %[[outercont:[^ ]*]] unwind label %[[lpad2:[^ ]*]]
    218 //
    219 // CHECK: [[outercont]]
    220 // CHECK-NEXT: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
    221 // CHECK-NEXT: call void @"\01?fin$0@0@nested___finally___finally_with_eh_edge@@"(i1 zeroext false, i8* %[[fp]])
    222 // CHECK-NEXT: ret i32 912
    223 //
    224 // CHECK: [[lpad1]]
    225 // CHECK-NEXT: landingpad
    226 // CHECK-NEXT: cleanup
    227 // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
    228 // CHECK: invoke void @"\01?fin$1@0@nested___finally___finally_with_eh_edge@@"(i1 zeroext true, i8* %[[fp]])
    229 // CHECK:          to label %[[outercont:[^ ]*]] unwind label %[[lpad2]]
    230 //
    231 // CHECK: [[lpad2]]
    232 // CHECK-NEXT: landingpad
    233 // CHECK-NEXT: cleanup
    234 // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
    235 // CHECK: call void @"\01?fin$0@0@nested___finally___finally_with_eh_edge@@"(i1 zeroext true, i8* %[[fp]])
    236 // CHECK: resume
    237 
    238 // CHECK-LABEL: define internal void @"\01?fin$0@0@nested___finally___finally_with_eh_edge@@"(i1 zeroext %abnormal_termination, i8* %frame_pointer)
    239 // CHECK: ret void
    240 
    241 // CHECK-LABEL: define internal void @"\01?fin$1@0@nested___finally___finally_with_eh_edge@@"(i1 zeroext %abnormal_termination, i8* %frame_pointer)
    242 // CHECK: unreachable
    243