From: Anders Carlsson Date: Fri, 20 Nov 2009 17:27:56 +0000 (+0000) Subject: Fix lifetime of conditional temporaries. Patch by Victor Zverovich! X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=a36bf8f74180e834c6bf2db867796fd5338495ab;p=clang Fix lifetime of conditional temporaries. Patch by Victor Zverovich! git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@89467 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/CGCXXTemp.cpp b/lib/CodeGen/CGCXXTemp.cpp index 4768556f6b..06a5fa6f66 100644 --- a/lib/CodeGen/CGCXXTemp.cpp +++ b/lib/CodeGen/CGCXXTemp.cpp @@ -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(); - } -} - diff --git a/lib/CodeGen/CGExprAgg.cpp b/lib/CodeGen/CGExprAgg.cpp index 0e10368ab0..0c8f1e6934 100644 --- a/lib/CodeGen/CGExprAgg.cpp +++ b/lib/CodeGen/CGExprAgg.cpp @@ -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); diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp index e9bbf35fcd..ca8adffb5e 100644 --- a/lib/CodeGen/CGExprScalar.cpp +++ b/lib/CodeGen/CGExprScalar.cpp @@ -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); diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp index 475c7bfefd..a4cbf449ef 100644 --- a/lib/CodeGen/CodeGenFunction.cpp +++ b/lib/CodeGen/CodeGenFunction.cpp @@ -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); } diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index d96c355101..0be527c8d4 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -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 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 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 diff --git a/test/CodeGenCXX/conditional-temporaries.cpp b/test/CodeGenCXX/conditional-temporaries.cpp new file mode 100644 index 0000000000..f6c466a931 --- /dev/null +++ b/test/CodeGenCXX/conditional-temporaries.cpp @@ -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 +}