[PATCH] Fix to PR5683 - issue diagnostic for pointer subtraction with type of size zero.
Serge Pavlov
sepavloff at gmail.com
Wed Jun 19 23:29:24 PDT 2013
Updated code in ExprConstant.cpp and test case.
Hi rsmith,
http://llvm-reviews.chandlerc.com/D637
CHANGE SINCE LAST DIFF
http://llvm-reviews.chandlerc.com/D637?vs=1580&id=2498#toc
Files:
include/clang/Basic/DiagnosticASTKinds.td
include/clang/Basic/DiagnosticSemaKinds.td
lib/AST/ExprConstant.cpp
lib/Sema/SemaExpr.cpp
test/Sema/empty1.c
Index: include/clang/Basic/DiagnosticASTKinds.td
===================================================================
--- include/clang/Basic/DiagnosticASTKinds.td
+++ include/clang/Basic/DiagnosticASTKinds.td
@@ -46,6 +46,8 @@
"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_types : Note<
+ "subtracted pointers point to elements of zero size type">;
def note_constexpr_pointer_comparison_base_classes : Note<
"comparison of addresses of subobjects of different base classes "
"has unspecified value">;
Index: include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- include/clang/Basic/DiagnosticSemaKinds.td
+++ include/clang/Basic/DiagnosticSemaKinds.td
@@ -4112,6 +4112,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 with 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
@@ -6360,6 +6360,13 @@
if (!HandleSizeof(Info, E->getExprLoc(), ElementType, ElementSize))
return false;
+ // Empty struct or union in C has size 0 (GCC extension). Meaning of
+ // pointer difference in such case is unspecified.
+ if (ElementSize.isZero()) {
+ CCEDiag(E, diag::note_constexpr_pointer_subtraction_zero_size_types);
+ 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
Index: lib/Sema/SemaExpr.cpp
===================================================================
--- lib/Sema/SemaExpr.cpp
+++ lib/Sema/SemaExpr.cpp
@@ -6865,6 +6865,19 @@
LHS.get(), RHS.get()))
return QualType();
+ if (!getLangOpts().CPlusPlus) {
+ // If pointee type is a structure or union of zero size (GCC extension),
+ // the 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' with 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' with 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' with 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' with 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' with 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' with 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]' with 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 []'}}
+}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D637.6.patch
Type: text/x-patch
Size: 5123 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20130619/9bbf2ebe/attachment.bin>
More information about the cfe-commits
mailing list