https://github.com/flash1729 updated 
https://github.com/llvm/llvm-project/pull/217465

>From b0501a0c3355856b6865eead1b2d8be90141e8d7 Mon Sep 17 00:00:00 2001
From: flash1729 <[email protected]>
Date: Mon, 17 Aug 2026 06:20:57 +0530
Subject: [PATCH 1/2] [clang][Sema] Don't report pointer subtraction on a VLA
 as zero size

CheckSubtractionOperands warns when the pointee type has zero size,
because the subtraction divides by that size. A variably modified type
such as int[n] has no statically known size, and getTypeInfoImpl models
it as zero, so the check reported it as an empty type even though its
size is only determined at run time.

Instead of trusting the static size, decide whether the size is provably
zero: walk the array dimensions, folding variable bounds as integer
constant expressions, and warn only when a dimension is provably zero or
the base element type has zero size. This keeps the warning for genuinely
zero-sized cases such as int[0], zero-sized structs, and VLAs of
zero-sized types, while dropping it when the size is simply unknown.

Fixes #28328
---
 clang/docs/ReleaseNotes.md        |  6 ++++++
 clang/lib/Sema/SemaExpr.cpp       | 32 ++++++++++++++++++++++++-------
 clang/test/Analysis/pointer-sub.c |  6 ++----
 clang/test/Sema/empty1.c          | 25 ++++++++++++++++++++++++
 4 files changed, 58 insertions(+), 11 deletions(-)

diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index 30afc3706b3c4..4f37c94443279 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -431,6 +431,12 @@ features cannot lower the translation-unit ABI level;
 
 - Clang now diagnoses more details when a constraint evaluates to false.
 
+- `-Wpointer-arith` no longer reports subtraction of pointers to a variably
+  modified type, such as `int[n]`, as a subtraction of pointers to a type of
+  zero size, unless the size is provably zero: a zero-sized base element or a
+  dimension that is a zero integer constant, as in `struct Empty vla[n]` or
+  `int vla[n][0]`. (#GH28328)
+
 ### Improvements to Clang's time-trace
 
 ### Improvements to Coverage Mapping
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 34f6ccdbc2fe6..8d5238b415224 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -11791,6 +11791,26 @@ QualType Sema::CheckAdditionOperands(ExprResult &LHS, 
ExprResult &RHS,
   return PExp->getType();
 }
 
+/// Determine whether the size of \p T is provably zero: some array dimension
+/// is provably zero or the base element type has zero size. A variable
+/// dimension that does not fold to an integer constant is assumed nonzero.
+static bool isProvablyZeroSize(const ASTContext &Ctx, QualType T) {
+  while (const ArrayType *AT = Ctx.getAsArrayType(T)) {
+    if (const auto *CAT = dyn_cast<ConstantArrayType>(AT)) {
+      if (CAT->isZeroSize())
+        return true;
+    } else if (const auto *VAT = dyn_cast<VariableArrayType>(AT)) {
+      if (const Expr *Bound = VAT->getSizeExpr())
+        if (std::optional<llvm::APSInt> Size =
+                Bound->getIntegerConstantExpr(Ctx))
+          if (*Size == 0)
+            return true;
+    }
+    T = AT->getElementType();
+  }
+  return !T->isIncompleteType() && Ctx.getTypeSizeInChars(T).isZero();
+}
+
 // C99 6.5.6
 QualType Sema::CheckSubtractionOperands(ExprResult &LHS, ExprResult &RHS,
                                         SourceLocation Loc,
@@ -11925,15 +11945,13 @@ QualType Sema::CheckSubtractionOperands(ExprResult 
&LHS, ExprResult &RHS,
 
       // The pointee type may have zero size.  As an extension, a structure or
       // union may have zero size or an array may have zero length.  In this
-      // case subtraction does not make sense.
-      if (!rpointee->isVoidType() && !rpointee->isFunctionType()) {
-        CharUnits ElementSize = Context.getTypeSizeInChars(rpointee);
-        if (ElementSize.isZero()) {
-          Diag(Loc,diag::warn_sub_ptr_zero_size_types)
+      // case subtraction does not make sense.  For a variably modified type,
+      // warn only when the size is provably zero.
+      if (!rpointee->isVoidType() && !rpointee->isFunctionType() &&
+          isProvablyZeroSize(Context, rpointee))
+        Diag(Loc, diag::warn_sub_ptr_zero_size_types)
             << rpointee.getUnqualifiedType()
             << LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
-        }
-      }
 
       if (CompLHSTy) *CompLHSTy = LHS.get()->getType();
       return Context.getPointerDiffType();
diff --git a/clang/test/Analysis/pointer-sub.c 
b/clang/test/Analysis/pointer-sub.c
index 25fb7f043d468..d2155e110ba54 100644
--- a/clang/test/Analysis/pointer-sub.c
+++ b/clang/test/Analysis/pointer-sub.c
@@ -65,11 +65,9 @@ void f4(void) {
   int (*p)[m] = a; // p == &a[0]
   p += 1; // p == &a[1]
 
-  // FIXME: This is a known problem with -Wpointer-arith 
(https://github.com/llvm/llvm-project/issues/28328)
-  int d = p - a; // d == 1 // expected-warning{{subtraction of pointers to 
type 'int[m]' of zero size has undefined behavior}}
+  int d = p - a; // d == 1
 
-  // FIXME: This is a known problem with -Wpointer-arith 
(https://github.com/llvm/llvm-project/issues/28328)
-  d = &(a[2]) - &(a[1]); // expected-warning{{subtraction of pointers to type 
'int[m]' of zero size has undefined behavior}}
+  d = &(a[2]) - &(a[1]);
 
   d = a[2] - a[1]; // expected-warning{{Subtraction of two pointers that}}
 }
diff --git a/clang/test/Sema/empty1.c b/clang/test/Sema/empty1.c
index 6c5fe76833f3f..0d483bed4fc72 100644
--- a/clang/test/Sema/empty1.c
+++ b/clang/test/Sema/empty1.c
@@ -85,3 +85,28 @@ int func_9(struct emp_1 (*x)[], struct emp_1 (*y)[]) {
 int func_10(int (*x)[0], int (*y)[0]) {
   return x - y; // expected-warning {{subtraction of pointers to type 'int[0]' 
of zero size has undefined behavior}}
 }
+
+// A variably modified type is modelled as having zero size because its size is
+// not known statically. It is not an empty type, so it must not be diagnosed.
+int func_11(int n) {
+  int v[n];
+  return &v + 1 - &v;
+}
+
+// Still provably zero-sized: zero-sized base element or a zero constant 
dimension.
+int func_12(int n) {
+  struct emp_1 v[n];
+  return &v + 1 - &v; // expected-warning {{subtraction of pointers to type 
'struct emp_1[n]' of zero size has undefined behavior}}
+}
+
+int func_13(int n) {
+  int v[n][0];
+  return &v + 1 - &v; // expected-warning {{subtraction of pointers to type 
'int[n][0]' of zero size has undefined behavior}}
+}
+
+// A variable bound that folds to a nonzero constant is not zero-sized.
+int func_14(void) {
+  const int four = 4;
+  int v[four];
+  return &v + 1 - &v;
+}

>From b1b6ad6964cfba7c18609271f02d2d08747c1423 Mon Sep 17 00:00:00 2001
From: flash1729 <[email protected]>
Date: Sun, 30 Aug 2026 17:59:48 +0530
Subject: [PATCH 2/2] Fix formatting

---
 clang/lib/Sema/SemaExpr.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 8d5238b415224..ad703248cf325 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -11950,8 +11950,8 @@ QualType Sema::CheckSubtractionOperands(ExprResult 
&LHS, ExprResult &RHS,
       if (!rpointee->isVoidType() && !rpointee->isFunctionType() &&
           isProvablyZeroSize(Context, rpointee))
         Diag(Loc, diag::warn_sub_ptr_zero_size_types)
-            << rpointee.getUnqualifiedType()
-            << LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
+            << rpointee.getUnqualifiedType() << LHS.get()->getSourceRange()
+            << RHS.get()->getSourceRange();
 
       if (CompLHSTy) *CompLHSTy = LHS.get()->getType();
       return Context.getPointerDiffType();

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

Reply via email to