https://github.com/erichkeane updated https://github.com/llvm/llvm-project/pull/197705
>From 48a7f45dc49d46040f93cfe6b6e01c55af6a6fc9 Mon Sep 17 00:00:00 2001 From: erichkeane <[email protected]> Date: Thu, 14 May 2026 07:36:18 -0700 Subject: [PATCH 1/4] [CIR] Add lexical scope for the 'range-for' body statement. Without this, we fail the verifier due to lack of a terminator on the scope if there is a destructed type in the 'body', as the cleanup scope on the cir.scope object will insert the yield in the body (since that is the last place we needed a cleanup), rather than actually putting one at the end of the scope itself. This patch adds a lexical scope to the body-statement, which makes sure the proper yields are emitted. --- clang/lib/CIR/CodeGen/CIRGenStmt.cpp | 1 + clang/test/CIR/CodeGen/forrange.cpp | 35 ++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/clang/lib/CIR/CodeGen/CIRGenStmt.cpp b/clang/lib/CIR/CodeGen/CIRGenStmt.cpp index a64a2a080bade..55661751ac217 100644 --- a/clang/lib/CIR/CodeGen/CIRGenStmt.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenStmt.cpp @@ -936,6 +936,7 @@ CIRGenFunction::emitCXXForRangeStmt(const CXXForRangeStmt &s, bool useCurrentScope = true; if (emitStmt(s.getLoopVarStmt(), useCurrentScope).failed()) loopRes = mlir::failure(); + LexicalScope lexScope{*this, loc, builder.getInsertionBlock()}; if (emitStmt(s.getBody(), useCurrentScope).failed()) loopRes = mlir::failure(); emitStopPoint(&s); diff --git a/clang/test/CIR/CodeGen/forrange.cpp b/clang/test/CIR/CodeGen/forrange.cpp index 0ffe4e2f29743..bbf2a79c697da 100644 --- a/clang/test/CIR/CodeGen/forrange.cpp +++ b/clang/test/CIR/CodeGen/forrange.cpp @@ -131,3 +131,38 @@ void for_range3() { // CIR: cir.yield // CIR: } // CIR: } + +struct HasDtor { ~HasDtor(); }; + +void for_range4() { + C3 c; + for (Element &e : c) { + HasDtor hd; + } +} +// CIR: cir.func{{.*}} @_Z10for_range4v() +// CIR: cir.scope { +// CIR: %[[RANGE_ADDR:.*]] = cir.alloca !cir.ptr<!rec_C3>{{.*}} ["__range1", init, const] +// CIR: %[[BEGIN_ADDR:.*]] = cir.alloca !rec_Iterator, !cir.ptr<!rec_Iterator>{{.*}} ["__begin1", init] +// CIR: %[[END_ADDR:.*]] = cir.alloca !rec_Iterator, !cir.ptr<!rec_Iterator>{{.*}} ["__end1", init] +// CIR: %[[E_ADDR:.*]] = cir.alloca !cir.ptr<!rec_Element>{{.*}} ["e", init, const] +// CIR: cir.store{{.*}} %[[C_ADDR]], %[[RANGE_ADDR]] +// CIR: cir.for : cond { +// CIR: %[[ITER_NE:.*]] = cir.call @_ZNK8IteratorneERKS_(%[[BEGIN_ADDR]], %[[END_ADDR]]) +// CIR: cir.condition(%[[ITER_NE]]) +// CIR: } body { +// CIR: %[[HD:.*]] = cir.alloca !rec_HasDtor, !cir.ptr<!rec_HasDtor>, ["hd"] +// CIR: %[[E:.*]] = cir.call @_ZN8IteratordeEv(%[[BEGIN_ADDR]]) +// CIR: cir.store{{.*}} %[[E]], %[[E_ADDR]] +// CIR: cir.cleanup.scope { +// CIR: cir.yield +// CIR: } cleanup normal { +// CIR: cir.call @_ZN7HasDtorD1Ev(%[[HD]]) nothrow +// CIR: cir.yield +// CIR: } +// CIR: cir.yield +// CIR: } step { +// CIR: %[[ITER_NEXT:.*]] = cir.call @_ZN8IteratorppEv(%[[BEGIN_ADDR]]) +// CIR: cir.yield +// CIR: } +// CIR: } >From 6a01694f6a7b2a5e28c82dcd6d719ac8c6d80c7d Mon Sep 17 00:00:00 2001 From: erichkeane <[email protected]> Date: Thu, 14 May 2026 07:41:41 -0700 Subject: [PATCH 2/4] Just make the body use its own scope! --- clang/lib/CIR/CodeGen/CIRGenStmt.cpp | 13 +++++++------ clang/test/CIR/CodeGen/forrange.cpp | 14 ++++++++------ 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/clang/lib/CIR/CodeGen/CIRGenStmt.cpp b/clang/lib/CIR/CodeGen/CIRGenStmt.cpp index 55661751ac217..0e20d8f30b892 100644 --- a/clang/lib/CIR/CodeGen/CIRGenStmt.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenStmt.cpp @@ -918,7 +918,9 @@ CIRGenFunction::emitCXXForRangeStmt(const CXXForRangeStmt &s, // We probably already do the right thing because of ScopeOp, but make // sure we handle all cases. assert(!cir::MissingFeatures::loopSpecificCleanupHandling()); - + // https://en.cppreference.com/w/cpp/language/for + // Given: + // for ( init-statement condition (optional) ; expression (optional) ) statement forOp = builder.createFor( getLoc(s.getSourceRange()), /*condBuilder=*/ @@ -930,14 +932,13 @@ CIRGenFunction::emitCXXForRangeStmt(const CXXForRangeStmt &s, }, /*bodyBuilder=*/ [&](mlir::OpBuilder &b, mlir::Location loc) { - // https://en.cppreference.com/w/cpp/language/for - // In C++ the scope of the init-statement and the scope of - // statement are one and the same. + // https://en.cppreference.com/cpp/language/range-for + // The scope of statement and the scope of expression are disjoint + // and nested within the scope of init-statement and condition. bool useCurrentScope = true; if (emitStmt(s.getLoopVarStmt(), useCurrentScope).failed()) loopRes = mlir::failure(); - LexicalScope lexScope{*this, loc, builder.getInsertionBlock()}; - if (emitStmt(s.getBody(), useCurrentScope).failed()) + if (emitStmt(s.getBody(), /*useCurrentScope=*/false).failed()) loopRes = mlir::failure(); emitStopPoint(&s); }, diff --git a/clang/test/CIR/CodeGen/forrange.cpp b/clang/test/CIR/CodeGen/forrange.cpp index bbf2a79c697da..f171171a01bb1 100644 --- a/clang/test/CIR/CodeGen/forrange.cpp +++ b/clang/test/CIR/CodeGen/forrange.cpp @@ -151,14 +151,16 @@ void for_range4() { // CIR: %[[ITER_NE:.*]] = cir.call @_ZNK8IteratorneERKS_(%[[BEGIN_ADDR]], %[[END_ADDR]]) // CIR: cir.condition(%[[ITER_NE]]) // CIR: } body { -// CIR: %[[HD:.*]] = cir.alloca !rec_HasDtor, !cir.ptr<!rec_HasDtor>, ["hd"] // CIR: %[[E:.*]] = cir.call @_ZN8IteratordeEv(%[[BEGIN_ADDR]]) // CIR: cir.store{{.*}} %[[E]], %[[E_ADDR]] -// CIR: cir.cleanup.scope { -// CIR: cir.yield -// CIR: } cleanup normal { -// CIR: cir.call @_ZN7HasDtorD1Ev(%[[HD]]) nothrow -// CIR: cir.yield +// CIR: cir.scope { +// CIR: %[[HD:.*]] = cir.alloca !rec_HasDtor, !cir.ptr<!rec_HasDtor>, ["hd"] +// CIR: cir.cleanup.scope { +// CIR: cir.yield +// CIR: } cleanup normal { +// CIR: cir.call @_ZN7HasDtorD1Ev(%[[HD]]) nothrow +// CIR: cir.yield +// CIR: } // CIR: } // CIR: cir.yield // CIR: } step { >From ab465c6f8e6f7af99b9c9a8f8ba59643ac30a408 Mon Sep 17 00:00:00 2001 From: erichkeane <[email protected]> Date: Thu, 14 May 2026 07:58:50 -0700 Subject: [PATCH 3/4] Clang format --- clang/lib/CIR/CodeGen/CIRGenStmt.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/clang/lib/CIR/CodeGen/CIRGenStmt.cpp b/clang/lib/CIR/CodeGen/CIRGenStmt.cpp index 0e20d8f30b892..961b9ba8dd577 100644 --- a/clang/lib/CIR/CodeGen/CIRGenStmt.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenStmt.cpp @@ -919,8 +919,9 @@ CIRGenFunction::emitCXXForRangeStmt(const CXXForRangeStmt &s, // sure we handle all cases. assert(!cir::MissingFeatures::loopSpecificCleanupHandling()); // https://en.cppreference.com/w/cpp/language/for - // Given: - // for ( init-statement condition (optional) ; expression (optional) ) statement + // Given: + // for ( init-statement condition (optional) ; expression (optional) ) + // statement forOp = builder.createFor( getLoc(s.getSourceRange()), /*condBuilder=*/ >From 1f8f5800bf2b29f121190ba51c21496092e31306 Mon Sep 17 00:00:00 2001 From: erichkeane <[email protected]> Date: Thu, 14 May 2026 08:47:13 -0700 Subject: [PATCH 4/4] clang-format --- clang/lib/CIR/CodeGen/CIRGenStmt.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clang/lib/CIR/CodeGen/CIRGenStmt.cpp b/clang/lib/CIR/CodeGen/CIRGenStmt.cpp index 961b9ba8dd577..dbe53891979e2 100644 --- a/clang/lib/CIR/CodeGen/CIRGenStmt.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenStmt.cpp @@ -920,8 +920,8 @@ CIRGenFunction::emitCXXForRangeStmt(const CXXForRangeStmt &s, assert(!cir::MissingFeatures::loopSpecificCleanupHandling()); // https://en.cppreference.com/w/cpp/language/for // Given: - // for ( init-statement condition (optional) ; expression (optional) ) - // statement + // for ( init-statement condition (optional) ; expression (optional) + // ) statement forOp = builder.createFor( getLoc(s.getSourceRange()), /*condBuilder=*/ _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
