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

Anders Carlsson andersca at mac.com
Sun Jun 27 10:52:16 PDT 2010


Author: andersca
Date: Sun Jun 27 12:52:15 2010
New Revision: 106983

URL: http://llvm.org/viewvc/llvm-project?rev=106983&view=rev
Log:
Correctly destroy reference temporaries with global storage. Remove ErrorUnsupported call when binding a global reference to a non-lvalue. Fixes PR7326.

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

Modified: cfe/trunk/lib/CodeGen/CGDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDeclCXX.cpp?rev=106983&r1=106982&r2=106983&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGDeclCXX.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGDeclCXX.cpp Sun Jun 27 12:52:15 2010
@@ -93,13 +93,9 @@
     EmitDeclDestroy(*this, D, DeclPtr);
     return;
   }
-  if (Init->isLvalue(getContext()) == Expr::LV_Valid) {
-    RValue RV = EmitReferenceBindingToExpr(Init, &D);
-    EmitStoreOfScalar(RV.getScalarVal(), DeclPtr, false, T);
-    return;
-  }
-  ErrorUnsupported(Init, 
-                   "global variable that binds reference to a non-lvalue");
+
+  RValue RV = EmitReferenceBindingToExpr(Init, &D);
+  EmitStoreOfScalar(RV.getScalarVal(), DeclPtr, false, T);
 }
 
 void
@@ -373,11 +369,7 @@
 
   if (D.getType()->isReferenceType()) {
     QualType T = D.getType();
-    // We don't want to pass true for IsInitializer here, because a static
-    // reference to a temporary does not extend its lifetime.
-    // FIXME: This is incorrect.
-    RValue RV = EmitReferenceBindingToExpr(D.getInit(),
-                                           /*InitializedDecl=*/0);
+    RValue RV = EmitReferenceBindingToExpr(D.getInit(), &D);
     EmitStoreOfScalar(RV.getScalarVal(), GV, /*Volatile=*/false, T);
 
   } else

Modified: cfe/trunk/lib/CodeGen/CGExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExpr.cpp?rev=106983&r1=106982&r2=106983&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExpr.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExpr.cpp Sun Jun 27 12:52:15 2010
@@ -308,9 +308,9 @@
           // the object we're binding to.
           QualType T = Adjustment.Field.Field->getType().getNonReferenceType()
                                                         .getUnqualifiedType();
-          Object = CGF.CreateTempAlloca(CGF.ConvertType(T), "lv");
-          LValue TempLV = 
-            LValue::MakeAddr(Object, Qualifiers::fromCVRMask(CVR));
+          Object = CreateReferenceTemporary(CGF, T, InitializedDecl);
+          LValue TempLV = LValue::MakeAddr(Object, 
+                                           Qualifiers::fromCVRMask(CVR));
           CGF.EmitStoreThroughLValue(CGF.EmitLoadOfLValue(LV, T), TempLV, T);
           break;
         }
@@ -348,20 +348,34 @@
                                                    ReferenceTemporaryDtor,
                                                    InitializedDecl);
 
+  if (!ReferenceTemporaryDtor)
+    return RValue::get(Value);
+  
   // Make sure to call the destructor for the reference temporary.
-  if (ReferenceTemporaryDtor) {
+  if (const VarDecl *VD = dyn_cast_or_null<VarDecl>(InitializedDecl)) {
+    if (VD->hasGlobalStorage()) {
+      llvm::Constant *DtorFn = 
+        CGM.GetAddrOfCXXDestructor(ReferenceTemporaryDtor, Dtor_Complete);
+      CGF.EmitCXXGlobalDtorRegistration(DtorFn, 
+                                      cast<llvm::Constant>(ReferenceTemporary));
+      
+      return RValue::get(Value);
+    }
+  }
+  
+  {
     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);
-    }
+  if (Exceptions) {
+    EHCleanupBlock Cleanup(*this);
+    EmitCXXDestructorCall(ReferenceTemporaryDtor, Dtor_Complete, 
+                          /*ForVirtualBase=*/false, ReferenceTemporary);
   }
 
   return RValue::get(Value);

Modified: cfe/trunk/test/CodeGenCXX/references.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/references.cpp?rev=106983&r1=106982&r2=106983&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/references.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/references.cpp Sun Jun 27 12:52:15 2010
@@ -160,7 +160,7 @@
 namespace N1 {
   const int foo = 1;
   // CHECK: @_ZN2N14test
-  int test(const int& arg = foo) {
+  void test(const int& arg = foo) {
     // Ensure this array is on the stack where we can set values instead of
     // being a global constant.
     // CHECK: %args_array = alloca
@@ -224,3 +224,37 @@
     i = 19;    
   }
 }
+
+namespace N3 {
+
+// PR7326
+
+struct A {
+  explicit A(int);
+  ~A();
+};
+
+// CHECK: define internal void @__cxx_global_var_init
+// CHECK: call void @_ZN2N31AC1Ei(%"class.N2::X"* @_ZGRN2N35sA123E, i32 123)
+// CHECK: call i32 @__cxa_atexit
+// CHECK: ret void
+const A &sA123 = A(123);
+}
+
+namespace N4 {
+  
+struct A {
+  A();
+  ~A();
+};
+
+void f() {
+  // CHECK: define void @_ZN2N41fEv
+  // CHECK: call void @_ZN2N41AC1Ev(%"class.N2::X"* @_ZGRZN2N41fEvE2ar)
+  // CHECK: call i32 @__cxa_atexit
+  // CHECK: ret void
+  static const A& ar = A();
+  
+}
+}
+





More information about the cfe-commits mailing list