From 29a11f45849aa87959e780abb0014a1876e0b39e Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Sat, 6 Apr 2013 00:46:20 +0000 Subject: [PATCH] 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 --- lib/CodeGen/CGExpr.cpp | 24 +++++++++++++++---- .../cxx0x-initializer-stdinitializerlist.cpp | 19 +++++++++++++++ 2 files changed, 39 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()) { + if (const InitListExpr *ILE = dyn_cast(E)) { + if (ILE->initializesStdInitializerList()) { + ReferenceInitializerList = ILE; + } + } + else if (const RecordType *RT = + E->getType()->getBaseElementTypeUnsafe()->getAs()){ + // Get the destructor for the reference temporary. CXXRecordDecl *ClassDecl = cast(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(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: diff --git a/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp b/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp index 8d9fce040f..fc908804c0 100644 --- a/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp +++ b/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp @@ -250,3 +250,22 @@ namespace PR12178 { map m{ {1, 2}, {3, 4} }; } + +namespace rdar13325066 { + struct X { ~X(); }; + + // CHECK: define void @_ZN12rdar133250664loopERNS_1XES1_ + void loop(X &x1, X &x2) { + // CHECK: br label + // CHECK: br i1 + // CHECK: br label + // CHECK call void @_ZN12rdar133250661XD1Ev + // CHECK: br label + // CHECK: br label + // CHECK: call void @_ZN12rdar133250661XD1Ev + // CHECK: br i1 + // CHECK: br label + // CHECK: ret void + for (X x : { x1, x2 }) { } + } +} -- 2.49.0