r178939 - <rdar://problem/13325066> Destroy std::initializer_list temporaries whose lifetime has been extended by reference binding.

Douglas Gregor dgregor at apple.com
Fri Apr 5 17:46:21 PDT 2013


Author: dgregor
Date: Fri Apr  5 19:46:20 2013
New Revision: 178939

URL: http://llvm.org/viewvc/llvm-project?rev=178939&view=rev
Log:
<rdar://problem/13325066> Destroy std::initializer_list temporaries whose lifetime has been extended by reference binding.

Modified:
    cfe/trunk/lib/CodeGen/CGExpr.cpp
    cfe/trunk/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp

Modified: cfe/trunk/lib/CodeGen/CGExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExpr.cpp?rev=178939&r1=178938&r2=178939&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExpr.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExpr.cpp Fri Apr  5 19:46:20 2013
@@ -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(CodeGenFunct
     return EmitExprForReferenceBinding(CGF, EWC->getSubExpr(), 
                                        ReferenceTemporary, 
                                        ReferenceTemporaryDtor,
+                                       ReferenceInitializerList,
                                        ObjCARCReferenceLifetimeType,
                                        InitializedDecl);
   }
@@ -314,9 +316,14 @@ EmitExprForReferenceBinding(CodeGenFunct
     }
     
     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::EmitReferenceBindingToE
                                             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::EmitReferenceBindingToE
     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::EmitReferenceBindingToE
         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::EmitReferenceBindingToE
                   destroyCXXObject, getLangOpts().Exceptions);
     else
       PushDestructorCleanup(ReferenceTemporaryDtor, ReferenceTemporary);
+  } else if (ReferenceInitializerList) {
+    EmitStdInitializerListCleanup(ReferenceTemporary,
+                                  ReferenceInitializerList);
   } else {
     switch (ObjCARCReferenceLifetimeType.getObjCLifetime()) {
     case Qualifiers::OCL_None:

Modified: cfe/trunk/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp?rev=178939&r1=178938&r2=178939&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp Fri Apr  5 19:46:20 2013
@@ -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 }) { }
+  }
+}





More information about the cfe-commits mailing list