[cfe-commits] r135036 - in /cfe/trunk: lib/CodeGen/CGClass.cpp lib/CodeGen/CGExprCXX.cpp test/CodeGenCXX/constructors.cpp

John McCall rjmccall at apple.com
Wed Jul 13 00:37:11 PDT 2011


Author: rjmccall
Date: Wed Jul 13 02:37:11 2011
New Revision: 135036

URL: http://llvm.org/viewvc/llvm-project?rev=135036&view=rev
Log:
Arrays are permitted to be zero-length in some situations.


Modified:
    cfe/trunk/lib/CodeGen/CGClass.cpp
    cfe/trunk/lib/CodeGen/CGExprCXX.cpp
    cfe/trunk/test/CodeGenCXX/constructors.cpp

Modified: cfe/trunk/lib/CodeGen/CGClass.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGClass.cpp?rev=135036&r1=135035&r2=135036&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGClass.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGClass.cpp Wed Jul 13 02:37:11 2011
@@ -1063,7 +1063,7 @@
 ///
 /// \param ctor the constructor to call for each element
 /// \param numElements the number of elements in the array;
-///   assumed to be non-zero
+///   may be zero
 /// \param argBegin,argEnd the arguments to evaluate and pass to the
 ///   constructor
 /// \param arrayBegin a T*, where T is the type constructed by ctor
@@ -1076,6 +1076,29 @@
                                          CallExpr::const_arg_iterator argBegin,
                                            CallExpr::const_arg_iterator argEnd,
                                             bool zeroInitialize) {
+
+  // It's legal for numElements to be zero.  This can happen both
+  // dynamically, because x can be zero in 'new A[x]', and statically,
+  // because of GCC extensions that permit zero-length arrays.  There
+  // are probably legitimate places where we could assume that this
+  // doesn't happen, but it's not clear that it's worth it.
+  llvm::BranchInst *zeroCheckBranch = 0;
+
+  // Optimize for a constant count.
+  llvm::ConstantInt *constantCount
+    = dyn_cast<llvm::ConstantInt>(numElements);
+  if (constantCount) {
+    // Just skip out if the constant count is zero.
+    if (constantCount->isZero()) return;
+
+  // Otherwise, emit the check.
+  } else {
+    llvm::BasicBlock *loopBB = createBasicBlock("new.ctorloop");
+    llvm::Value *iszero = Builder.CreateIsNull(numElements, "isempty");
+    zeroCheckBranch = Builder.CreateCondBr(iszero, loopBB, loopBB);
+    EmitBlock(loopBB);
+  }
+      
   // Find the end of the array.
   llvm::Value *arrayEnd = Builder.CreateInBoundsGEP(arrayBegin, numElements,
                                                     "arrayctor.end");
@@ -1130,6 +1153,9 @@
   llvm::BasicBlock *contBB = createBasicBlock("arrayctor.cont");
   Builder.CreateCondBr(done, contBB, loopBB);
 
+  // Patch the earlier check to skip over the loop.
+  if (zeroCheckBranch) zeroCheckBranch->setSuccessor(0, contBB);
+
   EmitBlock(contBB);
 }
 

Modified: cfe/trunk/lib/CodeGen/CGExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprCXX.cpp?rev=135036&r1=135035&r2=135036&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprCXX.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprCXX.cpp Wed Jul 13 02:37:11 2011
@@ -798,36 +798,10 @@
         RequiresZeroInitialization = true;
       }
 
-      // It's legal for NumElements to be zero, but
-      // EmitCXXAggrConstructorCall doesn't handle that, so we need to.
-      llvm::BranchInst *br = 0;
-
-      // Optimize for a constant count.
-      llvm::ConstantInt *constantCount
-        = dyn_cast<llvm::ConstantInt>(NumElements);
-      if (constantCount) {
-        // Just skip out if the constant count is zero.
-        if (constantCount->isZero()) return;
-
-      // Otherwise, emit the check.
-      } else {
-        llvm::BasicBlock *loopBB = CGF.createBasicBlock("new.ctorloop");
-        llvm::Value *iszero = CGF.Builder.CreateIsNull(NumElements, "isempty");
-        br = CGF.Builder.CreateCondBr(iszero, loopBB, loopBB);
-        CGF.EmitBlock(loopBB);
-      }
-      
       CGF.EmitCXXAggrConstructorCall(Ctor, NumElements, NewPtr, 
                                      E->constructor_arg_begin(), 
                                      E->constructor_arg_end(),
                                      RequiresZeroInitialization);
-
-      // Patch the earlier check to skip over the loop.
-      if (br) {
-        assert(CGF.Builder.GetInsertBlock()->empty());
-        br->setSuccessor(0, CGF.Builder.GetInsertBlock());
-      }
-
       return;
     } else if (E->getNumConstructorArgs() == 1 &&
                isa<ImplicitValueInitExpr>(E->getConstructorArg(0))) {

Modified: cfe/trunk/test/CodeGenCXX/constructors.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/constructors.cpp?rev=135036&r1=135035&r2=135036&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/constructors.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/constructors.cpp Wed Jul 13 02:37:11 2011
@@ -104,3 +104,14 @@
     C tmp = in;
   }
 }
+
+namespace test1 {
+  struct A { A(); void *ptr; };
+  struct B { B(); int x; A a[0]; };
+  B::B() {}
+  // CHECK:    define void @_ZN5test11BC2Ev(
+  // CHECK:      [[THIS:%.*]] = load [[B:%.*]]**
+  // CHECK-NEXT: [[A:%.*]] = getelementptr inbounds [[B:%.*]]* [[THIS]], i32 0, i32 1
+  // CHECK-NEXT: [[BEGIN:%.*]] = getelementptr inbounds [0 x {{%.*}}]* [[A]], i32 0, i32 0
+  // CHECK-NEXT: ret void
+}





More information about the cfe-commits mailing list