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 // RUN: %clang_cc1 %s -triple i686-pc-win32 -fms-extensions -emit-llvm -o - | FileCheck %s
      3 
      4 void abort(void) __attribute__((noreturn));
      5 void might_crash(void);
      6 void cleanup(void);
      7 int check_condition(void);
      8 void basic_finally(void) {
      9   __try {
     10     might_crash();
     11   } __finally {
     12     cleanup();
     13   }
     14 }
     15 
     16 // CHECK-LABEL: define void @basic_finally()
     17 // CHECK: invoke void @might_crash()
     18 // CHECK:     to label %[[invoke_cont:[^ ]*]] unwind label %[[lpad:[^ ]*]]
     19 //
     20 // CHECK: [[invoke_cont]]
     21 // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.localaddress()
     22 // CHECK: call void @"\01?fin$0@0@basic_finally@@"({{i8( zeroext)?}} 0, i8* %[[fp]])
     23 // CHECK-NEXT: ret void
     24 //
     25 // CHECK: [[lpad]]
     26 // CHECK-NEXT: %[[pad:[^ ]*]] = cleanuppad
     27 // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.localaddress()
     28 // CHECK: call void @"\01?fin$0@0@basic_finally@@"({{i8( zeroext)?}} 1, i8* %[[fp]])
     29 // CHECK-NEXT: cleanupret from %[[pad]] unwind to caller
     30 
     31 // CHECK: define internal void @"\01?fin$0@0@basic_finally@@"({{.*}})
     32 // CHECK-SAME: [[finally_attrs:#[0-9]+]]
     33 // CHECK: call void @cleanup()
     34 
     35 // Mostly check that we don't double emit 'r' which would crash.
     36 void decl_in_finally(void) {
     37   __try {
     38     might_crash();
     39   } __finally {
     40     int r;
     41   }
     42 }
     43 
     44 // Ditto, don't crash double emitting 'l'.
     45 void label_in_finally(void) {
     46   __try {
     47     might_crash();
     48   } __finally {
     49 l:
     50     cleanup();
     51     if (check_condition())
     52       goto l;
     53   }
     54 }
     55 
     56 // CHECK-LABEL: define void @label_in_finally()
     57 // CHECK: invoke void @might_crash()
     58 // CHECK:     to label %[[invoke_cont:[^ ]*]] unwind label %[[lpad:[^ ]*]]
     59 //
     60 // CHECK: [[invoke_cont]]
     61 // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.localaddress()
     62 // CHECK: call void @"\01?fin$0@0@label_in_finally@@"({{i8( zeroext)?}} 0, i8* %[[fp]])
     63 // CHECK: ret void
     64 
     65 // CHECK: define internal void @"\01?fin$0@0@label_in_finally@@"({{.*}})
     66 // CHECK-SAME: [[finally_attrs]]
     67 // CHECK: br label %[[l:[^ ]*]]
     68 //
     69 // CHECK: [[l]]
     70 // CHECK: call void @cleanup()
     71 // CHECK: call i32 @check_condition()
     72 // CHECK: br i1 {{.*}}, label
     73 // CHECK: br label %[[l]]
     74 
     75 int crashed;
     76 void use_abnormal_termination(void) {
     77   __try {
     78     might_crash();
     79   } __finally {
     80     crashed = __abnormal_termination();
     81   }
     82 }
     83 
     84 // CHECK-LABEL: define void @use_abnormal_termination()
     85 // CHECK: invoke void @might_crash()
     86 // CHECK:     to label %[[invoke_cont:[^ ]*]] unwind label %[[lpad:[^ ]*]]
     87 //
     88 // CHECK: [[invoke_cont]]
     89 // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.localaddress()
     90 // CHECK: call void @"\01?fin$0@0@use_abnormal_termination@@"({{i8( zeroext)?}} 0, i8* %[[fp]])
     91 // CHECK: ret void
     92 //
     93 // CHECK: [[lpad]]
     94 // CHECK-NEXT: %[[pad:[^ ]*]] = cleanuppad
     95 // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.localaddress()
     96 // CHECK: call void @"\01?fin$0@0@use_abnormal_termination@@"({{i8( zeroext)?}} 1, i8* %[[fp]])
     97 // CHECK-NEXT: cleanupret from %[[pad]] unwind to caller
     98 
     99 // CHECK: define internal void @"\01?fin$0@0@use_abnormal_termination@@"({{i8( zeroext)?}} %[[abnormal:abnormal_termination]], i8* %frame_pointer)
    100 // CHECK-SAME: [[finally_attrs]]
    101 // CHECK: %[[abnormal_zext:[^ ]*]] = zext i8 %[[abnormal]] to i32
    102 // CHECK: store i32 %[[abnormal_zext]], i32* @crashed
    103 // CHECK-NEXT: ret void
    104 
    105 void noreturn_noop_finally() {
    106   __try {
    107     __noop();
    108   } __finally {
    109     abort();
    110   }
    111 }
    112 
    113 // CHECK-LABEL: define void @noreturn_noop_finally()
    114 // CHECK: call void @"\01?fin$0@0@noreturn_noop_finally@@"({{.*}})
    115 // CHECK: ret void
    116 
    117 // CHECK: define internal void @"\01?fin$0@0@noreturn_noop_finally@@"({{.*}})
    118 // CHECK-SAME: [[finally_attrs]]
    119 // CHECK: call void @abort()
    120 // CHECK: unreachable
    121 
    122 void noreturn_finally() {
    123   __try {
    124     might_crash();
    125   } __finally {
    126     abort();
    127   }
    128 }
    129 
    130 // CHECK-LABEL: define void @noreturn_finally()
    131 // CHECK: invoke void @might_crash()
    132 // CHECK:     to label %[[cont:[^ ]*]] unwind label %[[lpad:[^ ]*]]
    133 //
    134 // CHECK: [[cont]]
    135 // CHECK: call void @"\01?fin$0@0@noreturn_finally@@"({{.*}})
    136 // CHECK: ret void
    137 //
    138 // CHECK: [[lpad]]
    139 // CHECK-NEXT: %[[pad:[^ ]*]] = cleanuppad
    140 // CHECK: call void @"\01?fin$0@0@noreturn_finally@@"({{.*}})
    141 // CHECK-NEXT: cleanupret from %[[pad]] unwind to caller
    142 
    143 // CHECK: define internal void @"\01?fin$0@0@noreturn_finally@@"({{.*}})
    144 // CHECK-SAME: [[finally_attrs]]
    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: call void @"\01?fin$0@0@finally_with_return@@"({{.*}})
    156 // CHECK-NEXT: ret i32 42
    157 
    158 // CHECK: define internal void @"\01?fin$0@0@finally_with_return@@"({{.*}})
    159 // CHECK-SAME: [[finally_attrs]]
    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: invoke void @"\01?fin$1@0@nested___finally___finally@@"({{.*}})
    178 // CHECK:          to label %[[outercont:[^ ]*]] unwind label %[[lpad:[^ ]*]]
    179 //
    180 // CHECK: [[outercont]]
    181 // CHECK: call void @"\01?fin$0@0@nested___finally___finally@@"({{.*}})
    182 // CHECK-NEXT: ret i32 0
    183 //
    184 // CHECK: [[lpad]]
    185 // CHECK-NEXT: %[[pad:[^ ]*]] = cleanuppad
    186 // CHECK: call void @"\01?fin$0@0@nested___finally___finally@@"({{.*}})
    187 // CHECK-NEXT: cleanupret from %[[pad]] unwind to caller
    188 
    189 // CHECK-LABEL: define internal void @"\01?fin$0@0@nested___finally___finally@@"({{.*}})
    190 // CHECK-SAME: [[finally_attrs]]
    191 // CHECK: ret void
    192 
    193 // CHECK-LABEL: define internal void @"\01?fin$1@0@nested___finally___finally@@"({{.*}})
    194 // CHECK-SAME: [[finally_attrs]]
    195 // CHECK: unreachable
    196 
    197 // FIXME: Our behavior seems suspiciously different.
    198 
    199 int nested___finally___finally_with_eh_edge() {
    200   __try {
    201     __try {
    202       might_crash();
    203     } __finally {
    204       return 899;
    205     }
    206   } __finally {
    207     // Intentionally no return here.
    208   }
    209   return 912;
    210 }
    211 // CHECK-LABEL: define i32 @nested___finally___finally_with_eh_edge
    212 // CHECK: invoke void @might_crash()
    213 // CHECK-NEXT: to label %[[invokecont:[^ ]*]] unwind label %[[lpad1:[^ ]*]]
    214 //
    215 // [[invokecont]]
    216 // CHECK: invoke void @"\01?fin$1@0@nested___finally___finally_with_eh_edge@@"({{.*}})
    217 // CHECK-NEXT:       to label %[[outercont:[^ ]*]] unwind label %[[lpad2:[^ ]*]]
    218 //
    219 // CHECK: [[outercont]]
    220 // CHECK: call void @"\01?fin$0@0@nested___finally___finally_with_eh_edge@@"({{.*}})
    221 // CHECK-NEXT: ret i32 912
    222 //
    223 // CHECK: [[lpad1]]
    224 // CHECK-NEXT: %[[innerpad:[^ ]*]] = cleanuppad
    225 // CHECK: invoke void @"\01?fin$1@0@nested___finally___finally_with_eh_edge@@"({{.*}})
    226 // CHECK-NEXT:    label %[[innercleanupretbb:[^ ]*]] unwind label %[[lpad2:[^ ]*]]
    227 //
    228 // CHECK: [[innercleanupretbb]]
    229 // CHECK-NEXT: cleanupret from %[[innerpad]] unwind label %[[lpad2]]
    230 //
    231 // CHECK: [[lpad2]]
    232 // CHECK-NEXT: %[[outerpad:[^ ]*]] = cleanuppad
    233 // CHECK: call void @"\01?fin$0@0@nested___finally___finally_with_eh_edge@@"({{.*}})
    234 // CHECK-NEXT: cleanupret from %[[outerpad]] unwind to caller
    235 
    236 // CHECK-LABEL: define internal void @"\01?fin$0@0@nested___finally___finally_with_eh_edge@@"({{.*}})
    237 // CHECK-SAME: [[finally_attrs]]
    238 // CHECK: ret void
    239 
    240 // CHECK-LABEL: define internal void @"\01?fin$1@0@nested___finally___finally_with_eh_edge@@"({{.*}})
    241 // CHECK-SAME: [[finally_attrs]]
    242 // CHECK: unreachable
    243 
    244 void finally_within_finally() {
    245   __try {
    246     might_crash();
    247   } __finally {
    248     __try {
    249       might_crash();
    250     } __finally {
    251     }
    252   }
    253 }
    254 
    255 // CHECK-LABEL: define void @finally_within_finally(
    256 // CHECK: invoke void @might_crash(
    257 
    258 // CHECK: call void @"\01?fin$0@0@finally_within_finally@@"(
    259 // CHECK: call void @"\01?fin$0@0@finally_within_finally@@"({{.*}}) [ "funclet"(
    260 
    261 // CHECK-LABEL: define internal void @"\01?fin$0@0@finally_within_finally@@"({{[^)]*}})
    262 // CHECK-SAME: [[finally_attrs]]
    263 // CHECK: invoke void @might_crash(
    264 
    265 // CHECK: call void @"\01?fin$1@0@finally_within_finally@@"(
    266 // CHECK: call void @"\01?fin$1@0@finally_within_finally@@"({{.*}}) [ "funclet"(
    267 
    268 // CHECK-LABEL: define internal void @"\01?fin$1@0@finally_within_finally@@"({{[^)]*}})
    269 // CHECK-SAME: [[finally_attrs]]
    270 
    271 // Look for the absence of noinline. Enum attributes come first, so check that
    272 // a string attribute is the first to verify that no enum attributes are
    273 // present.
    274 // CHECK: attributes [[finally_attrs]] = { "{{.*}}" }
    275