void CodeGenFunction::EmitSwitchStmt(const SwitchStmt &S) { llvm::Value *CondV = EmitScalarExpr(S.getCond()); // Handle nested switch statements. llvm::SwitchInst *SavedSwitchInsn = SwitchInsn; llvm::BasicBlock *SavedCRBlock = CaseRangeBlock; // Create basic block to hold stuff that comes after switch // statement. We also need to create a default block now so that // explicit case ranges tests can have a place to jump to on // failure. llvm::BasicBlock *NextBlock = createBasicBlock("sw.epilog"); llvm::BasicBlock *DefaultBlock = createBasicBlock("sw.default"); SwitchInsn = Builder.CreateSwitch(CondV, DefaultBlock); CaseRangeBlock = DefaultBlock; // Clear the insertion point to indicate we are in unreachable code. Builder.ClearInsertionPoint(); // All break statements jump to NextBlock. If BreakContinueStack is non empty // then reuse last ContinueBlock. llvm::BasicBlock *ContinueBlock = 0; if (!BreakContinueStack.empty()) ContinueBlock = BreakContinueStack.back().ContinueBlock; // Ensure any vlas created between there and here, are undone BreakContinueStack.push_back(BreakContinue(NextBlock, ContinueBlock)); // Emit switch body. EmitStmt(S.getBody()); BreakContinueStack.pop_back(); // Update the default block in case explicit case range tests have // been chained on top. SwitchInsn->setSuccessor(0, CaseRangeBlock); // If a default was never emitted then reroute any jumps to it and // discard. if (!DefaultBlock->getParent()) { DefaultBlock->replaceAllUsesWith(NextBlock); delete DefaultBlock; } // Emit continuation. EmitBlock(NextBlock, true); SwitchInsn = SavedSwitchInsn; CaseRangeBlock = SavedCRBlock; }