diff --git a/gen/runtime.cpp b/gen/runtime.cpp
index c6e4af3425a..3f72ace1f01 100644
--- a/gen/runtime.cpp
+++ b/gen/runtime.cpp
@@ -898,6 +898,14 @@ static void LLVM_D_BuildRuntimeModule()
         llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M);
     }
 
+    // void _d_eh_handle_collision(ptr exc_struct, ptr exc_struct)
+    {
+        llvm::StringRef fname("_d_eh_handle_collision");
+        LLType *types[] = { voidPtrTy, voidPtrTy };
+        LLFunctionType* fty = llvm::FunctionType::get(voidTy, types, false);
+        llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M);
+    }
+
     /////////////////////////////////////////////////////////////////////////////////////
     /////////////////////////////////////////////////////////////////////////////////////
     /////////////////////////////////////////////////////////////////////////////////////
diff --git a/ir/irlandingpad.cpp b/ir/irlandingpad.cpp
index b3ae23b6089..a3036f590a1 100644
--- a/ir/irlandingpad.cpp
+++ b/ir/irlandingpad.cpp
@@ -17,62 +17,56 @@
 #include "gen/tollvm.h"
 #include "ir/irlandingpad.h"
 
-IRLandingPadInfo::IRLandingPadInfo(Catch* catchstmt_, llvm::BasicBlock* end_) :
-    finallyBody(NULL), catchstmt(catchstmt_), end(end_)
+IRLandingPadCatchInfo::IRLandingPadCatchInfo(Catch* catchstmt_, llvm::BasicBlock* end_) :
+    catchStmt(catchstmt_), end(end_)
 {
     target = llvm::BasicBlock::Create(gIR->context(), "catch", gIR->topfunc(), end);
 
-    assert(catchstmt->type);
-    catchType = catchstmt->type->toBasetype()->isClassHandle();
+    assert(catchStmt->type);
+    catchType = catchStmt->type->toBasetype()->isClassHandle();
     assert(catchType);
     catchType->codegen(Type::sir);
 
-    if(catchstmt->var) {
-            if(!catchstmt->var->nestedrefs.dim) {
-                gIR->func()->gen->landingPadInfo.getExceptionStorage();
-            }
+    if (catchStmt->var) {
+        if (!catchStmt->var->nestedrefs.dim) {
+            gIR->func()->gen->landingPadInfo.getExceptionStorage();
+        }
     }
 }
 
-IRLandingPadInfo::IRLandingPadInfo(Statement* finallystmt) :
-    target(NULL), finallyBody(finallystmt), catchstmt(NULL)
-{
-
-}
-
-void IRLandingPadInfo::toIR()
+void IRLandingPadCatchInfo::toIR()
 {
-    if (!catchstmt)
+    if (!catchStmt)
         return;
 
     gIR->scope() = IRScope(target, target);
-    DtoDwarfBlockStart(catchstmt->loc);
+    DtoDwarfBlockStart(catchStmt->loc);
 
     // assign storage to catch var
-    if(catchstmt->var) {
+    if (catchStmt->var) {
         // use the same storage for all exceptions that are not accessed in
         // nested functions
-        if(!catchstmt->var->nestedrefs.dim) {
-            assert(!catchstmt->var->ir.irLocal);
-            catchstmt->var->ir.irLocal = new IrLocal(catchstmt->var);
+        if (!catchStmt->var->nestedrefs.dim) {
+            assert(!catchStmt->var->ir.irLocal);
+            catchStmt->var->ir.irLocal = new IrLocal(catchStmt->var);
             LLValue* catch_var = gIR->func()->gen->landingPadInfo.getExceptionStorage();
-            catchstmt->var->ir.irLocal->value = gIR->ir->CreateBitCast(catch_var, getPtrToType(DtoType(catchstmt->var->type)));
+            catchStmt->var->ir.irLocal->value = gIR->ir->CreateBitCast(catch_var, getPtrToType(DtoType(catchStmt->var->type)));
         }
 
         // this will alloca if we haven't already and take care of nested refs
-        DtoDeclarationExp(catchstmt->var);
+        DtoDeclarationExp(catchStmt->var);
 
         // the exception will only be stored in catch_var. copy it over if necessary
-        if(catchstmt->var->ir.irLocal->value != gIR->func()->gen->landingPadInfo.getExceptionStorage()) {
-            LLValue* exc = gIR->ir->CreateBitCast(DtoLoad(gIR->func()->gen->landingPadInfo.getExceptionStorage()), DtoType(catchstmt->var->type));
-            DtoStore(exc, catchstmt->var->ir.irLocal->value);
+        if (catchStmt->var->ir.irLocal->value != gIR->func()->gen->landingPadInfo.getExceptionStorage()) {
+            LLValue* exc = gIR->ir->CreateBitCast(DtoLoad(gIR->func()->gen->landingPadInfo.getExceptionStorage()), DtoType(catchStmt->var->type));
+            DtoStore(exc, catchStmt->var->ir.irLocal->value);
         }
     }
 
     // emit handler, if there is one
     // handler is zero for instance for 'catch { debug foo(); }'
-    if(catchstmt->handler)
-        catchstmt->handler->toIR(gIR);
+    if (catchStmt->handler)
+        catchStmt->handler->toIR(gIR);
 
     if (!gIR->scopereturned())
         gIR->ir->CreateBr(end);
@@ -80,89 +74,77 @@ void IRLandingPadInfo::toIR()
     DtoDwarfBlockEnd();
 }
 
-
 void IRLandingPad::addCatch(Catch* catchstmt, llvm::BasicBlock* end)
 {
-    unpushed_infos.push_front(IRLandingPadInfo(catchstmt, end));
+    unpushedScope.catches.push_back(IRLandingPadCatchInfo(catchstmt, end));
 }
 
 void IRLandingPad::addFinally(Statement* finallystmt)
 {
-    unpushed_infos.push_front(IRLandingPadInfo(finallystmt));
+    assert(unpushedScope.finallyBody == NULL && "only one finally per try-finally block");
+    unpushedScope.finallyBody = finallystmt;
 }
 
 void IRLandingPad::push(llvm::BasicBlock* inBB)
 {
-    // store infos such that matches are right to left
-    nInfos.push(infos.size());
-    infos.insert(infos.end(), unpushed_infos.begin(), unpushed_infos.end());
-    unpushed_infos.clear();
-
-    // store as invoke target
-    padBBs.push(inBB);
+    unpushedScope.target = inBB;
+    scopeStack.push(unpushedScope);
+    unpushedScope = IRLandingPadScope();
     gIR->func()->gen->landingPad = get();
 }
 
 void IRLandingPad::pop()
 {
-    llvm::BasicBlock *inBB = padBBs.top();
-    padBBs.pop();
+    IRLandingPadScope scope = scopeStack.top();
+    scopeStack.pop();
     gIR->func()->gen->landingPad = get();
 
-    size_t n = nInfos.top();
-    for (int i = n, c = infos.size(); i < c; ++i)
-        infos.at(i).toIR();
-    constructLandingPad(inBB);
-
-    infos.resize(n);
-    nInfos.pop();
+    std::deque<IRLandingPadCatchInfo>::iterator itr, end = scope.catches.end();
+    for (itr = scope.catches.begin(); itr != end; ++itr)
+        itr->toIR();
+    constructLandingPad(scope);
 }
 
 llvm::BasicBlock* IRLandingPad::get()
 {
-    if(padBBs.size() == 0)
+    if (scopeStack.size() == 0)
         return NULL;
     else
-        return padBBs.top();
+        return scopeStack.top().target;
 }
 
-void IRLandingPad::constructLandingPad(llvm::BasicBlock* inBB)
+// creates new landing pad
+static llvm::LandingPadInst *createLandingPadInst()
+{
+    llvm::Function* personality_fn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_eh_personality");
+    LLType *retType = LLStructType::get(LLType::getInt8PtrTy(gIR->context()),
+                                        LLType::getInt32Ty(gIR->context()),
+                                        NULL);
+    return gIR->ir->CreateLandingPad(retType, personality_fn, 0, "landing_pad");
+}
+
+void IRLandingPad::constructLandingPad(IRLandingPadScope scope)
 {
     // save and rewrite scope
-    IRScope savedscope = gIR->scope();
-    gIR->scope() = IRScope(inBB,savedscope.end);
+    IRScope savedIRScope = gIR->scope();
+    gIR->scope() = IRScope(scope.target, savedIRScope.end);
 
-    // personality fn
-    llvm::Function* personality_fn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_eh_personality");
     // create landingpad
-    LLType *retType = LLStructType::get(LLType::getInt8PtrTy(gIR->context()), LLType::getInt32Ty(gIR->context()), NULL);
-    llvm::LandingPadInst *landingPad = gIR->ir->CreateLandingPad(retType, personality_fn, 0);
+    llvm::LandingPadInst *landingPad = createLandingPadInst();
     LLValue* eh_ptr = DtoExtractValue(landingPad, 0);
     LLValue* eh_sel = DtoExtractValue(landingPad, 1);
 
     // add landingpad clauses, emit finallys and 'if' chain to catch the exception
     llvm::Function* eh_typeid_for_fn = GET_INTRINSIC_DECL(eh_typeid_for);
-    std::deque<IRLandingPadInfo> infos = this->infos;
-    std::stack<size_t> nInfos = this->nInfos;
-    std::deque<IRLandingPadInfo>::reverse_iterator rit, rend = infos.rend();
     bool isFirstCatch = true;
-    for(rit = infos.rbegin(); rit != rend; ++rit)
-    {
-        // if it's a finally, emit its code
-        if(rit->finallyBody)
-        {
-            size_t n = this->nInfos.top();
-            this->infos.resize(n);
-            this->nInfos.pop();
-            rit->finallyBody->toIR(gIR);
-            landingPad->setCleanup(true);
-        }
-        // otherwise it's a catch and we'll add a if-statement
-        else
-        {
+    std::stack<IRLandingPadScope> savedScopeStack = scopeStack;
+    std::deque<IRLandingPadCatchInfo>::iterator catchItr, catchItrEnd;
+    while (true) {
+        catchItr = scope.catches.begin();
+        catchItrEnd = scope.catches.end();
+        for (; catchItr != catchItrEnd; ++catchItr) {
             // if it is a first catch and some catch allocated storage, store exception object
-            if(isFirstCatch && catch_var)
-            {
+            if (isFirstCatch && catch_var) {
                 // eh_ptr is a pointer to _d_exception, which has a reference
                 // to the Throwable object at offset 0.
                 LLType *objectPtrTy = DtoType(ClassDeclaration::object->type->pointerTo());
@@ -173,21 +155,51 @@ void IRLandingPad::constructLandingPad(llvm::BasicBlock* inBB)
             // create next block
             llvm::BasicBlock *next = llvm::BasicBlock::Create(gIR->context(), "eh.next", gIR->topfunc(), gIR->scopeend());
             // get class info symbol
-            LLValue *classInfo = rit->catchType->ir.irAggr->getClassInfoSymbol();
+            LLValue *classInfo = catchItr->catchType->ir.irAggr->getClassInfoSymbol();
             // add that symbol as landing pad clause
             landingPad->addClause(classInfo);
             // call llvm.eh.typeid.for to get class info index in the exception table
             classInfo = DtoBitCast(classInfo, getPtrToType(DtoType(Type::tint8)));
             LLValue *eh_id = gIR->ir->CreateCall(eh_typeid_for_fn, classInfo);
             // check exception selector (eh_sel) against the class info index
-            gIR->ir->CreateCondBr(gIR->ir->CreateICmpEQ(eh_sel, eh_id), rit->target, next);
+            gIR->ir->CreateCondBr(gIR->ir->CreateICmpEQ(eh_sel, eh_id), catchItr->target, next);
             gIR->scope() = IRScope(next, gIR->scopeend());
         }
+
+        if (scope.finallyBody) {
+            // create collision landing pad that handles exceptions thrown inside the finally block
+            llvm::BasicBlock *collision = llvm::BasicBlock::Create(gIR->context(), "eh.collision", gIR->topfunc(), gIR->scopeend());
+            llvm::BasicBlock *bb = gIR->scopebb();
+            gIR->scope() = IRScope(collision, gIR->scopeend());
+            llvm::LandingPadInst *collisionLandingPad = createLandingPadInst();
+            LLValue* collision_eh_ptr = DtoExtractValue(collisionLandingPad, 0);
+            collisionLandingPad->setCleanup(true);
+            llvm::Function* collision_fn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_eh_handle_collision");
+            gIR->CreateCallOrInvoke2(collision_fn, collision_eh_ptr, eh_ptr);
+            gIR->ir->CreateUnreachable();
+            gIR->scope() = IRScope(bb, gIR->scopeend());
+
+            // set collision landing pad as unwind target and emit the body of the finally
+            DtoDwarfBlockStart(scope.finallyBody->loc);
+            scopeStack.push(IRLandingPadScope(collision));
+            gIR->func()->gen->landingPad = collision;
+            scope.finallyBody->toIR(gIR);
+            scopeStack.pop();
+            gIR->func()->gen->landingPad = get();
+            DtoDwarfBlockEnd();
+            landingPad->setCleanup(true);
+        }
+
+        if (scopeStack.empty())
+            break;
+        scope = scopeStack.top();
+        scopeStack.pop();
+        gIR->func()->gen->landingPad = get();
     }
 
     // restore landing pad infos
-    this->infos = infos;
-    this->nInfos = nInfos;
+    scopeStack = savedScopeStack;
+    gIR->func()->gen->landingPad = get();
 
     // no catch matched and all finallys executed - resume unwind
     llvm::Function* unwind_resume_fn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_eh_resume_unwind");
@@ -195,13 +207,12 @@ void IRLandingPad::constructLandingPad(llvm::BasicBlock* inBB)
     gIR->ir->CreateUnreachable();
 
     // restore scope
-    gIR->scope() = savedscope;
+    gIR->scope() = savedIRScope;
 }
 
 LLValue* IRLandingPad::getExceptionStorage()
 {
-    if(!catch_var)
-    {
+    if (!catch_var) {
         Logger::println("Making new catch var");
         catch_var = DtoAlloca(ClassDeclaration::object->type, "catchvar");
     }
diff --git a/ir/irlandingpad.h b/ir/irlandingpad.h
index 904a5cffc2f..708bb2563be 100644
--- a/ir/irlandingpad.h
+++ b/ir/irlandingpad.h
@@ -25,37 +25,39 @@ namespace llvm {
     class Value;
     class BasicBlock;
     class Function;
+    class LandingPadInst;
 }
 
-// only to be used within IRLandingPad
-// holds information about a single catch or finally
-struct IRLandingPadInfo
+// holds information about a single catch
+struct IRLandingPadCatchInfo
 {
     // default constructor for being able to store in a vector
-    IRLandingPadInfo() :
-        target(NULL), finallyBody(NULL), catchstmt(NULL)
+    IRLandingPadCatchInfo() :
+        target(NULL), end(0), catchStmt(NULL), catchType(0)
     {}
 
-    // constructor for catch
-    IRLandingPadInfo(Catch* catchstmt, llvm::BasicBlock* end);
-
-    // constructor for finally
-    IRLandingPadInfo(Statement* finallystmt);
+    IRLandingPadCatchInfo(Catch* catchStmt, llvm::BasicBlock* end);
 
     // codegen the catch block
     void toIR();
 
-    // the target catch bb if this is a catch
-    // or the target finally bb if this is a finally
-    llvm::BasicBlock* target;
+    llvm::BasicBlock *target;
+    llvm::BasicBlock *end;
+    Catch *catchStmt;
+    ClassDeclaration *catchType;
+};
 
-    // nonzero if this is a finally
-    Statement* finallyBody;
+// holds information about a single try-catch-inally block
+struct IRLandingPadScope
+{
+    explicit IRLandingPadScope(llvm::BasicBlock *target_ = NULL) : target(target_), finallyBody(0) {}
 
-    // nonzero if this is a catch
-    Catch* catchstmt;
-    llvm::BasicBlock* end;
-    ClassDeclaration* catchType;
+    // the target for invokes
+    llvm::BasicBlock *target;
+    // information about catch blocks
+    std::deque<IRLandingPadCatchInfo> catches;
+    // the body of finally
+    Statement *finallyBody;
 };
 
 
@@ -79,25 +81,19 @@ struct IRLandingPad
     // and its infos
     void pop();
 
-    // gets the current landing pad
-    llvm::BasicBlock* get();
-
     // creates or gets storage for exception object
     llvm::Value* getExceptionStorage();
 
 private:
-    // constructs the landing pad from infos
-    void constructLandingPad(llvm::BasicBlock* inBB);
-
-    // information needed to create landing pads
-    std::deque<IRLandingPadInfo> infos;
-    std::deque<IRLandingPadInfo> unpushed_infos;
+    // gets the current landing pad
+    llvm::BasicBlock* get();
 
-    // the number of infos we had before the push
-    std::stack<size_t> nInfos;
+    // constructs the landing pad
+    void constructLandingPad(IRLandingPadScope scope);
 
-    // the target for invokes
-    std::stack<llvm::BasicBlock*> padBBs;
+    // information about try-catch-finally blocks
+    std::stack<IRLandingPadScope> scopeStack;
+    IRLandingPadScope unpushedScope;
 
     // storage for the catch variable
     llvm::Value* catch_var;
diff --git a/runtime/druntime b/runtime/druntime
index adaeaf9e7b3..a245e8d2f2f 160000
--- a/runtime/druntime
+++ b/runtime/druntime
@@ -1 +1 @@
-Subproject commit adaeaf9e7b3151d2efb710dca3d79cb724bd30bb
+Subproject commit a245e8d2f2f8edce0ead880b5e1d0632df1c2bb1
diff --git a/tests/d2/dmd-testsuite b/tests/d2/dmd-testsuite
index 32aa48727a4..dbb7b9fa186 160000
--- a/tests/d2/dmd-testsuite
+++ b/tests/d2/dmd-testsuite
@@ -1 +1 @@
-Subproject commit 32aa48727a4db7a28878e6f13af603aaa3e0e48d
+Subproject commit dbb7b9fa186c46576fadf195d8da9117ee988a52