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

Richard Smith richard at metafoo.co.uk
Tue Sep 10 14:37:03 PDT 2013


Committed with a few tweaks as r190439.


On Mon, Sep 9, 2013 at 7:20 PM, Serge Pavlov <sepavloff at gmail.com> wrote:

> Friedly ping.
>
>
> 2013/8/30 Serge Pavlov <sepavloff at gmail.com>
>
>>   Added giagnostics related to constexpr.
>>   Error is produced by the code that expects constexpr. However issuing a
>> message why the
>>   expression is not constant is more user friendly. With this patch
>> compiler generates an
>>   appropriate note, similar to other cases in expression evaluators.
>> CCEDiag is used to
>>   report the message as this is core constant expression violation.
>>
>> Hi rsmith,
>>
>> http://llvm-reviews.chandlerc.com/D637
>>
>> CHANGE SINCE LAST DIFF
>>   http://llvm-reviews.chandlerc.com/D637?vs=3863&id=3913#toc
>>
>> Files:
>>   include/clang/Basic/DiagnosticASTKinds.td
>>   include/clang/Basic/DiagnosticSemaKinds.td
>>   lib/AST/ExprConstant.cpp
>>   lib/Sema/SemaExpr.cpp
>>   test/Sema/empty1.c
>>   test/SemaCXX/empty1.cpp
>>
>> Index: include/clang/Basic/DiagnosticASTKinds.td
>> ===================================================================
>> --- include/clang/Basic/DiagnosticASTKinds.td
>> +++ include/clang/Basic/DiagnosticASTKinds.td
>> @@ -139,6 +139,8 @@
>>  def warn_integer_constant_overflow : Warning<
>>    "overflow in expression; result is %0 with type %1">,
>>    InGroup<DiagGroup<"integer-overflow">>;
>> +def note_undefined_is_not_constexpr : Note<"operation with undefined
>> behavior "
>> +  "cannot be used in constant expression">;
>>
>>  // inline asm related.
>>  let CategoryName = "Inline Assembly Issue" in {
>> Index: include/clang/Basic/DiagnosticSemaKinds.td
>> ===================================================================
>> --- include/clang/Basic/DiagnosticSemaKinds.td
>> +++ include/clang/Basic/DiagnosticSemaKinds.td
>> @@ -4179,6 +4179,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
>> @@ -6570,6 +6570,17 @@
>>          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()) {
>> +          // C++11 [expr.const]p2:
>> +          //   A conditional-expression is a core constant expression
>> unless it
>> +          //   involves ... an operation that would have undefined
>> behavior...
>> +          CCEDiag(E, diag::note_undefined_is_not_constexpr);
>> +          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
>> @@ -7040,6 +7040,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/SemaCXX/empty1.cpp
>> ===================================================================
>> --- /dev/null
>> +++ test/SemaCXX/empty1.cpp
>> @@ -0,0 +1,19 @@
>> +// 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}} \
>> +                            // expected-note {{operation with undefined
>> behavior cannot be used in constant expression}} \
>> +                            // expected-error {{constexpr variable 'k'
>> must be initialized by a constant expression}}
>> +
>> +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}}
>> +}
>>
>
>
>
> --
> Thanks,
> --Serge
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20130910/be9ce447/attachment.html>


More information about the cfe-commits mailing list