return;
}
+ // We want to ensure that any vlas between here and when we
+ // push the break and continue context below can be destroyed
+ // when we break
+ llvm::Value *saveBreakStackDepth = StackDepth;
+
if (const DeclStmt *SD = dyn_cast<DeclStmt>(S.getElement())) {
EmitStmt(SD);
assert(HaveInsertPoint() && "DeclStmt destroyed insert point!");
llvm::BasicBlock *LoopStart = createBasicBlock("loopstart");
EmitBlock(LoopStart);
- // We want to ensure there are no vlas between here and when we
- // push the break and continue context below.
- llvm::Value *saveStackDepth = StackDepth;
-
llvm::Value *CounterPtr = CreateTempAlloca(UnsignedLongLTy, "counter.ptr");
Builder.CreateStore(Zero, CounterPtr);
llvm::BasicBlock *LoopEnd = createBasicBlock("loopend");
llvm::BasicBlock *AfterBody = createBasicBlock("afterbody");
- assert (StackDepth == saveStackDepth && "vla unhandled in for");
-
- BreakContinuePush(LoopEnd, AfterBody);
+ // Ensure any vlas created between there and here, are undone
+ BreakContinuePush(LoopEnd, AfterBody, saveBreakStackDepth, StackDepth);
EmitStmt(S.getBody());
EmitBlock(CondBlock);
+ llvm::Value *saveStackDepth = StackDepth;
+
// Evaluate the condition if present. If not, treat it as a
// non-zero-constant according to 6.8.5.3p2, aka, true.
if (S.getCond()) {
ContinueBlock = CondBlock;
// Store the blocks to use for break and continue.
- BreakContinuePush(AfterFor, ContinueBlock);
-
+ // Ensure any vlas created between there and here, are undone
+ BreakContinuePush(AfterFor, ContinueBlock,
+ saveStackDepth, saveStackDepth);
+
// If the condition is true, execute the body of the for stmt.
EmitStmt(S.getBody());
llvm::SwitchInst *SavedSwitchInsn = SwitchInsn;
llvm::BasicBlock *SavedCRBlock = CaseRangeBlock;
+ // Ensure any vlas created inside are destroyed on break.
+ llvm::Value *saveBreakStackDepth = StackDepth;
+
// 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
// All break statements jump to NextBlock. If BreakContinueStack is non empty
// then reuse last ContinueBlock.
llvm::BasicBlock *ContinueBlock = NULL;
- if (!BreakContinueStack.empty())
+ llvm::Value *saveContinueStackDepth = NULL;
+ if (!BreakContinueStack.empty()) {
ContinueBlock = BreakContinueStack.back().ContinueBlock;
- BreakContinuePush(NextBlock, ContinueBlock);
+ saveContinueStackDepth = BreakContinueStack.back().SaveContinueStackDepth;
+ }
+ // Ensure any vlas created between there and here, are undone
+ BreakContinuePush(NextBlock, ContinueBlock,
+ saveBreakStackDepth, saveContinueStackDepth);
// Emit switch body.
EmitStmt(S.getBody());
/// condition has possibly started a vla.
void BreakContinuePush(llvm::BasicBlock *bb, llvm::BasicBlock *cb) {
BreakContinueStack.push_back(BreakContinue(bb, cb, StackDepth,
+ StackDepth,
+ ObjCEHStack.size()));
+ }
+ void BreakContinuePush(llvm::BasicBlock *bb, llvm::BasicBlock *cb,
+ llvm::Value *bsd, llvm::Value *csd) {
+ BreakContinueStack.push_back(BreakContinue(bb, cb, bsd, csd,
ObjCEHStack.size()));
}
// of the eh stack.
struct BreakContinue {
BreakContinue(llvm::BasicBlock *bb, llvm::BasicBlock *cb,
- llvm::Value *sd, size_t ehss)
- : BreakBlock(bb), ContinueBlock(cb), SaveStackDepth(sd),
- EHStackSize(ehss) {}
+ llvm::Value *bsd, llvm::Value *csd, size_t ehss)
+ : BreakBlock(bb), ContinueBlock(cb), SaveBreakStackDepth(bsd),
+ SaveContinueStackDepth(csd), EHStackSize(ehss) {}
llvm::BasicBlock *BreakBlock;
llvm::BasicBlock *ContinueBlock;
- llvm::Value *SaveStackDepth;
+ llvm::Value *SaveBreakStackDepth;
+ llvm::Value *SaveContinueStackDepth;
size_t EHStackSize;
};
llvm::SmallVector<BreakContinue, 8> BreakContinueStack;