diff options
author | Douglas Gregor <dgregor@apple.com> | 2013-04-06 00:46:20 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2013-04-06 00:46:20 +0000 |
commit | 29a11f45849aa87959e780abb0014a1876e0b39e (patch) | |
tree | a532c95fe6233fe2914b1bd1e85a2ff2459cd4ad /lib/CodeGen | |
parent | 68eb4c25e961d18f82b47a0a385f90d7af09bcc3 (diff) |
<rdar://problem/13325066> Destroy std::initializer_list temporaries whose lifetime has been extended by reference binding.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@178939 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen')
-rw-r--r-- | lib/CodeGen/CGExpr.cpp | 24 |
1 files changed, 20 insertions, 4 deletions
diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index 2f5186d1f4..a0dd158533 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -201,6 +201,7 @@ static llvm::Value * EmitExprForReferenceBinding(CodeGenFunction &CGF, const Expr *E, llvm::Value *&ReferenceTemporary, const CXXDestructorDecl *&ReferenceTemporaryDtor, + const InitListExpr *&ReferenceInitializerList, QualType &ObjCARCReferenceLifetimeType, const NamedDecl *InitializedDecl) { const MaterializeTemporaryExpr *M = NULL; @@ -222,6 +223,7 @@ EmitExprForReferenceBinding(CodeGenFunction &CGF, const Expr *E, return EmitExprForReferenceBinding(CGF, EWC->getSubExpr(), ReferenceTemporary, ReferenceTemporaryDtor, + ReferenceInitializerList, ObjCARCReferenceLifetimeType, InitializedDecl); } @@ -314,9 +316,14 @@ EmitExprForReferenceBinding(CodeGenFunction &CGF, const Expr *E, } if (InitializedDecl) { - // Get the destructor for the reference temporary. - if (const RecordType *RT = - E->getType()->getBaseElementTypeUnsafe()->getAs<RecordType>()) { + if (const InitListExpr *ILE = dyn_cast<InitListExpr>(E)) { + if (ILE->initializesStdInitializerList()) { + ReferenceInitializerList = ILE; + } + } + else if (const RecordType *RT = + E->getType()->getBaseElementTypeUnsafe()->getAs<RecordType>()){ + // Get the destructor for the reference temporary. CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(RT->getDecl()); if (!ClassDecl->hasTrivialDestructor()) ReferenceTemporaryDtor = ClassDecl->getDestructor(); @@ -396,9 +403,11 @@ CodeGenFunction::EmitReferenceBindingToExpr(const Expr *E, const NamedDecl *InitializedDecl) { llvm::Value *ReferenceTemporary = 0; const CXXDestructorDecl *ReferenceTemporaryDtor = 0; + const InitListExpr *ReferenceInitializerList = 0; QualType ObjCARCReferenceLifetimeType; llvm::Value *Value = EmitExprForReferenceBinding(*this, E, ReferenceTemporary, ReferenceTemporaryDtor, + ReferenceInitializerList, ObjCARCReferenceLifetimeType, InitializedDecl); if (SanitizePerformTypeCheck && !E->getType()->isFunctionType()) { @@ -410,7 +419,8 @@ CodeGenFunction::EmitReferenceBindingToExpr(const Expr *E, QualType Ty = E->getType(); EmitTypeCheck(TCK_ReferenceBinding, E->getExprLoc(), Value, Ty); } - if (!ReferenceTemporaryDtor && ObjCARCReferenceLifetimeType.isNull()) + if (!ReferenceTemporaryDtor && !ReferenceInitializerList && + ObjCARCReferenceLifetimeType.isNull()) return RValue::get(Value); // Make sure to call the destructor for the reference temporary. @@ -430,6 +440,9 @@ CodeGenFunction::EmitReferenceBindingToExpr(const Expr *E, CleanupArg = cast<llvm::Constant>(ReferenceTemporary); } CGM.getCXXABI().registerGlobalDtor(*this, CleanupFn, CleanupArg); + } else if (ReferenceInitializerList) { + EmitStdInitializerListCleanup(ReferenceTemporary, + ReferenceInitializerList); } else { assert(!ObjCARCReferenceLifetimeType.isNull()); // Note: We intentionally do not register a global "destructor" to @@ -445,6 +458,9 @@ CodeGenFunction::EmitReferenceBindingToExpr(const Expr *E, destroyCXXObject, getLangOpts().Exceptions); else PushDestructorCleanup(ReferenceTemporaryDtor, ReferenceTemporary); + } else if (ReferenceInitializerList) { + EmitStdInitializerListCleanup(ReferenceTemporary, + ReferenceInitializerList); } else { switch (ObjCARCReferenceLifetimeType.getObjCLifetime()) { case Qualifiers::OCL_None: |