diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/CodeGen/CGStmt.cpp | 28 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.h | 25 |
2 files changed, 41 insertions, 12 deletions
diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp index 1c3f3577947..51b7cf8a112 100644 --- a/clang/lib/CodeGen/CGStmt.cpp +++ b/clang/lib/CodeGen/CGStmt.cpp @@ -153,9 +153,7 @@ RValue CodeGenFunction::EmitCompoundStmt(const CompoundStmt &S, bool GetLast, } // Keep track of the current cleanup stack depth. - size_t CleanupStackDepth = CleanupEntries.size(); - bool OldDidCallStackSave = DidCallStackSave; - DidCallStackSave = false; + CleanupScope Scope(*this); for (CompoundStmt::const_body_iterator I = S.body_begin(), E = S.body_end()-GetLast; I != E; ++I) @@ -185,10 +183,6 @@ RValue CodeGenFunction::EmitCompoundStmt(const CompoundStmt &S, bool GetLast, RV = EmitAnyExpr(cast<Expr>(LastStmt), AggLoc); } - DidCallStackSave = OldDidCallStackSave; - - EmitCleanupBlocks(CleanupStackDepth); - return RV; } @@ -294,8 +288,10 @@ void CodeGenFunction::EmitIndirectGotoStmt(const IndirectGotoStmt &S) { void CodeGenFunction::EmitIfStmt(const IfStmt &S) { // C99 6.8.4.1: The first substatement is executed if the expression compares // unequal to 0. The condition must be a scalar type. + CleanupScope ConditionScope(*this); + if (S.getConditionVariable()) - EmitDecl(*S.getConditionVariable()); + EmitLocalBlockVarDecl(*S.getConditionVariable()); // If the condition constant folds and can be elided, try to avoid emitting // the condition and the dead arm of the if/else. @@ -308,8 +304,10 @@ void CodeGenFunction::EmitIfStmt(const IfStmt &S) { // If the skipped block has no labels in it, just emit the executed block. // This avoids emitting dead code and simplifies the CFG substantially. if (!ContainsLabel(Skipped)) { - if (Executed) + if (Executed) { + CleanupScope ExecutedScope(*this); EmitStmt(Executed); + } return; } } @@ -324,14 +322,20 @@ void CodeGenFunction::EmitIfStmt(const IfStmt &S) { EmitBranchOnBoolExpr(S.getCond(), ThenBlock, ElseBlock); // Emit the 'then' code. - EmitBlock(ThenBlock); - EmitStmt(S.getThen()); + EmitBlock(ThenBlock); + { + CleanupScope ThenScope(*this); + EmitStmt(S.getThen()); + } EmitBranch(ContBlock); // Emit the 'else' code if present. if (const Stmt *Else = S.getElse()) { EmitBlock(ElseBlock); - EmitStmt(Else); + { + CleanupScope ElseScope(*this); + EmitStmt(Else); + } EmitBranch(ContBlock); } diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index dd26428f819..be1a15ed665 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -165,6 +165,31 @@ public: } }; + /// \brief Enters a new scope for capturing cleanups, all of which will be + /// executed once the scope is exited. + class CleanupScope { + CodeGenFunction& CGF; + size_t CleanupStackDepth; + bool OldDidCallStackSave; + + CleanupScope(const CleanupScope &); // DO NOT IMPLEMENT + CleanupScope &operator=(const CleanupScope &); // DO NOT IMPLEMENT + + public: + /// \brief Enter a new cleanup scope. + explicit CleanupScope(CodeGenFunction &CGF) : CGF(CGF) { + CleanupStackDepth = CGF.CleanupEntries.size(); + OldDidCallStackSave = CGF.DidCallStackSave; + } + + /// \brief Exit this cleanup scope, emitting any accumulated + /// cleanups. + ~CleanupScope() { + CGF.DidCallStackSave = OldDidCallStackSave; + CGF.EmitCleanupBlocks(CleanupStackDepth); + } + }; + /// EmitCleanupBlocks - Takes the old cleanup stack size and emits the cleanup /// blocks that have been added. void EmitCleanupBlocks(size_t OldCleanupStackSize); |