static void EmitCleanup(CodeGenFunction &CGF, EHScopeStack::Cleanup *Fn, EHScopeStack::Cleanup::Flags flags, llvm::Value *ActiveFlag) { // EH cleanups always occur within a terminate scope. if (flags.isForEHCleanup()) CGF.EHStack.pushTerminate(); // If there's an active flag, load it and skip the cleanup if it's // false. llvm::BasicBlock *ContBB = nullptr; if (ActiveFlag) { ContBB = CGF.createBasicBlock("cleanup.done"); llvm::BasicBlock *CleanupBB = CGF.createBasicBlock("cleanup.action"); llvm::Value *IsActive = CGF.Builder.CreateLoad(ActiveFlag, "cleanup.is_active"); CGF.Builder.CreateCondBr(IsActive, CleanupBB, ContBB); CGF.EmitBlock(CleanupBB); } // Ask the cleanup to emit itself. Fn->Emit(CGF, flags); assert(CGF.HaveInsertPoint() && "cleanup ended with no insertion point?"); // Emit the continuation block if there was an active flag. if (ActiveFlag) CGF.EmitBlock(ContBB); // Leave the terminate scope. if (flags.isForEHCleanup()) CGF.EHStack.popTerminate(); }
static void EmitCleanup(CodeGenFunction &CGF, EHScopeStack::Cleanup *Fn, EHScopeStack::Cleanup::Flags flags, llvm::Value *ActiveFlag) { // Itanium EH cleanups occur within a terminate scope. Microsoft SEH doesn't // have this behavior, and the Microsoft C++ runtime will call terminate for // us if the cleanup throws. bool PushedTerminate = false; if (flags.isForEHCleanup() && !CGF.getTarget().getCXXABI().isMicrosoft()) { CGF.EHStack.pushTerminate(); PushedTerminate = true; } // If there's an active flag, load it and skip the cleanup if it's // false. llvm::BasicBlock *ContBB = nullptr; if (ActiveFlag) { ContBB = CGF.createBasicBlock("cleanup.done"); llvm::BasicBlock *CleanupBB = CGF.createBasicBlock("cleanup.action"); llvm::Value *IsActive = CGF.Builder.CreateLoad(ActiveFlag, "cleanup.is_active"); CGF.Builder.CreateCondBr(IsActive, CleanupBB, ContBB); CGF.EmitBlock(CleanupBB); } // Ask the cleanup to emit itself. Fn->Emit(CGF, flags); assert(CGF.HaveInsertPoint() && "cleanup ended with no insertion point?"); // Emit the continuation block if there was an active flag. if (ActiveFlag) CGF.EmitBlock(ContBB); // Leave the terminate scope. if (PushedTerminate) CGF.EHStack.popTerminate(); }