Skip to content

Commit 43b4e5b

Browse files
authored
Use pushFullExprCleanup for deferred destroy (#88670)
Instead of directly pushing the `Destroy`, we should use `pushFullExprCleanup` which handles conditional branches. This fixes a backend crash due to 89ba7e1. Added minimized crash reproducer.
1 parent b153c05 commit 43b4e5b

File tree

2 files changed

+35
-3
lines changed

2 files changed

+35
-3
lines changed

clang/lib/CodeGen/CGDecl.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2216,8 +2216,11 @@ void CodeGenFunction::pushDestroyAndDeferDeactivation(
22162216
void CodeGenFunction::pushDestroyAndDeferDeactivation(
22172217
CleanupKind cleanupKind, Address addr, QualType type, Destroyer *destroyer,
22182218
bool useEHCleanupForArray) {
2219-
pushCleanupAndDeferDeactivation<DestroyObject>(
2220-
cleanupKind, addr, type, destroyer, useEHCleanupForArray);
2219+
llvm::Instruction *DominatingIP =
2220+
Builder.CreateFlagLoad(llvm::Constant::getNullValue(Int8PtrTy));
2221+
pushDestroy(cleanupKind, addr, type, destroyer, useEHCleanupForArray);
2222+
DeferredDeactivationCleanupStack.push_back(
2223+
{EHStack.stable_begin(), DominatingIP});
22212224
}
22222225

22232226
void CodeGenFunction::pushStackRestore(CleanupKind Kind, Address SPMem) {

clang/test/CodeGenCXX/control-flow-in-stmt-expr.cpp

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
// RUN: %clang_cc1 --std=c++20 -triple x86_64-linux-gnu -emit-llvm %s -o - | FileCheck %s
1+
// RUN: %clang_cc1 --std=c++20 -fexceptions -triple x86_64-linux-gnu -emit-llvm %s -o - | FileCheck -check-prefixes=EH %s
2+
// RUN: %clang_cc1 --std=c++20 -triple x86_64-linux-gnu -emit-llvm %s -o - | FileCheck -check-prefixes=NOEH,CHECK %s
23

34
struct Printy {
45
Printy(const char *name) : name(name) {}
@@ -349,6 +350,34 @@ void NewArrayInit() {
349350
// CHECK-NEXT: br label %return
350351
}
351352

353+
void DestroyInConditionalCleanup() {
354+
// EH-LABEL: DestroyInConditionalCleanupv()
355+
// NOEH-LABEL: DestroyInConditionalCleanupv()
356+
struct A {
357+
A() {}
358+
~A() {}
359+
};
360+
361+
struct Value {
362+
Value(A) {}
363+
~Value() {}
364+
};
365+
366+
struct V2 {
367+
Value K;
368+
Value V;
369+
};
370+
// Verify we use conditional cleanups.
371+
(void)(foo() ? V2{A(), A()} : V2{A(), A()});
372+
// NOEH: cond.true:
373+
// NOEH: call void @_ZZ27DestroyInConditionalCleanupvEN1AC1Ev
374+
// NOEH: store ptr %{{.*}}, ptr %cond-cleanup.save
375+
376+
// EH: cond.true:
377+
// EH: invoke void @_ZZ27DestroyInConditionalCleanupvEN1AC1Ev
378+
// EH: store ptr %{{.*}}, ptr %cond-cleanup.save
379+
}
380+
352381
void ArrayInitWithContinue() {
353382
// CHECK-LABEL: @_Z21ArrayInitWithContinuev
354383
// Verify that we start to emit the array destructor.

0 commit comments

Comments
 (0)