From 1a3fc9f97fe59ba8956a02b46e951f6a4f60b10e Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Fri, 4 Jan 2013 07:56:53 +0100 Subject: [PATCH] Fix break out of non-nothrow range foreach. Fixes DMD testcase 'test9068'. --- gen/irstate.cpp | 9 ++++++++- gen/statements.cpp | 12 ++++++++++-- ir/irfunction.h | 12 +++++++++++- 3 files changed, 29 insertions(+), 4 deletions(-) diff --git a/gen/irstate.cpp b/gen/irstate.cpp index 94835a71..20748c9d 100644 --- a/gen/irstate.cpp +++ b/gen/irstate.cpp @@ -54,12 +54,19 @@ IRTargetScope::IRTargetScope() { } -IRTargetScope::IRTargetScope(Statement* s, EnclosingHandler* enclosinghandler, llvm::BasicBlock* continueTarget, llvm::BasicBlock* breakTarget) +IRTargetScope::IRTargetScope( + Statement* s, + EnclosingHandler* enclosinghandler, + llvm::BasicBlock* continueTarget, + llvm::BasicBlock* breakTarget, + bool onlyLabeledBreak +) { this->s = s; this->enclosinghandler = enclosinghandler; this->breakTarget = breakTarget; this->continueTarget = continueTarget; + this->onlyLabeledBreak = onlyLabeledBreak; } ////////////////////////////////////////////////////////////////////////////////////////// diff --git a/gen/statements.cpp b/gen/statements.cpp index 99ee6d29..a96c09d3 100644 --- a/gen/statements.cpp +++ b/gen/statements.cpp @@ -554,7 +554,7 @@ void BreakStatement::toIR(IRState* p) FuncGen::TargetScopeVec::reverse_iterator it = p->func()->gen->targetScopes.rbegin(); FuncGen::TargetScopeVec::reverse_iterator it_end = p->func()->gen->targetScopes.rend(); while(it != it_end) { - if(it->breakTarget) { + if(it->breakTarget && !it->onlyLabeledBreak) { break; } ++it; @@ -683,7 +683,15 @@ void TryFinallyStatement::toIR(IRState* p) IRLandingPad& pad = gIR->func()->gen->landingPadInfo; pad.addFinally(finalbody); pad.push(landingpadbb); - gIR->func()->gen->targetScopes.push_back(IRTargetScope(this,new EnclosingTryFinally(this,gIR->func()->gen->landingPad),NULL,NULL)); + gIR->func()->gen->targetScopes.push_back( + IRTargetScope( + this, + new EnclosingTryFinally(this, gIR->func()->gen->landingPad), + NULL, + endbb, + true + ) + ); // // do the try block diff --git a/ir/irfunction.h b/ir/irfunction.h index e167f47a..0e4ef450 100644 --- a/ir/irfunction.h +++ b/ir/irfunction.h @@ -40,8 +40,18 @@ struct IRTargetScope llvm::BasicBlock* breakTarget; llvm::BasicBlock* continueTarget; + /// If true, the breakTarget is only considered if it is explicitly + /// specified (via s), and not for unqualified "break;" statements. + bool onlyLabeledBreak; + IRTargetScope(); - IRTargetScope(Statement* s, EnclosingHandler* enclosinghandler, llvm::BasicBlock* continueTarget, llvm::BasicBlock* breakTarget); + IRTargetScope( + Statement* s, + EnclosingHandler* enclosinghandler, + llvm::BasicBlock* continueTarget, + llvm::BasicBlock* breakTarget, + bool onlyLabeledBreak = false + ); }; struct FuncGen