[llvm-branch-commits] [clang] [Clang] [C++26] Expansion Statements (Part 3: Enumerating Expansion Statements) (PR #169682)

via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Mon May 4 08:53:29 PDT 2026


================
@@ -9372,19 +9372,101 @@ TreeTransform<Derived>::TransformCXXForRangeStmt(CXXForRangeStmt *S) {
 template <typename Derived>
 StmtResult TreeTransform<Derived>::TransformCXXExpansionStmtPattern(
     CXXExpansionStmtPattern *S) {
-  llvm_unreachable("TOOD");
+  assert(SemaRef.CurContext->isExpansionStmt());
+
+  Decl *ESD =
+      getDerived().TransformDecl(S->getDecl()->getLocation(), S->getDecl());
+  if (!ESD || ESD->isInvalidDecl())
+    return StmtError();
+  CXXExpansionStmtDecl *NewESD = cast<CXXExpansionStmtDecl>(ESD);
+
+  // This is required because some parts of an expansion statement (e.g. the
+  // init-statement) are not in a dependent context and must thus be transformed
+  // in the parent context.
+  auto TransformStmtInParentContext = [&] (Stmt *SubStmt) -> StmtResult {
+    Sema::ContextRAII CtxGuard(SemaRef, SemaRef.CurContext->getParent(),
+                               /*NewThis=*/false);
+    return getDerived().TransformStmt(SubStmt);
----------------
Sirraide wrote:

I think I mentioned that in part 2 just now, but that context object was mainly just for use in `Parser::ParseForStatement()` where we have code paths that are shared between expansion statements and regular for loops; I could use it here as well, but I’d have to move it into a header somewhere that’s accessible to both the parser and sema at that point; I’m not sure it’s worth it but I can do that if you prefer

https://github.com/llvm/llvm-project/pull/169682


More information about the llvm-branch-commits mailing list