summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
Diffstat (limited to 'clang')
-rw-r--r--clang/lib/CodeGen/CGExprCXX.cpp26
-rw-r--r--clang/test/CodeGenCXX/cxx11-initializer-array-new.cpp5
2 files changed, 26 insertions, 5 deletions
diff --git a/clang/lib/CodeGen/CGExprCXX.cpp b/clang/lib/CodeGen/CGExprCXX.cpp
index 7d5dc4c42c4..2dba75e4d48 100644
--- a/clang/lib/CodeGen/CGExprCXX.cpp
+++ b/clang/lib/CodeGen/CGExprCXX.cpp
@@ -864,9 +864,29 @@ CodeGenFunction::EmitNewArrayInitializer(const CXXNewExpr *E,
cleanupDominator->eraseFromParent();
}
- // Advance to the next element.
- llvm::Value *nextPtr = Builder.CreateConstGEP1_32(curPtr, 1, "array.next");
-
+ // FIXME: The code below intends to initialize the individual array base
+ // elements, one at a time - but when dealing with multi-dimensional arrays -
+ // the pointer arithmetic can get confused - so the fix below entails casting
+ // to the allocated type to ensure that we get the pointer arithmetic right.
+ // It seems like the right approach here, it to really initialize the
+ // individual array base elements one at a time since it'll generate less
+ // code. I think the problem is that the wrong type is being passed into
+ // StoreAnyExprIntoOneUnit, but directly fixing that doesn't really work,
+ // because the Init expression has the wrong type at this point.
+ // So... this is ok for a quick fix, but we can and should do a lot better
+ // here long-term.
+
+ // Advance to the next element by adjusting the pointer type as necessary.
+ // For new int[10][20][30], alloc type is int[20][30], base type is 'int'.
+ QualType AllocType = E->getAllocatedType();
+ llvm::Type *AllocPtrTy = ConvertTypeForMem(AllocType)->getPointerTo(
+ curPtr->getType()->getPointerAddressSpace());
+ llvm::Value *curPtrAllocTy = Builder.CreateBitCast(curPtr, AllocPtrTy);
+ llvm::Value *nextPtrAllocTy =
+ Builder.CreateConstGEP1_32(curPtrAllocTy, 1, "array.next");
+ // Cast it back to the base type so that we can compare it to the endPtr.
+ llvm::Value *nextPtr =
+ Builder.CreateBitCast(nextPtrAllocTy, endPtr->getType());
// Check whether we've gotten to the end of the array and, if so,
// exit the loop.
llvm::Value *isEnd = Builder.CreateICmpEQ(nextPtr, endPtr, "array.atend");
diff --git a/clang/test/CodeGenCXX/cxx11-initializer-array-new.cpp b/clang/test/CodeGenCXX/cxx11-initializer-array-new.cpp
index 23577bec661..8de88dcefb0 100644
--- a/clang/test/CodeGenCXX/cxx11-initializer-array-new.cpp
+++ b/clang/test/CodeGenCXX/cxx11-initializer-array-new.cpp
@@ -99,8 +99,9 @@ void *q = new S[n][3]{ { 1, 2, 3 }, { 4, 5, 6 } };
// CHECK: icmp eq %[[S]]* %[[NEXT_INNER]], %[[END_INNER]]
// CHECK: br i1
//
-// CHECK: %[[NEXT_OUTER:.*]] = getelementptr %[[S]]* %{{.*}}, i32 1
-// CHECK: icmp eq %[[S]]* %[[NEXT_OUTER]], %[[END_AS_S]]
+// CHECK: %[[NEXT_OUTER:.*]] = getelementptr [3 x %[[S]]]* %{{.*}}, i32 1
+// CHECK: %[[NEXT_OUTER_AS_S:.*]] = bitcast [3 x %[[S]]]* %[[NEXT_OUTER]] to %[[S]]*
+// CHECK: icmp eq %[[S]]* %[[NEXT_OUTER_AS_S]], %[[END_AS_S]]
// CHECK: br i1
//
// CHECK: }
OpenPOWER on IntegriCloud