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