[cfe-commits] r106981 - /cfe/trunk/lib/CodeGen/CGExpr.cpp

Anders Carlsson andersca at mac.com
Sun Jun 27 09:56:04 PDT 2010


Author: andersca
Date: Sun Jun 27 11:56:04 2010
New Revision: 106981

URL: http://llvm.org/viewvc/llvm-project?rev=106981&view=rev
Log:
Simplify CodeGenFunction::EmitReferenceBindingToExpr as a first step towards fixing PR7326.

Modified:
    cfe/trunk/lib/CodeGen/CGExpr.cpp

Modified: cfe/trunk/lib/CodeGen/CGExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExpr.cpp?rev=106981&r1=106980&r2=106981&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExpr.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExpr.cpp Sun Jun 27 11:56:04 2010
@@ -168,52 +168,38 @@
   }
 };
 
-RValue
-CodeGenFunction::EmitReferenceBindingToExpr(const Expr* E,
-                                            const NamedDecl *InitializedDecl) {
-  bool IsInitializer = InitializedDecl;
-
-  bool ShouldDestroyTemporaries = false;
-  unsigned OldNumLiveTemporaries = 0;
-
+static llvm::Value *
+EmitExprForReferenceBinding(CodeGenFunction& CGF, const Expr* E,
+                            llvm::Value *&ReferenceTemporary,
+                            const CXXDestructorDecl *&ReferenceTemporaryDtor,
+                            bool IsInitializer) {
   if (const CXXDefaultArgExpr *DAE = dyn_cast<CXXDefaultArgExpr>(E))
     E = DAE->getExpr();
-
+  
   if (const CXXExprWithTemporaries *TE = dyn_cast<CXXExprWithTemporaries>(E)) {
-    ShouldDestroyTemporaries = true;
-    
-    // Keep track of the current cleanup stack depth.
-    OldNumLiveTemporaries = LiveTemporaries.size();
-    
-    E = TE->getSubExpr();
+    CodeGenFunction::CXXTemporariesCleanupScope Scope(CGF);
+
+    return EmitExprForReferenceBinding(CGF, TE->getSubExpr(), 
+                                       ReferenceTemporary, 
+                                       ReferenceTemporaryDtor,
+                                       IsInitializer);
   }
-  
-  RValue Val;
-  if (E->isLvalue(getContext()) == Expr::LV_Valid) {
-    // Emit the expr as an lvalue.
-    LValue LV = EmitLValue(E);
-    if (LV.isSimple()) {
-      if (ShouldDestroyTemporaries) {
-        // Pop temporaries.
-        while (LiveTemporaries.size() > OldNumLiveTemporaries)
-          PopCXXTemporary();
-      }
-      
-      return RValue::get(LV.getAddress());
-    }
-    
-    Val = EmitLoadOfLValue(LV, E->getType());
+
+  RValue RV;
+  if (E->isLvalue(CGF.getContext()) == Expr::LV_Valid) {
+    // Emit the expression as an lvalue.
+    LValue LV = CGF.EmitLValue(E);
+
+    if (LV.isSimple())
+      return LV.getAddress();
     
-    if (ShouldDestroyTemporaries) {
-      // Pop temporaries.
-      while (LiveTemporaries.size() > OldNumLiveTemporaries)
-        PopCXXTemporary();
-    }      
+    // We have to load the lvalue.
+    RV = CGF.EmitLoadOfLValue(LV, E->getType());
   } else {
     QualType ResultTy = E->getType();
-    
+
     llvm::SmallVector<SubobjectAdjustment, 2> Adjustments;
-    do {
+    while (true) {
       if (const ParenExpr *PE = dyn_cast<ParenExpr>(E)) {
         E = PE->getSubExpr();
         continue;
@@ -236,7 +222,7 @@
           continue;
         }
       } else if (const MemberExpr *ME = dyn_cast<MemberExpr>(E)) {
-        if (ME->getBase()->isLvalue(getContext()) != Expr::LV_Valid &&
+        if (ME->getBase()->isLvalue(CGF.getContext()) != Expr::LV_Valid &&
             ME->getBase()->getType()->isRecordType()) {
           if (FieldDecl *Field = dyn_cast<FieldDecl>(ME->getMemberDecl())) {
             E = ME->getBase();
@@ -249,63 +235,44 @@
 
       // Nothing changed.
       break;
-    } while (true);
-      
-    Val = EmitAnyExprToTemp(E, /*IsAggLocVolatile=*/false,
-                            IsInitializer);
-
-    if (ShouldDestroyTemporaries) {
-      // Pop temporaries.
-      while (LiveTemporaries.size() > OldNumLiveTemporaries)
-        PopCXXTemporary();
-    }      
+    }
     
+    // Create a reference temporary if necessary.
+    if (CGF.hasAggregateLLVMType(E->getType()) &&
+        !E->getType()->isAnyComplexType())
+      ReferenceTemporary = CGF.CreateMemTemp(E->getType(), "ref.tmp");
+    RV = CGF.EmitAnyExpr(E, ReferenceTemporary, /*IsAggLocVolatile=*/false,
+                         /*IgnoreResult=*/false, IsInitializer);
+
     if (IsInitializer) {
-      // We might have to destroy the temporary variable.
+      // Get the destructor for the reference temporary.
       if (const RecordType *RT = E->getType()->getAs<RecordType>()) {
-        if (CXXRecordDecl *ClassDecl = dyn_cast<CXXRecordDecl>(RT->getDecl())) {
-          if (!ClassDecl->hasTrivialDestructor()) {
-            const CXXDestructorDecl *Dtor =
-              ClassDecl->getDestructor(getContext());
-
-            {
-              DelayedCleanupBlock Scope(*this);
-              EmitCXXDestructorCall(Dtor, Dtor_Complete,
-                                    /*ForVirtualBase=*/false,
-                                    Val.getAggregateAddr());
-              
-              // Make sure to jump to the exit block.
-              EmitBranch(Scope.getCleanupExitBlock());
-            }
-            if (Exceptions) {
-              EHCleanupBlock Cleanup(*this);
-              EmitCXXDestructorCall(Dtor, Dtor_Complete,
-                                    /*ForVirtualBase=*/false,
-                                    Val.getAggregateAddr());
-            }
-          }
-        }
+        CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(RT->getDecl());
+        if (!ClassDecl->hasTrivialDestructor())
+          ReferenceTemporaryDtor = ClassDecl->getDestructor(CGF.getContext());
       }
     }
-    
+
     // Check if need to perform derived-to-base casts and/or field accesses, to
     // get from the temporary object we created (and, potentially, for which we
     // extended the lifetime) to the subobject we're binding the reference to.
     if (!Adjustments.empty()) {
-      llvm::Value *Object = Val.getAggregateAddr();
+      llvm::Value *Object = RV.getAggregateAddr();
       for (unsigned I = Adjustments.size(); I != 0; --I) {
         SubobjectAdjustment &Adjustment = Adjustments[I-1];
         switch (Adjustment.Kind) {
         case SubobjectAdjustment::DerivedToBaseAdjustment:
-          Object = GetAddressOfBaseClass(Object, 
-                                         Adjustment.DerivedToBase.DerivedClass, 
-                                         *Adjustment.DerivedToBase.BasePath, 
-                                         /*NullCheckValue=*/false);
+          Object = 
+              CGF.GetAddressOfBaseClass(Object, 
+                                        Adjustment.DerivedToBase.DerivedClass, 
+                                        *Adjustment.DerivedToBase.BasePath, 
+                                        /*NullCheckValue=*/false);
           break;
             
         case SubobjectAdjustment::FieldAdjustment: {
           unsigned CVR = Adjustment.Field.CVRQualifiers;
-          LValue LV = EmitLValueForField(Object, Adjustment.Field.Field, CVR);
+          LValue LV = 
+            CGF.EmitLValueForField(Object, Adjustment.Field.Field, CVR);
           if (LV.isSimple()) {
             Object = LV.getAddress();
             break;
@@ -315,33 +282,61 @@
           // the object we're binding to.
           QualType T = Adjustment.Field.Field->getType().getNonReferenceType()
                                                         .getUnqualifiedType();
-          Object = CreateTempAlloca(ConvertType(T), "lv");
-          EmitStoreThroughLValue(EmitLoadOfLValue(LV, T), 
-                                 LValue::MakeAddr(Object, 
-                                                  Qualifiers::fromCVRMask(CVR)),
-                                 T);
+          Object = CGF.CreateTempAlloca(CGF.ConvertType(T), "lv");
+          LValue TempLV = 
+            LValue::MakeAddr(Object, Qualifiers::fromCVRMask(CVR));
+          CGF.EmitStoreThroughLValue(CGF.EmitLoadOfLValue(LV, T), TempLV, T);
           break;
         }
+
         }
       }
       
-      const llvm::Type *ResultPtrTy = ConvertType(ResultTy)->getPointerTo();
-      Object = Builder.CreateBitCast(Object, ResultPtrTy, "temp");
-      return RValue::get(Object);
+      const llvm::Type *ResultPtrTy = CGF.ConvertType(ResultTy)->getPointerTo();
+      return CGF.Builder.CreateBitCast(Object, ResultPtrTy, "temp");
     }
   }
 
-  if (Val.isAggregate())
-    return RValue::get(Val.getAggregateAddr());
-  
+  if (RV.isAggregate())
+    return RV.getAggregateAddr();
+
   // Create a temporary variable that we can bind the reference to.
-  llvm::Value *Temp = CreateMemTemp(E->getType(), "reftmp");
-  if (Val.isScalar())
-    EmitStoreOfScalar(Val.getScalarVal(), Temp, false, E->getType());
+  ReferenceTemporary = CGF.CreateMemTemp(E->getType(), "ref.tmp");
+  if (RV.isScalar())
+    CGF.EmitStoreOfScalar(RV.getScalarVal(), ReferenceTemporary,
+                          /*Volatile=*/false, E->getType());
   else
-    StoreComplexToAddr(Val.getComplexVal(), Temp, false);
+    CGF.StoreComplexToAddr(RV.getComplexVal(), ReferenceTemporary,
+                           /*Volatile=*/false);
+  return ReferenceTemporary;
+}
+
+RValue
+CodeGenFunction::EmitReferenceBindingToExpr(const Expr* E,
+                                            const NamedDecl *InitializedDecl) {
+  llvm::Value *ReferenceTemporary = 0;
+  const CXXDestructorDecl *ReferenceTemporaryDtor = 0;
+  llvm::Value *Value = EmitExprForReferenceBinding(*this, E, ReferenceTemporary,
+                                                   ReferenceTemporaryDtor,
+                                                   InitializedDecl);
+
+  // Make sure to call the destructor for the reference temporary.
+  if (ReferenceTemporaryDtor) {
+    DelayedCleanupBlock Scope(*this);
+    EmitCXXDestructorCall(ReferenceTemporaryDtor, Dtor_Complete, 
+                          /*ForVirtualBase=*/false, ReferenceTemporary);
+            
+    // Make sure to jump to the exit block.
+    EmitBranch(Scope.getCleanupExitBlock());
+
+    if (Exceptions) {
+      EHCleanupBlock Cleanup(*this);
+      EmitCXXDestructorCall(ReferenceTemporaryDtor, Dtor_Complete, 
+                            /*ForVirtualBase=*/false, ReferenceTemporary);
+    }
+  }
 
-  return RValue::get(Temp);
+  return RValue::get(Value);
 }
 
 





More information about the cfe-commits mailing list