[PATCH] Fix to PR5683 - issue diagnostic for pointer subtraction with type of size zero.

Serge Pavlov sepavloff at gmail.com
Sat Jun 22 03:55:14 PDT 2013


  Updated patch.

Hi rsmith,

http://llvm-reviews.chandlerc.com/D637

CHANGE SINCE LAST DIFF
  http://llvm-reviews.chandlerc.com/D637?vs=2518&id=2538#toc

Files:
  include/clang/Basic/DiagnosticSemaKinds.td
  lib/AST/ExprConstant.cpp
  lib/Sema/SemaExpr.cpp
  test/Sema/empty1.c
  test/Sema/empty1.cpp

Index: include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- include/clang/Basic/DiagnosticSemaKinds.td
+++ include/clang/Basic/DiagnosticSemaKinds.td
@@ -4113,6 +4113,9 @@
 def warn_offsetof_non_standardlayout_type : ExtWarn<
   "offset of on non-standard-layout type %0">, InGroup<InvalidOffsetof>;
 def err_offsetof_bitfield : Error<"cannot compute offset of bit-field %0">;
+def warn_sub_ptr_zero_size_types : Warning<
+  "subtraction of pointers to type %0 of zero size has undefined behavior">,
+  InGroup<PointerArith>;
 
 def warn_floatingpoint_eq : Warning<
   "comparing floating point with == or != is unsafe">,
Index: lib/AST/ExprConstant.cpp
===================================================================
--- lib/AST/ExprConstant.cpp
+++ lib/AST/ExprConstant.cpp
@@ -6405,6 +6405,14 @@
         if (!HandleSizeof(Info, E->getExprLoc(), ElementType, ElementSize))
           return false;
 
+        // As an extension, a type may have zero size (empty struct or union in
+        // C, array of zero length).  Meaning of pointer difference in such
+        // case is unspecified.
+        if (ElementSize.isZero()) {
+          Result = APValue(Info.Ctx.MakeIntValue(0, E->getType()));
+          return true;
+        }
+
         // FIXME: LLVM and GCC both compute LHSOffset - RHSOffset at runtime,
         // and produce incorrect results when it overflows. Such behavior
         // appears to be non-conforming, but is common, so perhaps we should
Index: lib/Sema/SemaExpr.cpp
===================================================================
--- lib/Sema/SemaExpr.cpp
+++ lib/Sema/SemaExpr.cpp
@@ -6870,6 +6870,18 @@
                                                LHS.get(), RHS.get()))
         return QualType();
 
+      // 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)
+            << rpointee.getUnqualifiedType()
+            << LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
+        }
+      }
+
       if (CompLHSTy) *CompLHSTy = LHS.get()->getType();
       return Context.getPointerDiffType();
     }
Index: test/Sema/empty1.c
===================================================================
--- test/Sema/empty1.c
+++ test/Sema/empty1.c
@@ -36,3 +36,50 @@
   struct emp_1 f1;
   union emp_2 f2;
 };
+
+
+// Checks for pointer subtraction (PR15683)
+
+struct emp_1* func_1p (struct emp_1* x) {
+  return x - 5;
+}
+
+int func_1 () {
+  struct emp_1 v[1];
+  return v - v;  // expected-warning {{subtraction of pointers to type 'struct emp_1' of zero size has undefined behavior}}
+}
+
+int func_2 (struct emp_1* x) {
+  return 1 + x - x;  // expected-warning {{subtraction of pointers to type 'struct emp_1' of zero size has undefined behavior}}
+}
+
+int func_3 (struct emp_1* x, struct emp_1* y) {
+  return x - y;  // expected-warning {{subtraction of pointers to type 'struct emp_1' of zero size has undefined behavior}}
+}
+
+int func_4 (struct emp_1* x, const struct emp_1* y) {
+  return x - y;  // expected-warning {{subtraction of pointers to type 'struct emp_1' of zero size has undefined behavior}}
+}
+
+int func_5 (volatile struct emp_1* x, const struct emp_1* y) {
+  return x - y;  // expected-warning {{subtraction of pointers to type 'struct emp_1' of zero size has undefined behavior}}
+}
+
+int func_6 () {
+  union emp_2 v[1];
+  return v - v;  // expected-warning {{subtraction of pointers to type 'union emp_2' of zero size has undefined behavior}}
+}
+
+struct A;  // expected-note {{forward declaration of 'struct A'}}
+
+int func_7 (struct A* x, struct A* y) {
+  return x - y;  // expected-error {{arithmetic on a pointer to an incomplete type 'struct A'}}
+}
+
+int func_8 (struct emp_1 (*x)[10], struct emp_1 (*y)[10]) {
+  return x - y;  // expected-warning {{subtraction of pointers to type 'struct emp_1 [10]' of zero size has undefined behavior}}
+}
+
+int func_9 (struct emp_1 (*x)[], struct emp_1 (*y)[]) {
+  return x - y;  // expected-error {{arithmetic on a pointer to an incomplete type 'struct emp_1 []'}}
+}
Index: test/Sema/empty1.cpp
===================================================================
--- /dev/null
+++ test/Sema/empty1.cpp
@@ -0,0 +1,17 @@
+// RUN: %clang_cc1 %s -fsyntax-only -std=c++11 -verify
+
+int func_1(int (*p1)[0], int (*p2)[0]) {
+  return p1 - p2;  // expected-warning {{subtraction of pointers to type 'int [0]' of zero size has undefined behavior}}
+}
+
+constexpr int (*p1)[0] = 0, (*p2)[0] = 0;
+constexpr int k = p2 - p1;  // expected-warning {{subtraction of pointers to type 'int [0]' of zero size has undefined behavior}}
+
+constexpr int func_2(int (*x1)[0], int (*x2)[0]) {
+  return x1 - x2;  // expected-warning {{subtraction of pointers to type 'int [0]' of zero size has undefined behavior}}
+}
+
+constexpr int func_3(int (*x1)[0], long (*x2)[0]) {
+  return x1 - x2;  // expected-error {{int (*)[0]' and 'long (*)[0]' are not pointers to compatible types}} \
+                   // expected-warning {{of zero size has undefined behavior}}
+}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D637.8.patch
Type: text/x-patch
Size: 5430 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20130622/d18cd2b8/attachment.bin>


More information about the cfe-commits mailing list