Skip to content

Commit fb4eb62

Browse files
committed
Merge pull request #1076 from klickverbot/multiple-catches
Fix throwing inside catch (should not target later catches of same try)
2 parents d98400f + 78ddb15 commit fb4eb62

File tree

1 file changed

+21
-11
lines changed

1 file changed

+21
-11
lines changed

gen/statements.cpp

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -716,15 +716,20 @@ class ToIRVisitor : public Visitor {
716716

717717
assert(stmt->catches);
718718

719+
typedef llvm::SmallVector<std::pair<ClassDeclaration*, llvm::BasicBlock*>, 6>
720+
CatchBlocks;
721+
CatchBlocks catchBlocks;
722+
catchBlocks.reserve(stmt->catches->dim);
723+
719724
for (Catches::reverse_iterator it = stmt->catches->rbegin(),
720725
end = stmt->catches->rend();
721726
it != end; ++it
722727
) {
723-
llvm::BasicBlock* catchBlock = llvm::BasicBlock::Create(irs->context(),
728+
llvm::BasicBlock* catchBB = llvm::BasicBlock::Create(irs->context(),
724729
llvm::Twine("catch.") + (*it)->type->toChars(),
725730
irs->topfunc(), endbb);
726731

727-
irs->scope() = IRScope(catchBlock);
732+
irs->scope() = IRScope(catchBB);
728733
irs->DBuilder.EmitBlockStart((*it)->loc);
729734

730735
llvm::Function* enterCatchFn =
@@ -733,7 +738,7 @@ class ToIRVisitor : public Visitor {
733738

734739
// For catches that use the Throwable object, create storage for it.
735740
// We will set it in the code that branches from the landing pads
736-
// (there might be more than one) to catchBlock.
741+
// (there might be more than one) to catchBB.
737742
if ((*it)->var) {
738743
llvm::Value* ehPtr = irs->func()->getOrCreateEhPtrSlot();
739744

@@ -777,12 +782,20 @@ class ToIRVisitor : public Visitor {
777782

778783
irs->DBuilder.EmitBlockEnd();
779784

780-
ClassDeclaration* catchType =
781-
(*it)->type->toBasetype()->isClassHandle();
782-
DtoResolveClass(catchType);
785+
catchBlocks.push_back(std::make_pair(
786+
(*it)->type->toBasetype()->isClassHandle(), catchBB));
787+
}
783788

789+
// Only after emitting all the catch bodies, register the catch scopes.
790+
// This is so that (re)throwing inside a catch does not match later
791+
// catches.
792+
for (CatchBlocks::iterator it = catchBlocks.begin(),
793+
end = catchBlocks.end();
794+
it != end; ++it
795+
) {
796+
DtoResolveClass(it->first);
784797
irs->func()->scopes->pushCatch(
785-
getIrAggr(catchType)->getClassInfoSymbol(), catchBlock);
798+
getIrAggr(it->first)->getClassInfoSymbol(), it->second);
786799
}
787800

788801
// Emit the try block.
@@ -799,10 +812,7 @@ class ToIRVisitor : public Visitor {
799812

800813
// Now that we have done the try block, remove the catches and continue
801814
// codegen in the end block the try and all the catches branch to.
802-
for (Catches::reverse_iterator it = stmt->catches->rbegin(),
803-
end = stmt->catches->rend();
804-
it != end; ++it
805-
) {
815+
for (size_t i = 0; i < catchBlocks.size(); ++i) {
806816
irs->func()->scopes->popCatch();
807817
}
808818

0 commit comments

Comments
 (0)