[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