Index: gcc/c-family/c-common.c
===================================================================
--- gcc/c-family/c-common.c	2019-12-06 10:31:11.286433308 +0000
+++ gcc/c-family/c-common.c	2019-12-12 15:13:55.789913884 +0000
@@ -923,11 +923,18 @@ bool_promoted_to_int_p (tree t)
 bool
 vector_targets_convertible_p (const_tree t1, const_tree t2)
 {
-  if (VECTOR_TYPE_P (t1) && VECTOR_TYPE_P (t2)
-      && (TYPE_VECTOR_OPAQUE (t1) || TYPE_VECTOR_OPAQUE (t2))
+  if (!VECTOR_TYPE_P (t1) || !VECTOR_TYPE_P (t2))
+    return false;
+
+  if ((TYPE_VECTOR_OPAQUE (t1) || TYPE_VECTOR_OPAQUE (t2))
       && tree_int_cst_equal (TYPE_SIZE (t1), TYPE_SIZE (t2)))
     return true;
 
+  if (gnu_vector_type_p (t1) != gnu_vector_type_p (t2)
+      && known_eq (TYPE_VECTOR_SUBPARTS (t1), TYPE_VECTOR_SUBPARTS (t2))
+      && lang_hooks.types_compatible_p (TREE_TYPE (t1), TREE_TYPE (t2)))
+    return true;
+
   return false;
 }
 
Index: gcc/cp/typeck.c
===================================================================
--- gcc/cp/typeck.c	2019-12-10 09:17:17.668010318 +0000
+++ gcc/cp/typeck.c	2019-12-12 15:13:55.789913884 +0000
@@ -1429,6 +1429,9 @@ structural_comptypes (tree t1, tree t2,
       if (maybe_ne (TYPE_VECTOR_SUBPARTS (t1), TYPE_VECTOR_SUBPARTS (t2))
 	  || !same_type_p (TREE_TYPE (t1), TREE_TYPE (t2)))
 	return false;
+      if (strict == COMPARE_STRICT
+	  && gnu_vector_type_p (t1) != gnu_vector_type_p (t2))
+	return false;
       break;
 
     case TYPE_PACK_EXPANSION:
@@ -1526,8 +1529,6 @@ comptypes (tree t1, tree t2, int strict)
       else
 	return structural_comptypes (t1, t2, strict);
     }
-  else if (strict == COMPARE_STRUCTURAL)
-    return structural_comptypes (t1, t2, COMPARE_STRICT);
   else
     return structural_comptypes (t1, t2, strict);
 }
@@ -1556,6 +1557,9 @@ similar_type_p (tree type1, tree type2)
   if (type1 == error_mark_node || type2 == error_mark_node)
     return false;
 
+  if (type1 == type2)
+    return true;
+
   /* Informally, two types are similar if, ignoring top-level cv-qualification:
      * they are the same type; or
      * they are both pointers, and the pointed-to types are similar; or
@@ -1564,8 +1568,18 @@ similar_type_p (tree type1, tree type2)
      * they are both arrays of the same size or both arrays of unknown bound,
        and the array element types are similar.  */
 
-  if (same_type_ignoring_top_level_qualifiers_p (type1, type2))
-    return true;
+  tree unqual_type1 = cp_build_qualified_type (type1, TYPE_UNQUALIFIED);
+  tree unqual_type2 = cp_build_qualified_type (type2, TYPE_UNQUALIFIED);
+  if (VECTOR_TYPE_P (unqual_type1) && VECTOR_TYPE_P (unqual_type2))
+    {
+      if (comptypes (unqual_type1, unqual_type2, COMPARE_STRUCTURAL))
+	return true;
+    }
+  else
+    {
+      if (same_type_p (unqual_type1, unqual_type2))
+	return true;
+    }
 
   if ((TYPE_PTR_P (type1) && TYPE_PTR_P (type2))
       || (TYPE_PTRDATAMEM_P (type1) && TYPE_PTRDATAMEM_P (type2))
Index: gcc/testsuite/g++.dg/ext/sve-sizeless-2.C
===================================================================
--- gcc/testsuite/g++.dg/ext/sve-sizeless-2.C	2019-12-06 18:22:12.084859448 +0000
+++ gcc/testsuite/g++.dg/ext/sve-sizeless-2.C	2019-12-12 15:13:55.793913855 +0000
@@ -197,8 +197,8 @@ statements (int n)
   sve_sc_ptr -= 0; // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} }
   sve_sc_ptr -= 1; // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} }
   sve_sc_ptr - sve_sc_ptr; // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} }
-  gnu_sc_ptr - sve_sc_ptr; // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} }
-  sve_sc_ptr - gnu_sc_ptr; // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} }
+  gnu_sc_ptr - sve_sc_ptr; // { dg-error {invalid operands of types 'int8x32_t\*'[^\n]* and 'svint8_t\*' to binary 'operator-'} }
+  sve_sc_ptr - gnu_sc_ptr; // { dg-error {invalid operands of types 'svint8_t\*' and 'int8x32_t\*'[^\n]* to binary 'operator-'} }
   sve_sc1 = sve_sc_ptr[0]; // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} }
   sve_sc1 = sve_sc_ptr[1]; // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} }
 
@@ -210,18 +210,18 @@ statements (int n)
   sve_sc_ptr <= &sve_sc1;
   sve_sc_ptr > &sve_sc1;
   sve_sc_ptr >= &sve_sc1;
-  gnu_sc_ptr == sve_sc_ptr;
-  gnu_sc_ptr != sve_sc_ptr;
-  gnu_sc_ptr < sve_sc_ptr;
-  gnu_sc_ptr <= sve_sc_ptr;
-  gnu_sc_ptr > sve_sc_ptr;
-  gnu_sc_ptr >= sve_sc_ptr;
-  sve_sc_ptr == gnu_sc_ptr;
-  sve_sc_ptr != gnu_sc_ptr;
-  sve_sc_ptr < gnu_sc_ptr;
-  sve_sc_ptr <= gnu_sc_ptr;
-  sve_sc_ptr > gnu_sc_ptr;
-  sve_sc_ptr >= gnu_sc_ptr;
+  gnu_sc_ptr == sve_sc_ptr; // { dg-error {comparison between distinct pointer types [^\n]*lacks a cast} }
+  gnu_sc_ptr != sve_sc_ptr; // { dg-error {comparison between distinct pointer types [^\n]*lacks a cast} }
+  gnu_sc_ptr < sve_sc_ptr; // { dg-error {comparison between distinct pointer types [^\n]*lacks a cast} }
+  gnu_sc_ptr <= sve_sc_ptr; // { dg-error {comparison between distinct pointer types [^\n]*lacks a cast} }
+  gnu_sc_ptr > sve_sc_ptr; // { dg-error {comparison between distinct pointer types [^\n]*lacks a cast} }
+  gnu_sc_ptr >= sve_sc_ptr; // { dg-error {comparison between distinct pointer types [^\n]*lacks a cast} }
+  sve_sc_ptr == gnu_sc_ptr; // { dg-error {comparison between distinct pointer types [^\n]*lacks a cast} }
+  sve_sc_ptr != gnu_sc_ptr; // { dg-error {comparison between distinct pointer types [^\n]*lacks a cast} }
+  sve_sc_ptr < gnu_sc_ptr; // { dg-error {comparison between distinct pointer types [^\n]*lacks a cast} }
+  sve_sc_ptr <= gnu_sc_ptr; // { dg-error {comparison between distinct pointer types [^\n]*lacks a cast} }
+  sve_sc_ptr > gnu_sc_ptr; // { dg-error {comparison between distinct pointer types [^\n]*lacks a cast} }
+  sve_sc_ptr >= gnu_sc_ptr; // { dg-error {comparison between distinct pointer types [^\n]*lacks a cast} }
 
   // New and delete.
 
@@ -243,8 +243,8 @@ statements (int n)
   0 ? 0 : sve_sc1; // { dg-error {different types 'int' and 'svint8_t'} }
   0 ? sve_sc1 : sve_sc1;
   0 ? sve_sc_ptr : sve_sc_ptr;
-  0 ? sve_sc_ptr : gnu_sc_ptr;
-  0 ? gnu_sc_ptr : sve_sc_ptr;
+  0 ? sve_sc_ptr : gnu_sc_ptr; // { dg-error {conditional expression between distinct pointer types [^\n]*lacks a cast} }
+  0 ? gnu_sc_ptr : sve_sc_ptr; // { dg-error {conditional expression between distinct pointer types [^\n]*lacks a cast} }
 
   // Function arguments.
 
@@ -321,11 +321,11 @@ statements (int n)
   { typedef int f[__is_pod (svint8_t) ? 1 : -1]; }
   { typedef int f[!__is_polymorphic (svint8_t) ? 1 : -1]; }
   { typedef int f[__is_same_as (svint8_t, svint8_t) ? 1 : -1]; }
-  { typedef int f[__is_same_as (svint8_t, int8x32_t) ? 1 : -1]; }
-  { typedef int f[__is_same_as (int8x32_t, svint8_t) ? 1 : -1]; }
+  { typedef int f[!__is_same_as (svint8_t, int8x32_t) ? 1 : -1]; }
+  { typedef int f[!__is_same_as (int8x32_t, svint8_t) ? 1 : -1]; }
   { typedef int f[__is_same_as (svint8_t *, svint8_t *) ? 1 : -1]; }
-  { typedef int f[__is_same_as (svint8_t *, int8x32_t *) ? 1 : -1]; }
-  { typedef int f[__is_same_as (int8x32_t *, svint8_t *) ? 1 : -1]; }
+  { typedef int f[!__is_same_as (svint8_t *, int8x32_t *) ? 1 : -1]; }
+  { typedef int f[!__is_same_as (int8x32_t *, svint8_t *) ? 1 : -1]; }
   { typedef int f[!__is_same_as (svint8_t, int) ? 1 : -1]; }
   { typedef int f[!__is_same_as (svint8_t, svint16_t) ? 1 : -1]; }
   { typedef int f[__is_trivial (svint8_t) ? 1 : -1]; }
Index: gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/gnu_vectors_1.C
===================================================================
--- gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/gnu_vectors_1.C	2019-12-04 09:17:59.654022577 +0000
+++ gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/gnu_vectors_1.C	2019-12-12 15:13:55.793913855 +0000
@@ -434,8 +434,8 @@ f (svuint8_t sve_u1, svint8_t sve_s1,
   // Conditional expressions.
 
   uc ? sve_u1 : sve_u1;
-  uc ? gnu_u1 : sve_u1; // { dg-error {operands to '\?:' have different types 'gnu_uint8_t'[^\n]* and 'svuint8_t'} "" { xfail *-*-* } }
-  uc ? sve_u1 : gnu_u1; // { dg-error {operands to '\?:' have different types 'svuint8_t' and 'gnu_uint8_t'} "" { xfail *-*-* } }
+  uc ? gnu_u1 : sve_u1; // { dg-error {operands to '\?:' have different types 'gnu_uint8_t'[^\n]* and 'svuint8_t'} }
+  uc ? sve_u1 : gnu_u1; // { dg-error {operands to '\?:' have different types 'svuint8_t' and 'gnu_uint8_t'} }
   uc ? gnu_u1 : gnu_u1;
 
   sve_u1 ? sve_u1 : sve_u1; // { dg-error {could not convert 'sve_u1' from 'svuint8_t' to 'bool'} }
Index: gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/gnu_vectors_2.C
===================================================================
--- gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/gnu_vectors_2.C	2019-12-04 09:17:59.654022577 +0000
+++ gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/gnu_vectors_2.C	2019-12-12 15:13:55.793913855 +0000
@@ -434,8 +434,8 @@ f (svuint8_t sve_u1, svint8_t sve_s1,
   // Conditional expressions.
 
   uc ? sve_u1 : sve_u1;
-  uc ? gnu_u1 : sve_u1; // { dg-error {operands to '\?:' have different types 'gnu_uint8_t'[^\n]* and 'svuint8_t'} "" { xfail *-*-* } }
-  uc ? sve_u1 : gnu_u1; // { dg-error {operands to '\?:' have different types 'svuint8_t' and 'gnu_uint8_t'} "" { xfail *-*-* } }
+  uc ? gnu_u1 : sve_u1; // { dg-error {operands to '\?:' have different types 'gnu_uint8_t'[^\n]* and 'svuint8_t'} }
+  uc ? sve_u1 : gnu_u1; // { dg-error {operands to '\?:' have different types 'svuint8_t' and 'gnu_uint8_t'} }
   uc ? gnu_u1 : gnu_u1;
 
   sve_u1 ? sve_u1 : sve_u1; // { dg-error {could not convert 'sve_u1' from 'svuint8_t' to 'bool'} }
