]> granicus.if.org Git - clang/commitdiff
When value-initializing the elements of an array not not included in the initializer...
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>
Thu, 28 Apr 2011 18:53:58 +0000 (18:53 +0000)
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>
Thu, 28 Apr 2011 18:53:58 +0000 (18:53 +0000)
that a non-trivial C++ constructor gets called.

Fixes rdar://9347552 & http://llvm.org/PR9801

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@130421 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGExprAgg.cpp
test/CodeGenCXX/value-init.cpp

index 53bc58b69c8d00e7595ae553f29778b7ddea24e8..457e44d086d56512fd1f079c267d8abb8e6ca81a 100644 (file)
@@ -622,6 +622,13 @@ void AggExprEmitter::VisitInitListExpr(InitListExpr *E) {
     QualType ElementType = CGF.getContext().getCanonicalType(E->getType());
     ElementType = CGF.getContext().getAsArrayType(ElementType)->getElementType();
 
+    bool hasNonTrivialCXXConstructor = false;
+    if (CGF.getContext().getLangOptions().CPlusPlus)
+      if (const RecordType *RT = ElementType->getAs<RecordType>()) {
+        const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
+        hasNonTrivialCXXConstructor = !RD->hasTrivialConstructor();
+      }
+
     // FIXME: were we intentionally ignoring address spaces and GC attributes?
 
     for (uint64_t i = 0; i != NumArrayElements; ++i) {
@@ -629,7 +636,8 @@ void AggExprEmitter::VisitInitListExpr(InitListExpr *E) {
       // then we're done.
       if (i == NumInitElements &&
           Dest.isZeroed() &&
-          CGF.getTypes().isZeroInitializable(ElementType))
+          CGF.getTypes().isZeroInitializable(ElementType) &&
+          !hasNonTrivialCXXConstructor)
         break;
 
       llvm::Value *NextVal = Builder.CreateStructGEP(DestPtr, i, ".array");
index 188c8f5a14183848bc2cda379df300d38b47ff96..890b144de3322f497edf3ae11a4d0d57ad19f572 100644 (file)
@@ -83,6 +83,47 @@ namespace ptrmem {
   }
 }
 
+namespace PR9801 {
+
+struct Test {
+  Test() : i(10) {}
+  Test(int i) : i(i) {}
+  int i;
+private:
+  int j;
+};
+
+struct Test2 {
+  Test t;
+};
+
+struct Test3 : public Test { };
+
+// CHECK: define void @_ZN6PR98011fEv
+void f() {
+  // CHECK: call void @_ZN6PR98014TestC1Ei
+  // CHECK: call void @_ZN6PR98014TestC1Ev
+  // CHECK: call void @_ZN6PR98014TestC1Ev
+  Test partial[3] = { 1 };
+
+  // CHECK: call void @_ZN6PR98014TestC1Ev
+  // CHECK: call void @_ZN6PR98014TestC1Ev
+  // CHECK: call void @_ZN6PR98014TestC1Ev
+  Test empty[3] = {};
+
+  // CHECK: call void @_ZN6PR98015Test2C1Ev
+  // CHECK: call void @_ZN6PR98015Test2C1Ev
+  // CHECK: call void @_ZN6PR98015Test2C1Ev
+  Test2 empty2[3] = {};
+
+  // CHECK: call void @_ZN6PR98015Test3C1Ev
+  // CHECK: call void @_ZN6PR98015Test3C1Ev
+  // CHECK: call void @_ZN6PR98015Test3C1Ev
+  Test3 empty3[3] = {};
+}
+
+}
+
 namespace zeroinit {
   struct S { int i; };