In some scenarios, a SELECT CASE could cause an error while lowering to FIR.
This was caused by a spurious extra branch added after the end statement. A
new test was added so this doesn't regress in the future.
Fixes #62726
Differential D151118
[Flang] Fix nested block constructs for SELECT CASE cseo on May 22 2023, 9:38 AM. Authored by
Details
In some scenarios, a SELECT CASE could cause an error while lowering to FIR. Fixes #62726
Diff Detail
Event Timeline
Comment Actions Added extra checks to select-case-statement.f90 Fixed the missing colon and added extra checks for 'end select'. Comment Actions Thanks @cseo for looking at this bug. Most construct END statements do not have any associated code. That changed fairly recently to support finalization and deallocation code where needed. That includes deallocation of a character SELECT CASE trim(str) selector expression result, as here. End-of-construct processing could be associated with an END construct statement (an EndSelectStmt here), or with the end of the construct itself (a CaseConstruct here). The two views must agree on which does what. Some other constructs already do this correctly. As with other cases, I recommend fixing the problem in construct code, rather than generic genFIR code. Something like the following, where the second set of diffs is for the genFIR SelectTypeConstruct function, which is also at risk for the same problem. (It may be worth noting that SELECT statements are always unstructured in the FIR sense.) diff --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp index c1dbac108b88..f1c93ccf5df8 100644 --- a/flang/lib/Lower/Bridge.cpp +++ b/flang/lib/Lower/Bridge.cpp @@ -1823,12 +1823,17 @@ private: void genFIR(const Fortran::parser::CaseConstruct &) { Fortran::lower::pft::Evaluation &eval = getEval(); Fortran::lower::StatementContext stmtCtx; pushActiveConstruct(eval, stmtCtx); - for (Fortran::lower::pft::Evaluation &e : getEval().getNestedEvaluations()) - genFIR(e); + for (Fortran::lower::pft::Evaluation &e : + getEval().getNestedEvaluations()) { + if (e.getIf<Fortran::parser::EndSelectStmt>()) + maybeStartBlock(e.block); + else + genFIR(e); + } popActiveConstruct(); } template <typename A> void genNestedStatement(const Fortran::parser::Statement<A> &stmt) { @@ -2684,11 +2689,11 @@ private: } } builder->restoreInsertionPoint(crtInsPt); ++typeGuardIdx; } else if (eval.getIf<Fortran::parser::EndSelectStmt>()) { - genFIR(eval); + maybeStartBlock(eval.block); if (hasLocalScope) localSymbols.popScope(); } else { genFIR(eval); } Comment Actions Looks good to me, thanks for addressing this!
Comment Actions @vdonaldson btw, I don't have commit access. So, whenever you think this change is good to go, feel free to push it. Comment Actions @cseo The preferred approach is to request commit access: obtaining-commit-access (Don't forget to update the test details!) |
Does checking for blockIsUnterminated() here work too, instead of using getIf()?
I'm not familiar with this code, but if the issue is being caused by successor->parentConstruct->lowerAsUnstructured() adding a terminator to the current block, then maybe checking for block termination may also catch other potential issues.