This patch refactors the pointer arithmetic checking into a single place in
SemaExpr.cpp. It provides two interfaces, one for checking a single pointer
operand, one for checking both operands of a binary operator. The second
interface goes to some lengths to DTRT for a mixture of good and bad
operands on the LHS or RHS.

It also cleans up several aspects of the accompanying diagnostics to be more
clearly worded, and provide more information when diagnosing (for example)
both the LHS and RHS of a binary operator. It also makes the types shown be
consistently shown as the pointee types instead of pointer types.

There is still a fair amount of cleanup I'd like to do here, potentially
either simplifying some code, hooking up more clients to the code, and/or
lifting more common checking into these routines. This should also help pave
the way for a more principled place to perform warnings such as the
NULL-pointer arithmetic warnings.

One thing I would be particularly interested in feedback on is the text of
the warnings themselves. Any suggestions for further polish or wordsmithing
would be great there. =]

Patch is attached, and also available here:
http://codereview.appspot.com/4631063/
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index 6b710f5..f2f8d28 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -2890,11 +2890,12 @@ def err_ivar_reference_type : Error<
 def err_typecheck_illegal_increment_decrement : Error<
   "cannot %select{decrement|increment}1 value of type %0">;
 def err_typecheck_arithmetic_incomplete_type : Error<
-  "arithmetic on pointer to incomplete type %0">;
+  "arithmetic on a pointer to incomplete type %0">;
 def err_typecheck_pointer_arith_function_type : Error<
-  "arithmetic on pointer to function type %0">;
+  "arithmetic on%select{ a|}0 pointer%select{|s}0 to function type%select{|s}0 "
+  "%1%select{| and %2}0">;
 def err_typecheck_pointer_arith_void_type : Error<
-  "arithmetic on pointer to void type">;
+  "arithmetic on%select{ a|}0 pointer%select{|s}0 to void type%select{|s}0">;
 def err_typecheck_decl_incomplete_type : Error<
   "variable has incomplete type %0">;
 def ext_typecheck_decl_incomplete_type : ExtWarn<
@@ -3082,9 +3083,12 @@ def note_forward_class : Note<
 def err_duplicate_property : Error<
   "property has a previous declaration">;
 def ext_gnu_void_ptr : Extension<
-  "use of GNU void* extension">, InGroup<PointerArith>;
+  "arithmetic on%select{ a|}0 pointer%select{|s}0 to void type%select{|s}0 is a GNU "
+  "extension">,
+  InGroup<PointerArith>;
 def ext_gnu_ptr_func_arith : Extension<
-  "arithmetic on pointer to function type %0 is a GNU extension">,
+  "arithmetic on%select{ a|}0 pointer%select{|s}0 to function type%select{|s}0 "
+  "%1%select{| and %2}0 is a GNU extension">,
   InGroup<PointerArith>;
 def error_readonly_property_assignment : Error<
   "assigning to property with 'readonly' attribute not allowed">;
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index a8e7348..e1d9f61 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -3092,8 +3092,9 @@ Sema::CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc,
 
   if (ResultType->isVoidType() && !getLangOptions().CPlusPlus) {
     // GNU extension: subscripting on pointer to void
+    // FIXME: Use a better warning for this.
     Diag(LLoc, diag::ext_gnu_void_ptr)
-      << BaseExpr->getSourceRange();
+      << 0 << BaseExpr->getSourceRange();
 
     // C forbids expressions of unqualified void type from being l-values.
     // See IsCForbiddenLValueType.
@@ -5602,6 +5603,139 @@ QualType Sema::CheckRemainderOperands(
   return compType;
 }
 
+/// \brief Diagnose invalid arithmetic on two void pointers.
+static void diagnoseArithmeticOnTwoVoidPointers(Sema &S, SourceLocation Loc,
+                                                Expr *LHS, Expr *RHS) {
+  S.Diag(Loc, S.getLangOptions().CPlusPlus
+                ? diag::err_typecheck_pointer_arith_void_type
+                : diag::ext_gnu_void_ptr)
+    << 1 << LHS->getSourceRange() << RHS->getSourceRange();
+}
+
+/// \brief Diagnose invalid arithmetic on a void pointer.
+static void diagnoseArithmeticOnVoidPointer(Sema &S, SourceLocation Loc,
+                                            Expr *Pointer) {
+  S.Diag(Loc, S.getLangOptions().CPlusPlus
+                ? diag::err_typecheck_pointer_arith_void_type
+                : diag::ext_gnu_void_ptr)
+    << 0 << Pointer->getSourceRange();
+}
+
+/// \brief Diagnose invalid arithmetic on two function pointers.
+static void diagnoseArithmeticOnTwoFunctionPointers(Sema &S, SourceLocation Loc,
+                                                    Expr *LHS, Expr *RHS) {
+  assert(LHS->getType()->isAnyPointerType());
+  assert(RHS->getType()->isAnyPointerType());
+  S.Diag(Loc, S.getLangOptions().CPlusPlus
+                ? diag::err_typecheck_pointer_arith_function_type
+                : diag::ext_gnu_ptr_func_arith)
+    << 1 << LHS->getType()->getPointeeType() << RHS->getType()->getPointeeType()
+    << LHS->getSourceRange() << RHS->getSourceRange();
+}
+
+/// \brief Diagnose invalid arithmetic on a function pointer.
+static void diagnoseArithmeticOnFunctionPointer(Sema &S, SourceLocation Loc,
+                                                Expr *Pointer) {
+  assert(Pointer->getType()->isAnyPointerType());
+  S.Diag(Loc, S.getLangOptions().CPlusPlus
+                ? diag::err_typecheck_pointer_arith_function_type
+                : diag::ext_gnu_ptr_func_arith)
+    << 0 << Pointer->getType()->getPointeeType() << Pointer->getSourceRange();
+}
+
+/// \brief Check the validity of an arithmetic pointer operand.
+///
+/// If the operand has pointer type, this code will check for pointer types
+/// which are invalid in arithmetic operations. These will be diagnosed
+/// appropriately, including whether or not the use is supported as an
+/// extension.
+///
+/// \returns True when the operand is valid to use (even if as an extension).
+static bool checkArithmeticOpPointerOperand(Sema &S, SourceLocation Loc,
+                                            Expr *Operand) {
+  if (!Operand->getType()->isAnyPointerType()) return true;
+
+  QualType PointeeTy = Operand->getType()->getPointeeType();
+  if (PointeeTy->isVoidType()) {
+    diagnoseArithmeticOnVoidPointer(S, Loc, Operand);
+    return !S.getLangOptions().CPlusPlus;
+  }
+  if (PointeeTy->isFunctionType()) {
+    diagnoseArithmeticOnFunctionPointer(S, Loc, Operand);
+    return !S.getLangOptions().CPlusPlus;
+  }
+
+  if ((Operand->getType()->isPointerType() &&
+       !Operand->getType()->isDependentType()) ||
+      Operand->getType()->isObjCObjectPointerType()) {
+    QualType PointeeTy = Operand->getType()->getPointeeType();
+    if (S.RequireCompleteType(
+          Loc, PointeeTy,
+          S.PDiag(diag::err_typecheck_arithmetic_incomplete_type)
+            << PointeeTy << Operand->getSourceRange()))
+      return false;
+  }
+
+  return true;
+}
+
+/// \brief Check the validity of a binary arithmetic operation w.r.t. pointer
+/// operands.
+///
+/// This routine will diagnose any invalid arithmetic on pointer operands much
+/// like \see checkArithmeticOpPointerOperand. However, it has special logic
+/// for emitting a single diagnostic even for operations where both LHS and RHS
+/// are (potentially problematic) pointers.
+///
+/// \returns True when the operand is valid to use (even if as an extension).
+static bool checkArithmeticBinOpPointerOperands(Sema &S, SourceLocation Loc,
+                                                Expr *LHS, Expr *RHS) {
+  bool isLHSPointer = LHS->getType()->isAnyPointerType();
+  bool isRHSPointer = RHS->getType()->isAnyPointerType();
+  if (!isLHSPointer && !isRHSPointer) return true;
+
+  QualType LHSPointeeTy, RHSPointeeTy;
+  if (isLHSPointer) LHSPointeeTy = LHS->getType()->getPointeeType();
+  if (isRHSPointer) RHSPointeeTy = RHS->getType()->getPointeeType();
+
+  // Check for arithmetic on pointers to incomplete types.
+  bool isLHSVoidPtr = isLHSPointer && LHSPointeeTy->isVoidType();
+  bool isRHSVoidPtr = isRHSPointer && RHSPointeeTy->isVoidType();
+  if (isLHSVoidPtr || isRHSVoidPtr) {
+    if (!isRHSVoidPtr) diagnoseArithmeticOnVoidPointer(S, Loc, LHS);
+    else if (!isLHSVoidPtr) diagnoseArithmeticOnVoidPointer(S, Loc, RHS);
+    else diagnoseArithmeticOnTwoVoidPointers(S, Loc, LHS, RHS);
+
+    return !S.getLangOptions().CPlusPlus;
+  }
+
+  bool isLHSFuncPtr = isLHSPointer && LHSPointeeTy->isFunctionType();
+  bool isRHSFuncPtr = isRHSPointer && RHSPointeeTy->isFunctionType();
+  if (isLHSFuncPtr || isRHSFuncPtr) {
+    if (!isRHSFuncPtr) diagnoseArithmeticOnFunctionPointer(S, Loc, LHS);
+    else if (!isLHSFuncPtr) diagnoseArithmeticOnFunctionPointer(S, Loc, RHS);
+    else diagnoseArithmeticOnTwoFunctionPointers(S, Loc, LHS, RHS);
+
+    return !S.getLangOptions().CPlusPlus;
+  }
+
+  Expr *Operands[] = { LHS, RHS };
+  for (unsigned i = 0; i < 2; ++i) {
+    Expr *Operand = Operands[i];
+    if ((Operand->getType()->isPointerType() &&
+         !Operand->getType()->isDependentType()) ||
+        Operand->getType()->isObjCObjectPointerType()) {
+      QualType PointeeTy = Operand->getType()->getPointeeType();
+      if (S.RequireCompleteType(
+            Loc, PointeeTy,
+            S.PDiag(diag::err_typecheck_arithmetic_incomplete_type)
+              << PointeeTy << Operand->getSourceRange()))
+        return false;
+    }
+  }
+  return true;
+}
+
 QualType Sema::CheckAdditionOperands( // C99 6.5.6
   ExprResult &lex, ExprResult &rex, SourceLocation Loc, QualType* CompLHSTy) {
   if (lex.get()->getType()->isVectorType() || rex.get()->getType()->isVectorType()) {
@@ -5627,42 +5761,12 @@ QualType Sema::CheckAdditionOperands( // C99 6.5.6
     std::swap(PExp, IExp);
 
   if (PExp->getType()->isAnyPointerType()) {
-
     if (IExp->getType()->isIntegerType()) {
-      QualType PointeeTy = PExp->getType()->getPointeeType();
-
-      // Check for arithmetic on pointers to incomplete types.
-      if (PointeeTy->isVoidType()) {
-        if (getLangOptions().CPlusPlus) {
-          Diag(Loc, diag::err_typecheck_pointer_arith_void_type)
-            << lex.get()->getSourceRange() << rex.get()->getSourceRange();
-          return QualType();
-        }
+      if (!checkArithmeticOpPointerOperand(*this, Loc, PExp))
+        return QualType();
 
-        // GNU extension: arithmetic on pointer to void
-        Diag(Loc, diag::ext_gnu_void_ptr)
-          << lex.get()->getSourceRange() << rex.get()->getSourceRange();
-      } else if (PointeeTy->isFunctionType()) {
-        if (getLangOptions().CPlusPlus) {
-          Diag(Loc, diag::err_typecheck_pointer_arith_function_type)
-            << PExp->getType() << PExp->getSourceRange();
-          return QualType();
-        }
+      QualType PointeeTy = PExp->getType()->getPointeeType();
 
-        // GNU extension: arithmetic on pointer to function
-        Diag(Loc, diag::ext_gnu_ptr_func_arith)
-          << PExp->getType() << PExp->getSourceRange();
-      } else {
-        // Check if we require a complete type.
-        if (((PExp->getType()->isPointerType() &&
-              !PExp->getType()->isDependentType()) ||
-              PExp->getType()->isObjCObjectPointerType()) &&
-             RequireCompleteType(Loc, PointeeTy,
-                           PDiag(diag::err_typecheck_arithmetic_incomplete_type)
-                             << PExp->getSourceRange()
-                             << PExp->getType()))
-          return QualType();
-      }
       // Diagnose bad cases where we step over interface counts.
       if (PointeeTy->isObjCObjectType() && LangOpts.ObjCNonFragileABI) {
         Diag(Loc, diag::err_arithmetic_nonfragile_interface)
@@ -5712,35 +5816,6 @@ QualType Sema::CheckSubtractionOperands(ExprResult &lex, ExprResult &rex,
   if (lex.get()->getType()->isAnyPointerType()) {
     QualType lpointee = lex.get()->getType()->getPointeeType();
 
-    // The LHS must be an completely-defined object type.
-
-    bool ComplainAboutVoid = false;
-    Expr *ComplainAboutFunc = 0;
-    if (lpointee->isVoidType()) {
-      if (getLangOptions().CPlusPlus) {
-        Diag(Loc, diag::err_typecheck_pointer_arith_void_type)
-          << lex.get()->getSourceRange() << rex.get()->getSourceRange();
-        return QualType();
-      }
-
-      // GNU C extension: arithmetic on pointer to void
-      ComplainAboutVoid = true;
-    } else if (lpointee->isFunctionType()) {
-      if (getLangOptions().CPlusPlus) {
-        Diag(Loc, diag::err_typecheck_pointer_arith_function_type)
-          << lex.get()->getType() << lex.get()->getSourceRange();
-        return QualType();
-      }
-
-      // GNU C extension: arithmetic on pointer to function
-      ComplainAboutFunc = lex.get();
-    } else if (!lpointee->isDependentType() &&
-               RequireCompleteType(Loc, lpointee,
-                                   PDiag(diag::err_typecheck_sub_ptr_object)
-                                     << lex.get()->getSourceRange()
-                                     << lex.get()->getType()))
-      return QualType();
-
     // Diagnose bad cases where we step over interface counts.
     if (lpointee->isObjCObjectType() && LangOpts.ObjCNonFragileABI) {
       Diag(Loc, diag::err_arithmetic_nonfragile_interface)
@@ -5750,13 +5825,8 @@ QualType Sema::CheckSubtractionOperands(ExprResult &lex, ExprResult &rex,
 
     // The result type of a pointer-int computation is the pointer type.
     if (rex.get()->getType()->isIntegerType()) {
-      if (ComplainAboutVoid)
-        Diag(Loc, diag::ext_gnu_void_ptr)
-          << lex.get()->getSourceRange() << rex.get()->getSourceRange();
-      if (ComplainAboutFunc)
-        Diag(Loc, diag::ext_gnu_ptr_func_arith)
-          << ComplainAboutFunc->getType()
-          << ComplainAboutFunc->getSourceRange();
+      if (!checkArithmeticOpPointerOperand(*this, Loc, lex.get()))
+        return QualType();
 
       if (CompLHSTy) *CompLHSTy = lex.get()->getType();
       return lex.get()->getType();
@@ -5766,33 +5836,6 @@ QualType Sema::CheckSubtractionOperands(ExprResult &lex, ExprResult &rex,
     if (const PointerType *RHSPTy = rex.get()->getType()->getAs<PointerType>()) {
       QualType rpointee = RHSPTy->getPointeeType();
 
-      // RHS must be a completely-type object type.
-      // Handle the GNU void* extension.
-      if (rpointee->isVoidType()) {
-        if (getLangOptions().CPlusPlus) {
-          Diag(Loc, diag::err_typecheck_pointer_arith_void_type)
-            << lex.get()->getSourceRange() << rex.get()->getSourceRange();
-          return QualType();
-        }
-
-        ComplainAboutVoid = true;
-      } else if (rpointee->isFunctionType()) {
-        if (getLangOptions().CPlusPlus) {
-          Diag(Loc, diag::err_typecheck_pointer_arith_function_type)
-            << rex.get()->getType() << rex.get()->getSourceRange();
-          return QualType();
-        }
-
-        // GNU extension: arithmetic on pointer to function
-        if (!ComplainAboutFunc)
-          ComplainAboutFunc = rex.get();
-      } else if (!rpointee->isDependentType() &&
-                 RequireCompleteType(Loc, rpointee,
-                                     PDiag(diag::err_typecheck_sub_ptr_object)
-                                       << rex.get()->getSourceRange()
-                                       << rex.get()->getType()))
-        return QualType();
-
       if (getLangOptions().CPlusPlus) {
         // Pointee types must be the same: C++ [expr.add]
         if (!Context.hasSameUnqualifiedType(lpointee, rpointee)) {
@@ -5813,13 +5856,9 @@ QualType Sema::CheckSubtractionOperands(ExprResult &lex, ExprResult &rex,
         }
       }
 
-      if (ComplainAboutVoid)
-        Diag(Loc, diag::ext_gnu_void_ptr)
-          << lex.get()->getSourceRange() << rex.get()->getSourceRange();
-      if (ComplainAboutFunc)
-        Diag(Loc, diag::ext_gnu_ptr_func_arith)
-          << ComplainAboutFunc->getType()
-          << ComplainAboutFunc->getSourceRange();
+      if (!checkArithmeticBinOpPointerOperands(*this, Loc,
+                                               lex.get(), rex.get()))
+        return QualType();
 
       if (CompLHSTy) *CompLHSTy = lex.get()->getType();
       return Context.getPointerDiffType();
@@ -6826,29 +6865,9 @@ static QualType CheckIncrementDecrementOperand(Sema &S, Expr *Op,
     QualType PointeeTy = ResType->getPointeeType();
 
     // C99 6.5.2.4p2, 6.5.6p2
-    if (PointeeTy->isVoidType()) {
-      if (S.getLangOptions().CPlusPlus) {
-        S.Diag(OpLoc, diag::err_typecheck_pointer_arith_void_type)
-          << Op->getSourceRange();
-        return QualType();
-      }
-
-      // Pointer to void is a GNU extension in C.
-      S.Diag(OpLoc, diag::ext_gnu_void_ptr) << Op->getSourceRange();
-    } else if (PointeeTy->isFunctionType()) {
-      if (S.getLangOptions().CPlusPlus) {
-        S.Diag(OpLoc, diag::err_typecheck_pointer_arith_function_type)
-          << Op->getType() << Op->getSourceRange();
-        return QualType();
-      }
-
-      S.Diag(OpLoc, diag::ext_gnu_ptr_func_arith)
-        << ResType << Op->getSourceRange();
-    } else if (S.RequireCompleteType(OpLoc, PointeeTy,
-                 S.PDiag(diag::err_typecheck_arithmetic_incomplete_type)
-                             << Op->getSourceRange()
-                             << ResType))
+    if (!checkArithmeticOpPointerOperand(S, OpLoc, Op))
       return QualType();
+
     // Diagnose bad cases where we step over interface counts.
     else if (PointeeTy->isObjCObjectType() && S.LangOpts.ObjCNonFragileABI) {
       S.Diag(OpLoc, diag::err_arithmetic_nonfragile_interface)
diff --git a/test/CXX/stmt.stmt/stmt.iter/stmt.ranged/p1.cpp b/test/CXX/stmt.stmt/stmt.iter/stmt.ranged/p1.cpp
index 7bfa6fe..0c92f62 100644
--- a/test/CXX/stmt.stmt/stmt.iter/stmt.ranged/p1.cpp
+++ b/test/CXX/stmt.stmt/stmt.iter/stmt.ranged/p1.cpp
@@ -129,7 +129,7 @@ void g() {
     void *begin(); // expected-note {{selected 'begin' function with iterator type 'void *'}}
     void *end();
   };
-  for (auto u : NoIncr()) { // expected-error {{arithmetic on pointer to void type}}
+  for (auto u : NoIncr()) { // expected-error {{arithmetic on a pointer to void type}}
   }
 
   struct NoNotEq {
diff --git a/test/Sema/incomplete-decl.c b/test/Sema/incomplete-decl.c
index e5b6d5f..18eac3a 100644
--- a/test/Sema/incomplete-decl.c
+++ b/test/Sema/incomplete-decl.c
@@ -22,7 +22,7 @@ void func() {
 }
 
 int h[]; // expected-warning {{tentative array definition assumed to have one element}}
-int (*i)[] = &h+1; // expected-error {{arithmetic on pointer to incomplete type 'int (*)[]'}}
+int (*i)[] = &h+1; // expected-error {{arithmetic on a pointer to incomplete type 'int []'}}
 
 struct bar j = {1}; // expected-error {{variable has incomplete type 'struct bar'}} \
     expected-note {{forward declaration of 'struct bar'}}
diff --git a/test/Sema/pointer-addition.c b/test/Sema/pointer-addition.c
index 01047a0..8cd697b 100644
--- a/test/Sema/pointer-addition.c
+++ b/test/Sema/pointer-addition.c
@@ -3,19 +3,19 @@
 typedef struct S S; // expected-note 3 {{forward declaration of 'struct S'}}
 void a(S* b, void* c) {
   void (*fp)(int) = 0;
-  b++;       // expected-error {{arithmetic on pointer to incomplete type}}
-  b += 1;    // expected-error {{arithmetic on pointer to incomplete type}}
-  c++;       // expected-warning {{use of GNU void* extension}}
-  c += 1;    // expected-warning {{use of GNU void* extension}}
-  c--;       // expected-warning {{use of GNU void* extension}}
-  c -= 1;    // expected-warning {{use of GNU void* extension}}
-  (void) c[1]; // expected-warning {{use of GNU void* extension}}
-  b = 1+b;   // expected-error {{arithmetic on pointer to incomplete type}}
+  b++;       // expected-error {{arithmetic on a pointer to incomplete type}}
+  b += 1;    // expected-error {{arithmetic on a pointer to incomplete type}}
+  c++;       // expected-warning {{arithmetic on a pointer to void type is a GNU extension}}
+  c += 1;    // expected-warning {{arithmetic on a pointer to void type is a GNU extension}}
+  c--;       // expected-warning {{arithmetic on a pointer to void type is a GNU extension}}
+  c -= 1;    // expected-warning {{arithmetic on a pointer to void type is a GNU extension}}
+  (void) c[1]; // expected-warning {{arithmetic on a pointer to void type is a GNU extension}}
+  b = 1+b;   // expected-error {{arithmetic on a pointer to incomplete type}}
   /* The next couple tests are only pedantic warnings in gcc */
   void (*d)(S*,void*) = a;
-  d += 1;    // expected-warning {{arithmetic on pointer to function type 'void (*)(S *, void *)' is a GNU extension}}
-  d++;       // expected-warning {{arithmetic on pointer to function type 'void (*)(S *, void *)' is a GNU extension}}
-  d--;       // expected-warning {{arithmetic on pointer to function type 'void (*)(S *, void *)' is a GNU extension}}
-  d -= 1;    // expected-warning {{arithmetic on pointer to function type 'void (*)(S *, void *)' is a GNU extension}}
-  (void)(1 + d); // expected-warning {{arithmetic on pointer to function type 'void (*)(S *, void *)' is a GNU extension}}
+  d += 1;    // expected-warning {{arithmetic on a pointer to function type 'void (S *, void *)' is a GNU extension}}
+  d++;       // expected-warning {{arithmetic on a pointer to function type 'void (S *, void *)' is a GNU extension}}
+  d--;       // expected-warning {{arithmetic on a pointer to function type 'void (S *, void *)' is a GNU extension}}
+  d -= 1;    // expected-warning {{arithmetic on a pointer to function type 'void (S *, void *)' is a GNU extension}}
+  (void)(1 + d); // expected-warning {{arithmetic on a pointer to function type 'void (S *, void *)' is a GNU extension}}
 }
diff --git a/test/Sema/pointer-subtract-compat.c b/test/Sema/pointer-subtract-compat.c
index 70340c6..44570c4 100644
--- a/test/Sema/pointer-subtract-compat.c
+++ b/test/Sema/pointer-subtract-compat.c
@@ -7,5 +7,5 @@ int a(char* a, rchar* b) {
 
 // <rdar://problem/6520707> 
 void f0(void (*fp)(void)) {
-  int x = fp - fp; // expected-warning{{arithmetic on pointer to function type 'void (*)(void)' is a GNU extension}}
+  int x = fp - fp; // expected-warning{{arithmetic on pointers to function types 'void (void)' and 'void (void)' is a GNU extension}}
 }
diff --git a/test/Sema/typecheck-binop.c b/test/Sema/typecheck-binop.c
index 712dad2..8e4d284 100644
--- a/test/Sema/typecheck-binop.c
+++ b/test/Sema/typecheck-binop.c
@@ -7,15 +7,15 @@ int sub1(int *a, double *b) {
 }
 
 void *sub2(struct incomplete *P) {
-  return P-4;      /* expected-error{{subtraction of pointer 'struct incomplete *' requires pointee to be a complete object type}} */
+  return P-4;      /* expected-error{{arithmetic on a pointer to incomplete type 'struct incomplete'}} */
 }
 
 void *sub3(void *P) {
-  return P-4;      /* expected-warning{{GNU void* extension}} */
+  return P-4;      /* expected-warning{{arithmetic on a pointer to void type is a GNU extension}} */
 }
 
 int sub4(void *P, void *Q) {
-  return P-Q;      /* expected-warning{{GNU void* extension}} */
+  return P-Q;      /* expected-warning{{arithmetic on pointers to void types is a GNU extension}} */
 }
 
 int sub5(void *P, int *Q) {
diff --git a/test/SemaCXX/null_in_arithmetic_ops.cpp b/test/SemaCXX/null_in_arithmetic_ops.cpp
index 26af5e6..0e9b3fc 100644
--- a/test/SemaCXX/null_in_arithmetic_ops.cpp
+++ b/test/SemaCXX/null_in_arithmetic_ops.cpp
@@ -33,7 +33,7 @@ void f() {
   v = 0 ? NULL + d : d + NULL; // \
     expected-error {{invalid operands to binary expression ('long' and 'void (X::*)()')}} \
     expected-error {{invalid operands to binary expression ('void (X::*)()' and 'long')}}
-  v = 0 ? NULL + e : e + NULL; // expected-error 2{{arithmetic on pointer to function type 'void (*)()'}}
+  v = 0 ? NULL + e : e + NULL; // expected-error 2{{arithmetic on a pointer to function type 'void ()'}}
   v = 0 ? NULL + f : f + NULL; // expected-warning 2{{use of NULL in arithmetic operation}}
   v = 0 ? NULL + "f" : "f" + NULL; // expected-warning 2{{use of NULL in arithmetic operation}}
 
diff --git a/test/SemaObjC/sizeof-interface.m b/test/SemaObjC/sizeof-interface.m
index 3fe3964..88d2ae1 100644
--- a/test/SemaObjC/sizeof-interface.m
+++ b/test/SemaObjC/sizeof-interface.m
@@ -7,7 +7,7 @@ int g0 = sizeof(I0); // expected-error{{invalid application of 'sizeof' to an in
 
 // rdar://6821047
 void *g3(I0 *P) {
-  P = P+5;        // expected-error {{arithmetic on pointer to incomplete type 'I0 *'}}
+  P = P+5;        // expected-error {{arithmetic on a pointer to incomplete type 'I0'}}
 
   return &P[4];   // expected-error{{subscript of pointer to incomplete type 'I0'}}
 }
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to