Anastasia updated this revision to Diff 245647.
Anastasia added a comment.

- Always set `isInvalid` for all error cases.
- Hoist setting `isInvalid` together with an error diagnostic.
- Updated more tests.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D74116/new/

https://reviews.llvm.org/D74116

Files:
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/include/clang/Sema/Sema.h
  clang/lib/Sema/SemaExpr.cpp
  clang/lib/Sema/SemaExprCXX.cpp
  clang/test/CXX/conv/conv.fctptr/p1.cpp
  clang/test/CXX/drs/dr3xx.cpp
  clang/test/CXX/except/except.handle/p16.cpp
  clang/test/CXX/expr/p13.cpp
  clang/test/CXX/temp/temp.spec/temp.expl.spec/p19.cpp
  clang/test/CXX/temp/temp.spec/temp.explicit/p10.cpp
  clang/test/CXX/temp/temp.spec/temp.explicit/p9.cpp
  clang/test/OpenMP/allocate_allocator_messages.cpp
  clang/test/Sema/block-call.c
  clang/test/Sema/block-return.c
  clang/test/Sema/callingconv-ms_abi.c
  clang/test/Sema/callingconv-sysv_abi.c
  clang/test/Sema/callingconv.c
  clang/test/Sema/overloadable.c
  clang/test/Sema/pass-object-size.c
  clang/test/Sema/preserve-call-conv.c
  clang/test/SemaCXX/addr-of-overloaded-function.cpp
  clang/test/SemaCXX/decl-microsoft-call-conv.cpp
  clang/test/SemaCXX/goto.cpp
  clang/test/SemaCXX/int-ptr-cast-SFINAE.cpp
  clang/test/SemaCXX/ms-property-error.cpp
  clang/test/SemaObjC/arc.m
  clang/test/SemaObjC/comptypes-legal.m
  clang/test/SemaObjCXX/arc-type-conversion.mm
  clang/test/SemaObjCXX/comptypes-1.mm
  clang/test/SemaObjCXX/comptypes-7.mm
  clang/test/SemaObjCXX/instantiate-expr.mm
  clang/test/SemaObjCXX/instantiate-stmt.mm
  clang/test/SemaObjCXX/noescape.mm
  clang/test/SemaObjCXX/nullability-pragmas.mm
  clang/test/SemaObjCXX/objc-container-subscripting.mm
  clang/test/SemaObjCXX/parameterized_classes_subst.mm
  clang/test/SemaObjCXX/property-invalid-type.mm
  clang/test/SemaOpenCL/address-spaces-conversions-cl2.0.cl
  clang/test/SemaOpenCL/address-spaces.cl
  clang/test/SemaTemplate/extern-templates.cpp
  clang/test/SemaTemplate/instantiate-member-class.cpp
  clang/test/SemaTemplate/member-access-expr.cpp
  clang/test/SemaTemplate/temp_arg_nontype.cpp

Index: clang/test/SemaTemplate/temp_arg_nontype.cpp
===================================================================
--- clang/test/SemaTemplate/temp_arg_nontype.cpp
+++ clang/test/SemaTemplate/temp_arg_nontype.cpp
@@ -194,7 +194,7 @@
   template<typename T>
   struct Y {
     static void f(T x) { 
-      x = 1; // expected-error{{assigning to 'int *' from incompatible type 'int'}}
+      x = 1; // expected-error{{incompatible integer to pointer conversion assigning to 'int *' from 'int'}}
     }
   };
 
Index: clang/test/SemaTemplate/member-access-expr.cpp
===================================================================
--- clang/test/SemaTemplate/member-access-expr.cpp
+++ clang/test/SemaTemplate/member-access-expr.cpp
@@ -156,7 +156,7 @@
     void get(B **ptr) {
       // It's okay if at some point we figure out how to diagnose this
       // at instantiation time.
-      *ptr = field; // expected-error {{assigning to 'test6::B *' from incompatible type 'test6::A *}}
+      *ptr = field; // expected-error {{incompatible pointer types assigning to 'test6::B *' from 'test6::A *'}}
     }
   };
 }
Index: clang/test/SemaTemplate/instantiate-member-class.cpp
===================================================================
--- clang/test/SemaTemplate/instantiate-member-class.cpp
+++ clang/test/SemaTemplate/instantiate-member-class.cpp
@@ -43,8 +43,8 @@
 X<float>::X *xf; // expected-error{{qualified reference to 'X' is a constructor name rather than a type}}
 
 void test_naming() {
-  c1 = c2; // expected-error{{assigning to 'X<int>::C *' from incompatible type 'X<float>::C *'}}
-  xi = xf;  // expected-error{{assigning to 'X<int>::X<int> *' from incompatible type 'X<float>::X<float> *'}}
+  c1 = c2; // expected-error{{incompatible pointer types assigning to 'X<int>::C *' from 'X<float>::C *'}}
+  xi = xf;  // expected-error{{incompatible pointer types assigning to 'X<int>::X<int> *' from 'X<float>::X<float> *'}}
     // FIXME: error above doesn't print the type X<int>::X cleanly!
 }
 
Index: clang/test/SemaTemplate/extern-templates.cpp
===================================================================
--- clang/test/SemaTemplate/extern-templates.cpp
+++ clang/test/SemaTemplate/extern-templates.cpp
@@ -23,9 +23,9 @@
 template<typename T>
 void X0<T>::Inner::g(T t) {
 #ifdef MS
-  t = 17; // expected-error{{assigning to 'long *' from incompatible}} expected-error{{assigning to 'int *' from incompatible}}
+  t = 17; // expected-error{{incompatible integer to pointer conversion assigning to 'long *'}} expected-error{{incompatible integer to pointer conversion assigning to 'int *'}}
 #else
-  t = 17; // expected-error{{assigning to 'long *' from incompatible}}
+  t = 17; // expected-error{{incompatible integer to pointer conversion assigning to 'long *'}}
 #endif
 }
 
Index: clang/test/SemaOpenCL/address-spaces.cl
===================================================================
--- clang/test/SemaOpenCL/address-spaces.cl
+++ clang/test/SemaOpenCL/address-spaces.cl
@@ -20,7 +20,7 @@
 #if !__OPENCL_CPP_VERSION__
 // expected-error@-2 {{assigning '__constant int *' to '__generic int *__private' changes address space of pointer}}
 #else
-// expected-error@-4 {{assigning to '__generic int *' from incompatible type '__constant int *'}}
+// expected-error@-4 {{assigning '__constant int *' to '__generic int *' changes address space of pointer}}
 #endif
 #endif
 }
@@ -176,46 +176,46 @@
 }
 #else
 void nested(__global int *g, __global int * __private *gg, __local int *l, __local int * __private *ll, __global float * __private *gg_f) {
-  g = gg;    // expected-error {{assigning to '__global int *' from incompatible type '__global int *__private *__private'}}
-  g = l;     // expected-error {{assigning to '__global int *' from incompatible type '__local int *__private'}}
-  g = ll;    // expected-error {{assigning to '__global int *' from incompatible type '__local int *__private *__private'}}
-  g = gg_f;  // expected-error {{assigning to '__global int *' from incompatible type '__global float *__private *__private'}}
+  g = gg;    // expected-error {{assigning '__global int *__private *__private' to '__global int *' changes address space of pointer}}
+  g = l;     // expected-error {{assigning '__local int *__private' to '__global int *' changes address space of pointer}}
+  g = ll;    // expected-error {{assigning '__local int *__private *__private' to '__global int *' changes address space of pointer}}
+  g = gg_f;  // expected-error {{assigning '__global float *__private *__private' to '__global int *' changes address space of pointer}}
   g = (__global int *)gg_f; // expected-error {{C-style cast from '__global float *__private *' to '__global int *' converts between mismatching address spaces}}
 
-  gg = g;    // expected-error {{assigning to '__global int *__private *' from incompatible type '__global int *__private'; take the address with &}}
-  gg = l;    // expected-error {{assigning to '__global int *__private *' from incompatible type '__local int *__private'}}
-  gg = ll;   // expected-error {{assigning to '__global int *__private *' from incompatible type '__local int *__private *__private'}}
-  gg = gg_f; // expected-error {{assigning to '__global int *__private *' from incompatible type '__global float *__private *__private'}}
+  gg = g;    // expected-error {{assigning '__global int *__private' to '__global int *__private *' changes address space of pointer}}
+  gg = l;    // expected-error {{assigning '__local int *__private' to '__global int *__private *' changes address space of pointer}}
+  gg = ll;   // expected-error {{assigning '__local int *__private *__private' to '__global int *__private *' changes address space of nested pointer}}
+  gg = gg_f; // expected-error {{incompatible pointer types assigning to '__global int *__private *' from '__global float *__private *__private'}}
   gg = (__global int * __private *)gg_f;
 
-  l = g;     // expected-error {{assigning to '__local int *' from incompatible type '__global int *__private'}}
-  l = gg;    // expected-error {{assigning to '__local int *' from incompatible type '__global int *__private *__private'}}
-  l = ll;    // expected-error {{assigning to '__local int *' from incompatible type '__local int *__private *__private'}}
-  l = gg_f;  // expected-error {{assigning to '__local int *' from incompatible type '__global float *__private *__private'}}
+  l = g;     // expected-error {{assigning '__global int *__private' to '__local int *' changes address space of pointer}}
+  l = gg;    // expected-error {{assigning '__global int *__private *__private' to '__local int *' changes address space of pointer}}
+  l = ll;    // expected-error {{assigning '__local int *__private *__private' to '__local int *' changes address space of pointer}}
+  l = gg_f;  // expected-error {{assigning '__global float *__private *__private' to '__local int *' changes address space of pointer}}
   l = (__local int *)gg_f; // expected-error {{C-style cast from '__global float *__private *' to '__local int *' converts between mismatching address spaces}}
 
-  ll = g;    // expected-error {{assigning to '__local int *__private *' from incompatible type '__global int *__private'}}
-  ll = gg;   // expected-error {{assigning to '__local int *__private *' from incompatible type '__global int *__private *__private'}}
-  ll = l;    // expected-error {{assigning to '__local int *__private *' from incompatible type '__local int *__private'; take the address with &}}
-  ll = gg_f; // expected-error {{assigning to '__local int *__private *' from incompatible type '__global float *__private *__private'}}
+  ll = g;    // expected-error {{assigning '__global int *__private' to '__local int *__private *' changes address space of pointer}}
+  ll = gg;   // expected-error {{assigning '__global int *__private *__private' to '__local int *__private *' changes address space of nested pointer}}
+  ll = l;    // expected-error {{assigning '__local int *__private' to '__local int *__private *' changes address space of pointer}}
+  ll = gg_f; // expected-error {{assigning '__global float *__private *__private' to '__local int *__private *' changes address space of nested pointer}}
   ll = (__local int *__private *)gg; //expected-warning{{C-style cast from '__global int *__private *' to '__local int *__private *' changes address space of nested pointers}}
 
-  gg_f = g;  // expected-error {{assigning to '__global float *__private *' from incompatible type '__global int *__private'}}
-  gg_f = gg; // expected-error {{assigning to '__global float *__private *' from incompatible type '__global int *__private *__private'}}
-  gg_f = l;  // expected-error {{assigning to '__global float *__private *' from incompatible type '__local int *__private'}}
-  gg_f = ll; // expected-error {{assigning to '__global float *__private *' from incompatible type '__local int *__private *__private'}}
+  gg_f = g;  // expected-error {{assigning '__global int *__private' to '__global float *__private *' changes address space of pointer}}
+  gg_f = gg; // expected-error {{incompatible pointer types assigning to '__global float *__private *' from '__global int *__private *__private'}}
+  gg_f = l;  // expected-error {{assigning '__local int *__private' to '__global float *__private *' changes address space of pointer}}
+  gg_f = ll; // expected-error {{assigning '__local int *__private *__private' to '__global float *__private *' changes address space of nested pointer}}
   gg_f = (__global float * __private *)gg;
 
   typedef __local int * l_t;
   typedef __global int * g_t;
   __private l_t * pl;
   __private g_t * pg;
-  gg = pl;  // expected-error {{assigning to '__global int *__private *' from incompatible type '__private l_t *__private' (aka '__local int *__private *__private')}}
-  pl = gg;  // expected-error {{assigning to '__private l_t *' (aka '__local int *__private *') from incompatible type '__global int *__private *__private'}}
+  gg = pl;  // expected-error {{assigning '__private l_t *__private' (aka '__local int *__private *__private') to '__global int *__private *' changes address space of nested pointer}}
+  pl = gg;  // expected-error {{assigning '__global int *__private *__private' to '__private l_t *' (aka '__local int *__private *') changes address space of nested pointer}}
   gg = pg;
   pg = gg;
-  pg = pl;  // expected-error {{assigning to '__private g_t *' (aka '__global int *__private *') from incompatible type '__private l_t *__private' (aka '__local int *__private *__private')}}
-  pl = pg;  // expected-error {{assigning to '__private l_t *' (aka '__local int *__private *') from incompatible type '__private g_t *__private' (aka '__global int *__private *__private')}}
+  pg = pl;  // expected-error {{assigning '__private l_t *__private' (aka '__local int *__private *__private') to '__private g_t *' (aka '__global int *__private *') changes address space of nested pointer}}
+  pl = pg;  // expected-error {{assigning '__private g_t *__private' (aka '__global int *__private *__private') to '__private l_t *' (aka '__local int *__private *') changes address space of nested pointer}}
 
   ll = (__local int * __private *)(void *)gg;
   void *vp = ll;
Index: clang/test/SemaOpenCL/address-spaces-conversions-cl2.0.cl
===================================================================
--- clang/test/SemaOpenCL/address-spaces-conversions-cl2.0.cl
+++ clang/test/SemaOpenCL/address-spaces-conversions-cl2.0.cl
@@ -178,7 +178,7 @@
 #if !__OPENCL_CPP_VERSION__
 // expected-error@-3{{assigning '__global int *__private' to '__constant int *__private' changes address space of pointer}}
 #else
-// expected-error@-5{{assigning to '__constant int *' from incompatible type '__global int *__private'}}
+// expected-error@-5{{assigning '__global int *__private' to '__constant int *' changes address space of pointer}}
 #endif
 #endif
 
@@ -187,7 +187,7 @@
 #if !__OPENCL_CPP_VERSION__
 // expected-error-re@-3{{assigning '__local int *__private' to '__{{global|constant}} int *__private' changes address space of pointer}}
 #else
-// expected-error-re@-5{{assigning to '__{{global|constant}} int *' from incompatible type '__local int *__private'}}
+// expected-error-re@-5{{assigning '__local int *__private' to '__{{global|constant}} int *' changes address space of pointer}}
 #endif
 #endif
 
@@ -196,7 +196,7 @@
 #if !__OPENCL_CPP_VERSION__
 // expected-error-re@-3{{assigning '__constant int *__private' to '__{{global|generic}} int *__private' changes address space of pointer}}
 #else
-// expected-error-re@-5{{assigning to '__{{global|generic}} int *' from incompatible type '__constant int *__private'}}
+// expected-error-re@-5{{assigning '__constant int *__private' to '__{{global|generic}} int *' changes address space of pointer}}
 #endif
 #endif
 
@@ -205,7 +205,7 @@
 #if !__OPENCL_CPP_VERSION__
 // expected-error-re@-3{{assigning '__private int *__private' to '__{{global|constant}} int *__private' changes address space of pointer}}
 #else
-// expected-error-re@-5{{assigning to '__{{global|constant}} int *' from incompatible type '__private int *__private'}}
+// expected-error-re@-5{{assigning '__private int *__private' to '__{{global|constant}} int *' changes address space of pointer}}
 #endif
 #endif
 
@@ -214,7 +214,7 @@
 #if !__OPENCL_CPP_VERSION__
 // expected-error-re@-3{{assigning '__generic int *__private' to '__{{global|constant}} int *__private' changes address space of pointer}}
 #else
-// expected-error-re@-5{{assigning to '__{{global|constant}} int *' from incompatible type '__generic int *__private'}}
+// expected-error-re@-5{{assigning '__generic int *__private' to '__{{global|constant}} int *' changes address space of pointer}}
 #endif
 #endif
 
@@ -518,7 +518,7 @@
 #if !__OPENCL_CPP_VERSION__
 // expected-error@-3 {{assigning '__local int *__local *__private' to '__generic int *__generic *__private' changes address space of nested pointer}}
 #else
-// expected-error@-5 {{assigning to '__generic int *__generic *' from incompatible type '__local int *__local *__private'}}
+// expected-error@-5 {{assigning '__local int *__local *__private' to '__generic int *__generic *' changes address space of nested pointer}}
 #endif
 #endif
 
Index: clang/test/SemaObjCXX/property-invalid-type.mm
===================================================================
--- clang/test/SemaObjCXX/property-invalid-type.mm
+++ clang/test/SemaObjCXX/property-invalid-type.mm
@@ -13,7 +13,7 @@
 @synthesize response;
 - (void) foo :(A*) a   // expected-error {{expected a type}}
 {
-  self.response = a; // expected-error{{assigning to 'int *' from incompatible type 'id'}}
+  self.response = a; // expected-error{{incompatible pointer types assigning to 'int *' from 'id'}}
 }
 @end
 
Index: clang/test/SemaObjCXX/parameterized_classes_subst.mm
===================================================================
--- clang/test/SemaObjCXX/parameterized_classes_subst.mm
+++ clang/test/SemaObjCXX/parameterized_classes_subst.mm
@@ -106,27 +106,27 @@
        NSArray<NSString *> *stringArray,
        void (^block)(void)) {
   int *ip;
-  ip = [stringSet firstObject]; // expected-error{{from incompatible type 'NSString *'}}
-  ip = [mutStringSet firstObject]; // expected-error{{from incompatible type 'NSString *'}}
-  ip = [widgetSet firstObject]; // expected-error{{from incompatible type 'Widget *'}}
-  ip = [untypedMutSet firstObject]; // expected-error{{from incompatible type 'id'}}
-  ip = [mutStringArraySet firstObject]; // expected-error{{from incompatible type 'NSArray<NSString *> *'}}
-  ip = [set firstObject]; // expected-error{{from incompatible type 'id'}}
-  ip = [mutSet firstObject]; // expected-error{{from incompatible type 'id'}}
-  ip = [mutArraySet firstObject]; // expected-error{{from incompatible type 'id'}}
-  ip = [block firstObject]; // expected-error{{from incompatible type 'id'}}
-
-  ip = [stringSet findObject:@"blah"]; // expected-error{{from incompatible type 'NSString *'}}
+  ip = [stringSet firstObject]; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSString *'}}
+  ip = [mutStringSet firstObject]; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSString *'}}
+  ip = [widgetSet firstObject]; // expected-error{{incompatible pointer types assigning to 'int *' from 'Widget *'}}
+  ip = [untypedMutSet firstObject]; // expected-error{{incompatible pointer types assigning to 'int *' from 'id'}}
+  ip = [mutStringArraySet firstObject]; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSArray<NSString *> *'}}
+  ip = [set firstObject]; // expected-error{{incompatible pointer types assigning to 'int *' from 'id'}}
+  ip = [mutSet firstObject]; // expected-error{{incompatible pointer types assigning to 'int *' from 'id'}}
+  ip = [mutArraySet firstObject]; // expected-error{{incompatible pointer types assigning to 'int *' from 'id'}}
+  ip = [block firstObject]; // expected-error{{incompatible pointer types assigning to 'int *' from 'id'}}
+
+  ip = [stringSet findObject:@"blah"]; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSString *'}}
 
   // Class messages.
-  ip = [NSSet<NSString *> alloc]; // expected-error{{from incompatible type 'NSSet<NSString *> *'}}
-  ip = [NSSet alloc]; // expected-error{{from incompatible type 'NSSet *'}}
-  ip = [MutableSetOfArrays<NSString *> alloc]; // expected-error{{from incompatible type 'MutableSetOfArrays<NSString *> *'}}
-  ip = [MutableSetOfArrays alloc];  // expected-error{{from incompatible type 'MutableSetOfArrays *'}}
-  ip = [NSArray<NSString *> array]; // expected-error{{from incompatible type 'NSArray<NSString *> *'}}
-  ip = [NSArray<NSString *><NSCopying> array]; // expected-error{{from incompatible type 'NSArray<NSString *> *'}}
+  ip = [NSSet<NSString *> alloc]; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSSet<NSString *> *'}}
+  ip = [NSSet alloc]; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSSet *'}}
+  ip = [MutableSetOfArrays<NSString *> alloc]; // expected-error{{incompatible pointer types assigning to 'int *' from 'MutableSetOfArrays<NSString *> *'}}
+  ip = [MutableSetOfArrays alloc];  // expected-error{{incompatible pointer types assigning to 'int *' from 'MutableSetOfArrays *'}}
+  ip = [NSArray<NSString *> array]; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSArray<NSString *> *'}}
+  ip = [NSArray<NSString *><NSCopying> array]; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSArray<NSString *> *'}}
 
-  ip = [[NSMutableArray<NSString *> alloc] init];  // expected-error{{from incompatible type 'NSMutableArray<NSString *> *'}}
+  ip = [[NSMutableArray<NSString *> alloc] init];  // expected-error{{incompatible pointer types assigning to 'int *' from 'NSMutableArray<NSString *> *'}}
 
   [[NSMutableArray alloc] initWithArray: stringArray]; // okay
   [[NSMutableArray<NSString *> alloc] initWithArray: stringArray]; // okay
@@ -166,16 +166,16 @@
        MutableSetOfArrays *mutArraySet,
        NSMutableDictionary *mutDict) {
   int *ip;
-  ip = stringSet.allObjects; // expected-error{{from incompatible type 'NSArray<NSString *> *'}}
-  ip = mutStringSet.allObjects; // expected-error{{from incompatible type 'NSArray<NSString *> *'}}
-  ip = widgetSet.allObjects; // expected-error{{from incompatible type 'NSArray<Widget *> *'}}
-  ip = untypedMutSet.allObjects; // expected-error{{from incompatible type 'NSArray *'}}
-  ip = mutStringArraySet.allObjects; // expected-error{{from incompatible type 'NSArray<NSArray<NSString *> *> *'}}
-  ip = set.allObjects; // expected-error{{from incompatible type 'NSArray *'}}
-  ip = mutSet.allObjects; // expected-error{{from incompatible type 'NSArray *'}}
-  ip = mutArraySet.allObjects; // expected-error{{from incompatible type 'NSArray *'}}
-
-  ip = mutDict.someRandomKey; // expected-error{{from incompatible type '__kindof id<NSCopying>'}}
+  ip = stringSet.allObjects; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSArray<NSString *> *'}}
+  ip = mutStringSet.allObjects; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSArray<NSString *> *'}}
+  ip = widgetSet.allObjects; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSArray<Widget *> *'}}
+  ip = untypedMutSet.allObjects; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSArray *'}}
+  ip = mutStringArraySet.allObjects; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSArray<NSArray<NSString *> *> *'}}
+  ip = set.allObjects; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSArray *'}}
+  ip = mutSet.allObjects; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSArray *'}}
+  ip = mutArraySet.allObjects; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSArray *'}}
+
+  ip = mutDict.someRandomKey; // expected-error{{incompatible pointer types assigning to 'int *' from '__kindof id<NSCopying>'}}
 }
 
 void test_property_write(
@@ -215,27 +215,27 @@
   Widget *widget;
   Window *window;
 
-  ip = stringArray[0]; // expected-error{{from incompatible type 'NSString *'}}
+  ip = stringArray[0]; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSString *'}}
 
-  ip = mutStringArray[0]; // expected-error{{from incompatible type 'NSString *'}}
+  ip = mutStringArray[0]; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSString *'}}
   mutStringArray[0] = ip; // expected-error{{parameter of type 'NSString *'}}
 
-  ip = array[0]; // expected-error{{from incompatible type 'id'}}
+  ip = array[0]; // expected-error{{incompatible pointer types assigning to 'int *' from 'id'}}
 
-  ip = mutArray[0]; // expected-error{{from incompatible type 'id'}}
+  ip = mutArray[0]; // expected-error{{incompatible pointer types assigning to 'int *' from 'id'}}
   mutArray[0] = ip; // expected-error{{parameter of type 'id'}}
 
-  ip = stringWidgetDict[string]; // expected-error{{from incompatible type 'Widget *'}}
+  ip = stringWidgetDict[string]; // expected-error{{incompatible pointer types assigning to 'int *' from 'Widget *'}}
   widget = stringWidgetDict[widget]; // expected-error{{parameter of type 'NSString *'}}
 
-  ip = mutStringWidgetDict[string]; // expected-error{{from incompatible type 'Widget *'}}
+  ip = mutStringWidgetDict[string]; // expected-error{{incompatible pointer types assigning to 'int *' from 'Widget *'}}
   widget = mutStringWidgetDict[widget]; // expected-error{{parameter of type 'NSString *'}}
   mutStringWidgetDict[string] = ip; // expected-error{{parameter of type 'Widget *'}}
   mutStringWidgetDict[widget] = widget; // expected-error{{parameter of type 'NSString *'}}
 
-  ip = dict[string]; // expected-error{{from incompatible type 'id'}}
+  ip = dict[string]; // expected-error{{incompatible pointer types assigning to 'int *' from 'id'}}
 
-  ip = mutDict[string]; // expected-error{{incompatible type 'id'}}
+  ip = mutDict[string]; // expected-error{{incompatible pointer types assigning to 'int *' from 'id'}}
   mutDict[string] = ip; // expected-error{{parameter of type 'id'}}
 
   widget = mutDict[window];
@@ -249,15 +249,15 @@
                             NSArray *array) {
   int *ip;
 
-  ip = stringArray->data; // expected-error{{from incompatible type 'NSString **'}}
-  ip = array->data; // expected-error{{from incompatible type 'id *'}}
+  ip = stringArray->data; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSString **'}}
+  ip = array->data; // expected-error{{incompatible pointer types assigning to 'int *' from 'id *'}}
 }
 
 @implementation WindowArray
 - (void)testInstanceVariable {
   int *ip;
 
-  ip = data; // expected-error{{from incompatible type 'Window **'}}
+  ip = data; // expected-error{{incompatible pointer types assigning to 'int *' from 'Window **'}}
 }
 @end
 
@@ -276,13 +276,13 @@
   stringArray = array;
 
   // Specialized -> specialized failure (same level).
-  stringArray = numberArray; // expected-error{{assigning to 'NSArray<NSString *> *' from incompatible type 'NSArray<NSNumber *> *'}}
+  stringArray = numberArray; // expected-error{{incompatible pointer types assigning to 'NSArray<NSString *> *' from 'NSArray<NSNumber *> *'}}
 
   // Specialized -> specialized (different levels).
   stringArray = mutStringArray;
 
   // Specialized -> specialized failure (different levels).
-  numberArray = mutStringArray; // expected-error{{assigning to 'NSArray<NSNumber *> *' from incompatible type 'NSMutableArray<NSString *> *'}}
+  numberArray = mutStringArray; // expected-error{{incompatible pointer types assigning to 'NSArray<NSNumber *> *' from 'NSMutableArray<NSString *> *'}}
 
   // Unspecialized -> specialized (different levels).
   stringArray = mutArray;
@@ -334,19 +334,19 @@
   int *ip;
   id object;
 
-  ip = cond ? stringArray : mutStringArray; // expected-error{{from incompatible type 'NSArray<NSString *> *'}}
-  ip = cond ? mutStringArray : stringArray; // expected-error{{from incompatible type 'NSArray<NSString *> *'}}
+  ip = cond ? stringArray : mutStringArray; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSArray<NSString *> *'}}
+  ip = cond ? mutStringArray : stringArray; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSArray<NSString *> *'}}
 
-  ip = cond ? stringArray2 : mutStringArray; // expected-error{{from incompatible type 'NSArray<NSString *> *'}}
-  ip = cond ? mutStringArray : stringArray2; // expected-error{{from incompatible type 'NSArray<NSString *> *'}}
+  ip = cond ? stringArray2 : mutStringArray; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSArray<NSString *> *'}}
+  ip = cond ? mutStringArray : stringArray2; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSArray<NSString *> *'}}
 
-  ip = cond ? stringArray : mutArray; // expected-error{{from incompatible type 'NSArray *'}}
+  ip = cond ? stringArray : mutArray; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSArray *'}}
 
-  ip = cond ? stringArray2 : mutArray; // expected-error{{from incompatible type 'NSArray *'}}
+  ip = cond ? stringArray2 : mutArray; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSArray *'}}
 
-  ip = cond ? mutArray : stringArray; // expected-error{{from incompatible type 'NSArray *'}}
+  ip = cond ? mutArray : stringArray; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSArray *'}}
 
-  ip = cond ? mutArray : stringArray2; // expected-error{{from incompatible type 'NSArray *'}}
+  ip = cond ? mutArray : stringArray2; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSArray *'}}
 
   object = cond ? stringArray : numberArray; // expected-warning{{incompatible operand types ('NSArray<NSString *> *' and 'NSArray<NSNumber *> *')}}
 }
@@ -357,14 +357,14 @@
 @implementation NSStringArray
 - (void)useSuperMethod {
   int *ip;
-  ip = super.lastObject; // expected-error{{from incompatible type 'NSString *'}}
-  ip = [super objectAtIndexedSubscript:0]; // expected-error{{from incompatible type 'NSString *'}}
+  ip = super.lastObject; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSString *'}}
+  ip = [super objectAtIndexedSubscript:0]; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSString *'}}
 }
 
 + (void)useSuperMethod {
   int *ip;
-  ip = super.array; // expected-error{{from incompatible type 'NSArray<NSString *> *'}}
-  ip = [super array]; // expected-error{{from incompatible type 'NSArray<NSString *> *'}}
+  ip = super.array; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSArray<NSString *> *'}}
+  ip = [super array]; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSArray<NSString *> *'}}
 }
 @end
 
Index: clang/test/SemaObjCXX/objc-container-subscripting.mm
===================================================================
--- clang/test/SemaObjCXX/objc-container-subscripting.mm
+++ clang/test/SemaObjCXX/objc-container-subscripting.mm
@@ -12,7 +12,7 @@
   base[key] = obj; // expected-error {{expected method to write array element not found on object of type 'NSMutableDictionary *'}} \
                    // expected-error {{cannot initialize a parameter of type 'id' with an lvalue of type 'int'}}
   obj = base[key];  // expected-error {{expected method to read array element not found on object of type 'NSMutableDictionary *'}} \
-                    // expected-error {{assigning to 'int' from incompatible type 'id'}}
+                    // expected-error {{incompatible pointer to integer conversion assigning to 'int' from 'id'}}
      
 }
 
Index: clang/test/SemaObjCXX/nullability-pragmas.mm
===================================================================
--- clang/test/SemaObjCXX/nullability-pragmas.mm
+++ clang/test/SemaObjCXX/nullability-pragmas.mm
@@ -32,26 +32,26 @@
   [a method4: a]; // expected-error{{cannot initialize a parameter of type 'NSErrorPtr  _Nullable * _Nullable' (aka 'NSError **') with an lvalue of type 'A * _Nonnull'}}
 
   float *ptr;
-  ptr = f13(); // expected-error{{assigning to 'float *' from incompatible type 'int_ptr _Nonnull' (aka 'int *')}}
-  ptr = f14(); // expected-error{{assigning to 'float *' from incompatible type 'A * _Nonnull'}}
-  ptr = [a method1:a]; // expected-error{{assigning to 'float *' from incompatible type 'A * _Nonnull'}}
-  ptr = a.aProp; // expected-error{{assigning to 'float *' from incompatible type 'A * _Nonnull'}}
-  ptr = global_int_ptr; // expected-error{{assigning to 'float *' from incompatible type 'int * _Nonnull'}}
-  ptr = f15(); // expected-error{{assigning to 'float *' from incompatible type 'int * _Null_unspecified'}}
-  ptr = f16(); // expected-error{{assigning to 'float *' from incompatible type 'A * _Null_unspecified'}}
-  ptr = [a method2]; // expected-error{{assigning to 'float *' from incompatible type 'A * _Null_unspecified'}}
-
-  ptr = aa->ivar1; // expected-error{{from incompatible type 'id'}}
-  ptr = aa->ivar2; // expected-error{{from incompatible type 'id _Nonnull'}}
+  ptr = f13(); // expected-error{{incompatible pointer types assigning to 'float *' from 'int_ptr _Nonnull' (aka 'int *')}}
+  ptr = f14(); // expected-error{{incompatible pointer types assigning to 'float *' from 'A * _Nonnull'}}
+  ptr = [a method1:a]; // expected-error{{incompatible pointer types assigning to 'float *' from 'A * _Nonnull'}}
+  ptr = a.aProp; // expected-error{{incompatible pointer types assigning to 'float *' from 'A * _Nonnull'}}
+  ptr = global_int_ptr; // expected-error{{incompatible pointer types assigning to 'float *' from 'int * _Nonnull'}}
+  ptr = f15(); // expected-error{{incompatible pointer types assigning to 'float *' from 'int * _Null_unspecified'}}
+  ptr = f16(); // expected-error{{incompatible pointer types assigning to 'float *' from 'A * _Null_unspecified'}}
+  ptr = [a method2]; // expected-error{{incompatible pointer types assigning to 'float *' from 'A * _Null_unspecified'}}
+
+  ptr = aa->ivar1; // expected-error{{incompatible pointer types assigning to 'float *' from 'id'}}
+  ptr = aa->ivar2; // expected-error{{incompatible pointer types assigning to 'float *' from 'id _Nonnull'}}
 }
 
 void test_pragmas_generics(void) {
   float *fp;
 
   NSGeneric<C *> *genC;
-  fp = [genC tee]; // expected-error{{from incompatible type 'C *'}}
-  fp = [genC maybeTee]; // expected-error{{from incompatible type 'C * _Nullable'}}
+  fp = [genC tee]; // expected-error{{incompatible pointer types assigning to 'float *' from 'C *'}}
+  fp = [genC maybeTee]; // expected-error{{incompatible pointer types assigning to 'float *' from 'C * _Nullable'}}
 
   Generic_with_C genC2;
-  fp = genC2; // expected-error{{from incompatible type 'Generic_with_C' (aka 'NSGeneric<C *> *')}}
+  fp = genC2; // expected-error{{incompatible pointer types assigning to 'float *' from 'Generic_with_C' (aka 'NSGeneric<C *> *')}}
 }
Index: clang/test/SemaObjCXX/noescape.mm
===================================================================
--- clang/test/SemaObjCXX/noescape.mm
+++ clang/test/SemaObjCXX/noescape.mm
@@ -74,7 +74,7 @@
 void test0() {
   fnptr0 = &func0;
   fnptr0 = &noescapeFunc2;
-  fnptr1 = &func0; // expected-error {{assigning to 'void (*)(__attribute__((noescape)) int *)' from incompatible type 'void (*)(int *)'}}
+  fnptr1 = &func0; // expected-error {{incompatible function pointer types assigning to 'void (*)(__attribute__((noescape)) int *)' from 'void (*)(int *)'}}
   fnptr1 = &noescapeFunc2;
   S4<&func0> e0;
   S4<&noescapeFunc2> e1;
Index: clang/test/SemaObjCXX/instantiate-stmt.mm
===================================================================
--- clang/test/SemaObjCXX/instantiate-stmt.mm
+++ clang/test/SemaObjCXX/instantiate-stmt.mm
@@ -64,7 +64,7 @@
 template<typename T, typename U>
 void try_catch_finally_test(U value) {
   @try {
-    value = 1; // expected-error{{assigning to 'int *' from incompatible type 'int'}}
+    value = 1; // expected-error{{incompatible integer to pointer conversion assigning to 'int *' from 'int'}}
   }
   @catch (T obj) { // expected-error{{@catch parameter is not a pointer to an interface type}}
     id x = obj;
Index: clang/test/SemaObjCXX/instantiate-expr.mm
===================================================================
--- clang/test/SemaObjCXX/instantiate-expr.mm
+++ clang/test/SemaObjCXX/instantiate-expr.mm
@@ -18,8 +18,8 @@
 
 template<unsigned N, typename T, typename U, typename V>
 void f(U value, V value2) {
-  get_an_A(N)->ivar = value; // expected-error{{assigning to 'int' from incompatible type 'int *'}}
-  get_an_A(N).prop = value2; // expected-error{{assigning to 'int' from incompatible type 'double *'}}
+  get_an_A(N)->ivar = value; // expected-error{{incompatible pointer to integer conversion assigning to 'int' from 'int *'; dereference with *}}
+  get_an_A(N).prop = value2; // expected-error{{incompatible pointer to integer conversion assigning to 'int' from 'double *'}}
   T c = get_an_id(N)->isa; // expected-error{{cannot initialize a variable of type 'int' with an lvalue of type 'Class'}} \
                            // expected-warning 3 {{direct access to Objective-C's isa is deprecated in favor of object_getClass()}}
 }
@@ -33,8 +33,8 @@
 // ivar reference.
 template<typename T, typename U, typename V>
 void f2(T ptr, U value, V value2) {
-  ptr->ivar = value; // expected-error{{assigning to 'int' from incompatible type 'int *'}}
-  ptr.prop = value2; // expected-error{{assigning to 'int' from incompatible type 'double *'}}
+  ptr->ivar = value; // expected-error{{incompatible pointer to integer conversion assigning to 'int' from 'int *'; dereference with *}}
+  ptr.prop = value2; // expected-error{{incompatible pointer to integer conversion assigning to 'int' from 'double *'}}
 }
 
 template void f2(A*, int, int);
@@ -60,7 +60,7 @@
 
 template<typename T>
 void f4(B *b, T value) {
-  b.foo = value; // expected-error{{assigning to 'int' from incompatible type 'int *'}}
+  b.foo = value; // expected-error{{incompatible pointer to integer conversion assigning to 'int' from 'int *'; dereference with *}}
 }
 
 template void f4(B*, int);
@@ -68,7 +68,7 @@
 
 template<typename T, typename U>
 void f5(T ptr, U value) {
-  ptr.foo = value; // expected-error{{assigning to 'int' from incompatible type 'int *'}}
+  ptr.foo = value; // expected-error{{incompatible pointer to integer conversion assigning to 'int' from 'int *'; dereference with *}}
 }
 
 template void f5(B*, int);
Index: clang/test/SemaObjCXX/comptypes-7.mm
===================================================================
--- clang/test/SemaObjCXX/comptypes-7.mm
+++ clang/test/SemaObjCXX/comptypes-7.mm
@@ -23,27 +23,27 @@
 
   /* These should all generate errors.  */
 
-  obj = i; // expected-error {{assigning to 'id' from incompatible type 'int'}}
-  obj = j; // expected-error {{assigning to 'id' from incompatible type 'int *'}}
+  obj = i; // expected-error {{incompatible integer to pointer conversion assigning to 'id' from 'int'}}
+  obj = j; // expected-error {{incompatible pointer types assigning to 'id' from 'int *'}}
 
-  obj_p = i; // expected-error {{assigning to 'id<MyProtocol>' from incompatible type 'int'}}
-  obj_p = j; // expected-error {{assigning to 'id<MyProtocol>' from incompatible type 'int *'}}
+  obj_p = i; // expected-error {{incompatible integer to pointer conversion assigning to 'id<MyProtocol>' from 'int'}}
+  obj_p = j; // expected-error {{incompatible pointer types assigning to 'id<MyProtocol>' from 'int *'}}
 
-  obj_c = i; // expected-error {{assigning to 'MyClass *' from incompatible type 'int'}}
-  obj_c = j; // expected-error {{assigning to 'MyClass *' from incompatible type 'int *'}}
+  obj_c = i; // expected-error {{incompatible integer to pointer conversion assigning to 'MyClass *' from 'int'}}
+  obj_c = j; // expected-error {{incompatible pointer types assigning to 'MyClass *' from 'int *'}}
 
-  obj_C = i; // expected-error {{assigning to 'Class' from incompatible type 'int'}}
-  obj_C = j; // expected-error {{assigning to 'Class' from incompatible type 'int *'}}
+  obj_C = i; // expected-error {{incompatible integer to pointer conversion assigning to 'Class' from 'int'}}
+  obj_C = j; // expected-error {{incompatible pointer types assigning to 'Class' from 'int *'}}
 
-  i = obj;   // expected-error {{assigning to 'int' from incompatible type 'id'}}
-  i = obj_p; // expected-error {{assigning to 'int' from incompatible type 'id<MyProtocol>'}}
-  i = obj_c; // expected-error {{assigning to 'int' from incompatible type 'MyClass *'}}
-  i = obj_C; // expected-error {{assigning to 'int' from incompatible type 'Class'}}
+  i = obj;   // expected-error {{incompatible pointer to integer conversion assigning to 'int' from 'id'}}
+  i = obj_p; // expected-error {{incompatible pointer to integer conversion assigning to 'int' from 'id<MyProtocol>'}}
+  i = obj_c; // expected-error {{incompatible pointer to integer conversion assigning to 'int' from 'MyClass *'}}
+  i = obj_C; // expected-error {{incompatible pointer to integer conversion assigning to 'int' from 'Class'}}
 
-  j = obj;   // expected-error {{assigning to 'int *' from incompatible type 'id'}}
-  j = obj_p; // expected-error {{assigning to 'int *' from incompatible type 'id<MyProtocol>'}}
-  j = obj_c; // expected-error {{assigning to 'int *' from incompatible type 'MyClass *'}}
-  j = obj_C; // expected-error {{assigning to 'int *' from incompatible type 'Class'}}
+  j = obj;   // expected-error {{incompatible pointer types assigning to 'int *' from 'id'}}
+  j = obj_p; // expected-error {{incompatible pointer types assigning to 'int *' from 'id<MyProtocol>'}}
+  j = obj_c; // expected-error {{incompatible pointer types assigning to 'int *' from 'MyClass *'}}
+  j = obj_C; // expected-error {{incompatible pointer types assigning to 'int *' from 'Class'}}
 
   if (obj == i) foo() ; // expected-error {{comparison between pointer and integer ('id' and 'int')}}
   if (i == obj) foo() ; // expected-error {{comparison between pointer and integer ('int' and 'id')}}
Index: clang/test/SemaObjCXX/comptypes-1.mm
===================================================================
--- clang/test/SemaObjCXX/comptypes-1.mm
+++ clang/test/SemaObjCXX/comptypes-1.mm
@@ -37,9 +37,9 @@
      warning, unless done from an 'id'.  */
   obj_c = obj;    /* Ok */
   obj_c = obj_p;  // expected-error {{assigning to 'MyClass *' from incompatible type 'id<MyProtocol>'}}
-  obj_c = obj_cp; // expected-error {{assigning to 'MyClass *' from incompatible type 'MyOtherClass *'}}
-  obj_c = obj_C;  // expected-error {{assigning to 'MyClass *' from incompatible type 'Class'}}
-  obj_c = obj_CP; // expected-error {{assigning to 'MyClass *' from incompatible type 'Class<MyProtocol>'}}
+  obj_c = obj_cp; // expected-error {{incompatible pointer types assigning to 'MyClass *' from 'MyOtherClass *'}}
+  obj_c = obj_C;  // expected-error {{incompatible pointer types assigning to 'MyClass *' from 'Class'}}
+  obj_c = obj_CP; // expected-error {{incompatible pointer types assigning to 'MyClass *' from 'Class<MyProtocol>'}}
 
   /* Assigning to an 'id<MyProtocol>' variable should generate a
      warning if done from a 'MyClass *' (which doesn't implement
@@ -48,28 +48,28 @@
   obj_p = obj;    /* Ok */
   obj_p = obj_c;  // expected-error {{assigning to 'id<MyProtocol>' from incompatible type 'MyClass *'}}
   obj_p = obj_cp; /* Ok  */
-  obj_p = obj_C;  // expected-error {{assigning to 'id<MyProtocol>' from incompatible type 'Class'}}
+  obj_p = obj_C;  // expected-error {{incompatible pointer types assigning to 'id<MyProtocol>' from 'Class'}}
   obj_p = obj_CP; // expected-error {{assigning to 'id<MyProtocol>' from incompatible type 'Class<MyProtocol>'}}
 
   /* Assigning to a 'MyOtherClass *' variable should always generate
      a warning, unless done from an 'id' or an 'id<MyProtocol>' (since
      MyOtherClass implements MyProtocol).  */
   obj_cp = obj;    /* Ok */
-  obj_cp = obj_c;  // expected-error {{assigning to 'MyOtherClass *' from incompatible type 'MyClass *'}}
+  obj_cp = obj_c;  // expected-error {{incompatible pointer types assigning to 'MyOtherClass *' from 'MyClass *'}}
   obj_cp = obj_p;  /* Ok */
-  obj_cp = obj_C;  // expected-error {{assigning to 'MyOtherClass *' from incompatible type 'Class'}}
-  obj_cp = obj_CP; // expected-error {{assigning to 'MyOtherClass *' from incompatible type 'Class<MyProtocol>'}}
+  obj_cp = obj_C;  // expected-error {{incompatible pointer types assigning to 'MyOtherClass *' from 'Class'}}
+  obj_cp = obj_CP; // expected-error {{incompatible pointer types assigning to 'MyOtherClass *' from 'Class<MyProtocol>'}}
 
   obj_C = obj;     // Ok
-  obj_C = obj_p;   // expected-error {{assigning to 'Class' from incompatible type 'id<MyProtocol>'}}
-  obj_C = obj_c;   // expected-error {{assigning to 'Class' from incompatible type 'MyClass *'}}
-  obj_C = obj_cp;  // expected-error {{assigning to 'Class' from incompatible type 'MyOtherClass *'}}
+  obj_C = obj_p;   // expected-error {{incompatible pointer types assigning to 'Class' from 'id<MyProtocol>'}}
+  obj_C = obj_c;   // expected-error {{incompatible pointer types assigning to 'Class' from 'MyClass *'}}
+  obj_C = obj_cp;  // expected-error {{incompatible pointer types assigning to 'Class' from 'MyOtherClass *'}}
   obj_C = obj_CP;  // Ok
 
   obj_CP = obj;     // Ok
   obj_CP = obj_p;   // expected-error {{assigning to 'Class<MyProtocol>' from incompatible type 'id<MyProtocol>'}}
-  obj_CP = obj_c;   // expected-error {{assigning to 'Class<MyProtocol>' from incompatible type 'MyClass *}}
-  obj_CP = obj_cp;  // expected-error {{assigning to 'Class<MyProtocol>' from incompatible type 'MyOtherClass *'}}
+  obj_CP = obj_c;   // expected-error {{incompatible pointer types assigning to 'Class<MyProtocol>' from 'MyClass *'}}
+  obj_CP = obj_cp;  // expected-error {{incompatible pointer types assigning to 'Class<MyProtocol>' from 'MyOtherClass *'}}
   obj_CP = obj_C;   // Ok
 
   /* Any comparison involving an 'id' must be without warnings.  */
Index: clang/test/SemaObjCXX/arc-type-conversion.mm
===================================================================
--- clang/test/SemaObjCXX/arc-type-conversion.mm
+++ clang/test/SemaObjCXX/arc-type-conversion.mm
@@ -124,12 +124,12 @@
                             __autoreleasing id *aip,
                             __unsafe_unretained id *uip,
                             const __unsafe_unretained id *cuip) {
-  uip = sip; // expected-error{{assigning to '__unsafe_unretained id *' from incompatible type '__strong id *'}}
-  uip = wip; // expected-error{{assigning to '__unsafe_unretained id *' from incompatible type '__weak id *'}}
-  uip = aip; // expected-error{{assigning to '__unsafe_unretained id *' from incompatible type '__autoreleasing id *'}}
+  uip = sip; // expected-error{{assigning '__strong id *' to '__unsafe_unretained id *' changes retain/release properties of pointer}}
+  uip = wip; // expected-error{{assigning '__weak id *' to '__unsafe_unretained id *' changes retain/release properties of pointer}}
+  uip = aip; // expected-error{{assigning '__autoreleasing id *' to '__unsafe_unretained id *' changes retain/release properties of pointer}}
 
   cuip = sip;
-  cuip = wip; // expected-error{{assigning to '__unsafe_unretained id const *' from incompatible type '__weak id *'}}
+  cuip = wip; // expected-error{{assigning '__weak id *' to '__unsafe_unretained id const *' changes retain/release properties of pointer}}
   cuip = aip;
 }
 
Index: clang/test/SemaObjC/comptypes-legal.m
===================================================================
--- clang/test/SemaObjC/comptypes-legal.m
+++ clang/test/SemaObjC/comptypes-legal.m
@@ -33,7 +33,7 @@
 {
   // GCC currently allows this (it has some fiarly new support for covariant return types and contravariant argument types).
   // Since registerFunc: expects a Derived object as it's second argument, I don't know why this would be legal.
-  [Derived registerFunc: ExternFunc];  // expected-warning{{incompatible pointer types sending 'NSObject *(NSObject *, NSObject *)' to parameter of type 'FuncSignature *'}}
+  [Derived registerFunc: ExternFunc];  // expected-warning{{incompatible function pointer types sending 'NSObject *(NSObject *, NSObject *)' to parameter of type 'FuncSignature *' (aka 'id (*)(NSObject *, Derived *)')}}
 }
 
 // rdar://10751015
Index: clang/test/SemaObjC/arc.m
===================================================================
--- clang/test/SemaObjC/arc.m
+++ clang/test/SemaObjC/arc.m
@@ -114,7 +114,8 @@
 
   __autoreleasing id *a = &x; // expected-error {{initializing '__autoreleasing id *' with an expression of type '__strong id *' changes retain/release properties of pointer}}
 
-  a = &x; // expected-error {{assigning '__strong id *' to '__autoreleasing id *' changes retain/release properties of pointer}}
+  __autoreleasing id *aa;
+  aa = &x; // expected-error {{assigning '__strong id *' to '__autoreleasing id *' changes retain/release properties of pointer}}
 
   extern void test5_helper2(id const *);
   test5_helper2(&x);
Index: clang/test/SemaCXX/ms-property-error.cpp
===================================================================
--- clang/test/SemaCXX/ms-property-error.cpp
+++ clang/test/SemaCXX/ms-property-error.cpp
@@ -19,7 +19,7 @@
     x[2][3] = 4;
     ++x[2][3];
     x[1][2] = x[3][4][5]; // expected-error {{too many arguments to function call, expected 2, have 3}}
-    ptr = x[1][2] = x[3][4]; // expected-error {{assigning to 'char *' from incompatible type 'int'}}
+    ptr = x[1][2] = x[3][4]; // expected-error {{incompatible integer to pointer conversion assigning to 'char *' from 'int'}}
   }
 };
 
Index: clang/test/SemaCXX/int-ptr-cast-SFINAE.cpp
===================================================================
--- clang/test/SemaCXX/int-ptr-cast-SFINAE.cpp
+++ clang/test/SemaCXX/int-ptr-cast-SFINAE.cpp
@@ -2,7 +2,7 @@
 // RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++17
 
 void foo(int* a, int *b) {
-  a -= b; // expected-warning {{incompatible integer to pointer conversion assigning to 'int *' from}}
+  a -= b; // expected-error {{incompatible integer to pointer conversion assigning to 'int *' from}}
 }
 
 template<typename T> T declval();
Index: clang/test/SemaCXX/goto.cpp
===================================================================
--- clang/test/SemaCXX/goto.cpp
+++ clang/test/SemaCXX/goto.cpp
@@ -40,7 +40,7 @@
 }
 
 void g() {
-  end = 1; // expected-error{{assigning to 'double *' from incompatible type 'int'}}
+  end = 1; // expected-error{{incompatible integer to pointer conversion assigning to 'double *' from 'int'}}
 }
 
 void h(int end) {
Index: clang/test/SemaCXX/decl-microsoft-call-conv.cpp
===================================================================
--- clang/test/SemaCXX/decl-microsoft-call-conv.cpp
+++ clang/test/SemaCXX/decl-microsoft-call-conv.cpp
@@ -239,7 +239,7 @@
   template <typename T>
   struct S {
     void f(T t) { // expected-note {{previous declaration is here}}
-      t = 42; // expected-error {{assigning to 'void *' from incompatible type 'int'}}
+      t = 42; // expected-error {{incompatible integer to pointer conversion assigning to 'void *' from 'int'}}
     }
   };
   template<> void __cdecl S<void*>::f(void*); // expected-error {{function declared 'cdecl' here was previously declared without calling convention}}
Index: clang/test/SemaCXX/addr-of-overloaded-function.cpp
===================================================================
--- clang/test/SemaCXX/addr-of-overloaded-function.cpp
+++ clang/test/SemaCXX/addr-of-overloaded-function.cpp
@@ -182,19 +182,19 @@
   void parameter_number() {
     void (*ptr1)(int, int) = &fun; // expected-error {{cannot initialize a variable of type 'void (*)(int, int)' with an rvalue of type 'void (*)(int)': different number of parameters (2 vs 1)}}
     void (*ptr2)(int, int);
-    ptr2 = &fun;  // expected-error {{assigning to 'void (*)(int, int)' from incompatible type 'void (*)(int)': different number of parameters (2 vs 1)}}
+    ptr2 = &fun;  // expected-error {{incompatible function pointer types assigning to 'void (*)(int, int)' from 'void (*)(int)'}}
   }
 
   void parameter_mismatch() {
     void (*ptr1)(double) = &fun; // expected-error {{cannot initialize a variable of type 'void (*)(double)' with an rvalue of type 'void (*)(int)': type mismatch at 1st parameter ('double' vs 'int')}}
     void (*ptr2)(double);
-    ptr2 = &fun; // expected-error {{assigning to 'void (*)(double)' from incompatible type 'void (*)(int)': type mismatch at 1st parameter ('double' vs 'int')}}
+    ptr2 = &fun; // expected-error {{incompatible function pointer types assigning to 'void (*)(double)' from 'void (*)(int)'}}
   }
 
   void return_type_test() {
     int (*ptr1)(int) = &fun; // expected-error {{cannot initialize a variable of type 'int (*)(int)' with an rvalue of type 'void (*)(int)': different return type ('int' vs 'void')}}
     int (*ptr2)(int);
-    ptr2 = &fun;  // expected-error {{assigning to 'int (*)(int)' from incompatible type 'void (*)(int)': different return type ('int' vs 'void')}}
+    ptr2 = &fun;  // expected-error {{incompatible function pointer types assigning to 'int (*)(int)' from 'void (*)(int)'}}
   }
 
   int foo(double x, double y) {return 0;} // expected-note {{candidate function has different number of parameters (expected 1 but has 2)}}
Index: clang/test/Sema/preserve-call-conv.c
===================================================================
--- clang/test/Sema/preserve-call-conv.c
+++ clang/test/Sema/preserve-call-conv.c
@@ -14,8 +14,8 @@
 
 void (__attribute__((preserve_most)) *pfoo1)(void *) = foo;
 
-void (__attribute__((cdecl)) *pfoo2)(void *) = foo; // expected-warning {{incompatible pointer types initializing 'void (*)(void *) __attribute__((cdecl))' with an expression of type 'void (void *) __attribute__((preserve_most))'}}
-void (*pfoo3)(void *) = foo; // expected-warning {{incompatible pointer types initializing 'void (*)(void *)' with an expression of type 'void (void *) __attribute__((preserve_most))'}}
+void (__attribute__((cdecl)) *pfoo2)(void *) = foo; // expected-warning {{incompatible function pointer types initializing 'void (*)(void *) __attribute__((cdecl))' with an expression of type 'void (void *) __attribute__((preserve_most))'}}
+void (*pfoo3)(void *) = foo; // expected-warning {{incompatible function pointer types initializing 'void (*)(void *)' with an expression of type 'void (void *) __attribute__((preserve_most))'}}
 
 typedef_fun_t typedef_fun_foo; // expected-note {{previous declaration is here}}
 void __attribute__((preserve_most)) typedef_fun_foo(int x) { } // expected-error {{function declared 'preserve_most' here was previously declared without calling convention}}
@@ -30,8 +30,8 @@
 
 void (__attribute__((preserve_all)) *pboo1)(void *) = boo;
 
-void (__attribute__((cdecl)) *pboo2)(void *) = boo; // expected-warning {{incompatible pointer types initializing 'void (*)(void *) __attribute__((cdecl))' with an expression of type 'void (void *) __attribute__((preserve_all))'}}
-void (*pboo3)(void *) = boo; // expected-warning {{incompatible pointer types initializing 'void (*)(void *)' with an expression of type 'void (void *) __attribute__((preserve_all))'}}
+void (__attribute__((cdecl)) *pboo2)(void *) = boo; // expected-warning {{incompatible function pointer types initializing 'void (*)(void *) __attribute__((cdecl))' with an expression of type 'void (void *) __attribute__((preserve_all))'}}
+void (*pboo3)(void *) = boo; // expected-warning {{incompatible function pointer types initializing 'void (*)(void *)' with an expression of type 'void (void *) __attribute__((preserve_all))'}}
 
 typedef_fun_t typedef_fun_boo; // expected-note {{previous declaration is here}}
 void __attribute__((preserve_all)) typedef_fun_boo(int x) { } // expected-error {{function declared 'preserve_all' here was previously declared without calling convention}}
Index: clang/test/Sema/pass-object-size.c
===================================================================
--- clang/test/Sema/pass-object-size.c
+++ clang/test/Sema/pass-object-size.c
@@ -44,8 +44,8 @@
   void (*p)(void *) = NotOverloaded; //expected-error{{cannot take address of function 'NotOverloaded' because parameter 1 has pass_object_size attribute}}
   void (*p2)(void *) = &NotOverloaded; //expected-error{{cannot take address of function 'NotOverloaded' because parameter 1 has pass_object_size attribute}}
 
-  void (*p3)(void *) = IsOverloaded; //expected-warning{{incompatible pointer types initializing 'void (*)(void *)' with an expression of type '<overloaded function type>'}}
-  void (*p4)(void *) = &IsOverloaded; //expected-warning{{incompatible pointer types initializing 'void (*)(void *)' with an expression of type '<overloaded function type>'}}
+  void (*p3)(void *) = IsOverloaded; //expected-warning{{incompatible function pointer types initializing 'void (*)(void *)' with an expression of type '<overloaded function type>'}}
+  void (*p4)(void *) = &IsOverloaded; //expected-warning{{incompatible function pointer types initializing 'void (*)(void *)' with an expression of type '<overloaded function type>'}}
 
   void (*p5)(char *) = IsOverloaded;
   void (*p6)(char *) = &IsOverloaded;
Index: clang/test/Sema/overloadable.c
===================================================================
--- clang/test/Sema/overloadable.c
+++ clang/test/Sema/overloadable.c
@@ -26,7 +26,7 @@
 void test_funcptr(int (*f1)(int, double),
                   int (*f2)(int, float)) {
   float *fp = accept_funcptr(f1);
-  accept_funcptr(f2); // expected-error{{call to 'accept_funcptr' is ambiguous}}
+  accept_funcptr(f2); // expected-error{{no matching function for call to 'accept_funcptr'}}
 }
 
 struct X { int x; float y; };
@@ -119,8 +119,8 @@
   void disabled(char *c) __attribute__((overloadable, enable_if(1, "The function name lies.")));
   // To be clear, these should all point to the last overload of 'disabled'
   void (*dptr1)(char *c) = &disabled;
-  void (*dptr2)(void *c) = &disabled; // expected-warning{{incompatible pointer types initializing 'void (*)(void *)' with an expression of type '<overloaded function type>'}} expected-note@-5{{candidate function made ineligible by enable_if}} expected-note@-4{{candidate function made ineligible by enable_if}} expected-note@-3{{candidate function has type mismatch at 1st parameter (expected 'void *' but has 'char *')}}
-  void (*dptr3)(int *c) = &disabled; // expected-warning{{incompatible pointer types initializing 'void (*)(int *)' with an expression of type '<overloaded function type>'}} expected-note@-6{{candidate function made ineligible by enable_if}} expected-note@-5{{candidate function made ineligible by enable_if}} expected-note@-4{{candidate function has type mismatch at 1st parameter (expected 'int *' but has 'char *')}}
+  void (*dptr2)(void *c) = &disabled; // expected-warning{{incompatible function pointer types initializing 'void (*)(void *)' with an expression of type '<overloaded function type>'}} expected-note@-5{{candidate function made ineligible by enable_if}} expected-note@-4{{candidate function made ineligible by enable_if}} expected-note@-3{{candidate function has type mismatch at 1st parameter (expected 'void *' but has 'char *')}}
+  void (*dptr3)(int *c) = &disabled; // expected-warning{{incompatible function pointer types initializing 'void (*)(int *)' with an expression of type '<overloaded function type>'}} expected-note@-6{{candidate function made ineligible by enable_if}} expected-note@-5{{candidate function made ineligible by enable_if}} expected-note@-4{{candidate function has type mismatch at 1st parameter (expected 'int *' but has 'char *')}}
 
   void *specific_disabled = &disabled;
 }
Index: clang/test/Sema/callingconv.c
===================================================================
--- clang/test/Sema/callingconv.c
+++ clang/test/Sema/callingconv.c
@@ -31,7 +31,7 @@
 
 void (__attribute__((stdcall)) *pbar)(float*) = bar;
 
-void (__attribute__((cdecl)) *ptest1)(void) = test1; // expected-warning {{incompatible pointer types}}
+void (__attribute__((cdecl)) *ptest1)(void) = test1; // expected-warning {{incompatible function pointer types}}
 
 void (*pctest0)() = ctest0;
 
Index: clang/test/Sema/callingconv-sysv_abi.c
===================================================================
--- clang/test/Sema/callingconv-sysv_abi.c
+++ clang/test/Sema/callingconv-sysv_abi.c
@@ -1,9 +1,9 @@
 // RUN: %clang_cc1 -fsyntax-only -verify -triple x86_64-pc-linux-gnu %s
 
 void __attribute__((ms_abi)) foo(void);
-void (*pfoo)(void) = foo; // expected-warning{{incompatible pointer types}}
+void (*pfoo)(void) = foo; // expected-warning{{incompatible function pointer types}}
 
 void __attribute__((sysv_abi)) bar(void);
 void (*pbar)(void) = bar;
 
-void (__attribute__((ms_abi)) *pbar2)(void) = bar; // expected-warning{{incompatible pointer types}}
+void (__attribute__((ms_abi)) *pbar2)(void) = bar; // expected-warning{{incompatible function pointer types}}
Index: clang/test/Sema/callingconv-ms_abi.c
===================================================================
--- clang/test/Sema/callingconv-ms_abi.c
+++ clang/test/Sema/callingconv-ms_abi.c
@@ -4,6 +4,6 @@
 void (*pfoo)(void) = foo;
 
 void __attribute__((sysv_abi)) bar(void);
-void (*pbar)(void) = bar; // expected-warning{{incompatible pointer types}}
+void (*pbar)(void) = bar; // expected-warning{{incompatible function pointer types}}
 
-void (__attribute__((sysv_abi)) *pfoo2)(void) = foo; // expected-warning{{incompatible pointer types}}
+void (__attribute__((sysv_abi)) *pfoo2)(void) = foo; // expected-warning{{incompatible function pointer types}}
Index: clang/test/Sema/block-return.c
===================================================================
--- clang/test/Sema/block-return.c
+++ clang/test/Sema/block-return.c
@@ -79,7 +79,7 @@
 void next();
 void foo4() {
   int (^xx)(const char *s) = ^(char *s) { return 1; }; // expected-error {{incompatible block pointer types initializing 'int (^)(const char *)' with an expression of type 'int (^)(char *)'}}
-  int (*yy)(const char *s) = funk; // expected-warning {{incompatible pointer types initializing 'int (*)(const char *)' with an expression of type 'int (char *)'}}
+  int (*yy)(const char *s) = funk; // expected-warning {{incompatible function pointer types initializing 'int (*)(const char *)' with an expression of type 'int (char *)'}}
   
   int (^nested)(char *s) = ^(char *str) { void (^nest)(void) = ^(void) { printf("%s\n", str); }; next(); return 1; }; // expected-warning{{implicitly declaring library function 'printf' with type 'int (const char *, ...)'}} \
   // expected-note{{include the header <stdio.h> or explicitly provide a declaration for 'printf'}}
Index: clang/test/Sema/block-call.c
===================================================================
--- clang/test/Sema/block-call.c
+++ clang/test/Sema/block-call.c
@@ -33,7 +33,7 @@
   int (^IPCC6) (int, char (^CArg) (float))  = IPCC4; // expected-error {{incompatible block pointer types initializing 'int (^)(int, char (^)(float))' with an expression of type 'int (^)(int, char (^)(double))'}}
 
   IPCC2 = 0;
-  IPCC2 = 1; // expected-error {{invalid block pointer conversion assigning to 'int *(^)()' from 'int'}}
+  IPCC1 = 1; // expected-error {{invalid block pointer conversion assigning to 'int *const (^)()' from 'int'}}
   int (^x)() = 0;
   int (^y)() = 3;   // expected-error {{invalid block pointer conversion initializing 'int (^)()' with an expression of type 'int'}}
   int a = 1;
Index: clang/test/OpenMP/allocate_allocator_messages.cpp
===================================================================
--- clang/test/OpenMP/allocate_allocator_messages.cpp
+++ clang/test/OpenMP/allocate_allocator_messages.cpp
@@ -28,7 +28,7 @@
 struct St1{
  int a;
  static int b;
-#pragma omp allocate(b) allocator(sss) // expected-error {{initializing 'const omp_allocator_handle_t' (aka 'void **const') with an expression of incompatible type 'int'}} expected-note {{previous allocator is specified here}}
+#pragma omp allocate(b) allocator(sss) // expected-error {{incompatible integer to pointer conversion initializing 'const omp_allocator_handle_t' (aka 'void **const') with an expression of type 'int'}} expected-note {{previous allocator is specified here}}
 #pragma omp allocate(b)
 #pragma omp allocate(b) allocator(omp_thread_mem_alloc) // expected-warning {{allocate directive specifies 'omp_thread_mem_alloc' allocator while previously used default}}
 } d; // expected-note 2 {{'d' defined here}}
Index: clang/test/CXX/temp/temp.spec/temp.explicit/p9.cpp
===================================================================
--- clang/test/CXX/temp/temp.spec/temp.explicit/p9.cpp
+++ clang/test/CXX/temp/temp.spec/temp.explicit/p9.cpp
@@ -3,7 +3,7 @@
 template<typename T>
 struct X0 {
   void f(T &t) {
-    t = 1; // expected-error{{incompatible type}}
+    t = 1; // expected-error{{incompatible integer to pointer conversion}}
   }
   
   void g(T &t);
@@ -15,7 +15,7 @@
 
 template<typename T>
 inline void X0<T>::g(T & t) {
-  t = 1; // expected-error{{incompatible type}}
+  t = 1; // expected-error{{incompatible integer to pointer conversion}}
 }
 
 template<typename T>
@@ -37,12 +37,12 @@
 
 template<typename T>
 void f0(T& t) {
-  t = 1; // expected-error{{incompatible type}}
+  t = 1; // expected-error{{incompatible integer to pointer conversion}}
 }
 
 template<typename T>
 inline void f1(T& t) {
-  t = 1; // expected-error 2{{incompatible type}}
+  t = 1; // expected-error 2{{incompatible integer to pointer conversion}}
 }
 
 extern template void f0<>(int *&);
Index: clang/test/CXX/temp/temp.spec/temp.explicit/p10.cpp
===================================================================
--- clang/test/CXX/temp/temp.spec/temp.explicit/p10.cpp
+++ clang/test/CXX/temp/temp.spec/temp.explicit/p10.cpp
@@ -11,7 +11,7 @@
 
 template<typename T>
 void X0<T>::f(T& t) { 
-  t = 1; // expected-error{{incompatible type}}
+  t = 1; // expected-error{{incompatible integer to pointer conversion}}
 }
 
 template<typename T>
Index: clang/test/CXX/temp/temp.spec/temp.expl.spec/p19.cpp
===================================================================
--- clang/test/CXX/temp/temp.spec/temp.expl.spec/p19.cpp
+++ clang/test/CXX/temp/temp.spec/temp.expl.spec/p19.cpp
@@ -14,7 +14,7 @@
 
 template<> template<typename U>
 void X<int>::f(int x, U y) { 
-  x = y; // expected-error{{incompatible type}}
+  x = y; // expected-error{{incompatible pointer to integer conversion}}
 }
 
 void test(X<int> xi, X<long> xl, float *fp) {
Index: clang/test/CXX/expr/p13.cpp
===================================================================
--- clang/test/CXX/expr/p13.cpp
+++ clang/test/CXX/expr/p13.cpp
@@ -11,7 +11,7 @@
 using F = void (Y::*)();
 
 void f(A a, B b, C c, D d, E e, F f, bool k) {
-  a = k ? a : b; // expected-error {{different exception specifications}}
+  a = k ? a : b; // expected-error {{incompatible function pointer types assigning to 'A' (aka 'void (*)() noexcept') from 'void (*)()'}}
   b = k ? a : b;
 
   c = k ? c : d; // expected-error {{different exception specifications}}
Index: clang/test/CXX/except/except.handle/p16.cpp
===================================================================
--- clang/test/CXX/except/except.handle/p16.cpp
+++ clang/test/CXX/except/except.handle/p16.cpp
@@ -11,12 +11,12 @@
 public:
   X(const X<T> &) {
     int *ip = 0;
-    ptr = ip; // expected-error{{assigning to 'float *' from incompatible type 'int *'}}
+    ptr = ip; // expected-error{{incompatible pointer types assigning to 'float *' from 'int *'}}
   }
 
   ~X() {
     float *fp = 0;
-    ptr = fp; // expected-error{{assigning to 'int *' from incompatible type 'float *'}}
+    ptr = fp; // expected-error{{incompatible pointer types assigning to 'int *' from 'float *'}}
   }
 };
 
Index: clang/test/CXX/drs/dr3xx.cpp
===================================================================
--- clang/test/CXX/drs/dr3xx.cpp
+++ clang/test/CXX/drs/dr3xx.cpp
@@ -372,7 +372,7 @@
     s = q; // expected-error {{incompatible}}
     s = q2; // expected-error {{incompatible}}
     s = t; // ok, adding const
-    t = s; // expected-error {{incompatible}}
+    t = s; // expected-error {{discards qualifiers}}
     (void) const_cast<P>(q);
     (void) const_cast<P>(q2);
     (void) const_cast<Q>(p);
Index: clang/test/CXX/conv/conv.fctptr/p1.cpp
===================================================================
--- clang/test/CXX/conv/conv.fctptr/p1.cpp
+++ clang/test/CXX/conv/conv.fctptr/p1.cpp
@@ -11,7 +11,7 @@
 Throw S::*d;
 
 void test() {
-  a = b; // expected-error {{assigning to 'Nothrow *' (aka 'void (*)() noexcept') from incompatible type 'Throw *' (aka 'void (*)()'): different exception specifications}}
+  a = b; // expected-error {{incompatible function pointer types assigning to 'Nothrow *' (aka 'void (*)() noexcept') from 'Throw *' (aka 'void (*)()')}}
   b = a;
   c = d; // expected-error {{assigning to 'Nothrow S::*' from incompatible type 'Throw S::*': different exception specifications}}
   d = c;
Index: clang/lib/Sema/SemaExprCXX.cpp
===================================================================
--- clang/lib/Sema/SemaExprCXX.cpp
+++ clang/lib/Sema/SemaExprCXX.cpp
@@ -3872,9 +3872,11 @@
     llvm_unreachable("Cannot perform an ellipsis conversion");
 
   case ImplicitConversionSequence::BadConversion:
-    bool Diagnosed =
-        DiagnoseAssignmentResult(Incompatible, From->getExprLoc(), ToType,
-                                 From->getType(), From, Action);
+    Sema::AssignConvertType ConvTy =
+        CheckAssignmentConstraints(From->getExprLoc(), ToType, From->getType());
+    bool Diagnosed = DiagnoseAssignmentResult(
+        ConvTy == Compatible ? Incompatible : ConvTy, From->getExprLoc(),
+        ToType, From->getType(), From, Action);
     assert(Diagnosed && "failed to diagnose bad conversion"); (void)Diagnosed;
     return ExprError();
   }
Index: clang/lib/Sema/SemaExpr.cpp
===================================================================
--- clang/lib/Sema/SemaExpr.cpp
+++ clang/lib/Sema/SemaExpr.cpp
@@ -8144,11 +8144,13 @@
     }
 
     // General pointer incompatibility takes priority over qualifiers.
+    if (RHSType->isFunctionPointerType() && LHSType->isFunctionPointerType())
+      return Sema::IncompatibleFunctionPointer;
     return Sema::IncompatiblePointer;
   }
   if (!S.getLangOpts().CPlusPlus &&
       S.IsFunctionConversion(ltrans, rtrans, ltrans))
-    return Sema::IncompatiblePointer;
+    return Sema::IncompatibleFunctionPointer;
   return ConvTy;
 }
 
@@ -14780,24 +14782,44 @@
       return false;
 
   case PointerToInt:
-    DiagKind = diag::ext_typecheck_convert_pointer_int;
+    if (getLangOpts().CPlusPlus) {
+      DiagKind = diag::err_typecheck_convert_pointer_int;
+      isInvalid = true;
+    } else {
+      DiagKind = diag::ext_typecheck_convert_pointer_int;
+    }
     ConvHints.tryToFixConversion(SrcExpr, SrcType, DstType, *this);
     MayHaveConvFixit = true;
     break;
   case IntToPointer:
-    DiagKind = diag::ext_typecheck_convert_int_pointer;
+    if (getLangOpts().CPlusPlus) {
+      DiagKind = diag::err_typecheck_convert_int_pointer;
+      isInvalid = true;
+    } else {
+      DiagKind = diag::ext_typecheck_convert_int_pointer;
+    }
+    ConvHints.tryToFixConversion(SrcExpr, SrcType, DstType, *this);
+    MayHaveConvFixit = true;
+    break;
+  case IncompatibleFunctionPointer:
+    if (getLangOpts().CPlusPlus) {
+      DiagKind = diag::err_typecheck_convert_incompatible_function_pointer;
+      isInvalid = true;
+    } else {
+      DiagKind = diag::ext_typecheck_convert_incompatible_function_pointer;
+    }
     ConvHints.tryToFixConversion(SrcExpr, SrcType, DstType, *this);
     MayHaveConvFixit = true;
     break;
   case IncompatiblePointer:
-    if (Action == AA_Passing_CFAudited)
+    if (Action == AA_Passing_CFAudited) {
       DiagKind = diag::err_arc_typecheck_convert_incompatible_pointer;
-    else if (SrcType->isFunctionPointerType() &&
-             DstType->isFunctionPointerType())
-      DiagKind = diag::ext_typecheck_convert_incompatible_function_pointer;
-    else
+    } else if (getLangOpts().CPlusPlus) {
+      DiagKind = diag::err_typecheck_convert_incompatible_pointer;
+      isInvalid = true;
+    } else {
       DiagKind = diag::ext_typecheck_convert_incompatible_pointer;
-
+    }
     CheckInferredResultType = DstType->isObjCObjectPointerType() &&
       SrcType->isObjCObjectPointerType();
     if (Hint.isNull() && !CheckInferredResultType) {
@@ -14810,15 +14832,27 @@
     MayHaveConvFixit = true;
     break;
   case IncompatiblePointerSign:
-    DiagKind = diag::ext_typecheck_convert_incompatible_pointer_sign;
+    if (getLangOpts().CPlusPlus) {
+      DiagKind = diag::err_typecheck_convert_incompatible_pointer_sign;
+      isInvalid = true;
+    } else {
+      DiagKind = diag::ext_typecheck_convert_incompatible_pointer_sign;
+    }
     break;
   case FunctionVoidPointer:
-    DiagKind = diag::ext_typecheck_convert_pointer_void_func;
+    if (getLangOpts().CPlusPlus) {
+      DiagKind = diag::err_typecheck_convert_pointer_void_func;
+      isInvalid = true;
+    } else {
+      DiagKind = diag::ext_typecheck_convert_pointer_void_func;
+    }
     break;
   case IncompatiblePointerDiscardsQualifiers: {
     // Perform array-to-pointer decay if necessary.
     if (SrcType->isArrayType()) SrcType = Context.getArrayDecayedType(SrcType);
 
+    isInvalid = true;
+
     Qualifiers lhq = SrcType->getPointeeType().getQualifiers();
     Qualifiers rhq = DstType->getPointeeType().getQualifiers();
     if (lhq.getAddressSpace() != rhq.getAddressSpace()) {
@@ -14846,19 +14880,33 @@
     if (getLangOpts().CPlusPlus &&
         IsStringLiteralToNonConstPointerConversion(SrcExpr, DstType))
       return false;
-    DiagKind = diag::ext_typecheck_convert_discards_qualifiers;
+    if (getLangOpts().CPlusPlus) {
+      DiagKind =  diag::err_typecheck_convert_discards_qualifiers;
+      isInvalid = true;
+    } else {
+      DiagKind =  diag::ext_typecheck_convert_discards_qualifiers;
+    }
+
     break;
   case IncompatibleNestedPointerQualifiers:
-    DiagKind = diag::ext_nested_pointer_qualifier_mismatch;
+    if (getLangOpts().CPlusPlus) {
+      isInvalid = true;
+      DiagKind = diag::err_nested_pointer_qualifier_mismatch;
+    } else {
+      DiagKind = diag::ext_nested_pointer_qualifier_mismatch;
+    }
     break;
   case IncompatibleNestedPointerAddressSpaceMismatch:
     DiagKind = diag::err_typecheck_incompatible_nested_address_space;
+    isInvalid = true;
     break;
   case IntToBlockPointer:
     DiagKind = diag::err_int_to_block_pointer;
+    isInvalid = true;
     break;
   case IncompatibleBlockPointer:
     DiagKind = diag::err_typecheck_convert_incompatible_block_pointer;
+    isInvalid = true;
     break;
   case IncompatibleObjCQualifiedId: {
     if (SrcType->isObjCQualifiedIdType()) {
@@ -14883,14 +14931,25 @@
             SrcType->castAs<ObjCObjectPointerType>()->getInterfaceType())
         IFace = IFaceT->getDecl();
     }
-    DiagKind = diag::warn_incompatible_qualified_id;
+    if (getLangOpts().CPlusPlus) {
+      DiagKind = diag::err_incompatible_qualified_id;
+      isInvalid = true;
+    } else {
+      DiagKind = diag::warn_incompatible_qualified_id;
+    }
     break;
   }
   case IncompatibleVectors:
-    DiagKind = diag::warn_incompatible_vectors;
+    if (getLangOpts().CPlusPlus) {
+      DiagKind = diag::err_incompatible_vectors;
+      isInvalid = true;
+    } else {
+      DiagKind = diag::warn_incompatible_vectors;
+    }
     break;
   case IncompatibleObjCWeakRef:
     DiagKind = diag::err_arc_weak_unavailable_assign;
+    isInvalid = true;
     break;
   case Incompatible:
     if (maybeDiagnoseAssignmentToFunction(*this, DstType, SrcExpr)) {
@@ -14948,9 +15007,10 @@
     HandleFunctionTypeMismatch(FDiag, SecondType, FirstType);
 
   Diag(Loc, FDiag);
-  if (DiagKind == diag::warn_incompatible_qualified_id &&
+  if ((DiagKind == diag::warn_incompatible_qualified_id ||
+       DiagKind == diag::err_incompatible_qualified_id) &&
       PDecl && IFace && !IFace->hasDefinition())
-      Diag(IFace->getLocation(), diag::note_incomplete_class_and_qualified_id)
+    Diag(IFace->getLocation(), diag::note_incomplete_class_and_qualified_id)
         << IFace << PDecl;
 
   if (SecondType == Context.OverloadTy)
Index: clang/include/clang/Sema/Sema.h
===================================================================
--- clang/include/clang/Sema/Sema.h
+++ clang/include/clang/Sema/Sema.h
@@ -10671,6 +10671,11 @@
     /// are not compatible, but we accept them as an extension.
     IncompatiblePointer,
 
+    /// IncompatibleFunctionPointer - The assignment is between two function
+    /// pointers types that are not compatible, but we accept them as an
+    /// extension.
+    IncompatibleFunctionPointer,
+
     /// IncompatiblePointerSign - The assignment is between two pointers types
     /// which point to integers which have a different sign, but are otherwise
     /// identical. This is a subset of the above, but broken out because it's by
Index: clang/include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -7314,6 +7314,21 @@
   "sending type to parameter of incompatible type}0,1"
   "|%diff{casting $ to incompatible type $|"
   "casting type to incompatible type}0,1}2">;
+def err_incompatible_qualified_id : Error<
+  "%select{%diff{assigning to $ from incompatible type $|"
+  "assigning to type from incompatible type}0,1"
+  "|%diff{passing $ to parameter of incompatible type $|"
+  "passing type to parameter of incompatible type}0,1"
+  "|%diff{returning $ from a function with incompatible result type $|"
+  "returning type from a function with incompatible result type}0,1"
+  "|%diff{converting $ to incompatible type $|"
+  "converting type to incompatible type}0,1"
+  "|%diff{initializing $ with an expression of incompatible type $|"
+  "initializing type with an expression of incompatible type}0,1"
+  "|%diff{sending $ to parameter of incompatible type $|"
+  "sending type to parameter of incompatible type}0,1"
+  "|%diff{casting $ to incompatible type $|"
+  "casting type to incompatible type}0,1}2">;
 def ext_typecheck_convert_pointer_int : ExtWarn<
   "incompatible pointer to integer conversion "
   "%select{%diff{assigning to $ from $|assigning to different types}0,1"
@@ -7332,6 +7347,23 @@
   "; remove *|"
   "; remove &}3">,
   InGroup<IntConversion>;
+def err_typecheck_convert_pointer_int : Error<
+  "incompatible pointer to integer conversion "
+  "%select{%diff{assigning to $ from $|assigning to different types}0,1"
+  "|%diff{passing $ to parameter of type $|"
+  "passing to parameter of different type}0,1"
+  "|%diff{returning $ from a function with result type $|"
+  "returning from function with different return type}0,1"
+  "|%diff{converting $ to type $|converting between types}0,1"
+  "|%diff{initializing $ with an expression of type $|"
+  "initializing with expression of different type}0,1"
+  "|%diff{sending $ to parameter of type $|"
+  "sending to parameter of different type}0,1"
+  "|%diff{casting $ to type $|casting between types}0,1}2"
+  "%select{|; dereference with *|"
+  "; take the address with &|"
+  "; remove *|"
+  "; remove &}3">;
 def ext_typecheck_convert_int_pointer : ExtWarn<
   "incompatible integer to pointer conversion "
   "%select{%diff{assigning to $ from $|assigning to different types}0,1"
@@ -7350,6 +7382,23 @@
   "; remove *|"
   "; remove &}3">,
   InGroup<IntConversion>, SFINAEFailure;
+def err_typecheck_convert_int_pointer : Error<
+  "incompatible integer to pointer conversion "
+  "%select{%diff{assigning to $ from $|assigning to different types}0,1"
+  "|%diff{passing $ to parameter of type $|"
+  "passing to parameter of different type}0,1"
+  "|%diff{returning $ from a function with result type $|"
+  "returning from function with different return type}0,1"
+  "|%diff{converting $ to type $|converting between types}0,1"
+  "|%diff{initializing $ with an expression of type $|"
+  "initializing with expression of different type}0,1"
+  "|%diff{sending $ to parameter of type $|"
+  "sending to parameter of different type}0,1"
+  "|%diff{casting $ to type $|casting between types}0,1}2"
+  "%select{|; dereference with *|"
+  "; take the address with &|"
+  "; remove *|"
+  "; remove &}3">;
 def ext_typecheck_convert_pointer_void_func : Extension<
   "%select{%diff{assigning to $ from $|assigning to different types}0,1"
   "|%diff{passing $ to parameter of type $|"
@@ -7363,6 +7412,19 @@
   "sending to parameter of different type}0,1"
   "|%diff{casting $ to type $|casting between types}0,1}2"
   " converts between void pointer and function pointer">;
+def err_typecheck_convert_pointer_void_func : Error<
+  "%select{%diff{assigning to $ from $|assigning to different types}0,1"
+  "|%diff{passing $ to parameter of type $|"
+  "passing to parameter of different type}0,1"
+  "|%diff{returning $ from a function with result type $|"
+  "returning from function with different return type}0,1"
+  "|%diff{converting $ to type $|converting between types}0,1"
+  "|%diff{initializing $ with an expression of type $|"
+  "initializing with expression of different type}0,1"
+  "|%diff{sending $ to parameter of type $|"
+  "sending to parameter of different type}0,1"
+  "|%diff{casting $ to type $|casting between types}0,1}2"
+  " converts between void pointer and function pointer">;
 def ext_typecheck_convert_incompatible_pointer_sign : ExtWarn<
   "%select{%diff{assigning to $ from $|assigning to different types}0,1"
   "|%diff{passing $ to parameter of type $|"
@@ -7377,6 +7439,19 @@
   "|%diff{casting $ to type $|casting between types}0,1}2"
   " converts between pointers to integer types with different sign">,
   InGroup<DiagGroup<"pointer-sign">>;
+def err_typecheck_convert_incompatible_pointer_sign : Error<
+  "%select{%diff{assigning to $ from $|assigning to different types}0,1"
+  "|%diff{passing $ to parameter of type $|"
+  "passing to parameter of different type}0,1"
+  "|%diff{returning $ from a function with result type $|"
+  "returning from function with different return type}0,1"
+  "|%diff{converting $ to type $|converting between types}0,1"
+  "|%diff{initializing $ with an expression of type $|"
+  "initializing with expression of different type}0,1"
+  "|%diff{sending $ to parameter of type $|"
+  "sending to parameter of different type}0,1"
+  "|%diff{casting $ to type $|casting between types}0,1}2"
+  " converts between pointers to integer types with different sign">;
 def ext_typecheck_convert_incompatible_pointer : ExtWarn<
   "incompatible pointer types "
   "%select{%diff{assigning to $ from $|assigning to different types}0,1"
@@ -7395,6 +7470,23 @@
   "; remove *|"
   "; remove &}3">,
   InGroup<IncompatiblePointerTypes>;
+def err_typecheck_convert_incompatible_pointer : Error<
+  "incompatible pointer types "
+  "%select{%diff{assigning to $ from $|assigning to different types}0,1"
+  "|%diff{passing $ to parameter of type $|"
+  "passing to parameter of different type}0,1"
+  "|%diff{returning $ from a function with result type $|"
+  "returning from function with different return type}0,1"
+  "|%diff{converting $ to type $|converting between types}0,1"
+  "|%diff{initializing $ with an expression of type $|"
+  "initializing with expression of different type}0,1"
+  "|%diff{sending $ to parameter of type $|"
+  "sending to parameter of different type}0,1"
+  "|%diff{casting $ to type $|casting between types}0,1}2"
+  "%select{|; dereference with *|"
+  "; take the address with &|"
+  "; remove *|"
+  "; remove &}3">;
 def ext_typecheck_convert_incompatible_function_pointer : ExtWarn<
   "incompatible function pointer types "
   "%select{%diff{assigning to $ from $|assigning to different types}0,1"
@@ -7413,6 +7505,23 @@
   "; remove *|"
   "; remove &}3">,
   InGroup<IncompatibleFunctionPointerTypes>;
+def err_typecheck_convert_incompatible_function_pointer : Error<
+  "incompatible function pointer types "
+  "%select{%diff{assigning to $ from $|assigning to different types}0,1"
+  "|%diff{passing $ to parameter of type $|"
+  "passing to parameter of different type}0,1"
+  "|%diff{returning $ from a function with result type $|"
+  "returning from function with different return type}0,1"
+  "|%diff{converting $ to type $|converting between types}0,1"
+  "|%diff{initializing $ with an expression of type $|"
+  "initializing with expression of different type}0,1"
+  "|%diff{sending $ to parameter of type $|"
+  "sending to parameter of different type}0,1"
+  "|%diff{casting $ to type $|casting between types}0,1}2"
+  "%select{|; dereference with *|"
+  "; take the address with &|"
+  "; remove *|"
+  "; remove &}3">;
 def ext_typecheck_convert_discards_qualifiers : ExtWarn<
   "%select{%diff{assigning to $ from $|assigning to different types}0,1"
   "|%diff{passing $ to parameter of type $|"
@@ -7427,6 +7536,19 @@
   "|%diff{casting $ to type $|casting between types}0,1}2"
   " discards qualifiers">,
   InGroup<IncompatiblePointerTypesDiscardsQualifiers>;
+def err_typecheck_convert_discards_qualifiers : Error<
+  "%select{%diff{assigning to $ from $|assigning to different types}0,1"
+  "|%diff{passing $ to parameter of type $|"
+  "passing to parameter of different type}0,1"
+  "|%diff{returning $ from a function with result type $|"
+  "returning from function with different return type}0,1"
+  "|%diff{converting $ to type $|converting between types}0,1"
+  "|%diff{initializing $ with an expression of type $|"
+  "initializing with expression of different type}0,1"
+  "|%diff{sending $ to parameter of type $|"
+  "sending to parameter of different type}0,1"
+  "|%diff{casting $ to type $|casting between types}0,1}2"
+  " discards qualifiers">;
 def ext_nested_pointer_qualifier_mismatch : ExtWarn<
   "%select{%diff{assigning to $ from $|assigning to different types}0,1"
   "|%diff{passing $ to parameter of type $|"
@@ -7441,6 +7563,19 @@
   "|%diff{casting $ to type $|casting between types}0,1}2"
   " discards qualifiers in nested pointer types">,
   InGroup<IncompatiblePointerTypesDiscardsQualifiers>;
+def err_nested_pointer_qualifier_mismatch : Error<
+  "%select{%diff{assigning to $ from $|assigning to different types}0,1"
+  "|%diff{passing $ to parameter of type $|"
+  "passing to parameter of different type}0,1"
+  "|%diff{returning $ from a function with result type $|"
+  "returning from function with different return type}0,1"
+  "|%diff{converting $ to type $|converting between types}0,1"
+  "|%diff{initializing $ with an expression of type $|"
+  "initializing with expression of different type}0,1"
+  "|%diff{sending $ to parameter of type $|"
+  "sending to parameter of different type}0,1"
+  "|%diff{casting $ to type $|casting between types}0,1}2"
+  " discards qualifiers in nested pointer types">;
 def warn_incompatible_vectors : Warning<
   "incompatible vector types "
   "%select{%diff{assigning to $ from $|assigning to different types}0,1"
@@ -7455,6 +7590,19 @@
   "sending to parameter of different type}0,1"
   "|%diff{casting $ to type $|casting between types}0,1}2">,
   InGroup<VectorConversion>, DefaultIgnore;
+def err_incompatible_vectors : Error<
+  "incompatible vector types "
+  "%select{%diff{assigning to $ from $|assigning to different types}0,1"
+  "|%diff{passing $ to parameter of type $|"
+  "passing to parameter of different type}0,1"
+  "|%diff{returning $ from a function with result type $|"
+  "returning from function with different return type}0,1"
+  "|%diff{converting $ to type $|converting between types}0,1"
+  "|%diff{initializing $ with an expression of type $|"
+  "initializing with expression of different type}0,1"
+  "|%diff{sending $ to parameter of type $|"
+  "sending to parameter of different type}0,1"
+  "|%diff{casting $ to type $|casting between types}0,1}2">;
 def err_int_to_block_pointer : Error<
   "invalid block pointer conversion "
   "%select{%diff{assigning to $ from $|assigning to different types}0,1"
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to