mkovacevic99 wrote:

Just to be clear about what my patch does — it does not change the capture 
lifetime rule. Captures are still destroyed at the end of the enclosing scope, 
exactly as they are on trunk. The patch only makes that end-of-scope cleanup 
conditional and gives it a dominating address, so it's emitted correctly when 
the initializer runs under the guard branch. On current trunk (without this 
patch) that path is broken: it either ICEs, or — when there's a throwing call 
after the init — runs __cxa_guard_abort on a guard that was already initialized.

@ahatanak — I compiled your example. The captured copy of a is destroyed at the 
end of test(), after bl(), and it's guarded so it only runs on the call that 
actually performed the initialization. So it stays correct and works on every 
call — the patch preserves that behavior rather than breaking it.

@rjmccall — agreed on the "simple lifetime extension, don't destroy the 
captures while the block may still be in use" framing; the patch keeps that. 
The captures are still destroyed at end of scope, never earlier.

On the heap-based point: agreed that storing a block pointer into a static 
(static BlockTy b = ^{...}; b();) needs the block to be heap-based to be valid 
across calls. My patch makes the single-activation case correct but doesn't 
heap-promote the block, which feels orthogonal to this crash fix. Do you want 
the heap-promotion handled in this PR, or as a follow-up?
[guarded-init-block-capture.patch](https://github.com/user-attachments/files/29292901/guarded-init-block-capture.patch)


https://github.com/llvm/llvm-project/pull/199508
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to