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 // Check if temporaries need to be conditional. If so, we'll create a
// condition boolean, initialize it to 0 and // condition boolean, initialize it to 0 and
if (!ConditionalTempDestructionStack.empty()) { if (ConditionalBranchLevel != 0) {
CondPtr = CreateTempAlloca(llvm::Type::getInt1Ty(VMContext), "cond"); CondPtr = CreateTempAlloca(llvm::Type::getInt1Ty(VMContext), "cond");
// Initialize it to false. This initialization takes place right after // Initialize it to false. This initialization takes place right after
@ -141,23 +141,3 @@ LValue CodeGenFunction::EmitCXXExprWithTemporariesLValue(
return LV; 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()); llvm::Value *Cond = CGF.EvaluateExprAsBool(E->getCond());
Builder.CreateCondBr(Cond, LHSBlock, RHSBlock); Builder.CreateCondBr(Cond, LHSBlock, RHSBlock);
CGF.PushConditionalTempDestruction(); CGF.StartConditionalBranch();
CGF.EmitBlock(LHSBlock); CGF.EmitBlock(LHSBlock);
// Handle the GNU extension for missing LHS. // Handle the GNU extension for missing LHS.
assert(E->getLHS() && "Must have LHS for aggregate value"); assert(E->getLHS() && "Must have LHS for aggregate value");
Visit(E->getLHS()); Visit(E->getLHS());
CGF.PopConditionalTempDestruction(); CGF.FinishConditionalBranch();
CGF.EmitBranch(ContBlock); CGF.EmitBranch(ContBlock);
CGF.PushConditionalTempDestruction(); CGF.StartConditionalBranch();
CGF.EmitBlock(RHSBlock); CGF.EmitBlock(RHSBlock);
Visit(E->getRHS()); Visit(E->getRHS());
CGF.PopConditionalTempDestruction(); CGF.FinishConditionalBranch();
CGF.EmitBranch(ContBlock); CGF.EmitBranch(ContBlock);
CGF.EmitBlock(ContBlock); CGF.EmitBlock(ContBlock);

View File

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

View File

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

View File

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