diff options
author | Fariborz Jahanian <fjahanian@apple.com> | 2010-03-24 16:57:01 +0000 |
---|---|---|
committer | Fariborz Jahanian <fjahanian@apple.com> | 2010-03-24 16:57:01 +0000 |
commit | ceb43b662bf09b44a08714e8f9d222780ca979d7 (patch) | |
tree | 15815464041c26f1cd3268ab0a35fb7237f3e8de | |
parent | ccd83d748c82c5255100f38e3f07537b949853b3 (diff) |
Code gen for multi-dimensional dynamic allocations.
Fixes PR6641.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@99404 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/CodeGen/CGExprCXX.cpp | 43 | ||||
-rw-r--r-- | test/CodeGenCXX/multi-dim-operator-new.cpp | 44 |
2 files changed, 81 insertions, 6 deletions
diff --git a/lib/CodeGen/CGExprCXX.cpp b/lib/CodeGen/CGExprCXX.cpp index 0328621604..28b1d3b501 100644 --- a/lib/CodeGen/CGExprCXX.cpp +++ b/lib/CodeGen/CGExprCXX.cpp @@ -411,7 +411,8 @@ static CharUnits CalculateCookiePadding(ASTContext &Ctx, const CXXNewExpr *E) { return CalculateCookiePadding(Ctx, E->getAllocatedType()); } -static llvm::Value *EmitCXXNewAllocSize(CodeGenFunction &CGF, +static llvm::Value *EmitCXXNewAllocSize(ASTContext &Context, + CodeGenFunction &CGF, const CXXNewExpr *E, llvm::Value *& NumElements) { QualType Type = E->getAllocatedType(); @@ -432,6 +433,15 @@ static llvm::Value *EmitCXXNewAllocSize(CodeGenFunction &CGF, NumElements = llvm::ConstantInt::get(SizeTy, Result.Val.getInt().getZExtValue()); + while (const ArrayType *AType = Context.getAsArrayType(Type)) { + const llvm::ArrayType *llvmAType = + cast<llvm::ArrayType>(CGF.ConvertType(Type)); + NumElements = + CGF.Builder.CreateMul(NumElements, + llvm::ConstantInt::get( + SizeTy, llvmAType->getNumElements())); + Type = AType->getElementType(); + } return llvm::ConstantInt::get(SizeTy, AllocSize.getQuantity()); } @@ -444,6 +454,16 @@ static llvm::Value *EmitCXXNewAllocSize(CodeGenFunction &CGF, CGF.Builder.CreateMul(NumElements, llvm::ConstantInt::get(SizeTy, TypeSize.getQuantity())); + + while (const ArrayType *AType = Context.getAsArrayType(Type)) { + const llvm::ArrayType *llvmAType = + cast<llvm::ArrayType>(CGF.ConvertType(Type)); + NumElements = + CGF.Builder.CreateMul(NumElements, + llvm::ConstantInt::get( + SizeTy, llvmAType->getNumElements())); + Type = AType->getElementType(); + } // And add the cookie padding if necessary. if (!CookiePadding.isZero()) @@ -504,7 +524,8 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) { QualType SizeTy = getContext().getSizeType(); llvm::Value *NumElements = 0; - llvm::Value *AllocSize = EmitCXXNewAllocSize(*this, E, NumElements); + llvm::Value *AllocSize = EmitCXXNewAllocSize(getContext(), + *this, E, NumElements); NewArgs.push_back(std::make_pair(RValue::get(AllocSize), SizeTy)); @@ -590,10 +611,20 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) { CookiePadding.getQuantity()); } - NewPtr = Builder.CreateBitCast(NewPtr, ConvertType(E->getType())); - - EmitNewInitializer(*this, E, NewPtr, NumElements); - + if (AllocType->isArrayType()) { + while (const ArrayType *AType = getContext().getAsArrayType(AllocType)) + AllocType = AType->getElementType(); + NewPtr = + Builder.CreateBitCast(NewPtr, + ConvertType(getContext().getPointerType(AllocType))); + EmitNewInitializer(*this, E, NewPtr, NumElements); + NewPtr = Builder.CreateBitCast(NewPtr, ConvertType(E->getType())); + } + else { + NewPtr = Builder.CreateBitCast(NewPtr, ConvertType(E->getType())); + EmitNewInitializer(*this, E, NewPtr, NumElements); + } + if (NullCheckResult) { Builder.CreateBr(NewEnd); NewNotNull = Builder.GetInsertBlock(); diff --git a/test/CodeGenCXX/multi-dim-operator-new.cpp b/test/CodeGenCXX/multi-dim-operator-new.cpp new file mode 100644 index 0000000000..46832ae919 --- /dev/null +++ b/test/CodeGenCXX/multi-dim-operator-new.cpp @@ -0,0 +1,44 @@ +// RUN: %clang_cc1 -emit-llvm-only -verify %s +// PR6641 + +extern "C" int printf(const char *, ...); + +struct Foo { + Foo() : iFoo (2) { + printf("%p\n", this); + } + int iFoo; +}; + + +typedef Foo (*T)[3][4]; + +T bar() { + return new Foo[2][3][4]; +} + +T bug(int i) { + return new Foo[i][3][4]; +} + +void pr(T a) { + for (int i = 0; i < 3; i++) + for (int j = 0; j < 4; j++) + printf("%p\n", a[i][j]); +} + +Foo *test() { + return new Foo[5]; +} + +int main() { + T f = bar(); + pr(f); + f = bug(3); + pr(f); + + Foo * g = test(); + for (int i = 0; i < 5; i++) + printf("%d\n", g[i].iFoo); + return 0; +} |