<div dir="ltr">Friendly ping.</div><div class="gmail_extra"><br><br><div class="gmail_quote">2013/4/10 Serge Pavlov <span dir="ltr"><<a href="mailto:sepavloff@gmail.com" target="_blank">sepavloff@gmail.com</a>></span><br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">  Small code enhancement: use overloaded operators of QualType<br>
<div class="im"><br>
Hi rsmith,<br>
<br>
<a href="http://llvm-reviews.chandlerc.com/D637" target="_blank">http://llvm-reviews.chandlerc.com/D637</a><br>
<br>
CHANGE SINCE LAST DIFF<br>
</div>  <a href="http://llvm-reviews.chandlerc.com/D637?vs=1563&id=1580#toc" target="_blank">http://llvm-reviews.chandlerc.com/D637?vs=1563&id=1580#toc</a><br>
<br>
Files:<br>
  include/clang/Basic/DiagnosticSemaKinds.td<br>
  lib/AST/ExprConstant.cpp<br>
<div class="im">  lib/Sema/SemaExpr.cpp<br>
  test/Sema/empty1.c<br>
<br>
Index: include/clang/Basic/DiagnosticSemaKinds.td<br>
===================================================================<br>
--- include/clang/Basic/DiagnosticSemaKinds.td<br>
+++ include/clang/Basic/DiagnosticSemaKinds.td<br>
</div><div><div class="h5">@@ -3976,6 +3976,9 @@<br>
 def warn_offsetof_non_standardlayout_type : ExtWarn<<br>
   "offset of on non-standard-layout type %0">, InGroup<InvalidOffsetof>;<br>
 def err_offsetof_bitfield : Error<"cannot compute offset of bit-field %0">;<br>
+def warn_sub_ptr_zero_size_types : Warning<<br>
+  "subtraction of pointers to type %0 with zero size has undefined behavior">,<br>
+  InGroup<PointerArith>;<br>
<br>
 def warn_floatingpoint_eq : Warning<<br>
   "comparing floating point with == or != is unsafe">,<br>
Index: lib/AST/ExprConstant.cpp<br>
===================================================================<br>
--- lib/AST/ExprConstant.cpp<br>
+++ lib/AST/ExprConstant.cpp<br>
@@ -5003,6 +5003,12 @@<br>
         if (!HandleSizeof(Info, E->getExprLoc(), ElementType, ElementSize))<br>
           return false;<br>
<br>
+        // Empty struct or union in C has size 0 (GCC extension). Meaning of<br>
+        // pointer difference in such case is unspecified, so set ElementSize<br>
+        // to 1 to avoid division by zero.<br>
+        if (ElementSize.isZero())<br>
+            ElementSize = CharUnits::One();<br>
+<br>
         // FIXME: LLVM and GCC both compute LHSOffset - RHSOffset at runtime,<br>
         // and produce incorrect results when it overflows. Such behavior<br>
         // appears to be non-conforming, but is common, so perhaps we should<br>
</div></div><div class="im">Index: lib/Sema/SemaExpr.cpp<br>
===================================================================<br>
--- lib/Sema/SemaExpr.cpp<br>
+++ lib/Sema/SemaExpr.cpp<br>
</div>@@ -6734,6 +6734,19 @@<br>
<div class="im">                                                LHS.get(), RHS.get()))<br>
         return QualType();<br>
<br>
+      if (!getLangOpts().CPlusPlus) {<br>
</div><div class="im">+        // If pointee type is a structure or union of zero size (GCC extension),<br>
</div>+        // the subtraction does not make sense.<br>
+        if (!rpointee->isVoidType() && !rpointee->isFunctionType()) {<br>
<div class="im">+          CharUnits ElementSize = Context.getTypeSizeInChars(rpointee);<br>
</div><div class="im">+          if (ElementSize.isZero()) {<br>
+            Diag(Loc,diag::warn_sub_ptr_zero_size_types)<br>
+              << rpointee.getUnqualifiedType()<br>
</div><div class="im">+              << LHS.get()->getSourceRange() << RHS.get()->getSourceRange();<br>
+          }<br>
</div><div class="im">+        }<br>
+      }<br>
+<br>
       if (CompLHSTy) *CompLHSTy = LHS.get()->getType();<br>
       return Context.getPointerDiffType();<br>
     }<br>
</div><div class="im">Index: test/Sema/empty1.c<br>
===================================================================<br>
--- /dev/null<br>
+++ test/Sema/empty1.c<br>
</div>@@ -0,0 +1,53 @@<br>
<div class="im">+// RUN: %clang_cc1 %s -fsyntax-only -verify<br>
+<br>
+struct empty {};<br>
+struct empty_2 {};<br>
</div>+union  empty_u {};<br>
<div class="im">+<br>
+struct empty* func_1p (struct empty* x) {<br>
+  return x - 5;<br>
+}<br>
+<br>
+int func_1 () {<br>
+  struct empty v[1];<br>
</div>+  return v - v;  // expected-warning {{subtraction of pointers to type 'struct empty' with zero size has undefined behavior}}<br>
<div class="im">+}<br>
+<br>
+int func_2 (struct empty* x) {<br>
</div>+  return 1 + x - x;  // expected-warning {{subtraction of pointers to type 'struct empty' with zero size has undefined behavior}}<br>
<div class="im">+}<br>
+<br>
+int func_3 (struct empty* x, struct empty* y) {<br>
</div>+  return x - y;  // expected-warning {{subtraction of pointers to type 'struct empty' with zero size has undefined behavior}}<br>
<div class="im">+}<br>
+<br>
+int func_4 (struct empty* x, const struct empty* y) {<br>
</div>+  return x - y;  // expected-warning {{subtraction of pointers to type 'struct empty' with zero size has undefined behavior}}<br>
<div class="im">+}<br>
+<br>
+int func_5 (volatile struct empty* x, const struct empty* y) {<br>
</div>+  return x - y;  // expected-warning {{subtraction of pointers to type 'struct empty' with zero size has undefined behavior}}<br>
<div class="im HOEnZb">+}<br>
+<br>
+int func_6 (struct empty* x, struct empty_2* y) {<br>
+  return x - y;  // expected-error {{'struct empty *' and 'struct empty_2 *' are not pointers to compatible types}}<br>
+}<br>
</div><div class="HOEnZb"><div class="h5">+<br>
+int func_7 () {<br>
+  union empty_u v[1];<br>
+  return v - v;  // expected-warning {{subtraction of pointers to type 'union empty_u' with zero size has undefined behavior}}<br>
+}<br>
+<br>
+struct A;  // expected-note {{forward declaration of 'struct A'}}<br>
+<br>
+int func_8 (struct A* x, struct A* y) {<br>
+  return x - y;  // expected-error {{arithmetic on a pointer to an incomplete type 'struct A'}}<br>
+}<br>
+<br>
+int func_9 (struct empty (*x)[10], struct empty (*y)[10]) {<br>
+  return x - y;  // expected-warning {{subtraction of pointers to type 'struct empty [10]' with zero size has undefined behavior}}<br>
+}<br>
+<br>
+int func_10 (struct empty (*x)[], struct empty (*y)[]) {<br>
+  return x - y;  // expected-error {{arithmetic on a pointer to an incomplete type 'struct empty []'}}<br>
+}<br>
</div></div></blockquote></div><br><br clear="all"><div><br></div>-- <br>Thanks,<br>--Serge<br>
</div>