https://github.com/AtariDreams created https://github.com/llvm/llvm-project/pull/82934
None >From 80d60869a593d59501e14bb673c1bd8938c38028 Mon Sep 17 00:00:00 2001 From: Rose <83477269+ataridre...@users.noreply.github.com> Date: Sun, 25 Feb 2024 14:52:59 -0500 Subject: [PATCH] [ObjC] Add support for finally blocks --- clang/lib/Analysis/CFG.cpp | 71 ++++++++++++++++++++++++++++++++------ 1 file changed, 61 insertions(+), 10 deletions(-) diff --git a/clang/lib/Analysis/CFG.cpp b/clang/lib/Analysis/CFG.cpp index de70cbbf6cdb38..15db6560d1561f 100644 --- a/clang/lib/Analysis/CFG.cpp +++ b/clang/lib/Analysis/CFG.cpp @@ -2356,6 +2356,9 @@ CFGBlock *CFGBuilder::Visit(Stmt * S, AddStmtChoice asc, case Stmt::ObjCAtTryStmtClass: return VisitObjCAtTryStmt(cast<ObjCAtTryStmt>(S)); + case Stmt::ObjCAtFinallyStmtClass: + return VisitObjCAtFinallyStmt(cast<ObjCAtFinallyStmt>(S)); + case Stmt::ObjCForCollectionStmtClass: return VisitObjCForCollectionStmt(cast<ObjCForCollectionStmt>(S)); @@ -4060,6 +4063,32 @@ CFGBlock *CFGBuilder::VisitObjCAtThrowStmt(ObjCAtThrowStmt *S) { return VisitStmt(S, AddStmtChoice::AlwaysAdd); } +CFGBlock *CFGBuilder::VisitObjCAtFinallyStmt(ObjCAtFinallyStmt *FS) { + // ObjCAtFinallyStmt are treated like labels, so they are the first statement + // in a block. + + if (FS->getFinallyBody()) + addStmt(FS->getFinallyBody()); + + CFGBlock *FinallyBlock = Block; + if (!FinallyBlock) + FinallyBlock = createBlock(); + + appendStmt(FinallyBlock, FS); + + // Also add the ObjCAtFinallyStmt as a label, like with regular labels. + FinallyBlock->setLabel(FS); + + // Bail out if the CFG is bad. + if (badCFG) + return nullptr; + + // We set Block to NULL to allow lazy creation of a new block (if necessary). + Block = nullptr; + + return FinallyBlock; +} + CFGBlock *CFGBuilder::VisitObjCAtTryStmt(ObjCAtTryStmt *Terminator) { // "@try"/"@catch" is a control-flow statement. Thus we stop processing the // current block. @@ -4072,17 +4101,27 @@ CFGBlock *CFGBuilder::VisitObjCAtTryStmt(ObjCAtTryStmt *Terminator) { } else TrySuccessor = Succ; - // FIXME: Implement @finally support. - if (Terminator->getFinallyStmt()) - return NYS(); - CFGBlock *PrevTryTerminatedBlock = TryTerminatedBlock; - // Create a new block that will contain the try statement. CFGBlock *NewTryTerminatedBlock = createBlock(false); // Add the terminator in the try block. NewTryTerminatedBlock->setTerminator(Terminator); + CFGBlock *FinallyBlock = nullptr; + + if (Terminator->getFinallyStmt()) { + Succ = TrySuccessor; + + Block = nullptr; + FinallyBlock = VisitObjCAtFinallyStmt(Terminator->getFinallyStmt()); + + if (!FinallyBlock) + return nullptr; + + // The code after the finally is the implicit successor. + addSuccessor(NewTryTerminatedBlock, FinallyBlock); + } + bool HasCatchAll = false; for (ObjCAtCatchStmt *CS : Terminator->catch_stmts()) { // The code after the try is the implicit successor. @@ -4092,19 +4131,31 @@ CFGBlock *CFGBuilder::VisitObjCAtTryStmt(ObjCAtTryStmt *Terminator) { } Block = nullptr; CFGBlock *CatchBlock = VisitObjCAtCatchStmt(CS); + if (!CatchBlock) return nullptr; + // Add this block to the list of successors for the block with the try // statement. addSuccessor(NewTryTerminatedBlock, CatchBlock); + + // After visiting the catch block, add the @finally block as a successor. + if (FinallyBlock) + addSuccessor(CatchBlock, FinallyBlock); } - // FIXME: This needs updating when @finally support is added. + // The @finally block, if it exists, should always be a successor. + if (!HasCatchAll) { - if (PrevTryTerminatedBlock) - addSuccessor(NewTryTerminatedBlock, PrevTryTerminatedBlock); - else - addSuccessor(NewTryTerminatedBlock, &cfg->getExit()); + CFGBlock *endBlock = NewTryTerminatedBlock; + if (FinallyBlock) + endBlock = FinallyBlock; + + if (PrevTryTerminatedBlock) { + addSuccessor(endBlock, PrevTryTerminatedBlock); + } else { + addSuccessor(endBlock, &cfg->getExit()); + } } // The code after the try is the implicit successor. _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits