diff options
-rw-r--r-- | lib/CodeGen/CGExpr.cpp | 24 | ||||
-rw-r--r-- | test/CodeGenCXX/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<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: 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 }) { } + } +} |