Don't assume that a new cleanup was added to InnermostEHScope.

After fa87fa97fb, this was no longer guaranteed to be the cleanup
just added by this code, if IsEHCleanup got disabled. Instead, use
stable_begin(), which _is_ guaranteed to be the cleanup just added.

This caused a crash when a object that is callee destroyed (e.g. with the MS ABI) was passed in a call from a noexcept function.

Added a test to verify.

Fixes: fa87fa97fb
This commit is contained in:
James Y Knight 2022-02-04 23:39:18 -05:00
parent dee058c670
commit caa1ebde70
2 changed files with 23 additions and 1 deletions

View File

@ -4331,7 +4331,7 @@ void CodeGenFunction::EmitCallArg(CallArgList &args, const Expr *E,
type);
// This unreachable is a temporary marker which will be removed later.
llvm::Instruction *IsActive = Builder.CreateUnreachable();
args.addArgCleanupDeactivation(EHStack.getInnermostEHScope(), IsActive);
args.addArgCleanupDeactivation(EHStack.stable_begin(), IsActive);
}
return;
}

View File

@ -32,6 +32,28 @@ void HasEHCleanup() {
// WIN32-NOT: @"??1A@@QAE@XZ"
// WIN32: }
// This test verifies the fix for a crash that occurred after
// fa87fa97fb79.
void HasEHCleanupNoexcept() noexcept {
TakesTwo(getA(), getA());
}
// With exceptions, we need to clean up at least one of these temporaries.
// WIN32-LABEL: define dso_local void @"?HasEHCleanupNoexcept@@YAXXZ"() {{.*}} {
// WIN32: %[[base:.*]] = call i8* @llvm.stacksave()
// WIN32: invoke void @"?getA@@YA?AUA@@XZ"(%struct.A* sret(%struct.A) align 4 %{{.*}})
// WIN32: invoke void @"?getA@@YA?AUA@@XZ"(%struct.A* sret(%struct.A) align 4 %{{.*}})
// WIN32: invoke noundef i32 @"?TakesTwo@@YAHUA@@0@Z"
// WIN32: call void @llvm.stackrestore
// WIN32: ret void
//
// Since all the calls terminate, there should be no dtors on the unwind
// WIN32: cleanuppad
// WIN32-NOT: @"??1A@@QAE@XZ"
// WIN32: }
void TakeRef(const A &a);
int HasDeactivatedCleanups() {
return TakesTwo((TakeRef(A()), A()), (TakeRef(A()), A()));