Index: lib/CodeGen/CGCleanup.cpp =================================================================== --- lib/CodeGen/CGCleanup.cpp +++ lib/CodeGen/CGCleanup.cpp @@ -157,6 +157,20 @@ return true; } +bool EHScopeStack::requiresLandingPad() const { + for (stable_iterator si = getInnermostEHScope(); si != stable_end(); ) { + // Skip lifetime markers. + if (auto *cleanup = dyn_cast(&*find(si))) + if (cleanup->isLifetimeMarker()) { + si = cleanup->getEnclosingEHScope(); + continue; + } + return true; + } + + return false; +} + EHScopeStack::stable_iterator EHScopeStack::getInnermostActiveNormalCleanup() const { for (stable_iterator si = getInnermostNormalCleanup(), se = stable_end(); Index: lib/CodeGen/CGDecl.cpp =================================================================== --- lib/CodeGen/CGDecl.cpp +++ lib/CodeGen/CGDecl.cpp @@ -1388,7 +1388,7 @@ // Make sure we call @llvm.lifetime.end. This needs to happen // *last*, so the cleanup needs to be pushed *first*. if (emission.useLifetimeMarkers()) { - EHStack.pushCleanup(NormalCleanup, + EHStack.pushCleanup(NormalAndEHCleanup, emission.getAllocatedAddress(), emission.getSizeForLifetimeMarkers()); EHCleanupScope &cleanup = cast(*EHStack.begin()); Index: lib/CodeGen/EHScopeStack.h =================================================================== --- lib/CodeGen/EHScopeStack.h +++ lib/CodeGen/EHScopeStack.h @@ -341,9 +341,7 @@ /// Determines whether the exception-scopes stack is empty. bool empty() const { return StartOfData == EndOfBuffer; } - bool requiresLandingPad() const { - return InnermostEHScope != stable_end(); - } + bool requiresLandingPad() const; /// Determines whether there are any normal cleanups on the stack. bool hasNormalCleanups() const { Index: test/CodeGenCXX/destructors.cpp =================================================================== --- test/CodeGenCXX/destructors.cpp +++ test/CodeGenCXX/destructors.cpp @@ -4,6 +4,8 @@ // RUN: FileCheck --check-prefix=CHECK3 --input-file=%t %s // RUN: FileCheck --check-prefix=CHECK4 --input-file=%t %s // RUN: FileCheck --check-prefix=CHECK5 --input-file=%t %s +// RUN: %clang_cc1 %s -triple x86_64-apple-darwin10 -emit-llvm -o - -fcxx-exceptions -fexceptions -O1 -disable-llvm-optzns -std=c++11 > %t2 +// RUN: FileCheck --check-prefix=CHECK6 --input-file=%t2 %s struct A { int a; @@ -428,3 +430,64 @@ return true; } } + +#if __cplusplus >= 201103L +namespace test11 { + +// Check that lifetime.end is emitted in the landing pad. + +// CHECK6-LABEL: define void @_ZN6test1115testLifetimeEndEi( +// CHECK6: entry: +// CHECK6: [[T1:%[a-z0-9]+]] = alloca %"struct.test11::S1" +// CHECK6: [[T2:%[a-z0-9]+]] = alloca %"struct.test11::S1" +// CHECK6: [[T3:%[a-z0-9]+]] = alloca %"struct.test11::S1" + +// CHECK6: {{^}}invoke.cont +// CHECK6: call void @_ZN6test112S1D1Ev(%"struct.test11::S1"* [[T1]]) +// CHECK6: [[BC1:%[a-z0-9]+]] = bitcast %"struct.test11::S1"* [[T1]] to i8* +// CHECK6: call void @llvm.lifetime.end(i64 32, i8* [[BC1]]) +// CHECK6: {{^}}lpad +// CHECK6: call void @_ZN6test112S1D1Ev(%"struct.test11::S1"* [[T1]]) +// CHECK6: [[BC2:%[a-z0-9]+]] = bitcast %"struct.test11::S1"* [[T1]] to i8* +// CHECK6: call void @llvm.lifetime.end(i64 32, i8* [[BC2]]) + +// CHECK6: {{^}}invoke.cont +// CHECK6: call void @_ZN6test112S1D1Ev(%"struct.test11::S1"* [[T2]]) +// CHECK6: [[BC3:%[a-z0-9]+]] = bitcast %"struct.test11::S1"* [[T2]] to i8* +// CHECK6: call void @llvm.lifetime.end(i64 32, i8* [[BC3]]) +// CHECK6: {{^}}lpad +// CHECK6: call void @_ZN6test112S1D1Ev(%"struct.test11::S1"* [[T2]]) +// CHECK6: [[BC4:%[a-z0-9]+]] = bitcast %"struct.test11::S1"* [[T2]] to i8* +// CHECK6: call void @llvm.lifetime.end(i64 32, i8* [[BC4]]) + +// CHECK6: {{^}}invoke.cont +// CHECK6: call void @_ZN6test112S1D1Ev(%"struct.test11::S1"* [[T3]]) +// CHECK6: [[BC5:%[a-z0-9]+]] = bitcast %"struct.test11::S1"* [[T3]] to i8* +// CHECK6: call void @llvm.lifetime.end(i64 32, i8* [[BC5]]) +// CHECK6: {{^}}lpad +// CHECK6: call void @_ZN6test112S1D1Ev(%"struct.test11::S1"* [[T3]]) +// CHECK6: [[BC6:%[a-z0-9]+]] = bitcast %"struct.test11::S1"* [[T3]] to i8* +// CHECK6: call void @llvm.lifetime.end(i64 32, i8* [[BC6]]) + + struct S1 { + ~S1(); + int a[8]; + }; + + void func1(S1 &) noexcept(false); + + void testLifetimeEnd(int n) { + if (n < 10) { + S1 t1; + func1(t1); + } else if (n < 100) { + S1 t2; + func1(t2); + } else if (n < 1000) { + S1 t3; + func1(t3); + } + } + +} +#endif