[clang] [ObjC] Add support for finally blocks (PR #82934)
via cfe-commits
cfe-commits at lists.llvm.org
Sun Feb 25 13:35:19 PST 2024
https://github.com/AtariDreams updated https://github.com/llvm/llvm-project/pull/82934
>From 3a4134ff040230e0f0e5054be57e28f779135728 Mon Sep 17 00:00:00 2001
From: Rose <83477269+AtariDreams at 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..f8288d17733d87 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.
More information about the cfe-commits
mailing list