diff --git a/dmd/statement.h b/dmd/statement.h index f04baf91..47ff1789 100644 --- a/dmd/statement.h +++ b/dmd/statement.h @@ -910,6 +910,7 @@ struct AsmStatement : Statement struct AsmBlockStatement : CompoundStatement { EnclosingHandler* enclosinghandler; + TryFinallyStatement* tf; AsmBlockStatement(Loc loc, Statements *s); Statements *flatten(Scope *sc); diff --git a/gen/asmstmt.cpp b/gen/asmstmt.cpp index de69c582..3b30c228 100644 --- a/gen/asmstmt.cpp +++ b/gen/asmstmt.cpp @@ -388,6 +388,7 @@ AsmBlockStatement::AsmBlockStatement(Loc loc, Statements* s) : CompoundStatement(loc, s) { enclosinghandler = NULL; + tf = NULL; } // rewrite argument indices to the block scope indices @@ -648,7 +649,7 @@ void AsmBlockStatement::toIR(IRState* p) sw->addCase(llvm::ConstantInt::get(llvm::IntegerType::get(32), it->second), casebb); p->scope() = IRScope(casebb,bb); - DtoGoto(&loc, it->first, enclosinghandler); + DtoGoto(&loc, it->first, enclosinghandler, tf); } p->scope() = IRScope(bb,oldend); @@ -680,6 +681,7 @@ Statement *AsmBlockStatement::syntaxCopy() Statement *AsmBlockStatement::semantic(Scope *sc) { enclosinghandler = sc->tfOfTry; + tf = sc->tf; return CompoundStatement::semantic(sc); } diff --git a/gen/llvmhelpers.cpp b/gen/llvmhelpers.cpp index 85cd44d8..f9cbd3ab 100644 --- a/gen/llvmhelpers.cpp +++ b/gen/llvmhelpers.cpp @@ -175,7 +175,7 @@ LabelStatement* DtoLabelStatement(Identifier* ident) /*//////////////////////////////////////////////////////////////////////////////////////// // GOTO HELPER ////////////////////////////////////////////////////////////////////////////////////////*/ -void DtoGoto(Loc* loc, Identifier* target, EnclosingHandler* enclosinghandler) +void DtoGoto(Loc* loc, Identifier* target, EnclosingHandler* enclosinghandler, TryFinallyStatement* sourcetf) { assert(!gIR->scopereturned()); @@ -204,7 +204,7 @@ void DtoGoto(Loc* loc, Identifier* target, EnclosingHandler* enclosinghandler) // goto into finally blocks is forbidden by the spec // though it should not be problematic to implement - if(lblstmt->tf) + if(lblstmt->tf != sourcetf) error(*loc, "spec disallows goto into finally block"); // emit code for finallys between goto and label diff --git a/gen/llvmhelpers.h b/gen/llvmhelpers.h index 282d665d..a607fad4 100644 --- a/gen/llvmhelpers.h +++ b/gen/llvmhelpers.h @@ -17,7 +17,7 @@ void DtoAssert(Loc* loc, DValue* msg); // return the LabelStatement from the current function with the given identifier or NULL if not found LabelStatement* DtoLabelStatement(Identifier* ident); // emit goto -void DtoGoto(Loc* loc, Identifier* target, EnclosingHandler* enclosingtryfinally); +void DtoGoto(Loc* loc, Identifier* target, EnclosingHandler* enclosingtryfinally, TryFinallyStatement* sourcetf); // generates IR for finally blocks between the 'start' and 'end' statements // will begin with the finally block belonging to 'start' and does not include diff --git a/gen/statements.cpp b/gen/statements.cpp index 7cd3fd86..b6f2df3a 100644 --- a/gen/statements.cpp +++ b/gen/statements.cpp @@ -1063,12 +1063,10 @@ void GotoStatement::toIR(IRState* p) if (global.params.symdebug) DtoDwarfStopPoint(loc.linnum); - assert(tf == NULL); - llvm::BasicBlock* oldend = gIR->scopeend(); llvm::BasicBlock* bb = llvm::BasicBlock::Create("aftergoto", p->topfunc(), oldend); - DtoGoto(&loc, label->ident, enclosinghandler); + DtoGoto(&loc, label->ident, enclosinghandler, tf); p->scope() = IRScope(bb,oldend); }