r190439 - PR5683: Issue a warning when subtracting pointers to types of zero size, and

Richard Smith richard-llvm at metafoo.co.uk
Tue Sep 10 14:34:14 PDT 2013


Author: rsmith
Date: Tue Sep 10 16:34:14 2013
New Revision: 190439

URL: http://llvm.org/viewvc/llvm-project?rev=190439&view=rev
Log:
PR5683: Issue a warning when subtracting pointers to types of zero size, and
treat such subtractions as being non-constant. Patch by Serge Pavlov! With a
few tweaks by me.

Modified:
    cfe/trunk/include/clang/Basic/DiagnosticASTKinds.td
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/lib/AST/ExprConstant.cpp
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/test/Sema/empty1.c
    cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp

Modified: cfe/trunk/include/clang/Basic/DiagnosticASTKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticASTKinds.td?rev=190439&r1=190438&r2=190439&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticASTKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticASTKinds.td Tue Sep 10 16:34:14 2013
@@ -46,6 +46,8 @@ def note_constexpr_float_arithmetic : No
   "floating point arithmetic produces %select{an infinity|a NaN}0">;
 def note_constexpr_pointer_subtraction_not_same_array : Note<
   "subtracted pointers are not elements of the same array">;
+def note_constexpr_pointer_subtraction_zero_size : Note<
+  "subtraction of pointers to type %0 of zero size">;
 def note_constexpr_pointer_comparison_base_classes : Note<
   "comparison of addresses of subobjects of different base classes "
   "has unspecified value">;

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=190439&r1=190438&r2=190439&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Tue Sep 10 16:34:14 2013
@@ -4191,6 +4191,9 @@ def warn_offsetof_non_pod_type : ExtWarn
 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">,

Modified: cfe/trunk/lib/AST/ExprConstant.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=190439&r1=190438&r2=190439&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ExprConstant.cpp (original)
+++ cfe/trunk/lib/AST/ExprConstant.cpp Tue Sep 10 16:34:14 2013
@@ -6570,6 +6570,15 @@ bool IntExprEvaluator::VisitBinaryOperat
         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). Pointer subtraction in such cases has
+        // undefined behavior, so is not constant.
+        if (ElementSize.isZero()) {
+          Info.Diag(E, diag::note_constexpr_pointer_subtraction_zero_size)
+            << ElementType;
+          return false;
+        }
+
         // 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

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=190439&r1=190438&r2=190439&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Tue Sep 10 16:34:14 2013
@@ -7041,6 +7041,18 @@ QualType Sema::CheckSubtractionOperands(
                                                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();
     }

Modified: cfe/trunk/test/Sema/empty1.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/empty1.c?rev=190439&r1=190438&r2=190439&view=diff
==============================================================================
--- cfe/trunk/test/Sema/empty1.c (original)
+++ cfe/trunk/test/Sema/empty1.c Tue Sep 10 16:34:14 2013
@@ -36,3 +36,50 @@ struct emp_9 { // expected-warning {{str
   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 []'}}
+}
+
+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}}
+}

Modified: cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp?rev=190439&r1=190438&r2=190439&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp (original)
+++ cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp Tue Sep 10 16:34:14 2013
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -triple i686-linux -Wno-string-plus-int -fsyntax-only -fcxx-exceptions -verify -std=c++11 -pedantic %s -Wno-comment
+// RUN: %clang_cc1 -triple i686-linux -Wno-string-plus-int -Wno-pointer-arith -Wno-zero-length-array -fsyntax-only -fcxx-exceptions -verify -std=c++11 -pedantic %s -Wno-comment
 
 namespace StaticAssertFoldTest {
 
@@ -1764,3 +1764,15 @@ namespace Bitfields {
     static_assert(X::f(3) == -1, "3 should truncate to -1");
   }
 }
+
+namespace ZeroSizeTypes {
+  constexpr int (*p1)[0] = 0, (*p2)[0] = 0;
+  constexpr int k = p2 - p1;
+  // expected-error at -1 {{constexpr variable 'k' must be initialized by a constant expression}}
+  // expected-note at -2 {{subtraction of pointers to type 'int [0]' of zero size}}
+
+  int arr[5][0];
+  constexpr int f() { // expected-error {{never produces a constant expression}}
+    return &arr[3] - &arr[0]; // expected-note {{subtraction of pointers to type 'int [0]' of zero size}}
+  }
+}





More information about the cfe-commits mailing list