]> granicus.if.org Git - clang/commitdiff
Fix lifetime of conditional temporaries. Patch by Victor Zverovich!
authorAnders Carlsson <andersca@mac.com>
Fri, 20 Nov 2009 17:27:56 +0000 (17:27 +0000)
committerAnders Carlsson <andersca@mac.com>
Fri, 20 Nov 2009 17:27:56 +0000 (17:27 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@89467 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGCXXTemp.cpp
lib/CodeGen/CGExprAgg.cpp
lib/CodeGen/CGExprScalar.cpp
lib/CodeGen/CodeGenFunction.cpp
lib/CodeGen/CodeGenFunction.h
test/CodeGenCXX/conditional-temporaries.cpp [new file with mode: 0644]

index 4768556f6bcacfa8aeb34a6099c195f507ccb38f..06a5fa6f6682eff4d2f4d54c4f3a1ea578b39288 100644 (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();
-  }
-}
-
index 0e10368ab04e7720996ef5e3a1967263a6c839ee..0c8f1e6934175e352f5cd89e4c0e9e76cc2b0b88 100644 (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);
index e9bbf35fcd8d4dab4add3ff6e466e6e2ff535844..ca8adffb5ea1052e62b65d821db00cb6a8b7f497 100644 (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);
 
index 475c7bfefd1d137c5ac881ad964019e8bb0c94df..a4cbf449efcfbd84de81cf9790b07638723aa410 100644 (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);
 }
index d96c3551010edddc265c3b1adeafba70e813ea17..0be527c8d465233d9ab7da94a4c7e2168c9b1651 100644 (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
diff --git a/test/CodeGenCXX/conditional-temporaries.cpp b/test/CodeGenCXX/conditional-temporaries.cpp
new file mode 100644 (file)
index 0000000..f6c466a
--- /dev/null
@@ -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
+}