brintos

brintos / llvm-project-archived public Read only

0
0
Text · 13.5 KiB · f174b5d Raw
460 lines · cpp
1// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -triple x86_64-apple-macosx10.13.99 -std=c++11 -emit-llvm -o - %s | FileCheck --check-prefixes=CHECK,UNALIGNED,THROWEND %s2// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -triple x86_64-apple-macosx10.14 -std=c++11 -emit-llvm -o - %s | FileCheck --check-prefixes=CHECK,ALIGNED,THROWEND %s3// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -triple x86_64-apple-macosx10.14 -std=c++11 -emit-llvm -o - %s -fassume-nothrow-exception-dtor -DNOTHROWEND | FileCheck --check-prefixes=CHECK,ALIGNED,NOTHROWEND %s4 5struct test1_D {6  double d;7} d1;8 9void test1() {10  throw d1;11}12 13// CHECK-LABEL:     define{{.*}} void @_Z5test1v()14// CHECK:       [[EXNOBJ:%.*]] = call ptr @__cxa_allocate_exception(i64 8)15// UNALIGNED-NEXT:  call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[EXNOBJ]], ptr align 8 @d1, i64 8, i1 false)16// ALIGNED-NEXT:  call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[EXNOBJ]], ptr align 8 @d1, i64 8, i1 false)17// CHECK-NEXT:  call void @__cxa_throw(ptr [[EXNOBJ]], ptr @_ZTI7test1_D, ptr null) [[NR:#[0-9]+]]18// CHECK-NEXT:  unreachable19 20 21struct test2_D {22  test2_D(const test2_D&o);23  test2_D();24  virtual void bar() { }25  int i; int j;26} d2;27 28void test2() {29  throw d2;30}31 32// CHECK-LABEL:     define{{.*}} void @_Z5test2v()33// CHECK:       [[EXNVAR:%.*]] = alloca ptr34// CHECK-NEXT:  [[SELECTORVAR:%.*]] = alloca i3235// CHECK-NEXT:  [[EXNOBJ:%.*]] = call ptr @__cxa_allocate_exception(i64 16)36// CHECK-NEXT:  invoke void @_ZN7test2_DC1ERKS_(ptr {{[^,]*}} [[EXNOBJ]], ptr noundef nonnull align {{[0-9]+}} dereferenceable({{[0-9]+}}) @d2)37// CHECK-NEXT:     to label %[[CONT:.*]] unwind label %{{.*}}38//      :     [[CONT]]:   (can't check this in Release-Asserts builds)39// CHECK:       call void @__cxa_throw(ptr [[EXNOBJ]], ptr @_ZTI7test2_D, ptr null) [[NR]]40// CHECK-NEXT:  unreachable41 42 43struct test3_D {44  test3_D() { }45  test3_D(volatile test3_D&o);46  virtual void bar();47};48 49void test3() {50  throw (volatile test3_D *)0;51}52 53// CHECK-LABEL:     define{{.*}} void @_Z5test3v()54// CHECK:       [[EXNOBJ:%.*]] = call ptr @__cxa_allocate_exception(i64 8)55// CHECK-NEXT:  store ptr null, ptr [[EXNOBJ]]56// CHECK-NEXT:  call void @__cxa_throw(ptr [[EXNOBJ]], ptr @_ZTIPV7test3_D, ptr null) [[NR]]57// CHECK-NEXT:  unreachable58 59 60void test4() {61  throw;62}63 64// CHECK-LABEL:     define{{.*}} void @_Z5test4v()65// CHECK:        call void @__cxa_rethrow() [[NR]]66// CHECK-NEXT:   unreachable67 68namespace test5 {69  struct A {70    A();71    A(const A&);72    ~A();73  };74 75  void test() {76    try { throw A(); } catch (A &x) {}77  }78// CHECK-LABEL:      define{{.*}} void @_ZN5test54testEv()79// CHECK:      [[EXNOBJ:%.*]] = call ptr @__cxa_allocate_exception(i64 1)80// CHECK: invoke void @_ZN5test51AC1Ev(ptr {{[^,]*}} [[EXNOBJ]])81// CHECK:      invoke void @__cxa_throw(ptr [[EXNOBJ]], ptr @_ZTIN5test51AE, ptr @_ZN5test51AD1Ev) [[NR]]82// CHECK-NEXT:   to label {{%.*}} unwind label %[[HANDLER:[^ ]*]]83//      :    [[HANDLER]]:  (can't check this in Release-Asserts builds)84// CHECK:      {{%.*}} = call i32 @llvm.eh.typeid.for.p0(ptr @_ZTIN5test51AE)85}86 87namespace test6 {88  template <class T> struct allocator {89    ~allocator() throw() { }90  };91 92  void foo() {93    allocator<int> a;94  }95}96 97// PR712798namespace test7 {99// CHECK-LABEL:      define{{.*}} i32 @_ZN5test73fooEv()100// CHECK-SAME:  personality ptr @__gxx_personality_v0101  int foo() {102// CHECK:      [[CAUGHTEXNVAR:%.*]] = alloca ptr103// CHECK-NEXT: [[SELECTORVAR:%.*]] = alloca i32104// CHECK-NEXT: [[INTCATCHVAR:%.*]] = alloca i32105    try {106      try {107// CHECK-NEXT: [[EXNALLOC:%.*]] = call ptr @__cxa_allocate_exception108// CHECK-NEXT: store i32 1, ptr109// CHECK-NEXT: invoke void @__cxa_throw(ptr [[EXNALLOC]], ptr @_ZTIi, ptr null110        throw 1;111      }112 113// CHECK:      [[CAUGHTVAL:%.*]] = landingpad { ptr, i32 }114// CHECK-NEXT:   catch ptr @_ZTIi115// CHECK-NEXT:   catch ptr null116// CHECK-NEXT: [[CAUGHTEXN:%.*]] = extractvalue { ptr, i32 } [[CAUGHTVAL]], 0117// CHECK-NEXT: store ptr [[CAUGHTEXN]], ptr [[CAUGHTEXNVAR]]118// CHECK-NEXT: [[SELECTOR:%.*]] = extractvalue { ptr, i32 } [[CAUGHTVAL]], 1119// CHECK-NEXT: store i32 [[SELECTOR]], ptr [[SELECTORVAR]]120// CHECK-NEXT: br label121// CHECK:      [[SELECTOR:%.*]] = load i32, ptr [[SELECTORVAR]]122// CHECK-NEXT: [[T0:%.*]] = call i32 @llvm.eh.typeid.for.p0(ptr @_ZTIi)123// CHECK-NEXT: icmp eq i32 [[SELECTOR]], [[T0]]124// CHECK-NEXT: br i1125// CHECK:      [[T0:%.*]] = load ptr, ptr [[CAUGHTEXNVAR]]126// CHECK-NEXT: [[T1:%.*]] = call ptr @__cxa_begin_catch(ptr [[T0]])127// CHECK-NEXT: [[T3:%.*]] = load i32, ptr [[T1]]128// CHECK-NEXT: store i32 [[T3]], ptr {{%.*}}, align 4129// CHECK-NEXT: invoke void @__cxa_rethrow130      catch (int) {131        throw;132      }133    }134// CHECK:      [[CAUGHTVAL:%.*]] = landingpad { ptr, i32 }135// CHECK-NEXT:   catch ptr null136// CHECK-NEXT: [[CAUGHTEXN:%.*]] = extractvalue { ptr, i32 } [[CAUGHTVAL]], 0137// CHECK-NEXT: store ptr [[CAUGHTEXN]], ptr [[CAUGHTEXNVAR]]138// CHECK-NEXT: [[SELECTOR:%.*]] = extractvalue { ptr, i32 } [[CAUGHTVAL]], 1139// CHECK-NEXT: store i32 [[SELECTOR]], ptr [[SELECTORVAR]]140// CHECK-NEXT: call void @__cxa_end_catch()141// CHECK-NEXT: br label142// CHECK:      load ptr, ptr [[CAUGHTEXNVAR]]143// CHECK-NEXT: call ptr @__cxa_begin_catch144// CHECK-NEXT: call void @__cxa_end_catch145    catch (...) {146    }147// CHECK:      ret i32 0148    return 0;149  }150}151 152// Ordering of destructors in a catch handler.153namespace test8 {154  struct A { A(const A&); ~A(); };155  void bar();156 157  // CHECK-LABEL: define{{.*}} void @_ZN5test83fooEv()158  void foo() {159    try {160      // CHECK:      invoke void @_ZN5test83barEv()161      bar();162    } catch (A a) {163      // CHECK:      call ptr @__cxa_get_exception_ptr164      // CHECK-NEXT: invoke void @_ZN5test81AC1ERKS0_(165      // CHECK:      call ptr @__cxa_begin_catch166      // CHECK-NEXT: call void @_ZN5test81AD1Ev(167      // CHECK:      call void @__cxa_end_catch()168      // CHECK:      ret void169    }170  }171}172 173// Constructor function-try-block must rethrow on fallthrough.174namespace test9 {175  void opaque();176 177  struct A { A(); };178 179 180  // CHECK-LABEL: define{{.*}} void @_ZN5test91AC2Ev(ptr {{[^,]*}} %this) unnamed_addr181  // CHECK-SAME:  personality ptr @__gxx_personality_v0182  A::A() try {183  // CHECK:      invoke void @_ZN5test96opaqueEv()184    opaque();185  } catch (int x) {186  // CHECK:      landingpad { ptr, i32 }187  // CHECK-NEXT:   catch ptr @_ZTIi188 189  // CHECK:      call ptr @__cxa_begin_catch190  // CHECK:      invoke void @_ZN5test96opaqueEv()191  // CHECK:      invoke void @__cxa_rethrow()192 193  // CHECK-LABEL:      define{{.*}} void @_ZN5test91AC1Ev(ptr {{[^,]*}} %this) unnamed_addr194  // CHECK:      call void @_ZN5test91AC2Ev195  // CHECK-NEXT: ret void196    opaque();197  }198}199 200// __cxa_end_catch can throw for some kinds of caught exceptions.201namespace test10 {202  void opaque();203 204  struct A { ~A(); };205  struct B { int x; };206 207  // CHECK-LABEL: define{{.*}} void @_ZN6test103fooEv()208  void foo() {209    A a; // force a cleanup context210 211    try {212    // CHECK:      invoke void @_ZN6test106opaqueEv()213      opaque();214    } catch (int i) {215    // CHECK:      call ptr @__cxa_begin_catch216    // CHECK-NEXT: load i32, ptr217    // CHECK-NEXT: store i32218    // CHECK-NEXT: call void @__cxa_end_catch() [[NUW:#[0-9]+]]219    } catch (B a) {220    // CHECK:      call ptr @__cxa_begin_catch221    // CHECK-NEXT: call void @llvm.memcpy222    // THROWEND-NEXT:   invoke void @__cxa_end_catch()223    // NOTHROWEND-NEXT: call void @__cxa_end_catch() [[NUW]]224    } catch (...) {225    // CHECK:      call ptr @__cxa_begin_catch226    // THROWEND-NEXT:   invoke void @__cxa_end_catch()227    // NOTHROWEND-NEXT: call void @__cxa_end_catch() [[NUW]]228    }229 230    // THROWEND:       call void @_ZN6test101AD1Ev(231    // NOTHROWEND-NOT: call void @_ZN6test101AD1Ev(232  }233}234 235// __cxa_begin_catch returns pointers by value, even when catching by reference236namespace test11 {237  void opaque();238 239  // CHECK-LABEL: define{{.*}} void @_ZN6test113fooEv()240  void foo() {241    try {242      // CHECK:      invoke void @_ZN6test116opaqueEv()243      opaque();244    } catch (int**&p) {245      // CHECK:      [[EXN:%.*]] = load ptr, ptr246      // CHECK-NEXT: call ptr @__cxa_begin_catch(ptr [[EXN]]) [[NUW]]247      // CHECK-NEXT: [[ADJ1:%.*]] = getelementptr i8, ptr [[EXN]], i32 32248      // CHECK-NEXT: store ptr [[ADJ1]], ptr [[P:%.*]]249      // CHECK-NEXT: call void @__cxa_end_catch() [[NUW]]250    }251  }252 253  struct A {};254 255  // CHECK-LABEL: define{{.*}} void @_ZN6test113barEv()256  void bar() {257    try {258      // CHECK:      [[EXNSLOT:%.*]] = alloca ptr259      // CHECK-NEXT: [[SELECTORSLOT:%.*]] = alloca i32260      // CHECK-NEXT: [[P:%.*]] = alloca ptr,261      // CHECK-NEXT: [[TMP:%.*]] = alloca ptr262      // CHECK-NEXT: invoke void @_ZN6test116opaqueEv()263      opaque();264    } catch (A*&p) {265      // CHECK:      [[EXN:%.*]] = load ptr, ptr [[EXNSLOT]]266      // CHECK-NEXT: [[ADJ1:%.*]] = call ptr @__cxa_begin_catch(ptr [[EXN]]) [[NUW]]267      // CHECK-NEXT: store ptr [[ADJ1]], ptr [[TMP]]268      // CHECK-NEXT: store ptr [[TMP]], ptr [[P]]269      // CHECK-NEXT: call void @__cxa_end_catch() [[NUW]]270    }271  }272}273 274// PR7686275namespace test12 {276  struct A { ~A() noexcept(false); };277  bool opaque(const A&);278 279  // CHECK-LABEL: define{{.*}} void @_ZN6test124testEv()280  void test() {281    // CHECK: [[X:%.*]] = alloca [[A:%.*]],282    // CHECK: [[EHCLEANUPDEST:%.*]] = alloca i32283    // CHECK: [[Y:%.*]] = alloca [[A:%.*]]284    // CHECK: [[Z:%.*]] = alloca [[A]]285    // CHECK: [[CLEANUPDEST:%.*]] = alloca i32286 287    A x;288    // CHECK: invoke noundef zeroext i1 @_ZN6test126opaqueERKNS_1AE(289    if (opaque(x)) {290      A y;291      A z;292 293      // CHECK: invoke void @_ZN6test121AD1Ev(ptr {{[^,]*}} [[Z]])294      // CHECK: invoke void @_ZN6test121AD1Ev(ptr {{[^,]*}} [[Y]])295      // CHECK-NOT: switch296      goto success;297    }298 299  success:300    bool _ = true;301 302    // CHECK: call void @_ZN6test121AD1Ev(ptr {{[^,]*}} [[X]])303    // CHECK-NEXT: ret void304  }305}306 307// Reduced from some TableGen code that was causing a self-host crash.308namespace test13 {309  struct A { ~A(); };310 311  void test0(int x) {312    try {313      switch (x) {314      case 0:315        break;316      case 1:{317        A a;318        break;319      }320      default:321        return;322      }323      return;324    } catch (int x) {325    }326    return;327  }328 329  void test1(int x) {330    A y;331    try {332      switch (x) {333      default: break;334      }335    } catch (int x) {}336  }337}338 339namespace test14 {340  struct A { ~A(); };341  struct B { ~B(); };342 343  B b();344  void opaque();345 346  void foo() {347    A a;348    try {349      B str = b();350      opaque();351    } catch (int x) {352    }353  }354}355 356// JumpDests shouldn't get confused by scopes that aren't normal cleanups.357namespace test15 {358  struct A { ~A(); };359 360  bool opaque(int);361 362  // CHECK-LABEL: define{{.*}} void @_ZN6test153fooEv()363  void foo() {364    A a;365 366    try {367      // CHECK:      [[X:%.*]] = alloca i32368      // CHECK:      store i32 10, ptr [[X]]369      // CHECK-NEXT: br label370      //   -> while.cond371      int x = 10;372 373      while (true) {374        // CHECK:      load i32, ptr [[X]]375        // CHECK-NEXT: [[COND:%.*]] = invoke noundef zeroext i1 @_ZN6test156opaqueEi376        // CHECK:      br i1 [[COND]]377        if (opaque(x))378        // CHECK:      br label379          break;380 381        // CHECK:      br label382      }383      // CHECK:      br label384    } catch (int x) { }385 386    // CHECK: call void @_ZN6test151AD1Ev387  }388}389 390namespace test16 {391  struct A { A(); ~A() noexcept(false); };392  struct B { int x; B(const A &); ~B() noexcept(false); };393  void foo();394  bool cond();395 396  // CHECK-LABEL: define{{.*}} void @_ZN6test163barEv()397  void bar() {398    // THROWEND:      [[EXN_SAVE:%.*]] = alloca ptr399    // THROWEND-NEXT: [[EXN_ACTIVE:%.*]] = alloca i1400    // THROWEND-NEXT: [[TEMP:%.*]] = alloca [[A:%.*]],401    // THROWEND-NEXT: [[EXNSLOT:%.*]] = alloca ptr402    // THROWEND-NEXT: [[SELECTORSLOT:%.*]] = alloca i32403    // THROWEND-NEXT: [[TEMP_ACTIVE:%.*]] = alloca i1404 405#ifndef NOTHROWEND406    cond() ? throw B(A()) : foo();407#endif408 409    // THROWEND-NEXT: [[COND:%.*]] = call noundef zeroext i1 @_ZN6test164condEv()410    // THROWEND-NEXT: store i1 false, ptr [[EXN_ACTIVE]]411    // THROWEND-NEXT: store i1 false, ptr [[TEMP_ACTIVE]]412    // THROWEND-NEXT: br i1 [[COND]],413 414    // THROWEND:      [[EXN:%.*]] = call ptr @__cxa_allocate_exception(i64 4)415    // THROWEND-NEXT: store ptr [[EXN]], ptr [[EXN_SAVE]]416    // THROWEND-NEXT: store i1 true, ptr [[EXN_ACTIVE]]417    // THROWEND-NEXT: invoke void @_ZN6test161AC1Ev(ptr {{[^,]*}} [[TEMP]])418    // THROWEND:      store i1 true, ptr [[TEMP_ACTIVE]]419    // THROWEND-NEXT: invoke void @_ZN6test161BC1ERKNS_1AE(ptr {{[^,]*}} [[EXN]], ptr noundef nonnull align {{[0-9]+}} dereferenceable({{[0-9]+}}) [[TEMP]])420    // THROWEND:      store i1 false, ptr [[EXN_ACTIVE]]421    // THROWEND-NEXT: invoke void @__cxa_throw(ptr [[EXN]],422 423    // THROWEND:      invoke void @_ZN6test163fooEv()424    // THROWEND:      br label425 426    // THROWEND:      invoke void @_ZN6test161AD1Ev(ptr {{[^,]*}} [[TEMP]])427    // THROWEND:      ret void428 429    // THROWEND:      [[T0:%.*]] = load i1, ptr [[EXN_ACTIVE]]430    // THROWEND-NEXT: br i1 [[T0]]431    // THROWEND:      [[T1:%.*]] = load ptr, ptr [[EXN_SAVE]]432    // THROWEND-NEXT: call void @__cxa_free_exception(ptr [[T1]])433    // THROWEND-NEXT: br label434  }435}436 437namespace test17 {438class BaseException {439private:440  int a[4];441public:442  BaseException() {};443};444 445class DerivedException: public BaseException {446};447 448int foo() {449  throw DerivedException();450  // The alignment passed to memset is 16 on Darwin.451 452  // CHECK: [[T0:%.*]] = call ptr @__cxa_allocate_exception(i64 16)453  // UNALIGNED-NEXT: call void @llvm.memset.p0.i64(ptr align 8 [[T0]], i8 0, i64 16, i1 false)454  // ALIGNED-NEXT: call void @llvm.memset.p0.i64(ptr align 16 [[T0]], i8 0, i64 16, i1 false)455}456}457 458// CHECK: attributes [[NUW]] = { nounwind }459// CHECK: attributes [[NR]] = { noreturn }460