brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.7 KiB · 27123a6 Raw
180 lines · cpp
1// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu %s -o - -emit-llvm -O1 \2// RUN:     -fexceptions -fcxx-exceptions -mllvm -simplifycfg-sink-common=false | FileCheck %s3//4// We should emit lifetime.ends for these temporaries in both the 'exception'5// and 'normal' paths in functions.6//7// -O1 is necessary to make lifetime markers appear.8 9struct Large {10  int cs[32];11};12 13Large getLarge();14 15// Used to ensure we emit invokes.16struct NontrivialDtor {17  int i;18  ~NontrivialDtor();19};20 21// CHECK-LABEL: define{{.*}} void @_Z33cleanupsAreEmittedWithoutTryCatchv22void cleanupsAreEmittedWithoutTryCatch() {23// CHECK: call void @llvm.lifetime.start.p0(ptr nonnull %[[CLEAN:.*]])24// CHECK: call void @llvm.lifetime.start.p0(ptr nonnull %[[T1:.*]])25// CHECK-NEXT: invoke void @_Z8getLargev26// CHECK-NEXT:     to label %[[CONT:[^ ]+]] unwind label %[[LPAD:[^ ]+]]27//28// CHECK: [[CONT]]:29// CHECK: call void @llvm.lifetime.end.p0(ptr nonnull %[[T1]])30// CHECK: call void @llvm.lifetime.start.p0(ptr nonnull %[[T2:.*]])31// CHECK-NEXT: invoke void @_Z8getLargev32// CHECK-NEXT:     to label %[[CONT2:[^ ]+]] unwind label %[[LPAD2:.+]]33//34// CHECK: [[CONT2]]:35// CHECK: call void @llvm.lifetime.end.p0(ptr nonnull %[[T2]])36// CHECK: call void @llvm.lifetime.end.p0(ptr nonnull %[[CLEAN]])37// CHECK: ret void38//39// CHECK: [[LPAD]]:40// CHECK: call void @llvm.lifetime.end.p0(ptr nonnull %[[T1]])41// CHECK: br label %[[EHCLEANUP:.+]]42//43// CHECK: [[LPAD2]]:44// CHECK: call void @llvm.lifetime.end.p0(ptr nonnull %[[T2]])45// CHECK: br label %[[EHCLEANUP]]46//47// CHECK: [[EHCLEANUP]]:48// CHECK: call void @llvm.lifetime.end.p0(ptr nonnull %[[CLEAN]])49 50  NontrivialDtor clean;51 52  getLarge();53  getLarge();54}55 56// CHECK-LABEL: define{{.*}} void @_Z30cleanupsAreEmittedWithTryCatchv57void cleanupsAreEmittedWithTryCatch() {58// CHECK: call void @llvm.lifetime.start.p0(ptr nonnull %[[CLEAN:.*]])59// CHECK: call void @llvm.lifetime.start.p0(ptr nonnull %[[T1:.*]])60// CHECK-NEXT: invoke void @_Z8getLargev61// CHECK-NEXT:     to label %[[CONT:[^ ]+]] unwind label %[[LPAD:[^ ]+]]62//63// CHECK: [[CONT]]:64// CHECK: call void @llvm.lifetime.end.p0(ptr nonnull %[[T1]])65// CHECK: call void @llvm.lifetime.start.p0(ptr nonnull %[[T2:.*]])66// CHECK-NEXT: invoke void @_Z8getLargev67// CHECK-NEXT:     to label %[[CONT2:[^ ]+]] unwind label %[[LPAD2:.+]]68//69// CHECK: [[CONT2]]:70// CHECK: call void @llvm.lifetime.end.p0(ptr nonnull %[[T2]])71// CHECK: br label %[[TRY_CONT:.+]]72//73// CHECK: [[LPAD]]:74// CHECK: call void @llvm.lifetime.end.p0(ptr nonnull %[[T1]])75// CHECK: br label %[[CATCH:.+]]76//77// CHECK: [[LPAD2]]:78// CHECK: call void @llvm.lifetime.end.p0(ptr nonnull %[[T2]])79// CHECK: br label %[[CATCH]]80//81// CHECK: [[CATCH]]:82// CHECK-NOT: call void @llvm.lifetime83// CHECK: invoke void84// CHECK-NEXT: to label %[[TRY_CONT]] unwind label %[[OUTER_LPAD:.+]]85//86// CHECK: [[TRY_CONT]]:87// CHECK: call void @llvm.lifetime.start.p0(ptr nonnull %[[T_OUTER:.*]])88// CHECK-NEXT: invoke void @_Z8getLargev89// CHECK-NEXT:     to label %[[OUTER_CONT:[^ ]+]] unwind label %[[OUTER_LPAD2:.+]]90//91// CHECK: [[OUTER_CONT]]:92// CHECK: call void @llvm.lifetime.end.p0(ptr nonnull %[[T_OUTER]])93// CHECK: call void @llvm.lifetime.end.p0(ptr nonnull %[[CLEAN]])94// CHECK: ret void95//96// CHECK: [[OUTER_LPAD]]:97// CHECK-NOT: call void @llvm.lifetime98// CHECK: br label %[[EHCLEANUP:.+]]99//100// CHECK: [[OUTER_LPAD2]]:101// CHECK: call void @llvm.lifetime.end.p0(ptr nonnull %[[T_OUTER]])102// CHECK: br label %[[EHCLEANUP]]103//104// CHECK: [[EHCLEANUP]]:105// CHECK: call void @llvm.lifetime.end.p0(ptr nonnull %[[CLEAN]])106 107  NontrivialDtor clean;108 109  try {110    getLarge();111    getLarge();112  } catch (...) {}113 114  getLarge();115}116 117// CHECK-LABEL: define{{.*}} void @_Z39cleanupInTryHappensBeforeCleanupInCatchv118void cleanupInTryHappensBeforeCleanupInCatch() {119// CHECK: call void @llvm.lifetime.start.p0(ptr nonnull %[[T1:.*]])120// CHECK-NEXT: invoke void @_Z8getLargev121// CHECK-NEXT:     to label %[[CONT:[^ ]+]] unwind label %[[LPAD:[^ ]+]]122//123// CHECK: [[CONT]]:124// CHECK: call void @llvm.lifetime.end.p0(ptr nonnull %[[T1]])125// CHECK: br label %[[TRY_CONT]]126//127// CHECK: [[LPAD]]:128// CHECK: call void @llvm.lifetime.end.p0(ptr nonnull %[[T1]])129// CHECK: br i1 {{[^,]+}}, label %[[CATCH_INT_MATCH:[^,]+]], label %[[CATCH_ALL:.+]]130//131// CHECK: [[CATCH_INT_MATCH]]:132// CHECK: call void @llvm.lifetime.start.p0(ptr nonnull %[[T2:.*]])133// CHECK-NEXT: invoke void @_Z8getLargev134// CHECK-NEXT:     to label %[[CATCH_INT_CONT:[^ ]+]] unwind label %[[CATCH_INT_LPAD:[^ ]+]]135//136// CHECK: [[CATCH_INT_CONT]]:137// CHECK: call void @llvm.lifetime.end.p0(ptr nonnull %[[T2]])138// CHECK: br label %[[TRY_CONT]]139//140// CHECK: [[TRY_CONT]]:141// CHECK: ret void142//143// CHECK: [[CATCH_ALL]]:144// CHECK: call void @llvm.lifetime.start.p0(ptr nonnull %[[T3:.*]])145// CHECK-NEXT: invoke void @_Z8getLargev146// CHECK-NEXT:     to label %[[CATCH_ALL_CONT:[^ ]+]] unwind label %[[CATCH_ALL_LPAD:[^ ]+]]147//148// CHECK: [[CATCH_ALL_CONT]]:149// CHECK: call void @llvm.lifetime.end.p0(ptr nonnull %[[T3]])150// CHECK: br label %[[TRY_CONT]]151//152// CHECK: [[CATCH_ALL_LPAD]]:153// CHECK: call void @llvm.lifetime.end.p0(ptr nonnull %[[T3]])154//155// CHECK: [[CATCH_INT_LPAD]]:156// CHECK: call void @llvm.lifetime.end.p0(ptr nonnull %[[T2]])157// CHECK-NOT: call void @llvm.lifetime158 159  try {160    getLarge();161  } catch (const int &) {162    getLarge();163  } catch (...) {164    getLarge();165  }166}167 168// FIXME: We don't currently emit lifetime markers for aggregate by-value169// temporaries (e.g. given a function `Large combine(Large, Large);`170// combine(getLarge(), getLarge()) "leaks" two `Large`s). We probably should. We171// also don't emit markers for things like:172//173// {174//   Large L = getLarge();175//   combine(L, L);176// }177//178// Though this arguably isn't as bad, since we pass a pointer to `L` as one of179// the two args.180