[clang] Remove overly strict assertion for this-capture in blocks (PR #219080)
Akira Hatanaka via cfe-commits
cfe-commits at lists.llvm.org
Wed Aug 26 17:49:49 PDT 2026
https://github.com/ahatanak created https://github.com/llvm/llvm-project/pull/219080
TransformBlockExpr asserted that if the instantiated block captures 'this', the uninstantiated pattern block must also have captured it. This assumption doesn't always hold: a block that accesses a member through a dependent qualified-id (e.g., 'T::m' inside a template deriving from T) has no way to know at parse time that the access will resolve to an implicit 'this->m', since T is unknown. Once the template is instantiated and 'T::m' resolves to a non-static data member, the instantiated block legitimately captures 'this' even though the pattern never did.
rdar://184776458
>From ccadf995d50bc47bfe7351d5b8628df7dce89e4d Mon Sep 17 00:00:00 2001
From: Akira Hatanaka <ahatanak at gmail.com>
Date: Wed, 26 Aug 2026 17:36:45 -0700
Subject: [PATCH] Remove overly strict assertion for this-capture in blocks
TransformBlockExpr asserted that if the instantiated block captures
'this', the uninstantiated pattern block must also have captured it.
This assumption doesn't always hold: a block that accesses a member
through a dependent qualified-id (e.g., 'T::m' inside a template
deriving from T) has no way to know at parse time that the access
will resolve to an implicit 'this->m', since T is unknown. Once the
template is instantiated and 'T::m' resolves to a non-static data
member, the instantiated block legitimately captures 'this' even
though the pattern never did.
rdar://184776458
---
clang/lib/Sema/TreeTransform.h | 6 ------
clang/test/CodeGenObjCXX/block-in-template-inst.mm | 11 +++++++++++
2 files changed, 11 insertions(+), 6 deletions(-)
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index 024f726b188b7..2de0cf300675b 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -17821,12 +17821,6 @@ TreeTransform<Derived>::TransformBlockExpr(BlockExpr *E) {
oldCapture));
assert(blockScope->CaptureMap.count(newCapture));
}
-
- // The this pointer may not be captured by the instantiated block, even when
- // it's captured by the original block, if the expression causing the
- // capture is in the discarded branch of a constexpr if statement.
- assert((!blockScope->isCXXThisCaptured() || oldBlock->capturesCXXThis()) &&
- "this pointer isn't captured in the old block");
}
#endif
diff --git a/clang/test/CodeGenObjCXX/block-in-template-inst.mm b/clang/test/CodeGenObjCXX/block-in-template-inst.mm
index 1ecd820be4501..50fc0896fd76d 100644
--- a/clang/test/CodeGenObjCXX/block-in-template-inst.mm
+++ b/clang/test/CodeGenObjCXX/block-in-template-inst.mm
@@ -68,3 +68,14 @@ void curry() {
auto t = c(1)(10)(100);
}
}
+
+namespace ThisCaptureViaDependentBase {
+ // This used to crash.
+ struct Base { int m; };
+
+ template <typename T> struct S : T {
+ void f() { ^{ (void)T::m; }(); }
+ };
+
+ template struct S<Base>;
+}
More information about the cfe-commits
mailing list