diff options
author | Douglas Gregor <dgregor@apple.com> | 2011-06-22 16:12:01 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2011-06-22 16:12:01 +0000 |
commit | d7b23167763f43d3e76b0de26141b1e52613ee3c (patch) | |
tree | 71644c427688cfee6c871d4b65502cb81fbe0964 /lib/CodeGen/CGExpr.cpp | |
parent | b4b7b5034bb8304ed03416635bf64c75c39889fc (diff) |
When binding a reference to an Automatic Reference Counting temporary,
retain/release the temporary object appropriately. Previously, we
would only perform the retain/release operations when the reference
would extend the lifetime of the temporary, but this does the wrong
thing across calls.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@133620 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/CGExpr.cpp')
-rw-r--r-- | lib/CodeGen/CGExpr.cpp | 97 |
1 files changed, 65 insertions, 32 deletions
diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index 2c00b9bf06..af0af7fbef 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -205,11 +205,21 @@ EmitExprForReferenceBinding(CodeGenFunction &CGF, const Expr *E, const CXXDestructorDecl *&ReferenceTemporaryDtor, QualType &ObjCARCReferenceLifetimeType, const NamedDecl *InitializedDecl) { - ObjCARCReferenceLifetimeType = QualType(); - // Look through expressions for materialized temporaries (for now). - if (isa<MaterializeTemporaryExpr>(E)) - E = cast<MaterializeTemporaryExpr>(E)->GetTemporaryExpr(); + if (const MaterializeTemporaryExpr *M + = dyn_cast<MaterializeTemporaryExpr>(E)) { + // Objective-C++ ARC: + // If we are binding a reference to a temporary that has ownership, we + // need to perform retain/release operations on the temporary. + if (CGF.getContext().getLangOptions().ObjCAutoRefCount && + E->getType()->isObjCLifetimeType() && + (E->getType().getObjCLifetime() == Qualifiers::OCL_Strong || + E->getType().getObjCLifetime() == Qualifiers::OCL_Weak || + E->getType().getObjCLifetime() == Qualifiers::OCL_Autoreleasing)) + ObjCARCReferenceLifetimeType = E->getType(); + + E = M->GetTemporaryExpr(); + } if (const CXXDefaultArgExpr *DAE = dyn_cast<CXXDefaultArgExpr>(E)) E = DAE->getExpr(); @@ -243,6 +253,57 @@ EmitExprForReferenceBinding(CodeGenFunction &CGF, const Expr *E, // We have to load the lvalue. RV = CGF.EmitLoadOfLValue(LV, E->getType()); } else { + if (!ObjCARCReferenceLifetimeType.isNull()) { + ReferenceTemporary = CreateReferenceTemporary(CGF, + ObjCARCReferenceLifetimeType, + InitializedDecl); + + + LValue RefTempDst = CGF.MakeAddrLValue(ReferenceTemporary, + ObjCARCReferenceLifetimeType); + + CGF.EmitScalarInit(E, dyn_cast_or_null<ValueDecl>(InitializedDecl), + RefTempDst, false); + + bool ExtendsLifeOfTemporary = false; + if (const VarDecl *Var = dyn_cast_or_null<VarDecl>(InitializedDecl)) { + if (Var->extendsLifetimeOfTemporary()) + ExtendsLifeOfTemporary = true; + } else if (InitializedDecl && isa<FieldDecl>(InitializedDecl)) { + ExtendsLifeOfTemporary = true; + } + + if (!ExtendsLifeOfTemporary) { + // Since the lifetime of this temporary isn't going to be extended, + // we need to clean it up ourselves at the end of the full expression. + switch (ObjCARCReferenceLifetimeType.getObjCLifetime()) { + case Qualifiers::OCL_None: + case Qualifiers::OCL_ExplicitNone: + case Qualifiers::OCL_Autoreleasing: + break; + + case Qualifiers::OCL_Strong: + CGF.PushARCReleaseCleanup(CGF.getARCCleanupKind(), + ObjCARCReferenceLifetimeType, + ReferenceTemporary, + /*Precise lifetime=*/false, + /*For full expression=*/true); + break; + + case Qualifiers::OCL_Weak: + CGF.PushARCWeakReleaseCleanup(NormalAndEHCleanup, + ObjCARCReferenceLifetimeType, + ReferenceTemporary, + /*For full expression=*/true); + break; + } + + ObjCARCReferenceLifetimeType = QualType(); + } + + return ReferenceTemporary; + } + llvm::SmallVector<SubobjectAdjustment, 2> Adjustments; while (true) { E = E->IgnoreParens(); @@ -298,34 +359,6 @@ EmitExprForReferenceBinding(CodeGenFunction &CGF, const Expr *E, if (!ClassDecl->hasTrivialDestructor()) ReferenceTemporaryDtor = ClassDecl->getDestructor(); } - else if (CGF.getContext().getLangOptions().ObjCAutoRefCount) { - if (const ValueDecl *InitVD = dyn_cast<ValueDecl>(InitializedDecl)) { - if (const ReferenceType *RefType - = InitVD->getType()->getAs<ReferenceType>()) { - QualType PointeeType = RefType->getPointeeType(); - if (PointeeType->isObjCLifetimeType() && - PointeeType.getObjCLifetime() != Qualifiers::OCL_ExplicitNone) { - // Objective-C++ ARC: We're binding a reference to - // lifetime-qualified type to a temporary, so we need to extend - // the lifetime of the temporary with appropriate retain/release/ - // autorelease calls. - ObjCARCReferenceLifetimeType = PointeeType; - - // Create a temporary variable that we can bind the reference to. - ReferenceTemporary = CreateReferenceTemporary(CGF, PointeeType, - InitializedDecl); - - unsigned Alignment = - CGF.getContext().getTypeAlignInChars(PointeeType).getQuantity(); - LValue lvalue = - CGF.MakeAddrLValue(ReferenceTemporary, PointeeType, Alignment); - - CGF.EmitScalarInit(E, InitVD, lvalue, false); - return ReferenceTemporary; - } - } - } - } } RV = CGF.EmitAnyExpr(E, AggSlot); |