Fix lifetime of conditional temporaries. Patch by Victor Zverovich!

llvm-svn: 89467
This commit is contained in:
Anders Carlsson 2009-11-20 17:27:56 +00:00
parent 9c7efbb996
commit 0a66c26191
6 changed files with 59 additions and 46 deletions

View File

@ -23,7 +23,7 @@ void CodeGenFunction::PushCXXTemporary(const CXXTemporary *Temporary,
// Check if temporaries need to be conditional. If so, we'll create a
// condition boolean, initialize it to 0 and
if (!ConditionalTempDestructionStack.empty()) {
if (ConditionalBranchLevel != 0) {
CondPtr = CreateTempAlloca(llvm::Type::getInt1Ty(VMContext), "cond");
// Initialize it to false. This initialization takes place right after
@ -141,23 +141,3 @@ LValue CodeGenFunction::EmitCXXExprWithTemporariesLValue(
return LV;
}
void
CodeGenFunction::PushConditionalTempDestruction() {
// Store the current number of live temporaries.
ConditionalTempDestructionStack.push_back(LiveTemporaries.size());
}
void CodeGenFunction::PopConditionalTempDestruction() {
size_t NumLiveTemporaries = ConditionalTempDestructionStack.back();
ConditionalTempDestructionStack.pop_back();
// Pop temporaries.
while (LiveTemporaries.size() > NumLiveTemporaries) {
assert(LiveTemporaries.back().CondPtr &&
"Conditional temporary must have a cond ptr!");
PopCXXTemporary();
}
}

View File

@ -389,21 +389,21 @@ void AggExprEmitter::VisitConditionalOperator(const ConditionalOperator *E) {
llvm::Value *Cond = CGF.EvaluateExprAsBool(E->getCond());
Builder.CreateCondBr(Cond, LHSBlock, RHSBlock);
CGF.PushConditionalTempDestruction();
CGF.StartConditionalBranch();
CGF.EmitBlock(LHSBlock);
// Handle the GNU extension for missing LHS.
assert(E->getLHS() && "Must have LHS for aggregate value");
Visit(E->getLHS());
CGF.PopConditionalTempDestruction();
CGF.FinishConditionalBranch();
CGF.EmitBranch(ContBlock);
CGF.PushConditionalTempDestruction();
CGF.StartConditionalBranch();
CGF.EmitBlock(RHSBlock);
Visit(E->getRHS());
CGF.PopConditionalTempDestruction();
CGF.FinishConditionalBranch();
CGF.EmitBranch(ContBlock);
CGF.EmitBlock(ContBlock);

View File

@ -1583,10 +1583,10 @@ Value *ScalarExprEmitter::VisitBinLAnd(const BinaryOperator *E) {
PI != PE; ++PI)
PN->addIncoming(llvm::ConstantInt::getFalse(VMContext), *PI);
CGF.PushConditionalTempDestruction();
CGF.StartConditionalBranch();
CGF.EmitBlock(RHSBlock);
Value *RHSCond = CGF.EvaluateExprAsBool(E->getRHS());
CGF.PopConditionalTempDestruction();
CGF.FinishConditionalBranch();
// Reaquire the RHS block, as there may be subblocks inserted.
RHSBlock = Builder.GetInsertBlock();
@ -1633,13 +1633,13 @@ Value *ScalarExprEmitter::VisitBinLOr(const BinaryOperator *E) {
PI != PE; ++PI)
PN->addIncoming(llvm::ConstantInt::getTrue(VMContext), *PI);
CGF.PushConditionalTempDestruction();
CGF.StartConditionalBranch();
// Emit the RHS condition as a bool value.
CGF.EmitBlock(RHSBlock);
Value *RHSCond = CGF.EvaluateExprAsBool(E->getRHS());
CGF.PopConditionalTempDestruction();
CGF.FinishConditionalBranch();
// Reaquire the RHS block, as there may be subblocks inserted.
RHSBlock = Builder.GetInsertBlock();
@ -1753,7 +1753,7 @@ VisitConditionalOperator(const ConditionalOperator *E) {
Builder.CreateCondBr(CondBoolVal, LHSBlock, RHSBlock);
}
CGF.PushConditionalTempDestruction();
CGF.StartConditionalBranch();
CGF.EmitBlock(LHSBlock);
// Handle the GNU extension for missing LHS.
@ -1763,15 +1763,15 @@ VisitConditionalOperator(const ConditionalOperator *E) {
else // Perform promotions, to handle cases like "short ?: int"
LHS = EmitScalarConversion(CondVal, E->getCond()->getType(), E->getType());
CGF.PopConditionalTempDestruction();
CGF.FinishConditionalBranch();
LHSBlock = Builder.GetInsertBlock();
CGF.EmitBranch(ContBlock);
CGF.PushConditionalTempDestruction();
CGF.StartConditionalBranch();
CGF.EmitBlock(RHSBlock);
Value *RHS = Visit(E->getRHS());
CGF.PopConditionalTempDestruction();
CGF.FinishConditionalBranch();
RHSBlock = Builder.GetInsertBlock();
CGF.EmitBranch(ContBlock);

View File

@ -29,7 +29,8 @@ CodeGenFunction::CodeGenFunction(CodeGenModule &cgm)
Builder(cgm.getModule().getContext()),
DebugInfo(0), IndirectBranch(0),
SwitchInsn(0), CaseRangeBlock(0), InvokeDest(0),
CXXThisDecl(0) {
CXXThisDecl(0),
ConditionalBranchLevel(0) {
LLVMIntTy = ConvertType(getContext().IntTy);
LLVMPointerWidth = Target.getPointerWidth(0);
}

View File

@ -176,19 +176,23 @@ public:
/// this behavior for branches?
void EmitBranchThroughCleanup(llvm::BasicBlock *Dest);
/// PushConditionalTempDestruction - Should be called before a conditional
/// part of an expression is emitted. For example, before the RHS of the
/// expression below is emitted:
/// StartConditionalBranch - Should be called before a conditional part of an
/// expression is emitted. For example, before the RHS of the expression below
/// is emitted:
///
/// b && f(T());
///
/// This is used to make sure that any temporaryes created in the conditional
/// This is used to make sure that any temporaries created in the conditional
/// branch are only destroyed if the branch is taken.
void PushConditionalTempDestruction();
void StartConditionalBranch() {
++ConditionalBranchLevel;
}
/// PopConditionalTempDestruction - Should be called after a conditional
/// part of an expression has been emitted.
void PopConditionalTempDestruction();
/// FinishConditionalBranch - Should be called after a conditional part of an
/// expression has been emitted.
void FinishConditionalBranch() {
--ConditionalBranchLevel;
}
private:
CGDebugInfo *DebugInfo;
@ -298,10 +302,10 @@ private:
llvm::SmallVector<CXXLiveTemporaryInfo, 4> LiveTemporaries;
/// ConditionalTempDestructionStack - Contains the number of live temporaries
/// when PushConditionalTempDestruction was called. This is used so that
/// we know how many temporaries were created by a certain expression.
llvm::SmallVector<size_t, 4> ConditionalTempDestructionStack;
/// ConditionalBranchLevel - Contains the nesting level of the current
/// conditional branch. This is used so that we know if a temporary should be
/// destroyed conditionally.
unsigned ConditionalBranchLevel;
/// ByrefValueInfoMap - For each __block variable, contains a pair of the LLVM

View File

@ -0,0 +1,28 @@
// RUN: clang-cc -emit-llvm %s -o - -triple=x86_64-apple-darwin9 | FileCheck %s
struct I {
int i;
I();
~I();
};
void g(int);
volatile int i;
void f1() {
// CHECK: call void @_ZN1IC1Ev
g(i ? I().i : 0);
// CHECK: call void @_Z1gi
// CHECK: call void @_ZN1ID1Ev
// CHECK: call void @_ZN1IC1Ev
g(i || I().i);
// CHECK: call void @_Z1gi
// CHECK: call void @_ZN1ID1Ev
// CHECK: call void @_ZN1IC1Ev
g(i && I().i);
// CHECK: call void @_Z1gi
// CHECK: call void @_ZN1ID1Ev
}