https://github.com/AbdallahRashed updated 
https://github.com/llvm/llvm-project/pull/196837

>From 2605f7f71afdcab9b670aace4d19e68c0ef5d993 Mon Sep 17 00:00:00 2001
From: AbdallahRashed <[email protected]>
Date: Sun, 10 May 2026 22:25:17 +0200
Subject: [PATCH] [CIR][CodeGen] Support VLA pointer arithmetic

Implement pointer arithmetic on variable-length array types in CIR
codegen, removing two NYI diagnostics:

1. Binary pointer arithmetic (p + i, p - i) where the pointee is a VLA:
   multiply the index by the runtime VLA size before emitting
   PtrStrideOp.

2. Unary increment/decrement (p++, p--) on pointers to VLA types:
   stride by the VLA element count, negating for decrement.

Fixes #192318
---
 clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp | 24 ++++++---
 clang/test/CIR/CodeGen/vla-pointer-arith.c | 62 ++++++++++++++++++++++
 2 files changed, 80 insertions(+), 6 deletions(-)
 create mode 100644 clang/test/CIR/CodeGen/vla-pointer-arith.c

diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp 
b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
index 231039ec5da29..2ff20badca655 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
@@ -668,10 +668,15 @@ class ScalarExprEmitter : public 
StmtVisitor<ScalarExprEmitter, mlir::Value> {
       }
     } else if (const PointerType *ptr = type->getAs<PointerType>()) {
       QualType type = ptr->getPointeeType();
-      if (cgf.getContext().getAsVariableArrayType(type)) {
+      if (const VariableArrayType *vla =
+              cgf.getContext().getAsVariableArrayType(type)) {
         // VLA types don't have constant size.
-        cgf.cgm.errorNYI(e->getSourceRange(), "Pointer arithmetic on VLA");
-        return {};
+        mlir::Location loc = cgf.getLoc(e->getSourceRange());
+        mlir::Value numElts = cgf.getVLASize(vla).numElts;
+        if (!e->isIncrementOp())
+          numElts = cgf.getBuilder().createNeg(numElts);
+        assert(!cir::MissingFeatures::sanitizers());
+        value = cgf.getBuilder().createPtrStride(loc, value, numElts);
       } else {
         // For everything else, we can just do a simple increment.
         mlir::Location loc = cgf.getLoc(e->getSourceRange());
@@ -1898,9 +1903,16 @@ static mlir::Value emitPointerArithmetic(CIRGenFunction 
&cgf,
   }
 
   QualType elementType = pointerType->getPointeeType();
-  if (cgf.getContext().getAsVariableArrayType(elementType)) {
-    cgf.cgm.errorNYI("variable array type");
-    return nullptr;
+  if (const VariableArrayType *vla =
+          cgf.getContext().getAsVariableArrayType(elementType)) {
+    mlir::Value numElements = cgf.getVLASize(vla).numElts;
+    mlir::Location loc = cgf.getLoc(op.e->getExprLoc());
+    index = cgf.getBuilder().createCast(cir::CastKind::integral, index,
+                                        numElements.getType());
+    index = cgf.getBuilder().createMul(loc, index, numElements);
+    assert(!cir::MissingFeatures::sanitizers());
+    return cir::PtrStrideOp::create(cgf.getBuilder(), loc, pointer.getType(),
+                                    pointer, index);
   }
 
   assert(!cir::MissingFeatures::sanitizers());
diff --git a/clang/test/CIR/CodeGen/vla-pointer-arith.c 
b/clang/test/CIR/CodeGen/vla-pointer-arith.c
new file mode 100644
index 0000000000000..aa59031433a78
--- /dev/null
+++ b/clang/test/CIR/CodeGen/vla-pointer-arith.c
@@ -0,0 +1,62 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o 
%t.cir
+// RUN: FileCheck --input-file=%t.cir %s -check-prefix=CIR
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o 
%t-cir.ll
+// RUN: FileCheck --input-file=%t-cir.ll %s -check-prefix=LLVM
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o %t.ll
+// RUN: FileCheck --input-file=%t.ll %s -check-prefix=OGCG
+
+// Test pointer arithmetic on VLA types.
+
+void test_vla_ptr_add(int n) {
+  int arr[n];
+  int (*p)[n] = &arr;
+  p = p + 1;
+}
+
+// CIR-LABEL: @test_vla_ptr_add
+// CIR: %[[P:.*]] = cir.load{{.*}} %{{.*}} : !cir.ptr<!cir.ptr<!s32i>>, 
!cir.ptr<!s32i>
+// CIR: %[[ONE:.*]] = cir.const #cir.int<1> : !u64i
+// CIR: %[[SCALED:.*]] = cir.mul %[[ONE]], %{{.*}} : !u64i
+// CIR: cir.ptr_stride %[[P]], %[[SCALED]] : (!cir.ptr<!s32i>, !u64i) -> 
!cir.ptr<!s32i>
+
+// LLVM-LABEL: @test_vla_ptr_add
+// LLVM: %[[SCALED:.*]] = mul i64 1, %{{.*}}
+// LLVM: %[[RESULT:.*]] = getelementptr i32, ptr %{{.*}}, i64 %[[SCALED]]
+
+// OGCG-LABEL: @test_vla_ptr_add
+// OGCG: getelementptr inbounds i32, ptr %{{.*}}, i64 %{{.*}}
+
+void test_vla_ptr_inc(int n) {
+  int arr[n];
+  int (*p)[n] = &arr;
+  p++;
+}
+
+// CIR-LABEL: @test_vla_ptr_inc
+// CIR: %[[P:.*]] = cir.load{{.*}} %{{.*}} : !cir.ptr<!cir.ptr<!s32i>>, 
!cir.ptr<!s32i>
+// CIR: cir.ptr_stride %[[P]], %{{.*}} : (!cir.ptr<!s32i>, !u64i) -> 
!cir.ptr<!s32i>
+
+// LLVM-LABEL: @test_vla_ptr_inc
+// LLVM: getelementptr i32, ptr %{{.*}}, i64 %{{.*}}
+
+// OGCG-LABEL: @test_vla_ptr_inc
+// OGCG: getelementptr inbounds nuw i32, ptr %{{.*}}, i64 %{{.*}}
+
+void test_vla_ptr_dec(int n) {
+  int arr[n];
+  int (*p)[n] = &arr;
+  p--;
+}
+
+// CIR-LABEL: @test_vla_ptr_dec
+// CIR: %[[P:.*]] = cir.load{{.*}} %{{.*}} : !cir.ptr<!cir.ptr<!s32i>>, 
!cir.ptr<!s32i>
+// CIR: %[[SIGNED:.*]] = cir.cast integral %{{.*}} : !u64i -> !s64i
+// CIR: %[[NEG:.*]] = cir.minus %[[SIGNED]] : !s64i
+// CIR: cir.ptr_stride %[[P]], %[[NEG]] : (!cir.ptr<!s32i>, !s64i) -> 
!cir.ptr<!s32i>
+
+// LLVM-LABEL: @test_vla_ptr_dec
+// LLVM: getelementptr i32, ptr %{{.*}}, i64 %{{.*}}
+
+// OGCG-LABEL: @test_vla_ptr_dec
+// OGCG: getelementptr inbounds i32, ptr %{{.*}}, i64 %{{.*}}
+

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

Reply via email to