[cfe-commits] r89783 - in /cfe/trunk: lib/CodeGen/CGCXX.cpp lib/CodeGen/CGExprCXX.cpp lib/CodeGen/CodeGenFunction.h test/CodeGenCXX/default-arguments.cpp

Anders Carlsson andersca at mac.com
Tue Nov 24 10:43:52 PST 2009


Author: andersca
Date: Tue Nov 24 12:43:52 2009
New Revision: 89783

URL: http://llvm.org/viewvc/llvm-project?rev=89783&view=rev
Log:
Handle cases where we're constructing an array of objects and the constructor has default arguments.

Modified:
    cfe/trunk/lib/CodeGen/CGCXX.cpp
    cfe/trunk/lib/CodeGen/CGExprCXX.cpp
    cfe/trunk/lib/CodeGen/CodeGenFunction.h
    cfe/trunk/test/CodeGenCXX/default-arguments.cpp

Modified: cfe/trunk/lib/CodeGen/CGCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCXX.cpp?rev=89783&r1=89782&r2=89783&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGCXX.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGCXX.cpp Tue Nov 24 12:43:52 2009
@@ -463,20 +463,25 @@
 /// It is assumed that all relevant checks have been made by the caller.
 void
 CodeGenFunction::EmitCXXAggrConstructorCall(const CXXConstructorDecl *D,
-                                            const ConstantArrayType *ArrayTy,
-                                            llvm::Value *ArrayPtr) {
+                                          const ConstantArrayType *ArrayTy,
+                                          llvm::Value *ArrayPtr,
+                                          CallExpr::const_arg_iterator ArgBeg,
+                                          CallExpr::const_arg_iterator ArgEnd) {
+
   const llvm::Type *SizeTy = ConvertType(getContext().getSizeType());
   llvm::Value * NumElements =
     llvm::ConstantInt::get(SizeTy, 
                            getContext().getConstantArrayElementCount(ArrayTy));
 
-  EmitCXXAggrConstructorCall(D, NumElements, ArrayPtr);
+  EmitCXXAggrConstructorCall(D, NumElements, ArrayPtr, ArgBeg, ArgEnd);
 }
 
 void
 CodeGenFunction::EmitCXXAggrConstructorCall(const CXXConstructorDecl *D,
-                                            llvm::Value *NumElements,
-                                            llvm::Value *ArrayPtr) {
+                                          llvm::Value *NumElements,
+                                          llvm::Value *ArrayPtr,
+                                          CallExpr::const_arg_iterator ArgBeg,
+                                          CallExpr::const_arg_iterator ArgEnd) {
   const llvm::Type *SizeTy = ConvertType(getContext().getSizeType());
 
   // Create a temporary for the loop index and initialize it with 0.
@@ -506,8 +511,24 @@
   Counter = Builder.CreateLoad(IndexPtr);
   llvm::Value *Address = Builder.CreateInBoundsGEP(ArrayPtr, Counter, 
                                                    "arrayidx");
-  EmitCXXConstructorCall(D, Ctor_Complete, Address, 0, 0);
 
+  // C++ [class.temporary]p4: 
+  // There are two contexts in which temporaries are destroyed at a different
+  // point than the end of the full- expression. The first context is when a
+  // default constructor is called to initialize an element of an array. 
+  // If the constructor has one or more default arguments, the destruction of 
+  // every temporary created in a default argument expression is sequenced 
+  // before the construction of the next array element, if any.
+  
+  // Keep track of the current number of live temporaries.
+  unsigned OldNumLiveTemporaries = LiveTemporaries.size();
+
+  EmitCXXConstructorCall(D, Ctor_Complete, Address, ArgBeg, ArgEnd);
+
+  // Pop temporaries.
+  while (LiveTemporaries.size() > OldNumLiveTemporaries)
+    PopCXXTemporary();
+  
   EmitBlock(ContinueBlock);
 
   // Emit the increment of the loop counter.
@@ -714,7 +735,8 @@
     BasePtr = llvm::PointerType::getUnqual(BasePtr);
     llvm::Value *BaseAddrPtr =
       Builder.CreateBitCast(Dest, BasePtr);
-    EmitCXXAggrConstructorCall(CD, Array, BaseAddrPtr);
+    EmitCXXAggrConstructorCall(CD, Array, BaseAddrPtr, 
+                               E->arg_begin(), E->arg_end());
   }
   else
     // Call the constructor.
@@ -1559,7 +1581,9 @@
       llvm::Value *BaseAddrPtr =
         CGF.Builder.CreateBitCast(LHS.getAddress(), BasePtr);
       CGF.EmitCXXAggrConstructorCall(MemberInit->getConstructor(),
-                                     Array, BaseAddrPtr);
+                                     Array, BaseAddrPtr,
+                                     MemberInit->const_arg_begin(),
+                                     MemberInit->const_arg_end());
     }
     else
       CGF.EmitCXXConstructorCall(MemberInit->getConstructor(),

Modified: cfe/trunk/lib/CodeGen/CGExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprCXX.cpp?rev=89783&r1=89782&r2=89783&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprCXX.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprCXX.cpp Tue Nov 24 12:43:52 2009
@@ -83,39 +83,41 @@
 static void EmitNewInitializer(CodeGenFunction &CGF, const CXXNewExpr *E,
                                llvm::Value *NewPtr,
                                llvm::Value *NumElements) {
+  if (E->isArray()) {
+    if (CXXConstructorDecl *Ctor = E->getConstructor())
+      CGF.EmitCXXAggrConstructorCall(Ctor, NumElements, NewPtr, 
+                                     E->constructor_arg_begin(), 
+                                     E->constructor_arg_end());
+    return;
+  }
+  
   QualType AllocType = E->getAllocatedType();
 
-  if (!E->isArray()) {
-    if (CXXConstructorDecl *Ctor = E->getConstructor()) {
-      CGF.EmitCXXConstructorCall(Ctor, Ctor_Complete, NewPtr,
-                                 E->constructor_arg_begin(),
-                                 E->constructor_arg_end());
+  if (CXXConstructorDecl *Ctor = E->getConstructor()) {
+    CGF.EmitCXXConstructorCall(Ctor, Ctor_Complete, NewPtr,
+                               E->constructor_arg_begin(),
+                               E->constructor_arg_end());
 
-      return;
-    }
+    return;
+  }
     
-    // We have a POD type.
-    if (E->getNumConstructorArgs() == 0)
-      return;
+  // We have a POD type.
+  if (E->getNumConstructorArgs() == 0)
+    return;
 
-    assert(E->getNumConstructorArgs() == 1 &&
-           "Can only have one argument to initializer of POD type.");
+  assert(E->getNumConstructorArgs() == 1 &&
+         "Can only have one argument to initializer of POD type.");
       
-    const Expr *Init = E->getConstructorArg(0);
+  const Expr *Init = E->getConstructorArg(0);
     
-    if (!CGF.hasAggregateLLVMType(AllocType)) 
-      CGF.EmitStoreOfScalar(CGF.EmitScalarExpr(Init), NewPtr,
-                        AllocType.isVolatileQualified(), AllocType);
-    else if (AllocType->isAnyComplexType())
-      CGF.EmitComplexExprIntoAddr(Init, NewPtr, 
-                                  AllocType.isVolatileQualified());
-    else
-      CGF.EmitAggExpr(Init, NewPtr, AllocType.isVolatileQualified());
-    return;
-  }
-  
-  if (CXXConstructorDecl *Ctor = E->getConstructor())
-    CGF.EmitCXXAggrConstructorCall(Ctor, NumElements, NewPtr);
+  if (!CGF.hasAggregateLLVMType(AllocType)) 
+    CGF.EmitStoreOfScalar(CGF.EmitScalarExpr(Init), NewPtr,
+                          AllocType.isVolatileQualified(), AllocType);
+  else if (AllocType->isAnyComplexType())
+    CGF.EmitComplexExprIntoAddr(Init, NewPtr, 
+                                AllocType.isVolatileQualified());
+  else
+    CGF.EmitAggExpr(Init, NewPtr, AllocType.isVolatileQualified());
 }
 
 llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) {

Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=89783&r1=89782&r2=89783&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Tue Nov 24 12:43:52 2009
@@ -671,10 +671,15 @@
 
   void EmitCXXAggrConstructorCall(const CXXConstructorDecl *D,
                                   const ConstantArrayType *ArrayTy,
-                                  llvm::Value *ArrayPtr);
+                                  llvm::Value *ArrayPtr,
+                                  CallExpr::const_arg_iterator ArgBeg,
+                                  CallExpr::const_arg_iterator ArgEnd);
+  
   void EmitCXXAggrConstructorCall(const CXXConstructorDecl *D,
                                   llvm::Value *NumElements,
-                                  llvm::Value *ArrayPtr);
+                                  llvm::Value *ArrayPtr,
+                                  CallExpr::const_arg_iterator ArgBeg,
+                                  CallExpr::const_arg_iterator ArgEnd);
 
   void EmitCXXAggrDestructorCall(const CXXDestructorDecl *D,
                                  const ArrayType *Array,

Modified: cfe/trunk/test/CodeGenCXX/default-arguments.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/default-arguments.cpp?rev=89783&r1=89782&r2=89783&view=diff

==============================================================================
--- cfe/trunk/test/CodeGenCXX/default-arguments.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/default-arguments.cpp Tue Nov 24 12:43:52 2009
@@ -1,4 +1,4 @@
-// RUN: clang-cc -emit-llvm %s -o - -triple=x86_64-apple-darwin10
+// RUN: clang-cc %s -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s
 
 // PR5484
 namespace PR5484 {
@@ -11,3 +11,59 @@
   f();
 }
 }
+
+struct A1 {
+ A1();
+ ~A1();
+};
+
+struct A2 {
+ A2();
+ ~A2();
+};
+
+struct B {
+ B(const A1& = A1(), const A2& = A2());
+};
+
+// CHECK: define void @_Z2f1v()
+void f1() {
+
+ // CHECK: call void @_ZN2A1C1Ev(
+ // CHECK: call void @_ZN2A2C1Ev(
+ // CHECK: call void @_ZN1BC1ERK2A1RK2A2(
+ // CHECK: call void @_ZN2A2D1Ev
+ // CHECK: call void @_ZN2A1D1Ev
+ B bs[2];
+}
+
+struct C {
+ B bs[2];
+ C();
+};
+
+// CHECK: define void @_ZN1CC1Ev(
+// CHECK: call void @_ZN2A1C1Ev(
+// CHECK: call void @_ZN2A2C1Ev(
+// CHECK: call void @_ZN1BC1ERK2A1RK2A2(
+// CHECK: call void @_ZN2A2D1Ev
+// CHECK: call void @_ZN2A1D1Ev
+
+// CHECK: define void @_ZN1CC2Ev(
+// CHECK: call void @_ZN2A1C1Ev(
+// CHECK: call void @_ZN2A2C1Ev(
+// CHECK: call void @_ZN1BC1ERK2A1RK2A2(
+// CHECK: call void @_ZN2A2D1Ev
+// CHECK: call void @_ZN2A1D1Ev
+C::C() { }
+
+// CHECK: define void @_Z2f3v()
+void f3() {
+ // CHECK: call void @_ZN2A1C1Ev(
+ // CHECK: call void @_ZN2A2C1Ev(
+ // CHECK: call void @_ZN1BC1ERK2A1RK2A2(
+ // CHECK: call void @_ZN2A2D1Ev
+ // CHECK: call void @_ZN2A1D1Ev
+ B *bs = new B[2];
+ delete bs;
+}





More information about the cfe-commits mailing list