Home | History | Annotate | Download | only in CodeGenCXX
      1 // RUN: %clang_cc1 -std=c++11 -fblocks -fms-extensions %s -triple=x86_64-windows-msvc -emit-llvm \
      2 // RUN:         -o - -mconstructor-aliases -fcxx-exceptions -fexceptions | \
      3 // RUN:         FileCheck %s --check-prefix=CHECK --check-prefix=CXXEH
      4 // RUN: %clang_cc1 -std=c++11 -fblocks -fms-extensions %s -triple=x86_64-windows-msvc -emit-llvm \
      5 // RUN:         -o - -mconstructor-aliases -O1 -disable-llvm-optzns | \
      6 // RUN:         FileCheck %s --check-prefix=CHECK --check-prefix=NOCXX
      7 
      8 extern "C" unsigned long _exception_code();
      9 extern "C" void might_throw();
     10 
     11 struct HasCleanup {
     12   HasCleanup();
     13   ~HasCleanup();
     14   int padding;
     15 };
     16 
     17 extern "C" void use_cxx() {
     18   HasCleanup x;
     19   might_throw();
     20 }
     21 
     22 // Make sure we use __CxxFrameHandler3 for C++ EH.
     23 
     24 // CXXEH-LABEL: define void @use_cxx()
     25 // CXXEH-SAME:  personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*)
     26 // CXXEH: call %struct.HasCleanup* @"\01??0HasCleanup@@QEAA@XZ"(%struct.HasCleanup* %{{.*}})
     27 // CXXEH: invoke void @might_throw()
     28 // CXXEH:       to label %[[cont:[^ ]*]] unwind label %[[lpad:[^ ]*]]
     29 //
     30 // CXXEH: [[cont]]
     31 // CXXEH: call void @"\01??1HasCleanup@@QEAA@XZ"(%struct.HasCleanup* %{{.*}})
     32 // CXXEH: ret void
     33 //
     34 // CXXEH: [[lpad]]
     35 // CXXEH: cleanuppad
     36 // CXXEH: call void @"\01??1HasCleanup@@QEAA@XZ"(%struct.HasCleanup* %{{.*}})
     37 // CXXEH: cleanupret
     38 
     39 // NOCXX-LABEL: define void @use_cxx()
     40 // NOCXX-NOT: invoke
     41 // NOCXX: call %struct.HasCleanup* @"\01??0HasCleanup@@QEAA@XZ"(%struct.HasCleanup* %{{.*}})
     42 // NOCXX-NOT: invoke
     43 // NOCXX: call void @might_throw()
     44 // NOCXX-NOT: invoke
     45 // NOCXX: call void @"\01??1HasCleanup@@QEAA@XZ"(%struct.HasCleanup* %{{.*}})
     46 // NOCXX-NOT: invoke
     47 // NOCXX: ret void
     48 
     49 extern "C" void use_seh() {
     50   __try {
     51     might_throw();
     52   } __except(1) {
     53   }
     54 }
     55 
     56 // Make sure we use __C_specific_handler for SEH.
     57 
     58 // CHECK-LABEL: define void @use_seh()
     59 // CHECK-SAME:  personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*)
     60 // CHECK: invoke void @might_throw() #[[NOINLINE:[0-9]+]]
     61 // CHECK:       to label %[[cont:[^ ]*]] unwind label %[[lpad:[^ ]*]]
     62 //
     63 // CHECK: [[lpad]]
     64 // CHECK-NEXT: %[[switch:.*]] = catchswitch within none [label %[[cpad:.*]]] unwind to caller
     65 //
     66 // CHECK: [[cpad]]
     67 // CHECK-NEXT: catchpad within %[[switch]]
     68 // CHECK: catchret {{.*}} label %[[except:[^ ]*]]
     69 //
     70 // CHECK: [[except]]
     71 // CHECK: br label %[[ret:[^ ]*]]
     72 //
     73 // CHECK: [[ret]]
     74 // CHECK: ret void
     75 //
     76 // CHECK: [[cont]]
     77 // CHECK: br label %[[ret]]
     78 
     79 void use_seh_in_lambda() {
     80   ([]() {
     81     __try {
     82       might_throw();
     83     } __except(1) {
     84     }
     85   })();
     86   HasCleanup x;
     87   might_throw();
     88 }
     89 
     90 // CXXEH-LABEL: define void @"\01?use_seh_in_lambda@@YAXXZ"()
     91 // CXXEH-SAME:  personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*)
     92 // CXXEH: cleanuppad
     93 
     94 // NOCXX-LABEL: define void @"\01?use_seh_in_lambda@@YAXXZ"()
     95 // NOCXX-NOT: invoke
     96 // NOCXX: ret void
     97 
     98 // CHECK-LABEL: define internal void @"\01??R<lambda_0>@?0??use_seh_in_lambda@@YAXXZ@QEBA@XZ"(%class.anon* %this)
     99 // CXXEH-SAME:  personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*)
    100 // CHECK: invoke void @might_throw() #[[NOINLINE]]
    101 // CHECK: catchpad
    102 
    103 static int my_unique_global;
    104 
    105 extern "C" inline void use_seh_in_inline_func() {
    106   __try {
    107     might_throw();
    108   } __except(_exception_code() == 424242) {
    109   }
    110   __try {
    111     might_throw();
    112   } __finally {
    113     my_unique_global = 1234;
    114   }
    115 }
    116 
    117 void use_inline() {
    118   use_seh_in_inline_func();
    119 }
    120 
    121 // CHECK-LABEL: define linkonce_odr void @use_seh_in_inline_func() #{{[0-9]+}} comdat
    122 // CHECK-SAME:  personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*)
    123 // CHECK: invoke void @might_throw()
    124 //
    125 // CHECK: catchpad {{.*}} [i8* bitcast (i32 (i8*, i8*)* @"\01?filt$0@0@use_seh_in_inline_func@@" to i8*)]
    126 //
    127 // CHECK: invoke void @might_throw()
    128 //
    129 // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.localaddress()
    130 // CHECK: call void @"\01?fin$0@0@use_seh_in_inline_func@@"(i8 0, i8* %[[fp]])
    131 // CHECK: ret void
    132 //
    133 // CHECK: cleanuppad
    134 // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.localaddress()
    135 // CHECK: call void @"\01?fin$0@0@use_seh_in_inline_func@@"(i8 1, i8* %[[fp]])
    136 
    137 // CHECK-LABEL: define internal i32 @"\01?filt$0@0@use_seh_in_inline_func@@"(i8* %exception_pointers, i8* %frame_pointer) #{{[0-9]+}} comdat($use_seh_in_inline_func)
    138 // CHECK: icmp eq i32 %{{.*}}, 424242
    139 // CHECK: zext i1 %{{.*}} to i32
    140 // CHECK: ret i32
    141 
    142 // CHECK-LABEL: define internal void @"\01?fin$0@0@use_seh_in_inline_func@@"(i8 %abnormal_termination, i8* %frame_pointer) #{{[0-9]+}} comdat($use_seh_in_inline_func)
    143 // CHECK: store i32 1234, i32* @my_unique_global
    144 
    145 // CHECK: attributes #[[NOINLINE]] = { {{.*noinline.*}} }
    146