]> granicus.if.org Git - clang/commitdiff
Fix miscompilation. The cookie was not used when new'ing arrays with multiple dimensions.
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>
Thu, 26 Aug 2010 15:23:38 +0000 (15:23 +0000)
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>
Thu, 26 Aug 2010 15:23:38 +0000 (15:23 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@112188 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGExprCXX.cpp
test/CodeGenCXX/new.cpp

index 7fb6b3edc24d87448d748dd79d70681d1a643334..97ee76cebda3864374f03e2bebcd3fa172dad55f 100644 (file)
@@ -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<RecordType>();
   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.
index 372bf463647cc9d1a0edfdcd88ccf0c561602304..42d7c9f1a37b2cbec0b57fd6dc7fb07d2698b59f 100644 (file)
@@ -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];
 }