// 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
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();
- }
-}
-
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);
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();
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();
Builder.CreateCondBr(CondBoolVal, LHSBlock, RHSBlock);
}
- CGF.PushConditionalTempDestruction();
+ CGF.StartConditionalBranch();
CGF.EmitBlock(LHSBlock);
// Handle the GNU extension for missing LHS.
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);
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);
}
/// 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;
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
--- /dev/null
+// 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
+}