summaryrefslogtreecommitdiffstats
path: root/clang/lib/CodeGen/CGExpr.cpp
diff options
context:
space:
mode:
authorAnders Carlsson <andersca@mac.com>2010-06-27 17:52:15 +0000
committerAnders Carlsson <andersca@mac.com>2010-06-27 17:52:15 +0000
commit3f48c603fbc3105f11350c397faf5fbf9d2b285d (patch)
tree5d54059a5e23a4b198b6b4f748ca4213944eb590 /clang/lib/CodeGen/CGExpr.cpp
parent18c205ecdfc790a9ad516bf764a9182f5ac9c9fa (diff)
downloadbcm5719-llvm-3f48c603fbc3105f11350c397faf5fbf9d2b285d.tar.gz
bcm5719-llvm-3f48c603fbc3105f11350c397faf5fbf9d2b285d.zip
Correctly destroy reference temporaries with global storage. Remove ErrorUnsupported call when binding a global reference to a non-lvalue. Fixes PR7326.
llvm-svn: 106983
Diffstat (limited to 'clang/lib/CodeGen/CGExpr.cpp')
-rw-r--r--clang/lib/CodeGen/CGExpr.cpp32
1 files changed, 23 insertions, 9 deletions
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index 0d5369d0d3c..2bda5adb42b 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -308,9 +308,9 @@ EmitExprForReferenceBinding(CodeGenFunction& CGF, const Expr* E,
// 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 @@ CodeGenFunction::EmitReferenceBindingToExpr(const Expr* E,
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);
OpenPOWER on IntegriCloud