[cfe-commits] r84451 - in /cfe/trunk: lib/CodeGen/CGExpr.cpp test/CodeGenCXX/references.cpp

Anders Carlsson andersca at mac.com
Sun Oct 18 16:09:22 PDT 2009


Author: andersca
Date: Sun Oct 18 18:09:21 2009
New Revision: 84451

URL: http://llvm.org/viewvc/llvm-project?rev=84451&view=rev
Log:
When binding a reference to a temporary, it's important that other temporaries created as on the RHS are destroyed before emitting the dtor for the temporary.

Modified:
    cfe/trunk/lib/CodeGen/CGExpr.cpp
    cfe/trunk/test/CodeGenCXX/references.cpp

Modified: cfe/trunk/lib/CodeGen/CGExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExpr.cpp?rev=84451&r1=84450&r2=84451&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGExpr.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExpr.cpp Sun Oct 18 18:09:21 2009
@@ -78,24 +78,18 @@
 RValue CodeGenFunction::EmitReferenceBindingToExpr(const Expr* E,
                                                    QualType DestType,
                                                    bool IsInitializer) {
+  bool ShouldDestroyTemporaries = false;
+  unsigned OldNumLiveTemporaries = 0;
+  
   if (const CXXExprWithTemporaries *TE = dyn_cast<CXXExprWithTemporaries>(E)) {
-    // If we shouldn't destroy the temporaries, just emit the
-    // child expression.
-    if (!TE->shouldDestroyTemporaries())
-      return EmitReferenceBindingToExpr(TE->getSubExpr(), DestType,
-                                        IsInitializer);
-    
-    // Keep track of the current cleanup stack depth.
-    unsigned OldNumLiveTemporaries = LiveTemporaries.size();
-    
-    RValue RV = EmitReferenceBindingToExpr(TE->getSubExpr(), DestType,
-                                           IsInitializer);
-    
-    // Pop temporaries.
-    while (LiveTemporaries.size() > OldNumLiveTemporaries)
-      PopCXXTemporary();
+    ShouldDestroyTemporaries = TE->shouldDestroyTemporaries();
+
+    if (ShouldDestroyTemporaries) {
+      // Keep track of the current cleanup stack depth.
+      OldNumLiveTemporaries = LiveTemporaries.size();
+    }
     
-    return RV;
+    E = TE->getSubExpr();
   }
   
   RValue Val;
@@ -105,6 +99,12 @@
     if (LV.isSimple())
       return RValue::get(LV.getAddress());
     Val = EmitLoadOfLValue(LV, E->getType());
+    
+    if (ShouldDestroyTemporaries) {
+      // Pop temporaries.
+      while (LiveTemporaries.size() > OldNumLiveTemporaries)
+        PopCXXTemporary();
+    }      
   } else {
     const CXXRecordDecl *BaseClassDecl = 0;
     const CXXRecordDecl *DerivedClassDecl = 0;
@@ -124,6 +124,12 @@
     Val = EmitAnyExprToTemp(E, /*IsAggLocVolatile=*/false,
                             IsInitializer);
 
+    if (ShouldDestroyTemporaries) {
+      // Pop temporaries.
+      while (LiveTemporaries.size() > OldNumLiveTemporaries)
+        PopCXXTemporary();
+    }      
+    
     if (IsInitializer) {
       // We might have to destroy the temporary variable.
       if (const RecordType *RT = E->getType()->getAs<RecordType>()) {

Modified: cfe/trunk/test/CodeGenCXX/references.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/references.cpp?rev=84451&r1=84450&r2=84451&view=diff

==============================================================================
--- cfe/trunk/test/CodeGenCXX/references.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/references.cpp Sun Oct 18 18:09:21 2009
@@ -107,3 +107,26 @@
   const C& c = D();
 }
 
+namespace T {
+  struct A {
+    A();
+    ~A();
+  };
+
+  struct B {
+    B();
+    ~B();
+    A f();
+  };
+
+  void f() {
+    // CHECK: call void @_ZN1T1BC1Ev
+    // CHECK: call void @_ZN1T1B1fEv
+    // CHECK: call void @_ZN1T1BD1Ev
+    const A& a = B().f();
+    // CHECK: call void @_ZN1T1fEv
+    f();
+    // CHECK: call void @_ZN1T1AD1Ev
+  }
+}
+





More information about the cfe-commits mailing list