Author: Erich Keane
Date: 2026-09-23T13:47:21-07:00
New Revision: fc1f3ff5a3b3da827cfca31d07a79c036e03b545

URL: 
https://github.com/llvm/llvm-project/commit/fc1f3ff5a3b3da827cfca31d07a79c036e03b545
DIFF: 
https://github.com/llvm/llvm-project/commit/fc1f3ff5a3b3da827cfca31d07a79c036e03b545.diff

LOG: [CIR] Fix 'cookie' size of array delete on aligned type (#225806)

This came up in some test suite, the cookie size calcuation of a array
delete with a 'cookie' was incorrect if the type had an alignment. This
patch strings the correct alignment through the 'element_align' tag on
the array-delete operation, and uses that for the final calculation,
matching classic codegen.

Added: 
    clang/test/CIR/CodeGen/delete-array-overaligned-cookie.cpp

Modified: 
    clang/include/clang/CIR/Dialect/IR/CIROps.td
    clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp
    clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp
    clang/lib/CIR/Dialect/Transforms/TargetLowering/CIRCXXABI.cpp
    clang/lib/CIR/Dialect/Transforms/TargetLowering/CIRCXXABI.h
    clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerItaniumCXXABI.cpp
    clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerMicrosoftCXXABI.cpp
    clang/test/CIR/CodeGen/delete-array-aligned.cpp
    clang/test/CIR/CodeGen/delete-array-throwing-dtor.cpp
    clang/test/CIR/IR/invalid-delete-array.cir

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td 
b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index f6b524176a655..e3276adef0d1e 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -4547,6 +4547,10 @@ def CIR_DeleteArrayOp : CIR_Op<"delete_array"> {
 
     The `dtor_may_throw` unit property, when present, indicates that the
     element destructor may throw exceptions.
+
+    The `element_align` attribute gives the element type's preferred
+    alignment in bytes, which should be the same value the corresponding 
`new[]`
+    uses to size its array cookie.
   }];
 
   let arguments = (ins
@@ -4554,16 +4558,19 @@ def CIR_DeleteArrayOp : CIR_Op<"delete_array"> {
     FlatSymbolRefAttr:$delete_fn,
     CIR_UsualDeleteParamsAttr:$delete_params,
     OptionalAttr<FlatSymbolRefAttr>:$element_dtor,
-    UnitProp:$dtor_may_throw
+    UnitProp:$dtor_may_throw,
+    I64Attr:$element_align
   );
 
   let builders = [
     OpBuilder<(ins "mlir::Value":$address,
                    "mlir::FlatSymbolRefAttr":$delete_fn,
-                   "cir::UsualDeleteParamsAttr":$delete_params), [{
+                   "cir::UsualDeleteParamsAttr":$delete_params,
+                   "uint64_t":$element_align), [{
       build($_builder, $_state, address, delete_fn, delete_params,
             /*element_dtor=*/mlir::FlatSymbolRefAttr{},
-            /*dtor_may_throw=*/false);
+            /*dtor_may_throw=*/false,
+            $_builder.getI64IntegerAttr(element_align));
     }]>
   ];
 

diff  --git a/clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp 
b/clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp
index d0105c96cfd39..56d54a374cf5c 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp
@@ -1536,6 +1536,11 @@ void CIRGenFunction::emitCXXDeleteExpr(const 
CXXDeleteExpr *e) {
         builder.getContext(), udp.Size, align,
         isTypeAwareAllocation(udp.TypeAwareDelete), udp.DestroyingDelete);
 
+    // Alignment of the element, used for the 'cookie' later.
+    uint64_t elementAlign = cgm.getASTContext()
+                                .getPreferredTypeAlignInChars(deleteTy)
+                                .getQuantity();
+
     mlir::FlatSymbolRefAttr elementDtor;
     bool hasThrowingDtor = false;
     if (const auto *rd = deleteTy->getAsCXXRecordDecl()) {
@@ -1552,7 +1557,8 @@ void CIRGenFunction::emitCXXDeleteExpr(const 
CXXDeleteExpr *e) {
 
     cir::DeleteArrayOp::create(builder, ptr.getPointer().getLoc(),
                                ptr.getPointer(), deleteFn, deleteParams,
-                               elementDtor, hasThrowingDtor);
+                               elementDtor, hasThrowingDtor,
+                               builder.getI64IntegerAttr(elementAlign));
   } else {
     emitObjectDelete(*this, e, ptr, deleteTy);
   }

diff  --git a/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp 
b/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp
index d2774877d11e3..5062b4f231fbb 100644
--- a/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp
@@ -675,8 +675,10 @@ mlir::LogicalResult 
CIRDeleteArrayOpABILowering::matchAndRewrite(
 
   if (cookieRequired) {
     ptrTy = mlir::cast<cir::PointerType>(loweredAddress.getType());
-    cxxABI.readArrayCookie(loc, loweredAddress, dl, cirBuilder, numElements,
-                           deletePtr, cookieSize);
+    clang::CharUnits elementAlign =
+        clang::CharUnits::fromQuantity(op.getElementAlign());
+    cxxABI.readArrayCookie(loc, loweredAddress, elementAlign, dl, cirBuilder,
+                           numElements, deletePtr, cookieSize);
   } else {
     deletePtr = cir::CastOp::create(rewriter, loc, cirBuilder.getVoidPtrTy(),
                                     cir::CastKind::bitcast, loweredAddress);

diff  --git a/clang/lib/CIR/Dialect/Transforms/TargetLowering/CIRCXXABI.cpp 
b/clang/lib/CIR/Dialect/Transforms/TargetLowering/CIRCXXABI.cpp
index 6046f3f126d98..df8ab49c067ec 100644
--- a/clang/lib/CIR/Dialect/Transforms/TargetLowering/CIRCXXABI.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering/CIRCXXABI.cpp
@@ -23,6 +23,7 @@ unsigned CIRCXXABI::getPtrSizeInBits() const {
 }
 
 void CIRCXXABI::readArrayCookie(mlir::Location loc, mlir::Value elementPtr,
+                                clang::CharUnits elementAlign,
                                 const mlir::DataLayout &dataLayout,
                                 CIRBaseBuilderTy &builder,
                                 mlir::Value &numElements, mlir::Value 
&allocPtr,
@@ -31,8 +32,7 @@ void CIRCXXABI::readArrayCookie(mlir::Location loc, 
mlir::Value elementPtr,
   auto ptrDiffTy = builder.getSIntNTy(getPtrSizeInBits());
   auto voidPtrTy = builder.getVoidPtrTy();
 
-  auto ptrTy = mlir::cast<cir::PointerType>(elementPtr.getType());
-  cookieSize = getArrayCookieSizeImpl(ptrTy.getPointee(), dataLayout);
+  cookieSize = getArrayCookieSizeImpl(elementAlign);
 
   mlir::Value bytePtr = cir::CastOp::create(builder, loc, u8PtrTy,
                                             cir::CastKind::bitcast, 
elementPtr);
@@ -45,13 +45,11 @@ void CIRCXXABI::readArrayCookie(mlir::Location loc, 
mlir::Value elementPtr,
   allocPtr = cir::CastOp::create(builder, loc, voidPtrTy,
                                  cir::CastKind::bitcast, allocBytePtr);
 
-  // cookieSize is always a multiple of the element ABI alignment (both are
+  // cookieSize is always a multiple of the element alignment (both are
   // powers of 2 and cookieSize >= elementAlign), so subtracting it preserves
   // alignment. The cookie alignment therefore equals the element alignment.
-  clang::CharUnits cookieAlignment = clang::CharUnits::fromQuantity(
-      dataLayout.getTypePreferredAlignment(ptrTy.getPointee()));
-  numElements = readArrayCookieImpl(loc, allocBytePtr, cookieSize,
-                                    cookieAlignment, dataLayout, builder);
+  numElements = readArrayCookieImpl(loc, allocBytePtr, cookieSize, 
elementAlign,
+                                    dataLayout, builder);
 }
 
 } // namespace cir

diff  --git a/clang/lib/CIR/Dialect/Transforms/TargetLowering/CIRCXXABI.h 
b/clang/lib/CIR/Dialect/Transforms/TargetLowering/CIRCXXABI.h
index 1f65c871d8315..1a2b5bb119cb7 100644
--- a/clang/lib/CIR/Dialect/Transforms/TargetLowering/CIRCXXABI.h
+++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering/CIRCXXABI.h
@@ -139,11 +139,12 @@ class CIRCXXABI {
                          mlir::OpBuilder &builder) const = 0;
 
   /// Read the array cookie for a dynamically-allocated array whose first
-  /// element is at \p elementPtr. Returns the number of elements, the
-  /// original allocation pointer (before the cookie) as a void*, and the
-  /// cookie size in bytes. Delegates to getArrayCookieSizeImpl and
-  /// readArrayCookieImpl.
+  /// element is at \p elementPtr. \p elementAlign is the element type's
+  /// preferred alignment in bytes. Returns the number of elements, the 
original
+  /// allocation pointer (before the cookie) as a void*, and the cookie size in
+  /// bytes. Delegates to getArrayCookieSizeImpl and readArrayCookieImpl.
   void readArrayCookie(mlir::Location loc, mlir::Value elementPtr,
+                       clang::CharUnits elementAlign,
                        const mlir::DataLayout &dataLayout,
                        CIRBaseBuilderTy &builder, mlir::Value &numElements,
                        mlir::Value &allocPtr,
@@ -151,10 +152,10 @@ class CIRCXXABI {
 
 protected:
   /// Returns the cookie size in bytes for a dynamically-allocated array of
-  /// elements with the given type. Only called when a cookie is required.
+  /// elements with the given preferred alignment. Only called when a cookie
+  /// is required.
   virtual clang::CharUnits
-  getArrayCookieSizeImpl(mlir::Type elementType,
-                         const mlir::DataLayout &dataLayout) const = 0;
+  getArrayCookieSizeImpl(clang::CharUnits elementAlign) const = 0;
 
   /// Reads the element count from an array cookie. \p allocPtr is a byte
   /// pointer to the start of the allocation (the beginning of the cookie).

diff  --git 
a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerItaniumCXXABI.cpp 
b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerItaniumCXXABI.cpp
index fdfbea028926a..26dbe40c2c93f 100644
--- a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerItaniumCXXABI.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerItaniumCXXABI.cpp
@@ -117,8 +117,7 @@ class LowerItaniumCXXABI : public CIRCXXABI {
                                      mlir::OpBuilder &builder) const override;
 
   clang::CharUnits
-  getArrayCookieSizeImpl(mlir::Type elementType,
-                         const mlir::DataLayout &dataLayout) const override;
+  getArrayCookieSizeImpl(clang::CharUnits elementAlign) const override;
 
   mlir::Value readArrayCookieImpl(mlir::Location loc, mlir::Value allocPtr,
                                   clang::CharUnits cookieSize,
@@ -889,14 +888,12 @@ 
LowerItaniumCXXABI::lowerVTableGetTypeInfo(cir::VTableGetTypeInfoOp op,
 }
 
 clang::CharUnits LowerItaniumCXXABI::getArrayCookieSizeImpl(
-    mlir::Type elementType, const mlir::DataLayout &dataLayout) const {
+    clang::CharUnits elementAlign) const {
   // The array cookie is a size_t; pad that up to the element alignment.
   // The cookie is actually right-justified in that space.
   clang::CharUnits sizeOfSizeT =
       clang::CharUnits::fromQuantity(getPtrSizeInBits() / 8);
-  clang::CharUnits eltAlign = clang::CharUnits::fromQuantity(
-      dataLayout.getTypePreferredAlignment(elementType));
-  return std::max(sizeOfSizeT, eltAlign);
+  return std::max(sizeOfSizeT, elementAlign);
 }
 
 mlir::Value LowerItaniumCXXABI::readArrayCookieImpl(

diff  --git 
a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerMicrosoftCXXABI.cpp 
b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerMicrosoftCXXABI.cpp
index f670981453bed..1cd7306d74dba 100644
--- a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerMicrosoftCXXABI.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerMicrosoftCXXABI.cpp
@@ -135,8 +135,7 @@ class LowerMicrosoftCXXABI : public CIRCXXABI {
   }
 
   clang::CharUnits
-  getArrayCookieSizeImpl(mlir::Type elementType,
-                         const mlir::DataLayout &dataLayout) const override {
+  getArrayCookieSizeImpl(clang::CharUnits elementAlign) const override {
     llvm_unreachable("Microsoft ABI array cookie lowering NYI");
   }
 

diff  --git a/clang/test/CIR/CodeGen/delete-array-aligned.cpp 
b/clang/test/CIR/CodeGen/delete-array-aligned.cpp
index 41372cb1c1be8..a02476de7da04 100644
--- a/clang/test/CIR/CodeGen/delete-array-aligned.cpp
+++ b/clang/test/CIR/CodeGen/delete-array-aligned.cpp
@@ -15,7 +15,7 @@ struct alignas(128) OverAlignedTy {
 };
 void test_global_aligned(OverAlignedTy *p) { delete[] p; }
 // CIR-LABEL: cir.func no_inline dso_local 
@_Z19test_global_alignedP13OverAlignedTy(
-// CIR-BEFORE: cir.delete_array %{{.*}} : !cir.ptr<!rec_OverAlignedTy> 
{delete_fn = @_ZdaPvSt11align_val_t, delete_params = 
#cir.usual_delete_params<alignment = 128>}
+// CIR-BEFORE: cir.delete_array %{{.*}} : !cir.ptr<!rec_OverAlignedTy> 
{delete_fn = @_ZdaPvSt11align_val_t, delete_params = 
#cir.usual_delete_params<alignment = 128>, element_align = 128 : i64}
 
 // CIR-AFTER:      %[[PTR:.*]] = cir.cast bitcast %{{.*}} : 
!cir.ptr<!rec_OverAlignedTy> -> !cir.ptr<!void>
 // CIR-AFTER-NEXT: cir.cleanup.scope {
@@ -36,7 +36,7 @@ struct alignas(128) OverAlignedTyClassDelete {
 };
 void test_class_align_only(OverAlignedTyClassDelete *p) { delete[] p; }
 // CIR-LABEL: cir.func no_inline dso_local 
@_Z21test_class_align_onlyP24OverAlignedTyClassDelete(
-// CIR-BEFORE: cir.delete_array %{{.*}} : 
!cir.ptr<!rec_OverAlignedTyClassDelete> {delete_fn = 
@_ZN24OverAlignedTyClassDeletedaEPvSt11align_val_t, delete_params = 
#cir.usual_delete_params<alignment = 128>}
+// CIR-BEFORE: cir.delete_array %{{.*}} : 
!cir.ptr<!rec_OverAlignedTyClassDelete> {delete_fn = 
@_ZN24OverAlignedTyClassDeletedaEPvSt11align_val_t, delete_params = 
#cir.usual_delete_params<alignment = 128>, element_align = 128 : i64}
 // CIR-AFTER: %[[PTR:.*]] = cir.cast bitcast %{{.*}} : 
!cir.ptr<!rec_OverAlignedTyClassDelete> -> !cir.ptr<!void>
 // CIR-AFTER-NEXT: cir.cleanup.scope {
 // CIR-AFTER-NEXT:   cir.yield
@@ -56,7 +56,7 @@ struct alignas(128) OverAlignedTyClassDeleteCookie {
 };
 void test_class_size_align(OverAlignedTyClassDeleteCookie *p) { delete[] p; }
 // CIR-LABEL: cir.func no_inline dso_local 
@_Z21test_class_size_alignP30OverAlignedTyClassDeleteCookie(
-// CIR-BEFORE: cir.delete_array %{{.*}} : 
!cir.ptr<!rec_OverAlignedTyClassDeleteCookie> {delete_fn = 
@_ZN30OverAlignedTyClassDeleteCookiedaEPvmSt11align_val_t, delete_params = 
#cir.usual_delete_params<size = true, alignment = 128>}
+// CIR-BEFORE: cir.delete_array %{{.*}} : 
!cir.ptr<!rec_OverAlignedTyClassDeleteCookie> {delete_fn = 
@_ZN30OverAlignedTyClassDeleteCookiedaEPvmSt11align_val_t, delete_params = 
#cir.usual_delete_params<size = true, alignment = 128>, element_align = 128 : 
i64}
 // CIR-AFTER:      %[[ORIG_PTR:.*]] = cir.cast bitcast %{{.*}} : 
!cir.ptr<!rec_OverAlignedTyClassDeleteCookie> -> !cir.ptr<!u8i>
 // CIR-AFTER:      %[[COOKIE_STRIDE:.*]] = cir.ptr_stride %[[ORIG_PTR]], 
%{{.*}} : (!cir.ptr<!u8i>, !s64i) -> !cir.ptr<!u8i>
 // CIR-AFTER-NEXT: %[[PTR:.*]] = cir.cast bitcast %[[COOKIE_STRIDE]] : 
!cir.ptr<!u8i> -> !cir.ptr<!void>
@@ -80,7 +80,7 @@ struct alignas(128) OverAlignedTyClassDeleteDtor {
 };
 void test_class_align_only_dtor(OverAlignedTyClassDeleteDtor *p) { delete[] p; 
}
 // CIR-LABEL: cir.func no_inline dso_local 
@_Z26test_class_align_only_dtorP28OverAlignedTyClassDeleteDtor(
-// CIR-BEFORE: cir.delete_array %{{.*}} : 
!cir.ptr<!rec_OverAlignedTyClassDeleteDtor> {delete_fn = 
@_ZN28OverAlignedTyClassDeleteDtordaEPvSt11align_val_t, delete_params = 
#cir.usual_delete_params<alignment = 128>, element_dtor = 
@_ZN28OverAlignedTyClassDeleteDtorD1Ev}
+// CIR-BEFORE: cir.delete_array %{{.*}} : 
!cir.ptr<!rec_OverAlignedTyClassDeleteDtor> {delete_fn = 
@_ZN28OverAlignedTyClassDeleteDtordaEPvSt11align_val_t, delete_params = 
#cir.usual_delete_params<alignment = 128>, element_align = 128 : i64, 
element_dtor = @_ZN28OverAlignedTyClassDeleteDtorD1Ev}
 // CIR-AFTER:      %[[ORIG_PTR:.*]] = cir.cast bitcast %{{.*}} : 
!cir.ptr<!rec_OverAlignedTyClassDeleteDtor> -> !cir.ptr<!u8i>
 // CIR-AFTER:      %[[COOKIE_STRIDE:.*]] = cir.ptr_stride %[[ORIG_PTR]], 
%{{.*}} : (!cir.ptr<!u8i>, !s64i) -> !cir.ptr<!u8i>
 // CIR-AFTER-NEXT: %[[PTR:.*]] = cir.cast bitcast %[[COOKIE_STRIDE]] : 
!cir.ptr<!u8i> -> !cir.ptr<!void>
@@ -114,7 +114,7 @@ void 
test_class_size_align_dtor(OverAlignedTyClassDeleteCookieDtor *p) {
   delete[] p;
 }
 // CIR-LABEL: cir.func no_inline dso_local 
@_Z26test_class_size_align_dtorP34OverAlignedTyClassDeleteCookieDtor(
-// CIR-BEFORE: cir.delete_array %{{.*}} : 
!cir.ptr<!rec_OverAlignedTyClassDeleteCookieDtor> {delete_fn = 
@_ZN34OverAlignedTyClassDeleteCookieDtordaEPvmSt11align_val_t, delete_params = 
#cir.usual_delete_params<size = true, alignment = 128>, element_dtor = 
@_ZN34OverAlignedTyClassDeleteCookieDtorD1Ev}
+// CIR-BEFORE: cir.delete_array %{{.*}} : 
!cir.ptr<!rec_OverAlignedTyClassDeleteCookieDtor> {delete_fn = 
@_ZN34OverAlignedTyClassDeleteCookieDtordaEPvmSt11align_val_t, delete_params = 
#cir.usual_delete_params<size = true, alignment = 128>, element_align = 128 : 
i64, element_dtor = @_ZN34OverAlignedTyClassDeleteCookieDtorD1Ev}
 // CIR-AFTER:      %[[ORIG_PTR:.*]] = cir.cast bitcast %{{.*}} : 
!cir.ptr<!rec_OverAlignedTyClassDeleteCookieDtor> -> !cir.ptr<!u8i>
 // CIR-AFTER:      %[[COOKIE_STRIDE:.*]] = cir.ptr_stride %[[ORIG_PTR]], 
%{{.*}} : (!cir.ptr<!u8i>, !s64i) -> !cir.ptr<!u8i>
 // CIR-AFTER-NEXT: %[[PTR:.*]] = cir.cast bitcast %[[COOKIE_STRIDE]] : 
!cir.ptr<!u8i> -> !cir.ptr<!void>

diff  --git a/clang/test/CIR/CodeGen/delete-array-overaligned-cookie.cpp 
b/clang/test/CIR/CodeGen/delete-array-overaligned-cookie.cpp
new file mode 100644
index 0000000000000..e9c4a329ac5a1
--- /dev/null
+++ b/clang/test/CIR/CodeGen/delete-array-overaligned-cookie.cpp
@@ -0,0 +1,87 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++17 -fclangir 
-mconstructor-aliases -emit-cir -mmlir 
-mlir-print-ir-before=cir-cxxabi-lowering %s -o %t.cir 2> %t-before.cir
+// RUN: FileCheck --input-file=%t-before.cir -check-prefix=CIR,CIR-BEFORE %s
+// RUN: FileCheck --input-file=%t.cir --check-prefix=CIR,CIR-AFTER %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++17 -fclangir 
-mconstructor-aliases -emit-llvm %s -o %t-cir.ll
+// RUN: FileCheck --input-file=%t-cir.ll --check-prefix=LLVM %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++17 
-mconstructor-aliases -emit-llvm %s -o %t.ll
+// RUN: FileCheck --input-file=%t.ll --check-prefix=LLVM %s
+
+typedef decltype(sizeof(0)) size_t;
+namespace std { enum class align_val_t : size_t {}; }
+
+struct alignas(64) OverAligned {
+  int *p;
+  OverAligned() : p(nullptr) {}
+  ~OverAligned();
+};
+
+void test_delete_array(OverAligned *a) {
+  delete[] a;
+}
+// CIR-LABEL: cir.func {{.*}}@_Z17test_delete_arrayP11OverAligned(
+// CIR-BEFORE:     cir.delete_array %{{.*}} : !cir.ptr<!rec_OverAligned> 
{delete_fn = @_ZdaPvmSt11align_val_t, delete_params = 
#cir.usual_delete_params<size = true, alignment = 64>, element_align = 64 : 
i64, element_dtor = @_ZN11OverAlignedD1Ev}
+
+// CIR-AFTER: %[[A:.*]] = cir.alloca "a" align(8) init : 
!cir.ptr<!cir.ptr<!rec_OverAligned>>
+// CIR-AFTER: %[[LOAD_A:.*]] = cir.load align(8) %[[A]] : 
!cir.ptr<!cir.ptr<!rec_OverAligned>>, !cir.ptr<!rec_OverAligned>
+// CIR-AFTER:   %[[CAST_TO_BYTES:.*]] = cir.cast bitcast %[[LOAD_A]] : 
!cir.ptr<!rec_OverAligned> -> !cir.ptr<!u8i>
+// CIR-AFTER:   %[[COOKIE_OFFSET:.*]] = cir.const #cir.int<-64> : !s64i
+// CIR-AFTER:   %[[BEFORE_COOKIE:.*]] = cir.ptr_stride %[[CAST_TO_BYTES]], 
%[[COOKIE_OFFSET]] : (!cir.ptr<!u8i>, !s64i) -> !cir.ptr<!u8i>
+// CIR-AFTER:   %[[COUNT_OFFSET:.*]] = cir.const #cir.int<56> : !s64i
+// CIR-AFTER:   %[[AFTER_COUNT:.*]] = cir.ptr_stride %[[BEFORE_COOKIE]], 
%[[COUNT_OFFSET]] : (!cir.ptr<!u8i>, !s64i) -> !cir.ptr<!u8i>
+// CIR-AFTER:   %[[TO_SIZE:.*]] = cir.cast bitcast %[[AFTER_COUNT]] : 
!cir.ptr<!u8i> -> !cir.ptr<!u64i>
+// CIR-AFTER:   %[[LOAD_VAL:.*]] = cir.load align(8) %[[TO_SIZE]] : 
!cir.ptr<!u64i>, !u64i
+// CIR-AFTER:   } cleanup normal {
+// CIR-AFTER:     %[[ELT_SIZE:.*]] = cir.const #cir.int<64> : !u64i
+// CIR-AFTER:     %[[ELT_OFFSET:.*]] = cir.mul %[[ELT_SIZE]], %[[LOAD_VAL]] : 
!u64i
+// CIR-AFTER:     %[[COOKIE_SIZE:.*]] = cir.const #cir.int<64> : !u64i
+// CIR-AFTER:     %[[TOTAL_SIZE:.*]] = cir.add %[[ELT_OFFSET]], 
%[[COOKIE_SIZE]] : !u64i
+// CIR-AFTER:     %[[ALIGN:.*]] = cir.const #cir.int<64> : !u64i
+// CIR-AFTER:  cir.call @_ZdaPvmSt11align_val_t(%{{.*}}, %[[TOTAL_SIZE]], 
%[[ALIGN]]) nothrow : (!cir.ptr<!void>, !u64i, !u64i) -> ()
+
+// LLVM-LABEL: define {{.*}}@_Z17test_delete_arrayP11OverAligned(
+// LLVM: %[[A:.*]] = alloca ptr, align 8
+// LLVM: %[[LOAD_A:.*]] = load ptr, ptr %[[A]], align 8
+// LLVM: %[[BEFORE_COOKIE:.*]] = getelementptr {{.*}}i8, ptr %[[LOAD_A]], i64 
-64
+// LLVM: %[[AFTER_COUNT:.*]] = getelementptr {{.*}}i8, ptr %[[BEFORE_COOKIE]], 
i64 56
+// LLVM: %[[LOAD_VAL:.*]] = load i64, ptr %[[AFTER_COUNT]], align 8
+// LLVM: %[[ELT_OFFSET:.*]] = mul i64 64, %[[LOAD_VAL]]
+// LLVM: %[[TOTAL_SIZE:.*]] = add i64 %[[ELT_OFFSET]], 64
+// LLVM: call void @_ZdaPvmSt11align_val_t(ptr {{.*}}%{{.*}}, i64 
{{.*}}%[[TOTAL_SIZE]], i64 {{.*}}64) 
+
+
+struct alignas(16) NotAlignedNewButNeedCookie {
+  float x, y, z, a;
+  ~NotAlignedNewButNeedCookie();
+};
+
+void test_not_aligned_new_but_need_cookie(NotAlignedNewButNeedCookie *a) {
+  delete [] a;
+}
+// CIR-LABEL: cir.func 
{{.*}}@_Z36test_not_aligned_new_but_need_cookieP26NotAlignedNewButNeedCookie(
+// CIR-BEFORE: cir.delete_array %{{.*}} : 
!cir.ptr<!rec_NotAlignedNewButNeedCookie> {delete_fn = @_ZdaPvm, delete_params 
= #cir.usual_delete_params<size = true>, element_align = 16 : i64, element_dtor 
= @_ZN26NotAlignedNewButNeedCookieD1Ev}
+// CIR-AFTER: %[[A:.*]] = cir.alloca "a" align(8) init : 
!cir.ptr<!cir.ptr<!rec_NotAlignedNewButNeedCookie>>
+
+// CIR-AFTER: %[[LOAD_A:.*]] = cir.load align(8) %[[A]] : 
!cir.ptr<!cir.ptr<!rec_NotAlignedNewButNeedCookie>>, 
!cir.ptr<!rec_NotAlignedNewButNeedCookie>
+// CIR-AFTER: %[[CAST_TO_BYTES:.*]] = cir.cast bitcast %[[LOAD_A]] : 
!cir.ptr<!rec_NotAlignedNewButNeedCookie> -> !cir.ptr<!u8i>
+// CIR-AFTER: %[[COOKIE_OFFSET:.*]] = cir.const #cir.int<-16> : !s64i
+// CIR-AFTER: %[[BEFORE_COOKIE:.*]] = cir.ptr_stride %[[CAST_TO_BYTES]], 
%[[COOKIE_OFFSET]] : (!cir.ptr<!u8i>, !s64i) -> !cir.ptr<!u8i>
+// CIR-AFTER: %[[COUNT_OFFSET:.*]] = cir.const #cir.int<8> : !s64i
+// CIR-AFTER: %[[AFTER_COUNT:.*]] = cir.ptr_stride %[[BEFORE_COOKIE]], 
%[[COUNT_OFFSET]] : (!cir.ptr<!u8i>, !s64i) -> !cir.ptr<!u8i>
+// CIR-AFTER: %[[TO_SIZE:.*]] = cir.cast bitcast %[[AFTER_COUNT]] : 
!cir.ptr<!u8i> -> !cir.ptr<!u64i>
+// CIR-AFTER: %[[LOAD_VAL:.*]] = cir.load align(8) %[[TO_SIZE]] : 
!cir.ptr<!u64i>, !u64i
+// CIR-AFTER: } cleanup normal {
+// CIR-AFTER:   %[[ELT_SIZE:.*]] = cir.const #cir.int<16> : !u64i
+// CIR-AFTER:   %[[ELT_OFFSET:.*]] = cir.mul %[[ELT_SIZE]], %[[LOAD_VAL]] : 
!u64i
+// CIR-AFTER:   %[[COOKIE_SIZE:.*]] = cir.const #cir.int<16> : !u64i
+// CIR-AFTER:   %[[TOTAL_SIZE:.*]] = cir.add %[[ELT_OFFSET]], %[[COOKIE_SIZE]] 
: !u64i
+// CIR-AFTER:   cir.call @_ZdaPvm(%{{.*}}, %[[TOTAL_SIZE]]) nothrow : 
(!cir.ptr<!void>, !u64i) -> ()
+
+// LLVM-LABEL: define 
{{.*}}@_Z36test_not_aligned_new_but_need_cookieP26NotAlignedNewButNeedCookie(
+// LLVM: %[[A:.*]] = alloca ptr, align 8
+// LLVM: %[[LOAD_A:.*]] = load ptr, ptr %[[A]], align 8
+// LLVM: %[[BEFORE_COOKIE:.*]] = getelementptr {{.*}}i8, ptr %[[LOAD_A]], i64 
-16
+// LLVM: %[[AFTER_COUNT:.*]] = getelementptr {{.*}}i8, ptr %[[BEFORE_COOKIE]], 
i64 8
+// LLVM: %[[LOAD_VAL:.*]] = load i64, ptr %[[AFTER_COUNT]], align 8
+// LLVM: %[[ELT_OFFEST:.*]] = mul i64 16, %[[LOAD_VAL]]
+// LLVM: %[[TOTAL_SIZE:.*]] = add i64 %[[ELT_OFFSET]], 16
+// LLVM: call void @_ZdaPvm(ptr {{.*}}%{{.*}}, i64 {{.*}}%[[TOTAL_SIZE]])

diff  --git a/clang/test/CIR/CodeGen/delete-array-throwing-dtor.cpp 
b/clang/test/CIR/CodeGen/delete-array-throwing-dtor.cpp
index 090617bd34375..d5a63bc65edc8 100644
--- a/clang/test/CIR/CodeGen/delete-array-throwing-dtor.cpp
+++ b/clang/test/CIR/CodeGen/delete-array-throwing-dtor.cpp
@@ -23,7 +23,7 @@ void test_delete_array_throwing_dtor(ThrowingDtor *ptr) {
 // CIR-BEFORE-CXXABI:   %[[NULL:.*]] = cir.const #cir.ptr<null>
 // CIR-BEFORE-CXXABI:   %[[NOT_NULL:.*]] = cir.cmp ne %[[PTR]], %[[NULL]]
 // CIR-BEFORE-CXXABI:   cir.if %[[NOT_NULL]] {
-// CIR-BEFORE-CXXABI:     cir.delete_array %[[PTR]] : 
!cir.ptr<!rec_ThrowingDtor> dtor_may_throw {delete_fn = @_ZdaPvm, delete_params 
= #cir.usual_delete_params<size = true>, element_dtor = @_ZN12ThrowingDtorD1Ev}
+// CIR-BEFORE-CXXABI:     cir.delete_array %[[PTR]] : 
!cir.ptr<!rec_ThrowingDtor> dtor_may_throw {delete_fn = @_ZdaPvm, delete_params 
= #cir.usual_delete_params<size = true>, element_align = 4 : i64, element_dtor 
= @_ZN12ThrowingDtorD1Ev}
 // CIR-BEFORE-CXXABI:   }
 
 // CIR-AFTER-CXXABI: IR Dump After CXXABILowering: cir-cxxabi-lowering

diff  --git a/clang/test/CIR/IR/invalid-delete-array.cir 
b/clang/test/CIR/IR/invalid-delete-array.cir
index 7d6ce8be0951f..a9ac7c6355459 100644
--- a/clang/test/CIR/IR/invalid-delete-array.cir
+++ b/clang/test/CIR/IR/invalid-delete-array.cir
@@ -9,7 +9,13 @@ module {
 
   cir.func @bad_delete_array_throw_without_dtor(%p: !cir.ptr<!rec_S>) {
     // expected-error@+1 {{'cir.delete_array' op 'dtor_may_throw' requires an 
'element_dtor' to be present}}
-    cir.delete_array %p : !cir.ptr<!rec_S> dtor_may_throw {delete_fn = 
@_ZdaPvm, delete_params = #cir.usual_delete_params<size = true>}
+    cir.delete_array %p : !cir.ptr<!rec_S> dtor_may_throw {delete_fn = 
@_ZdaPvm, element_align = 1, delete_params = #cir.usual_delete_params<size = 
true>}
+    cir.return
+  }
+
+  cir.func @bad_delete_array_throw_without_align(%p: !cir.ptr<!rec_S>) {
+    // expected-error@+1 {{'cir.delete_array' op requires attribute 
'element_align'}}
+    cir.delete_array %p : !cir.ptr<!rec_S> dtor_may_throw {delete_fn = 
@_ZdaPvm, dtor_may_throw = true, delete_params = #cir.usual_delete_params<size 
= true>}
     cir.return
   }
 }


        
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to