summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/CodeGen/CGStmt.cpp28
-rw-r--r--clang/lib/CodeGen/CodeGenFunction.h25
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);
OpenPOWER on IntegriCloud