[PATCH] Fix to PR5683 - issue diagnostic for pointer subtraction with type of size zero.
Eli Friedman
eli.friedman at gmail.com
Mon Aug 19 12:36:35 PDT 2013
On Mon, Aug 19, 2013 at 9:10 AM, Serge Pavlov <sepavloff at gmail.com> wrote:
> Friendly ping.
>
>
> 2013/6/22 Serge Pavlov <sepavloff at gmail.com>
>
>> 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
>>
>>
C++-specific tests should go into test/SemaCXX/
Otherwise looks fine, but please let Richard take another look at the
ExprConstant.cpp changes first.
-Eli
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20130819/48e475a9/attachment.html>
More information about the cfe-commits
mailing list