Store the size of the EH stack inside each BreakContinue struct so we know when a break/continue won't cross a try block.

llvm-svn: 60998
This commit is contained in:
Anders Carlsson 2008-12-13 22:52:24 +00:00
parent 24092271cc
commit 6b958f9634
3 changed files with 16 additions and 10 deletions

View File

@ -492,7 +492,8 @@ void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S)
llvm::BasicBlock *LoopEnd = createBasicBlock("loopend");
llvm::BasicBlock *AfterBody = createBasicBlock("afterbody");
BreakContinueStack.push_back(BreakContinue(LoopEnd, AfterBody));
BreakContinueStack.push_back(BreakContinue(LoopEnd, AfterBody,
ObjCEHStack.size()));
EmitStmt(S.getBody());

View File

@ -322,7 +322,8 @@ void CodeGenFunction::EmitWhileStmt(const WhileStmt &S) {
Builder.CreateCondBr(BoolCondVal, LoopBody, ExitBlock);
// Store the blocks to use for break and continue.
BreakContinueStack.push_back(BreakContinue(ExitBlock, LoopHeader));
BreakContinueStack.push_back(BreakContinue(ExitBlock, LoopHeader,
ObjCEHStack.size()));
// Emit the loop body.
EmitBlock(LoopBody);
@ -355,7 +356,8 @@ void CodeGenFunction::EmitDoStmt(const DoStmt &S) {
llvm::BasicBlock *DoCond = createBasicBlock("do.cond");
// Store the blocks to use for break and continue.
BreakContinueStack.push_back(BreakContinue(AfterDo, DoCond));
BreakContinueStack.push_back(BreakContinue(AfterDo, DoCond,
ObjCEHStack.size()));
// Emit the body of the loop into the block.
EmitStmt(S.getBody());
@ -433,7 +435,8 @@ void CodeGenFunction::EmitForStmt(const ForStmt &S) {
ContinueBlock = CondBlock;
// Store the blocks to use for break and continue.
BreakContinueStack.push_back(BreakContinue(AfterFor, ContinueBlock));
BreakContinueStack.push_back(BreakContinue(AfterFor, ContinueBlock,
ObjCEHStack.size()));
// If the condition is true, execute the body of the for stmt.
EmitStmt(S.getBody());
@ -510,7 +513,7 @@ void CodeGenFunction::EmitBreakStmt(const BreakStmt &S) {
assert(!BreakContinueStack.empty() && "break stmt not in a loop or switch!");
// FIXME: Implement break in @try or @catch blocks.
if (!ObjCEHStack.empty()) {
if (ObjCEHStack.size() != BreakContinueStack.back().EHStackSize) {
CGM.ErrorUnsupported(&S, "continue inside an Obj-C exception block");
return;
}
@ -528,7 +531,7 @@ void CodeGenFunction::EmitContinueStmt(const ContinueStmt &S) {
assert(!BreakContinueStack.empty() && "continue stmt not in a loop!");
// FIXME: Implement continue in @try or @catch blocks.
if (!ObjCEHStack.empty()) {
if (ObjCEHStack.size() != BreakContinueStack.back().EHStackSize) {
CGM.ErrorUnsupported(&S, "continue inside an Obj-C exception block");
return;
}
@ -646,7 +649,8 @@ void CodeGenFunction::EmitSwitchStmt(const SwitchStmt &S) {
llvm::BasicBlock *ContinueBlock = NULL;
if (!BreakContinueStack.empty())
ContinueBlock = BreakContinueStack.back().ContinueBlock;
BreakContinueStack.push_back(BreakContinue(NextBlock, ContinueBlock));
BreakContinueStack.push_back(BreakContinue(NextBlock, ContinueBlock,
ObjCEHStack.size()));
// Emit switch body.
EmitStmt(S.getBody());

View File

@ -148,13 +148,14 @@ private:
llvm::DenseMap<const LabelStmt*, llvm::BasicBlock*> LabelMap;
// BreakContinueStack - This keeps track of where break and continue
// statements should jump to.
// statements should jump to, as well as the size of the eh stack.
struct BreakContinue {
BreakContinue(llvm::BasicBlock *bb, llvm::BasicBlock *cb)
: BreakBlock(bb), ContinueBlock(cb) {}
BreakContinue(llvm::BasicBlock *bb, llvm::BasicBlock *cb, size_t ehss)
: BreakBlock(bb), ContinueBlock(cb), EHStackSize(ehss) {}
llvm::BasicBlock *BreakBlock;
llvm::BasicBlock *ContinueBlock;
size_t EHStackSize;
};
llvm::SmallVector<BreakContinue, 8> BreakContinueStack;