Home | History | Annotate | Download | only in CodeGenCXX
      1 // RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -triple=x86_64-pc-windows-msvc -mconstructor-aliases -fexceptions -fcxx-exceptions | FileCheck -check-prefix WIN64 %s
      2 
      3 extern "C" void might_throw();
      4 
      5 // Simplify the generated IR with noexcept.
      6 extern "C" void recover() noexcept(true);
      7 extern "C" void handle_exception(void *e) noexcept(true);
      8 
      9 extern "C" void catch_all() {
     10   try {
     11     might_throw();
     12   } catch (...) {
     13     recover();
     14   }
     15 }
     16 
     17 // WIN64-LABEL: define void @catch_all()
     18 // WIN64: invoke void @might_throw()
     19 // WIN64-NEXT: to label %[[cont:[^ ]*]] unwind label %[[lpad:[^ ]*]]
     20 //
     21 // WIN64: [[cont]]
     22 // WIN64: br label %[[ret:[^ ]*]]
     23 //
     24 // WIN64: [[lpad]]
     25 // WIN64: landingpad { i8*, i32 }
     26 // WIN64-NEXT: catch i8* null
     27 // WIN64: call void @llvm.eh.begincatch(i8* %{{[^,]*}}, i8* null)
     28 // WIN64: call void @recover()
     29 // WIN64: call void @llvm.eh.endcatch()
     30 // WIN64: br label %[[ret]]
     31 //
     32 // WIN64: [[ret]]
     33 // WIN64: ret void
     34 
     35 extern "C" void catch_int() {
     36   try {
     37     might_throw();
     38   } catch (int e) {
     39     handle_exception(&e);
     40   }
     41 }
     42 
     43 // WIN64-LABEL: define void @catch_int()
     44 // WIN64: landingpad { i8*, i32 }
     45 // WIN64: %[[e_i8:[^ ]*]] = bitcast i32* %[[e_addr:[^ ]*]] to i8*
     46 // WIN64: call void @llvm.eh.begincatch(i8* %{{.*}}, i8* %[[e_i8]])
     47 // WIN64: %[[e_i8:[^ ]*]] = bitcast i32* %[[e_addr]] to i8*
     48 // WIN64: call void @handle_exception(i8* %[[e_i8]])
     49 // WIN64: call void @llvm.eh.endcatch()
     50 
     51 extern "C" void catch_int_unnamed() {
     52   try {
     53     might_throw();
     54   } catch (int) {
     55   }
     56 }
     57 
     58 // WIN64-LABEL: define void @catch_int_unnamed()
     59 // WIN64: landingpad { i8*, i32 }
     60 // WIN64: call void @llvm.eh.begincatch(i8* %{{.*}}, i8* null)
     61 // WIN64: call void @llvm.eh.endcatch()
     62 
     63 struct A {
     64   A();
     65   A(const A &o);
     66   ~A();
     67   int a;
     68 };
     69 
     70 struct B : A {
     71   B();
     72   B(const B &o);
     73   ~B();
     74   int b;
     75 };
     76 
     77 extern "C" void catch_a_byval() {
     78   try {
     79     might_throw();
     80   } catch (A e) {
     81     handle_exception(&e);
     82   }
     83 }
     84 
     85 // WIN64-LABEL: define void @catch_a_byval()
     86 // WIN64: %[[e_addr:[^ ]*]] = alloca %struct.A
     87 // WIN64: landingpad { i8*, i32 }
     88 // WIN64: %[[e_i8:[^ ]*]] = bitcast %struct.A* %[[e_addr]] to i8*
     89 // WIN64: call void @llvm.eh.begincatch(i8* %{{.*}}, i8* %[[e_i8]])
     90 // WIN64: %[[e_i8:[^ ]*]] = bitcast %struct.A* %[[e_addr]] to i8*
     91 // WIN64: call void @handle_exception(i8* %[[e_i8]])
     92 // WIN64: call void @llvm.eh.endcatch()
     93 
     94 extern "C" void catch_a_ref() {
     95   try {
     96     might_throw();
     97   } catch (A &e) {
     98     handle_exception(&e);
     99   }
    100 }
    101 
    102 // WIN64-LABEL: define void @catch_a_ref()
    103 // WIN64: %[[e_addr:[^ ]*]] = alloca %struct.A*
    104 // WIN64: landingpad { i8*, i32 }
    105 // WIN64: %[[e_i8:[^ ]*]] = bitcast %struct.A** %[[e_addr]] to i8*
    106 // WIN64: call void @llvm.eh.begincatch(i8* %{{.*}}, i8* %[[e_i8]])
    107 // WIN64: %[[eptr:[^ ]*]] = load %struct.A*, %struct.A** %[[e_addr]]
    108 // WIN64: %[[eptr_i8:[^ ]*]] = bitcast %struct.A* %[[eptr]] to i8*
    109 // WIN64: call void @handle_exception(i8* %[[eptr_i8]])
    110 // WIN64: call void @llvm.eh.endcatch()
    111 
    112 extern "C" void fn_with_exc_spec() throw(int) {
    113   might_throw();
    114 }
    115 
    116 // WIN64-LABEL: define void @fn_with_exc_spec()
    117 // WIN64: call void @might_throw()
    118 // WIN64-NEXT: ret void
    119