https://github.com/andykaylor created 
https://github.com/llvm/llvm-project/pull/184933

If an array is explicitly initialized with more than eight non-zero values 
followed by a number of explicit zero initializers, CIR generates a constant 
record initializer with a constant array that is declared as the size of the 
non-zero initializers but with the explicit zero initializers included in the 
array initialization attribute. This resulted in an error when we tried to 
lower that attribute to LLVM IR.

This patch fixes that problem and adds a verifier to ConstantArrayAttr to check 
for that condition.

>From ea1b1d53aa728199d32f2509f3dc7b0a0ab3624a Mon Sep 17 00:00:00 2001
From: Andy Kaylor <[email protected]>
Date: Thu, 5 Mar 2026 17:33:02 -0800
Subject: [PATCH] [CIR] Fix array constant initialization with trailing zeros

If an array is explicitly initialized with more than eight non-zero values
followed by a number of explicit zero initializers, CIR generates a
constant record initializer with a constant array that is declared as the
size of the non-zero initializers but with the explicit zero initializers
included in the array initialization attribute. This resulted in an error
when we tried to lower that attribute to LLVM IR.

This patch fixes that problem and adds a verifier to ConstantArrayAttr to
check for that condition.
---
 clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp |  4 ++--
 clang/lib/CIR/Dialect/IR/CIRAttrs.cpp        |  4 ++++
 clang/test/CIR/CodeGen/array.cpp             | 23 ++++++++++++++++++++
 clang/test/CIR/IR/invalid-const-array.cir    |  6 +++++
 4 files changed, 35 insertions(+), 2 deletions(-)
 create mode 100644 clang/test/CIR/IR/invalid-const-array.cir

diff --git a/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp 
b/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp
index 9d17c8937aac9..b697ca5cd3f6d 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp
@@ -1167,8 +1167,8 @@ emitArrayConstant(CIRGenModule &cgm, mlir::Type 
desiredType,
       // (the nonzero data and the zeroinitializer).
       SmallVector<mlir::Attribute> eles;
       eles.reserve(nonzeroLength);
-      for (const auto &element : elements)
-        eles.push_back(element);
+      for (unsigned i = 0; i < nonzeroLength; ++i)
+        eles.push_back(elements[i]);
       auto initial = cir::ConstArrayAttr::get(
           cir::ArrayType::get(commonElementType, nonzeroLength),
           mlir::ArrayAttr::get(builder.getContext(), eles));
diff --git a/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp 
b/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp
index 67509f3cf452a..4cd2073bf49aa 100644
--- a/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp
@@ -501,6 +501,10 @@ ConstArrayAttr::verify(function_ref<InFlightDiagnostic()> 
emitError, Type type,
   const auto arrayTy = mlir::cast<ArrayType>(type);
 
   // Make sure both number of elements and subelement types match type.
+  if (arrayAttr.size() > arrayTy.getSize())
+    return emitError() << "constant array has " << arrayAttr.size()
+                       << " values but array type has size "
+                       << arrayTy.getSize();
   if (arrayTy.getSize() != arrayAttr.size() + trailingZerosNum)
     return emitError() << "constant array size should match type size";
   return success();
diff --git a/clang/test/CIR/CodeGen/array.cpp b/clang/test/CIR/CodeGen/array.cpp
index 4808abbc3200d..8edcde82c4dbf 100644
--- a/clang/test/CIR/CodeGen/array.cpp
+++ b/clang/test/CIR/CodeGen/array.cpp
@@ -86,6 +86,29 @@ int g[16] = {1, 2, 3, 4, 5, 6, 7, 8};
 // OGCG-SAME:               i32 5, i32 6, i32 7, i32 8],
 // OGCG-SAME:             [8 x i32] zeroinitializer }>
 
+// If we have explicit trailing zeros, those should still be combined into
+// a zero initializer array.
+int h[16] = {1, 2, 3, 4, 5, 6, 7, 8, 0, 0, 0, 0, 0, 0, 0, 0};
+
+// CIR:      cir.global external @h = #cir.const_record<{
+// CIR-SAME:   #cir.const_array<[#cir.int<1> : !s32i, #cir.int<2> : !s32i,
+// CIR-SAME:                     #cir.int<3> : !s32i, #cir.int<4> : !s32i,
+// CIR-SAME:                     #cir.int<5> : !s32i, #cir.int<6> : !s32i,
+// CIR-SAME:                     #cir.int<7> : !s32i, #cir.int<8> : !s32i]>
+// CIR-SAME:                     : !cir.array<!s32i x 8>,
+// CIR-SAME:   #cir.zero : !cir.array<!s32i x 8>}> : !rec_anon_struct1
+
+// LLVM:       @h = global <{ [8 x i32], [8 x i32] }>
+// LLVM-SAME:          <{ [8 x i32]
+// LLVM-SAME:              [i32 1, i32 2, i32 3, i32 4,
+// LLVM-SAME:               i32 5, i32 6, i32 7, i32 8],
+// LLVM-SAME:             [8 x i32] zeroinitializer }>
+
+// OGCG:       @h = global <{ [8 x i32], [8 x i32] }>
+// OGCG-SAME:          <{ [8 x i32]
+// OGCG-SAME:              [i32 1, i32 2, i32 3, i32 4,
+// OGCG-SAME:               i32 5, i32 6, i32 7, i32 8],
+// OGCG-SAME:             [8 x i32] zeroinitializer }>
 
 extern int b[10];
 // CIR: cir.global "private" external @b : !cir.array<!s32i x 10>
diff --git a/clang/test/CIR/IR/invalid-const-array.cir 
b/clang/test/CIR/IR/invalid-const-array.cir
new file mode 100644
index 0000000000000..e2de226e5533e
--- /dev/null
+++ b/clang/test/CIR/IR/invalid-const-array.cir
@@ -0,0 +1,6 @@
+// RUN: cir-opt %s -verify-diagnostics
+
+!s32i = !cir.int<s, 32>
+
+// expected-error @below {{constant array has 4 values but array type has size 
2}}
+cir.global external @a = #cir.const_array<[#cir.int<1> : !s32i, #cir.int<2> : 
!s32i, #cir.int<0> : !s32i, #cir.int<0> : !s32i]> : !cir.array<!s32i x 2>

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

Reply via email to