From: Argyrios Kyrtzidis Date: Thu, 26 Aug 2010 15:23:38 +0000 (+0000) Subject: Fix miscompilation. The cookie was not used when new'ing arrays with multiple dimensions. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=e7ab92e1d62f9c243bbd1f42f72a7b3c2666d33e;p=clang Fix miscompilation. The cookie was not used when new'ing arrays with multiple dimensions. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@112188 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/CGExprCXX.cpp b/lib/CodeGen/CGExprCXX.cpp index 7fb6b3edc2..97ee76cebd 100644 --- a/lib/CodeGen/CGExprCXX.cpp +++ b/lib/CodeGen/CGExprCXX.cpp @@ -296,6 +296,7 @@ CodeGenFunction::EmitCXXConstructExpr(llvm::Value *Dest, } static CharUnits CalculateCookiePadding(ASTContext &Ctx, QualType ElementType) { + ElementType = Ctx.getBaseElementType(ElementType); const RecordType *RT = ElementType->getAs(); if (!RT) return CharUnits::Zero(); @@ -376,18 +377,29 @@ static llvm::Value *EmitCXXNewAllocSize(ASTContext &Context, const CXXNewExpr *E, llvm::Value *&NumElements, llvm::Value *&SizeWithoutCookie) { - QualType Type = E->getAllocatedType(); - CharUnits TypeSize = CGF.getContext().getTypeSizeInChars(Type); - const llvm::Type *SizeTy = CGF.ConvertType(CGF.getContext().getSizeType()); + QualType ElemType = E->getAllocatedType(); if (!E->isArray()) { + CharUnits TypeSize = CGF.getContext().getTypeSizeInChars(ElemType); + const llvm::Type *SizeTy = CGF.ConvertType(CGF.getContext().getSizeType()); SizeWithoutCookie = llvm::ConstantInt::get(SizeTy, TypeSize.getQuantity()); return SizeWithoutCookie; } // Emit the array size expression. + // We multiply the size of all dimensions for NumElements. + // e.g for 'int[2][3]', ElemType is 'int' and NumElements is 6. NumElements = CGF.EmitScalarExpr(E->getArraySize()); - + while (const ConstantArrayType *CAT + = CGF.getContext().getAsConstantArrayType(ElemType)) { + ElemType = CAT->getElementType(); + llvm::Value *ArraySize + = llvm::ConstantInt::get(CGF.CGM.getLLVMContext(), CAT->getSize()); + NumElements = CGF.Builder.CreateMul(NumElements, ArraySize); + } + + CharUnits TypeSize = CGF.getContext().getTypeSizeInChars(ElemType); + const llvm::Type *SizeTy = CGF.ConvertType(CGF.getContext().getSizeType()); llvm::Value *Size = llvm::ConstantInt::get(SizeTy, TypeSize.getQuantity()); // If someone is doing 'new int[42]' there is no need to do a dynamic check. diff --git a/test/CodeGenCXX/new.cpp b/test/CodeGenCXX/new.cpp index 372bf46364..42d7c9f1a3 100644 --- a/test/CodeGenCXX/new.cpp +++ b/test/CodeGenCXX/new.cpp @@ -146,12 +146,15 @@ void t13(int n) { } struct Alloc{ + int x; void* operator new[](size_t size); void operator delete[](void* p); + ~Alloc(); }; void f() { - // CHECK: call i8* @_ZN5AllocnaEm(i64 200) + // CHECK: call i8* @_ZN5AllocnaEm(i64 808) + // CHECK: store i64 200 // CHECK: call void @_ZN5AllocdaEPv(i8* delete[] new Alloc[10][20]; }